Consider the following code that copys an srcImage
from gpu to cpu dstImage
:
vkCmdCopyImage(command_buffer, srcImage,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region);
VkImageMemoryBarrier visible_barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
dstImage, // VkImage image
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // VkImageSubresourceRange subresourceRange
};
vkCmdPipelineBarrier(command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT,
0, 0, nullptr, 0, nullptr, 1, &visible_barrier);
vkMapMemory()
vkInvalidateMappedMemoryRanges()//Do we need this line at all?
vkUnmapmemory()
The barrier(i.e. memory dependency) above already generates an availability operation that makes the write to dstImage
available in the device domain, a memory domain operation that makes the write in the device domain available to the host domain, and a visibility operation that makes the write visible to the host.
Is there still a need to call vkInvalidateMappedMemoryRanges
, after the barrier, to make the write visible to the host?
CodePudding user response:
Yes, the invalidate is still needed. In addition to the rules in the memory dependency section, you also have to apply the rules in the access flags section.
From section "7.1.3 Access Types" in the Vulkan 1.3 specification:
If a memory object does not have the
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
property, then [...]vkInvalidateMappedMemoryRanges
must be called to guarantee that writes which are available to the host domain are made visible to host operations.
CodePudding user response:
vkInvalidateMappedMemoryRanges
is used to make sure your mapped memory is valid, if the device memory is not host coherent.
vkCmdPipelineBarrier
is used to make sure your GPU won't run commands out of order, it's a synchronization mechanism inside the GPU.
They are two totally different thing.
To your question, whether to use vkInvalidateMappedMemoryRanges
depends on two things:
- do you want to read the content of the target image back on CPU side? If no, I don't see any reason to call
vkInvalidateMappedMemoryRanges
. - if you do want to read the content back, does the device memory your target image bound host coherent? If yes, you don't need
vkInvalidateMappedMemoryRanges