Home > Enterprise >  Difference between vkInvalidateMappedMemoryRanges and vkCmdPipelineBarrier in Vulkan
Difference between vkInvalidateMappedMemoryRanges and vkCmdPipelineBarrier in Vulkan

Time:02-03

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, &copy_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:

  1. 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.
  2. 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
  • Related