MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ capture_frame()

void MayaFlux::Core::BackendWindowHandler::capture_frame ( WindowRenderContext &  ctx)
private

Capture the current frame from a window's swapchain.

Parameters
ctxWindow render context to capture from

This initiates an asynchronous readback of the current swapchain image into CPU-accessible memory. The result is stored in the capture state for retrieval via the display service.

Definition at line 937 of file BackendWindowHandler.cpp.

938{
939 if (!ctx.swapchain || ctx.window->get_rendering_buffers().empty()
940 || !ctx.window->is_capture_enabled())
941 return;
942
943 auto dev = m_context.get_device();
944 const auto ext = ctx.swapchain->get_extent();
945 const vk::Format fmt = ctx.swapchain->get_image_format();
946 const uint32_t bpp = Core::vk_format_bytes_per_pixel(fmt);
947 const vk::Image src = ctx.swapchain->get_images()[ctx.current_image_index];
948
949 if (!ctx.capture) {
951 }
952
953 auto& slot = *ctx.capture->slots[ctx.capture->slot_index];
954
955 if (slot.pending.load(std::memory_order_acquire))
956 return;
957
958 if (slot.image && slot.extent != ext) {
959 dev.destroyImage(slot.image);
960 dev.freeMemory(slot.mem);
961 slot.image = vk::Image {};
962 slot.mem = vk::DeviceMemory {};
963 }
964
965 if (!slot.image) {
966 vk::ImageCreateInfo ici {};
967 ici.imageType = vk::ImageType::e2D;
968 ici.format = fmt;
969 ici.extent = vk::Extent3D { ext.width, ext.height, 1 };
970 ici.arrayLayers = 1;
971 ici.mipLevels = 1;
972 ici.samples = vk::SampleCountFlagBits::e1;
973 ici.tiling = vk::ImageTiling::eLinear;
974 ici.usage = vk::ImageUsageFlagBits::eTransferDst;
975
976 slot.image = dev.createImage(ici);
977
978 auto req = dev.getImageMemoryRequirements(slot.image);
979 vk::MemoryAllocateInfo mai {};
980 mai.allocationSize = req.size;
981 mai.memoryTypeIndex = m_resource_manager->find_memory_type(
982 req.memoryTypeBits,
983 vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
984
985 slot.mem = dev.allocateMemory(mai);
986 dev.bindImageMemory(slot.image, slot.mem, 0);
987 slot.extent = ext;
988 }
989
990 slot.cmd.reset({});
991 vk::CommandBufferBeginInfo bi {};
992 bi.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
993 slot.cmd.begin(bi);
994
995 vk::ImageMemoryBarrier b {};
996 b.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
997 b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
998 b.subresourceRange = { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 };
999
1000 b.image = slot.image;
1001 b.oldLayout = vk::ImageLayout::eUndefined;
1002 b.newLayout = vk::ImageLayout::eTransferDstOptimal;
1003 b.srcAccessMask = {};
1004 b.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
1005 slot.cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
1006 vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, b);
1007
1008 b.image = src;
1009 b.oldLayout = vk::ImageLayout::ePresentSrcKHR;
1010 b.newLayout = vk::ImageLayout::eTransferSrcOptimal;
1011 b.srcAccessMask = vk::AccessFlagBits::eMemoryRead;
1012 b.dstAccessMask = vk::AccessFlagBits::eTransferRead;
1013 slot.cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
1014 vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, b);
1015
1016 vk::ImageCopy copy {};
1017 copy.srcSubresource = { vk::ImageAspectFlagBits::eColor, 0, 0, 1 };
1018 copy.dstSubresource = { vk::ImageAspectFlagBits::eColor, 0, 0, 1 };
1019 copy.extent = vk::Extent3D { ext.width, ext.height, 1 };
1020 slot.cmd.copyImage(src, vk::ImageLayout::eTransferSrcOptimal,
1021 slot.image, vk::ImageLayout::eTransferDstOptimal, 1, &copy);
1022
1023 b.image = slot.image;
1024 b.oldLayout = vk::ImageLayout::eTransferDstOptimal;
1025 b.newLayout = vk::ImageLayout::eGeneral;
1026 b.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
1027 b.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
1028 slot.cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
1029 vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, b);
1030
1031 b.image = src;
1032 b.oldLayout = vk::ImageLayout::eTransferSrcOptimal;
1033 b.newLayout = vk::ImageLayout::ePresentSrcKHR;
1034 b.srcAccessMask = vk::AccessFlagBits::eTransferRead;
1035 b.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
1036 slot.cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
1037 vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, b);
1038
1039 slot.cmd.end();
1040
1041 (void)dev.resetFences(1, &slot.fence);
1042
1043 vk::SubmitInfo si {};
1044 si.commandBufferCount = 1;
1045 si.pCommandBuffers = &slot.cmd;
1046
1047 slot.pending.store(true, std::memory_order_release);
1048
1049 if (auto result = m_context.get_graphics_queue().submit(1, &si, slot.fence); result != vk::Result::eSuccess) {
1051 "Failed to submit capture command buffer for window '{}': {}",
1052 ctx.window->get_create_info().title, vk::to_string(result));
1053 slot.pending.store(false, std::memory_order_release);
1054 return;
1055 }
1056
1057 ctx.capture->slot_index = (ctx.capture->slot_index + 1) % ctx.capture->slots.size();
1058}
#define MF_RT_ERROR(comp, ctx,...)
const uint32_t * src
size_t b
uint32_t find_memory_type(uint32_t type_filter, vk::MemoryPropertyFlags properties) const
Find a suitable memory type for Vulkan buffer allocation.
void ensure_capture_state(WindowRenderContext &ctx)
Ensure capture state is initialized for a window context.
vk::Device get_device() const
Get logical device.
Definition VKContext.hpp:49
vk::Queue get_graphics_queue() const
Get graphics queue.
Definition VKContext.hpp:54
uint32_t vk_format_bytes_per_pixel(vk::Format fmt)
Byte width of a single pixel for a given Vulkan format.
@ GraphicsCallback
Graphics/visual rendering callback - frame-rate real-time.
@ Core
Core engine, backend, subsystems.
CopiedText copy(std::string_view text, const LayoutResult &layout, size_t a, size_t b)
Copy a byte range: the text it spans, and the quads that render it.

References b, MayaFlux::Core::WindowRenderContext::capture, MayaFlux::Journal::Core, MayaFlux::Core::WindowRenderContext::current_image_index, MayaFlux::Portal::Text::CopiedText::end, MayaFlux::Journal::GraphicsCallback, MF_RT_ERROR, src, MayaFlux::Core::WindowRenderContext::swapchain, MayaFlux::Core::vk_format_bytes_per_pixel(), and MayaFlux::Core::WindowRenderContext::window.

+ Here is the call graph for this function: