| 5389 | } |
| 5390 | |
| 5391 | static void VulkanReadPixels(HContext _context, int32_t x, int32_t y, uint32_t width, uint32_t height, void* buffer, uint32_t buffer_size) |
| 5392 | { |
| 5393 | VulkanContext* context = (VulkanContext*) _context; |
| 5394 | |
| 5395 | assert (buffer_size >= width * height * 4); |
| 5396 | |
| 5397 | HRenderTarget currentt_rt_h = context->m_CurrentRenderTarget; |
| 5398 | bool in_render_pass = IsRenderTargetbound(context, currentt_rt_h); |
| 5399 | |
| 5400 | // We can't copy an image if we are inside a render pass. |
| 5401 | // This is considered an expensive operation, but unless we have user facing functionality to begin/end render passes, |
| 5402 | // this is as good as it gets currently. |
| 5403 | if (in_render_pass) |
| 5404 | { |
| 5405 | EndRenderPass(context); |
| 5406 | } |
| 5407 | |
| 5408 | // Create a temporary stage buffer that we can map to |
| 5409 | DeviceBuffer stage_buffer(VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| 5410 | VkResult res = CreateDeviceBuffer(context->m_PhysicalDevice.m_Device, context->m_LogicalDevice.m_Device, buffer_size, |
| 5411 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stage_buffer); |
| 5412 | CHECK_VK_ERROR(res); |
| 5413 | |
| 5414 | // Keep the readback in a single temporary command buffer so the swapchain image is restored |
| 5415 | // to its presentable layout before any later main render pass rebind or final present. |
| 5416 | |
| 5417 | VkCommandBuffer vk_command_buffer = BeginSingleTimeCommands(context->m_LogicalDevice.m_Device, context->m_LogicalDevice.m_CommandPool); |
| 5418 | |
| 5419 | DM_MUTEX_SCOPED_LOCK(context->m_BaseContext.m_AssetHandleContainerMutex); |
| 5420 | VulkanTexture* tex_sc = GetAssetFromContainer<VulkanTexture>(context->m_BaseContext.m_AssetHandleContainer, context->m_CurrentSwapchainTexture); |
| 5421 | |
| 5422 | TransitionImageLayoutWithCmdBuffer( |
| 5423 | vk_command_buffer, |
| 5424 | tex_sc, |
| 5425 | VK_IMAGE_ASPECT_COLOR_BIT, |
| 5426 | VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| 5427 | 0, |
| 5428 | 1); |
| 5429 | |
| 5430 | VkBufferImageCopy vk_copy_region = {}; |
| 5431 | vk_copy_region.imageOffset.x = x; |
| 5432 | vk_copy_region.imageOffset.y = y; |
| 5433 | vk_copy_region.imageExtent.width = width; |
| 5434 | vk_copy_region.imageExtent.height = height; |
| 5435 | vk_copy_region.imageExtent.depth = 1; |
| 5436 | vk_copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| 5437 | vk_copy_region.imageSubresource.layerCount = 1; |
| 5438 | |
| 5439 | TouchResource(context, tex_sc); |
| 5440 | TouchResource(context, &stage_buffer); |
| 5441 | |
| 5442 | vkCmdCopyImageToBuffer( |
| 5443 | vk_command_buffer, |
| 5444 | context->m_SwapChain->Image(), |
| 5445 | VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| 5446 | stage_buffer.m_Handle.m_Buffer, |
| 5447 | 1, &vk_copy_region); |
| 5448 |
nothing calls this directly
no test coverage detected