diff --git a/util/test/demos/vk/vk_image_layouts.cpp b/util/test/demos/vk/vk_image_layouts.cpp index e8364f3b6..3be0db137 100644 --- a/util/test/demos/vk/vk_image_layouts.cpp +++ b/util/test/demos/vk/vk_image_layouts.cpp @@ -65,8 +65,9 @@ RD_TEST(VK_Image_Layouts, VulkanGraphicsTest) vb.upload(DefaultTri); - vkh::ImageCreateInfo preinitInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + vkh::ImageCreateInfo preinitInfo( + 4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); preinitInfo.tiling = VK_IMAGE_TILING_LINEAR; preinitInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; @@ -77,15 +78,11 @@ RD_TEST(VK_Image_Layouts, VulkanGraphicsTest) vkCreateImage(device, preinitInfo, NULL, &unboundImg); setName(unboundImg, "Unbound image"); + VkImage preinitImg = VK_NULL_HANDLE; + VkDeviceMemory preinitMem = VK_NULL_HANDLE; + while(Running()) { - VkImage preinitImg = VK_NULL_HANDLE; - VkDeviceMemory preinitMem = VK_NULL_HANDLE; - - vkCreateImage(device, preinitInfo, NULL, &preinitImg); - - setName(preinitImg, "Image:Preinitialised"); - AllocatedImage undefImg( this, vkh::ImageCreateInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM, @@ -94,36 +91,6 @@ RD_TEST(VK_Image_Layouts, VulkanGraphicsTest) setName(undefImg.image, "Image:Undefined"); - { - VkMemoryRequirements mrq; - vkGetImageMemoryRequirements(device, preinitImg, &mrq); - - VkMemoryAllocateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - info.allocationSize = mrq.size; - info.memoryTypeIndex = 100; - - for(uint32_t i = 0; i < props->memoryTypeCount; i++) - { - if(mrq.memoryTypeBits & (1 << i) && - (props->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) - { - info.memoryTypeIndex = i; - break; - } - } - - TEST_ASSERT(info.memoryTypeIndex != 100, "Couldn't find compatible memory type"); - - vkAllocateMemory(device, &info, NULL, &preinitMem); - vkBindImageMemory(device, preinitImg, preinitMem, 0); - - void *data = NULL; - vkMapMemory(device, preinitMem, 0, mrq.size, 0, &data); - memset(data, 0x40, (size_t)mrq.size); - vkUnmapMemory(device, preinitMem); - } - VkCommandBuffer cmd = GetCommandBuffer(); vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo()); @@ -148,27 +115,31 @@ RD_TEST(VK_Image_Layouts, VulkanGraphicsTest) vkh::ClearColorValue(0.2f, 0.2f, 0.2f, 1.0f), 1, vkh::ImageSubresourceRange()); - // the manual images are transitioned into general for copying, from pre-initialised and - // undefined - vkh::cmdPipelineBarrier( - cmd, { - vkh::ImageMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_PREINITIALIZED, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, preinitImg), - vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, undefImg.image), - }); + if(preinitImg != VK_NULL_HANDLE) + { + // the manual images are transitioned into general for copying, from pre-initialised and + // undefined + vkh::cmdPipelineBarrier( + cmd, + { + vkh::ImageMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_PREINITIALIZED, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, preinitImg), + vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, undefImg.image), + }); - VkImageCopy region = { - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {0, 0, 0}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {0, 0, 0}, - {4, 4, 1}, - }; + VkImageCopy region = { + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, + {4, 4, 1}, + }; - vkCmdCopyImage(cmd, preinitImg, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, undefImg.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmdCopyImage(cmd, preinitImg, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, undefImg.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } vkCmdBeginRenderPass( cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor), @@ -182,22 +153,79 @@ RD_TEST(VK_Image_Layouts, VulkanGraphicsTest) vkCmdEndRenderPass(cmd); + if(preinitImg != VK_NULL_HANDLE) + { + vkh::cmdPipelineBarrier( + cmd, { + vkh::ImageMemoryBarrier( + VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, preinitImg), + }); + + setMarker(cmd, "Preinit clear"); + vkCmdClearColorImage(cmd, preinitImg, VK_IMAGE_LAYOUT_GENERAL, + vkh::ClearColorValue(0.8f, 0.8f, 0.8f, 1.0f), 1, + vkh::ImageSubresourceRange()); + } + FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); vkEndCommandBuffer(cmd); Submit(0, 1, {cmd}); - Present(); - vkDeviceWaitIdle(device); vkDestroyImage(device, preinitImg, NULL); vkFreeMemory(device, preinitMem, NULL); undefImg.free(); + + { + VkMemoryRequirements mrq; + vkCreateImage(device, preinitInfo, NULL, &preinitImg); + vkGetImageMemoryRequirements(device, preinitImg, &mrq); + vkDestroyImage(device, preinitImg, NULL); + + VkMemoryAllocateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + info.allocationSize = mrq.size; + info.memoryTypeIndex = 100; + + for(uint32_t i = 0; i < props->memoryTypeCount; i++) + { + if(mrq.memoryTypeBits & (1 << i) && + (props->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + { + info.memoryTypeIndex = i; + break; + } + } + + TEST_ASSERT(info.memoryTypeIndex != 100, "Couldn't find compatible memory type"); + + vkAllocateMemory(device, &info, NULL, &preinitMem); + + void *data = NULL; + vkMapMemory(device, preinitMem, 0, mrq.size, 0, &data); + memset(data, 0x40, (size_t)mrq.size); + vkUnmapMemory(device, preinitMem); + } + + Present(); + + // make preinit image for next frame so the write must be preserved + + vkCreateImage(device, preinitInfo, NULL, &preinitImg); + vkBindImageMemory(device, preinitImg, preinitMem, 0); + + setName(preinitImg, "Image:Preinitialised"); } + vkDestroyImage(device, unboundImg, NULL); + vkDestroyImage(device, preinitImg, NULL); + vkFreeMemory(device, preinitMem, NULL); + return 0; } }; diff --git a/util/test/tests/Vulkan/VK_Image_Layouts.py b/util/test/tests/Vulkan/VK_Image_Layouts.py index b646687aa..abac0a621 100644 --- a/util/test/tests/Vulkan/VK_Image_Layouts.py +++ b/util/test/tests/Vulkan/VK_Image_Layouts.py @@ -47,9 +47,12 @@ class VK_Image_Layouts(rdtest.TestCase): if res.name == "Image:Preinitialised": if img.layouts[0].name != "VK_IMAGE_LAYOUT_PREINITIALIZED": raise rdtest.TestFailureException("Pre-initialised image is in {} layout".format(img.layouts[0].name)) + # check the preinitialised image has the right data + self.check_pixel_value(img.resourceId, 0, 0, [0.25, 0.25, 0.25, 0.25], eps=0.01) elif res.name == "Image:Undefined": if img.layouts[0].name != "VK_IMAGE_LAYOUT_UNDEFINED": raise rdtest.TestFailureException("Undefined image is in {} layout".format(img.layouts[0].name)) + # don't check undefined image contents elif res.name == "Image:Swapchain": if img.layouts[0].name != "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR": raise rdtest.TestFailureException("Swapchain image is in {} layout".format(img.layouts[0].name)) @@ -69,9 +72,46 @@ class VK_Image_Layouts(rdtest.TestCase): if res.name == "Image:Preinitialised": if img.layouts[0].name != "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL": raise rdtest.TestFailureException("Pre-initialised image is in {} layout".format(img.layouts[0].name)) + # check the preinitialised image has the right data + self.check_pixel_value(img.resourceId, 0, 0, [0.25, 0.25, 0.25, 0.25], eps=0.01) elif res.name == "Image:Undefined": if img.layouts[0].name != "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL": raise rdtest.TestFailureException("Undefined image is in {} layout".format(img.layouts[0].name)) + # check the preinitialised image data was copied correctly to the previously undefined image + self.check_pixel_value(img.resourceId, 0, 0, [0.25, 0.25, 0.25, 0.25], eps=0.01) elif img.resourceId == pipe.currentPass.framebuffer.attachments[0].resource: if img.layouts[0].name != "VK_IMAGE_LAYOUT_GENERAL": raise rdtest.TestFailureException("Rendered swapchain image is in {} layout".format(img.layouts[0].name)) + + action = self.find_action("Preinit clear") + + self.check(action is not None) + + self.controller.SetFrameEvent(action.eventId+1, False) + + pipe: rd.VKState = self.controller.GetVulkanPipelineState() + + # check that the pre-initialised image has transitioned + been cleared + for img in pipe.images: + img: rd.VKImageData + res = self.get_resource(img.resourceId) + if res.name == "Image:Preinitialised": + if img.layouts[0].name != "VK_IMAGE_LAYOUT_GENERAL": + raise rdtest.TestFailureException("Pre-initialised image is in {} layout".format(img.layouts[0].name)) + # check the preinitialised image has the right data + self.check_pixel_value(img.resourceId, 0, 0, [0.8, 0.8, 0.8, 1.0], eps=0.01) + + # finally check that it has reset to the correct value back at the start of the frame + self.controller.SetFrameEvent(1, False) + + pipe: rd.VKState = self.controller.GetVulkanPipelineState() + + for img in pipe.images: + img: rd.VKImageData + res = self.get_resource(img.resourceId) + if res.name == "Image:Preinitialised": + if img.layouts[0].name != "VK_IMAGE_LAYOUT_PREINITIALIZED": + raise rdtest.TestFailureException("Pre-initialised image is in {} layout".format(img.layouts[0].name)) + # check the preinitialised image has the right data + self.check_pixel_value(img.resourceId, 0, 0, [0.25, 0.25, 0.25, 0.25], eps=0.01) + \ No newline at end of file