feat: real screenshot capture — BMP from swapchain image via vkCmdCopyImageToBuffer

- Added vkCmdCopyImageToBuffer to P/Invoke layer
- Screenshot embedded in main command buffer (barrier PresentSrcKHR→TransferSrc, copy, barrier back)
- Deferred read: staging buffer read on next frame after fence signaled
- BMP format written directly to FileStream (row by row, avoids large heap allocations)
- BGRA→BGRA direct copy for B8G8R8A8 swapchain format
- All 16 camera tour screenshots captured successfully (1280x720x32bpp)
- 66/66 tests pass
This commit is contained in:
emil28092005
2026-06-17 23:27:58 +03:00
parent 80238b08f5
commit 544f6b59c0
3 changed files with 239 additions and 15 deletions
+4
View File
@@ -80,6 +80,7 @@ internal static unsafe class Vk
public static PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
public static PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
public static PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
public static PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
public static PFN_vkCmdClearColorImage vkCmdClearColorImage;
public static PFN_vkCmdPushConstants vkCmdPushConstants;
public static PFN_vkCreateSampler vkCreateSampler;
@@ -186,6 +187,7 @@ internal static unsafe class Vk
vkCmdPipelineBarrier = VulkanNative.LoadDeviceFunction<PFN_vkCmdPipelineBarrier>(device, "vkCmdPipelineBarrier");
vkCmdCopyBuffer = VulkanNative.LoadDeviceFunction<PFN_vkCmdCopyBuffer>(device, "vkCmdCopyBuffer");
vkCmdCopyBufferToImage = VulkanNative.LoadDeviceFunction<PFN_vkCmdCopyBufferToImage>(device, "vkCmdCopyBufferToImage");
vkCmdCopyImageToBuffer = VulkanNative.LoadDeviceFunction<PFN_vkCmdCopyImageToBuffer>(device, "vkCmdCopyImageToBuffer");
vkCmdClearColorImage = VulkanNative.LoadDeviceFunction<PFN_vkCmdClearColorImage>(device, "vkCmdClearColorImage");
vkCmdPushConstants = VulkanNative.LoadDeviceFunction<PFN_vkCmdPushConstants>(device, "vkCmdPushConstants");
vkCreateSampler = VulkanNative.LoadDeviceFunction<PFN_vkCreateSampler>(device, "vkCreateSampler");
@@ -386,6 +388,8 @@ unsafe internal delegate void PFN_vkCmdCopyBuffer(VkCommandBuffer commandBuffer,
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
unsafe internal delegate void PFN_vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, int dstImageLayout, uint regionCount, VkBufferImageCopy* pRegions);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
unsafe internal delegate void PFN_vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, int srcImageLayout, VkBuffer dstBuffer, uint regionCount, VkBufferImageCopy* pRegions);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
unsafe internal delegate void PFN_vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, int imageLayout, VkClearColorValue* pColor, uint rangeCount, VkImageSubresourceRange* pRanges);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
unsafe internal delegate void PFN_vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint offset, uint size, void* pValues);