@@ -572,6 +572,7 @@ class VulkanDevice : public offloadtest::Device {
572572 VkFramebuffer FrameBuffer = VK_NULL_HANDLE;
573573 ImageRef DepthStencil = {0 , 0 , 0 };
574574 std::shared_ptr<VulkanTexture> RenderTarget;
575+ std::shared_ptr<VulkanBuffer> RTReadback;
575576 std::optional<ResourceRef> VertexBuffer = std::nullopt ;
576577
577578 VkRenderPass RenderPass = VK_NULL_HANDLE;
@@ -737,21 +738,6 @@ class VulkanDevice : public offloadtest::Device {
737738 llvm::Expected<std::shared_ptr<offloadtest::Buffer>>
738739 createBuffer (std::string Name, BufferCreateDesc &Desc,
739740 size_t SizeInBytes) override {
740- VkMemoryPropertyFlags MemFlags = 0 ;
741- switch (Desc.Location ) {
742- case MemoryLocation::GpuOnly:
743- MemFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
744- break ;
745- case MemoryLocation::CpuToGpu:
746- MemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
747- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
748- break ;
749- case MemoryLocation::GpuToCpu:
750- MemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
751- VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
752- break ;
753- }
754-
755741 VkBufferCreateInfo BufInfo = {};
756742 BufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
757743 BufInfo.size = SizeInBytes;
@@ -771,8 +757,8 @@ class VulkanDevice : public offloadtest::Device {
771757 VkMemoryAllocateInfo AllocInfo = {};
772758 AllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
773759 AllocInfo.allocationSize = MemReqs.size ;
774- auto MemIdx =
775- getMemoryIndex (PhysicalDevice, MemReqs. memoryTypeBits , MemFlags );
760+ auto MemIdx = getMemoryIndex (PhysicalDevice, MemReqs. memoryTypeBits ,
761+ getVulkanMemoryFlags (Desc. Location ) );
776762 if (!MemIdx)
777763 return MemIdx.takeError ();
778764 AllocInfo.memoryTypeIndex = *MemIdx;
@@ -2153,6 +2139,63 @@ class VulkanDevice : public offloadtest::Device {
21532139 }
21542140 }
21552141
2142+ // Record commands to copy a texture into a readback buffer.
2143+ void copyTextureToReadback (VkCommandBuffer CmdBuffer,
2144+ const VulkanTexture &Tex,
2145+ const VulkanBuffer &Readback,
2146+ VkImageLayout OldLayout,
2147+ VkAccessFlags SrcAccessMask,
2148+ VkPipelineStageFlags SrcStageMask) {
2149+ const VkImageAspectFlags AspectMask = isDepthFormat (Tex.Desc .Format )
2150+ ? VK_IMAGE_ASPECT_DEPTH_BIT
2151+ : VK_IMAGE_ASPECT_COLOR_BIT;
2152+
2153+ // Transition texture to transfer source.
2154+ VkImageSubresourceRange SubRange = {};
2155+ SubRange.aspectMask = AspectMask;
2156+ SubRange.baseMipLevel = 0 ;
2157+ SubRange.levelCount = 1 ;
2158+ SubRange.layerCount = 1 ;
2159+
2160+ VkImageMemoryBarrier ImageBarrier = {};
2161+ ImageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2162+ ImageBarrier.subresourceRange = SubRange;
2163+ ImageBarrier.srcAccessMask = SrcAccessMask;
2164+ ImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2165+ ImageBarrier.oldLayout = OldLayout;
2166+ ImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2167+ ImageBarrier.image = Tex.Image ;
2168+ vkCmdPipelineBarrier (CmdBuffer, SrcStageMask,
2169+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0 , 0 , nullptr , 0 ,
2170+ nullptr , 1 , &ImageBarrier);
2171+
2172+ // Copy image to readback buffer.
2173+ VkBufferImageCopy Region = {};
2174+ Region.imageSubresource .aspectMask = AspectMask;
2175+ Region.imageSubresource .mipLevel = 0 ;
2176+ Region.imageSubresource .baseArrayLayer = 0 ;
2177+ Region.imageSubresource .layerCount = 1 ;
2178+ Region.imageExtent .width = Tex.Desc .Width ;
2179+ Region.imageExtent .height = Tex.Desc .Height ;
2180+ Region.imageExtent .depth = 1 ;
2181+ vkCmdCopyImageToBuffer (CmdBuffer, Tex.Image ,
2182+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2183+ Readback.Buffer , 1 , &Region);
2184+
2185+ // Barrier to make the readback buffer visible to the host.
2186+ VkBufferMemoryBarrier BufBarrier = {};
2187+ BufBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
2188+ BufBarrier.size = VK_WHOLE_SIZE;
2189+ BufBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2190+ BufBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2191+ BufBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2192+ BufBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2193+ BufBarrier.buffer = Readback.Buffer ;
2194+ vkCmdPipelineBarrier (CmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2195+ VK_PIPELINE_STAGE_HOST_BIT, 0 , 0 , nullptr , 1 ,
2196+ &BufBarrier, 0 , nullptr );
2197+ }
2198+
21562199 void copyResourceDataToHost (InvocationState &IS, ResourceBundle &R) {
21572200 if (!R.isReadWrite ())
21582201 return ;
@@ -2345,7 +2388,10 @@ class VulkanDevice : public offloadtest::Device {
23452388 vkCmdDraw (IS.CmdBuffer , P.Bindings .getVertexCount (), 1 , 0 , 0 );
23462389 llvm::outs () << " Drew " << P.Bindings .getVertexCount () << " vertices.\n " ;
23472390 vkCmdEndRenderPass (IS.CmdBuffer );
2348- copyResourceDataToHost (IS, IS.FrameBufferResource );
2391+ copyTextureToReadback (IS.CmdBuffer , *IS.RenderTarget , *IS.RTReadback ,
2392+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2393+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2394+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
23492395 }
23502396
23512397 for (auto &R : IS.Resources )
@@ -2400,17 +2446,15 @@ class VulkanDevice : public offloadtest::Device {
24002446 Range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
24012447 Range.offset = 0 ;
24022448 Range.size = VK_WHOLE_SIZE;
2403- const ResourceRef &ResRef = IS.FrameBufferResource . ResourceRefs [ 0 ] ;
2449+ Range. memory = IS.RTReadback -> Memory ;
24042450
24052451 void *Mapped = nullptr ; // NOLINT(misc-const-correctness)
2406- vkMapMemory (Device, ResRef.Host .Memory , 0 , VK_WHOLE_SIZE, 0 , &Mapped);
2407-
2408- Range.memory = ResRef.Host .Memory ;
2452+ vkMapMemory (Device, IS.RTReadback ->Memory , 0 , VK_WHOLE_SIZE, 0 , &Mapped);
24092453 vkInvalidateMappedMemoryRanges (Device, 1 , &Range);
24102454
24112455 const CPUBuffer &B = *P.Bindings .RTargetBufferPtr ;
24122456 memcpy (B.Data [0 ].get (), Mapped, B.size ());
2413- vkUnmapMemory (Device, ResRef. Host . Memory );
2457+ vkUnmapMemory (Device, IS. RTReadback -> Memory );
24142458 }
24152459 return llvm::Error::success ();
24162460 }
@@ -2458,13 +2502,6 @@ class VulkanDevice : public offloadtest::Device {
24582502 vkDestroyBuffer (Device, IS.VertexBuffer ->Host .Buffer , nullptr );
24592503 vkFreeMemory (Device, IS.VertexBuffer ->Host .Memory , nullptr );
24602504 }
2461- for (auto &ResRef : IS.FrameBufferResource .ResourceRefs ) {
2462- // We know the device resource is an image, so no need to check it.
2463- vkDestroyImage (Device, ResRef.Image .Image , nullptr );
2464- vkFreeMemory (Device, ResRef.Image .Memory , nullptr );
2465- vkDestroyBuffer (Device, ResRef.Host .Buffer , nullptr );
2466- vkFreeMemory (Device, ResRef.Host .Memory , nullptr );
2467- }
24682505 vkDestroyImage (Device, IS.DepthStencil .Image , nullptr );
24692506 vkFreeMemory (Device, IS.DepthStencil .Memory , nullptr );
24702507 vkDestroyFramebuffer (Device, IS.FrameBuffer , nullptr );
@@ -2518,10 +2555,10 @@ class VulkanDevice : public offloadtest::Device {
25182555 if (auto Err = createResources (P, State))
25192556 return Err;
25202557 if (P.isGraphics ()) {
2521- if (auto Err = createRenderPass (P, State))
2558+ if (auto Err = createRenderPass (State))
25222559 return Err;
25232560 llvm::outs () << " Render pass created.\n " ;
2524- if (auto Err = createFrameBuffer (P, State))
2561+ if (auto Err = createFrameBuffer (State))
25252562 return Err;
25262563 llvm::outs () << " Frame buffer created.\n " ;
25272564 }
0 commit comments