| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2020 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file vktSynchronizationNoneStageTests.cpp |
| * \brief Tests for VK_PIPELINE_STAGE_NONE{_2}_KHR that iterate over each writable layout |
| and over each readable layout. Data to tested image is writen using method |
| appropriate for the writable layout and read via readable layout appropriate method. |
| Betwean read and write operation there are bariers that use none stage. |
| Implemented tests are also testing generalized layouts (VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, |
| VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) and access flags (MEMORY_ACCESS_READ|WRITE_BIT) to |
| test contextual synchronization introduced with VK_KHR_synchronization2 extension. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktSynchronizationNoneStageTests.hpp" |
| #include "vktSynchronizationOperation.hpp" |
| #include "vktSynchronizationUtil.hpp" |
| #include "vktTestCase.hpp" |
| |
| #include "vkBuilderUtil.hpp" |
| #include "vkBarrierUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| |
| #include "tcuImageCompare.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuStringTemplate.hpp" |
| |
| #include "deUniquePtr.hpp" |
| |
| #include <vector> |
| |
| namespace vkt |
| { |
| namespace synchronization |
| { |
| |
| using namespace vk; |
| using namespace de; |
| using namespace tcu; |
| |
| namespace |
| { |
| |
| static const deUint32 IMAGE_ASPECT_DEPTH_STENCIL = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; |
| static const deUint32 IMAGE_ASPECT_ALL = 0u; |
| |
| struct TestParams |
| { |
| SynchronizationType type; |
| bool useGenericAccessFlags; |
| VkImageLayout writeLayout; |
| VkImageAspectFlags writeAspect; |
| VkImageLayout readLayout; |
| VkImageAspectFlags readAspect; |
| }; |
| |
| // Helper class representing image |
| class ImageWrapper |
| { |
| public: |
| |
| ImageWrapper () = default; |
| void create (Context& context, SimpleAllocator& alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage); |
| |
| public: |
| Move<VkImage> handle; |
| MovePtr<Allocation> memory; |
| }; |
| |
| void ImageWrapper::create(Context& context, SimpleAllocator& alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice& device = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| const VkImageCreateInfo imageParams |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| 0u, // flags |
| VK_IMAGE_TYPE_2D, // imageType |
| format, // format |
| extent, // extent |
| 1u, // mipLevels |
| 1u, // arraySize |
| VK_SAMPLE_COUNT_1_BIT, // samples |
| VK_IMAGE_TILING_OPTIMAL, // tiling |
| usage, // usage |
| VK_SHARING_MODE_EXCLUSIVE, // sharingMode |
| 1u, // queueFamilyIndexCount |
| &queueFamilyIndex, // pQueueFamilyIndices |
| VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout |
| }; |
| |
| handle = createImage(vk, device, &imageParams); |
| memory = alloc.allocate(getImageMemoryRequirements(vk, device, *handle), MemoryRequirement::Any); |
| |
| vk.bindImageMemory(device, *handle, memory->getMemory(), memory->getOffset()); |
| } |
| |
| // Helper class representing buffer |
| class BufferWrapper |
| { |
| public: |
| |
| BufferWrapper () = default; |
| void create (Context& context, SimpleAllocator& alloc, VkDeviceSize size, VkBufferUsageFlags usage); |
| |
| public: |
| Move<VkBuffer> handle; |
| MovePtr<Allocation> memory; |
| }; |
| |
| void BufferWrapper::create(Context& context, SimpleAllocator& alloc, VkDeviceSize size, VkBufferUsageFlags usage) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice& device = context.getDevice(); |
| const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(size, usage); |
| |
| handle = createBuffer(vk, device, &bufferCreateInfo); |
| memory = alloc.allocate(getBufferMemoryRequirements(vk, device, *handle), MemoryRequirement::HostVisible); |
| |
| VK_CHECK(vk.bindBufferMemory(device, *handle, memory->getMemory(), memory->getOffset())); |
| } |
| |
| class NoneStageTestInstance : public vkt::TestInstance |
| { |
| public: |
| NoneStageTestInstance (Context& context, |
| const TestParams& testParams); |
| virtual ~NoneStageTestInstance (void) = default; |
| |
| tcu::TestStatus iterate (void) override; |
| |
| protected: |
| |
| VkAccessFlags2KHR getAccessFlag (VkAccessFlags2KHR access); |
| VkBufferImageCopy buildCopyRegion (VkExtent3D extent, |
| VkImageAspectFlags aspect); |
| void buildVertexBuffer (void); |
| Move<VkRenderPass> buildBasicRenderPass (VkFormat outputFormat, |
| VkImageLayout outputLayout, |
| VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE); |
| Move<VkRenderPass> buildComplexRenderPass (VkFormat intermediateFormat, |
| VkImageLayout intermediateLayout, |
| VkFormat outputFormat, |
| VkImageLayout outputLayout); |
| Move<VkImageView> buildImageView (VkImage image, |
| VkFormat format, |
| const VkImageSubresourceRange& subresourceRange); |
| Move<VkFramebuffer> buildFramebuffer (VkRenderPass renderPass, |
| const VkImageView* outView1, |
| const VkImageView* outView2 = DE_NULL); |
| Move<VkSampler> buildSampler (void); |
| Move<VkDescriptorSetLayout> buildDescriptorSetLayout (VkDescriptorType descriptorType); |
| Move<VkDescriptorPool> buildDescriptorPool (VkDescriptorType descriptorType); |
| Move<VkDescriptorSet> buildDescriptorSet (VkDescriptorPool descriptorPool, |
| VkDescriptorSetLayout descriptorSetLayout, |
| VkDescriptorType descriptorType, |
| VkImageView inputView, |
| VkImageLayout inputLayout, |
| const VkSampler* sampler = DE_NULL); |
| Move<VkPipeline> buildPipeline (deUint32 subpass, |
| VkImageAspectFlags resultAspect, |
| VkPipelineLayout pipelineLayout, |
| VkShaderModule vertShaderModule, |
| VkShaderModule fragShaderModule, |
| VkRenderPass renderPass); |
| bool verifyResult (const PixelBufferAccess& reference, |
| const PixelBufferAccess& result); |
| |
| private: |
| |
| const TestParams m_testParams; |
| |
| VkFormat m_referenceImageFormat; |
| VkFormat m_transitionImageFormat; |
| VkFormat m_readImageFormat; |
| VkImageSubresourceRange m_referenceSubresourceRange; |
| VkImageSubresourceRange m_transitionSubresourceRange; |
| VkImageSubresourceRange m_readSubresourceRange; |
| VkImageAspectFlags m_transitionImageAspect; |
| |
| VkExtent3D m_imageExtent; |
| VkImageLayout m_writeRenderPassOutputLayout; |
| |
| // flag indicating that graphics pipeline is constructed to write data to tested image |
| bool m_usePipelineToWrite; |
| |
| // flag indicating that graphics pipeline is constructed to read data from tested image |
| bool m_usePipelineToRead; |
| |
| // flag indicating that write pipeline should be constructed in a special way to fill stencil buffer |
| bool m_useStencilDuringWrite; |
| |
| // flag indicating that read pipeline should be constructed in a special way to use input attachment as a data source |
| bool m_useInputAttachmentToRead; |
| |
| VkPipelineStageFlags2KHR m_srcStageToNoneStageMask; |
| VkAccessFlags2KHR m_srcAccessToNoneAccessMask; |
| VkPipelineStageFlags2KHR m_dstStageFromNoneStageMask; |
| VkAccessFlags2KHR m_dstAccessFromNoneAccessMask; |
| |
| SimpleAllocator m_alloc; |
| |
| ImageWrapper m_referenceImage; |
| VkImageUsageFlags m_referenceImageUsage; |
| |
| // objects/variables initialized only when needed |
| ImageWrapper m_imageToWrite; |
| VkImageUsageFlags m_imageToWriteUsage; |
| |
| ImageWrapper m_imageToRead; |
| |
| BufferWrapper m_vertexBuffer; |
| std::vector<Move<VkImageView> > m_attachmentViews; |
| |
| std::string m_writeFragShaderName; |
| Move<VkShaderModule> m_writeVertShaderModule; |
| Move<VkShaderModule> m_writeFragShaderModule; |
| Move<VkRenderPass> m_writeRenderPass; |
| Move<VkSampler> m_writeSampler; |
| Move<VkDescriptorSetLayout> m_writeDescriptorSetLayout; |
| Move<VkDescriptorPool> m_writeDescriptorPool; |
| Move<VkDescriptorSet> m_writeDescriptorSet; |
| Move<VkPipelineLayout> m_writePipelineLayout; |
| Move<VkPipeline> m_writePipeline; |
| Move<VkFramebuffer> m_writeFramebuffer; |
| |
| std::string m_readFragShaderName; |
| Move<VkShaderModule> m_readVertShaderModule; |
| Move<VkShaderModule> m_readFragShaderModule; |
| Move<VkShaderModule> m_readFragShaderModule2; |
| Move<VkRenderPass> m_readRenderPass; |
| Move<VkSampler> m_readSampler; |
| Move<VkDescriptorSetLayout> m_readDescriptorSetLayout; |
| Move<VkDescriptorPool> m_readDescriptorPool; |
| Move<VkDescriptorSet> m_readDescriptorSet; |
| Move<VkPipelineLayout> m_readPipelineLayout; |
| Move<VkPipeline> m_readPipeline; |
| Move<VkFramebuffer> m_readFramebuffer; |
| }; |
| |
| NoneStageTestInstance::NoneStageTestInstance(Context& context, const TestParams& testParams) |
| : vkt::TestInstance(context) |
| , m_testParams (testParams) |
| , m_imageExtent { 32, 32, 1 } |
| , m_alloc (m_context.getDeviceInterface(), |
| m_context.getDevice(), |
| getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())) |
| { |
| // note: for clarity whole configuration of whats going on in iterate method was moved here |
| |
| const auto writeLayout = m_testParams.writeLayout; |
| const auto writeAspect = m_testParams.writeAspect; |
| const auto readLayout = m_testParams.readLayout; |
| const auto readAspect = m_testParams.readAspect; |
| |
| // select format that will be used for test |
| if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) |
| { |
| m_transitionImageFormat = VK_FORMAT_D32_SFLOAT; |
| m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT; |
| m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; |
| } |
| else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT)) |
| { |
| m_transitionImageFormat = VK_FORMAT_S8_UINT; |
| m_transitionImageAspect = VK_IMAGE_ASPECT_STENCIL_BIT; |
| m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL; |
| } |
| else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL)) |
| { |
| m_transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT; |
| // note: in test we focus only on depth aspect; no need to check both in those cases |
| m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT; |
| m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| } |
| else |
| { |
| m_transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM; |
| m_transitionImageAspect = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| } |
| |
| m_referenceSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u }; |
| m_transitionSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u }; |
| m_readSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u }; |
| m_referenceImageFormat = m_transitionImageFormat; |
| m_readImageFormat = m_transitionImageFormat; |
| m_referenceImageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| m_imageToWriteUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| |
| // pipeline is not created for transfer and general layouts (general layouts in tests follow same path as transfer layouts) |
| m_usePipelineToWrite = (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL); |
| m_usePipelineToRead = (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL); |
| m_useStencilDuringWrite = false; |
| |
| m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR; |
| m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR); |
| m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR; |
| m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR); |
| |
| // when graphics pipelines are not created only image with gradient is used for test |
| if (!m_usePipelineToWrite && !m_usePipelineToRead) |
| { |
| m_referenceImageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| return; |
| } |
| |
| if (m_usePipelineToWrite) |
| { |
| // depth/stencil layouts need diferent configuration |
| if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) |
| { |
| if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT) |
| { |
| m_referenceImageFormat = VK_FORMAT_R32_SFLOAT; |
| m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| m_referenceSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| m_writeFragShaderName = "frag-color-to-depth"; |
| } |
| else |
| { |
| m_referenceImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| m_useStencilDuringWrite = true; |
| m_writeFragShaderName = "frag-color-to-stencil"; |
| } |
| |
| m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR; |
| m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR); |
| m_imageToWriteUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| } |
| else |
| { |
| m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR; |
| m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR); |
| m_writeFragShaderName = "frag-color"; |
| m_imageToWriteUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| } |
| } |
| |
| if (m_usePipelineToRead) |
| { |
| m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR; |
| m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR); |
| |
| m_readSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_DEPTH_BIT) |
| m_readImageFormat = VK_FORMAT_R32_SFLOAT; |
| else if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_STENCIL_BIT) |
| m_readImageFormat = VK_FORMAT_R8_UINT; |
| |
| // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read |
| if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) && (readAspect != IMAGE_ASPECT_DEPTH_STENCIL)) |
| { |
| m_useInputAttachmentToRead = true; |
| m_readFragShaderName = "frag-depth-or-stencil-to-color"; |
| m_imageToWriteUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR); |
| |
| if (!m_usePipelineToWrite) |
| m_referenceImageUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| } |
| else // use image sampler for color and depth_stencil layouts |
| { |
| m_useInputAttachmentToRead = false; |
| m_readFragShaderName = "frag-color"; |
| m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| m_imageToWriteUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| // for depth_stencil layouts we need to have depth_stencil_attachment usage |
| if (!m_usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT)) |
| m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| |
| // when we read stencil as color we need to use usampler2D |
| if (writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) |
| m_readFragShaderName = "frag-stencil-to-color"; |
| } |
| } |
| } |
| |
| VkAccessFlags2KHR NoneStageTestInstance::getAccessFlag(VkAccessFlags2KHR access) |
| { |
| if (m_testParams.useGenericAccessFlags) |
| { |
| switch (access) |
| { |
| case VK_ACCESS_2_HOST_READ_BIT_KHR: |
| case VK_ACCESS_2_TRANSFER_READ_BIT_KHR: |
| case VK_ACCESS_2_SHADER_READ_BIT_KHR: |
| case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR: |
| return VK_ACCESS_2_MEMORY_READ_BIT_KHR; |
| |
| case VK_ACCESS_2_HOST_WRITE_BIT_KHR: |
| case VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR: |
| case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR: |
| case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR: |
| return VK_ACCESS_2_MEMORY_WRITE_BIT_KHR; |
| |
| default: |
| TCU_THROW(TestError, "Unhandled access flag"); |
| } |
| } |
| return access; |
| } |
| |
| VkBufferImageCopy NoneStageTestInstance::buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect) |
| { |
| return |
| { |
| 0u, // VkDeviceSize bufferOffset |
| extent.width, // deUint32 bufferRowLength |
| extent.height, // deUint32 bufferImageHeight |
| { aspect, 0u, 0u, 1u }, // VkImageSubresourceLayers imageSubresource |
| { 0, 0, 0 }, // VkOffset3D imageOffset |
| extent // VkExtent3D imageExtent |
| }; |
| } |
| |
| void NoneStageTestInstance::buildVertexBuffer() |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| std::vector<float> vertices |
| { |
| 1.0f, 1.0f, 0.0f, 1.0f, |
| -1.0f, 1.0f, 0.0f, 1.0f, |
| 1.0f, -1.0f, 0.0f, 1.0f, |
| -1.0f, -1.0f, 0.0f, 1.0f, |
| }; |
| m_vertexBuffer.create(m_context, m_alloc, sizeof(float) * vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| |
| deMemcpy(m_vertexBuffer.memory->getHostPtr(), vertices.data(), vertices.size() * sizeof(float)); |
| flushAlloc(vk, device, *m_vertexBuffer.memory); |
| } |
| |
| Move<VkRenderPass> NoneStageTestInstance::buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout, VkAttachmentLoadOp loadOp) |
| { |
| // output color/depth attachment |
| VkAttachmentDescription2 attachmentDescription |
| { |
| VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags |
| outputFormat, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| loadOp, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| loadOp, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout |
| outputLayout // VkImageLayout finalLayout |
| }; |
| |
| VkImageAspectFlags imageAspect = getImageAspectFlags(mapVkFormat(outputFormat)); |
| VkAttachmentReference2 attachmentRef |
| { |
| VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, outputLayout, imageAspect |
| }; |
| |
| VkAttachmentReference2* pColorAttachment = DE_NULL; |
| VkAttachmentReference2* pDepthStencilAttachment = DE_NULL; |
| if (imageAspect == VK_IMAGE_ASPECT_COLOR_BIT) |
| pColorAttachment = &attachmentRef; |
| else |
| pDepthStencilAttachment = &attachmentRef; |
| |
| VkSubpassDescription2 subpassDescription |
| { |
| VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, |
| DE_NULL, |
| (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint |
| 0u, // deUint32 viewMask |
| 0u, // deUint32 inputAttachmentCount |
| DE_NULL, // const VkAttachmentReference2* pInputAttachments |
| !!pColorAttachment, // deUint32 colorAttachmentCount |
| pColorAttachment, // const VkAttachmentReference2* pColorAttachments |
| DE_NULL, // const VkAttachmentReference2* pResolveAttachments |
| pDepthStencilAttachment, // const VkAttachmentReference2* pDepthStencilAttachment |
| 0u, // deUint32 preserveAttachmentCount |
| DE_NULL // const deUint32* pPreserveAttachments |
| }; |
| |
| const VkRenderPassCreateInfo2 renderPassInfo |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, |
| DE_NULL, // const void* pNext |
| (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags |
| 1u, // deUint32 attachmentCount |
| &attachmentDescription, // const VkAttachmentDescription* pAttachments |
| 1u, // deUint32 subpassCount |
| &subpassDescription, // const VkSubpassDescription* pSubpasses |
| 0u, // deUint32 dependencyCount |
| DE_NULL, // const VkSubpassDependency* pDependencies |
| 0u, // deUint32 correlatedViewMaskCount |
| DE_NULL // const deUint32* pCorrelatedViewMasks |
| }; |
| |
| return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);; |
| } |
| |
| Move<VkRenderPass> NoneStageTestInstance::buildComplexRenderPass(VkFormat intermediateFormat, VkImageLayout intermediateLayout, |
| VkFormat outputFormat, VkImageLayout outputLayout) |
| { |
| std::vector<VkAttachmentDescription2> attachmentDescriptions |
| { |
| // depth/stencil attachment (when used in read pipeline it loads data filed in write pipeline) |
| { |
| VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags |
| intermediateFormat, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp |
| intermediateLayout, // VkImageLayout initialLayout |
| intermediateLayout // VkImageLayout finalLayout |
| }, |
| // color attachment |
| { |
| VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags |
| outputFormat, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout |
| outputLayout // VkImageLayout finalLayout |
| } |
| }; |
| |
| VkImageAspectFlags intermediateAspect = getImageAspectFlags(mapVkFormat(intermediateFormat)); |
| VkImageAspectFlags outputAspect = getImageAspectFlags(mapVkFormat(outputFormat)); |
| std::vector<VkAttachmentReference2> attachmentRefs |
| { |
| { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, intermediateLayout, intermediateAspect }, |
| { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 1u, outputLayout, outputAspect } |
| }; |
| |
| VkAttachmentReference2* pDepthStencilAttachment = &attachmentRefs[0]; |
| VkAttachmentReference2* pColorAttachment = &attachmentRefs[1]; |
| |
| std::vector<VkSubpassDescription2> subpassDescriptions |
| { |
| { |
| VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, |
| DE_NULL, |
| (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint |
| 0u, // deUint32 viewMask |
| 1u, // deUint32 inputAttachmentCount |
| pDepthStencilAttachment, // const VkAttachmentReference2* pInputAttachments |
| 1u, // deUint32 colorAttachmentCount |
| pColorAttachment, // const VkAttachmentReference2* pColorAttachments |
| DE_NULL, // const VkAttachmentReference2* pResolveAttachments |
| DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment |
| 0u, // deUint32 preserveAttachmentCount |
| DE_NULL // deUint32* pPreserveAttachments |
| } |
| }; |
| |
| const VkRenderPassCreateInfo2 renderPassInfo |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, |
| DE_NULL, // const void* pNext |
| (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags |
| (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount |
| attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments |
| (deUint32)subpassDescriptions.size(), // deUint32 subpassCount |
| subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses |
| 0u, // deUint32 dependencyCount |
| DE_NULL, // const VkSubpassDependency* pDependencies |
| 0u, // deUint32 correlatedViewMaskCount |
| DE_NULL // const deUint32* pCorrelatedViewMasks |
| }; |
| |
| return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo); |
| } |
| |
| Move<VkImageView> NoneStageTestInstance::buildImageView(VkImage image, VkFormat format, const VkImageSubresourceRange& subresourceRange) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| const VkImageViewCreateInfo imageViewParams |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkImageViewCreateFlags flags |
| image, // VkImage image |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType |
| format, // VkFormat format |
| makeComponentMappingRGBA(), // VkComponentMapping components |
| subresourceRange, // VkImageSubresourceRange subresourceRange |
| }; |
| |
| return createImageView(vk, device, &imageViewParams); |
| } |
| |
| Move<VkFramebuffer> NoneStageTestInstance::buildFramebuffer(VkRenderPass renderPass, const VkImageView* outView1, const VkImageView* outView2) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| std::vector<VkImageView> imageViews = { *outView1 }; |
| if (outView2) |
| imageViews.push_back(*outView2); |
| |
| const VkFramebufferCreateInfo framebufferParams |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkFramebufferCreateFlags flags |
| renderPass, // VkRenderPass renderPass |
| (deUint32)imageViews.size(), // deUint32 attachmentCount |
| imageViews.data(), // const VkImageView* pAttachments |
| m_imageExtent.width, // deUint32 width |
| m_imageExtent.height, // deUint32 height |
| 1u, // deUint32 layers |
| }; |
| return createFramebuffer(vk, device, &framebufferParams); |
| } |
| |
| Move<VkSampler> NoneStageTestInstance::buildSampler() |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| const VkSamplerCreateInfo samplerInfo |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkSamplerCreateFlags flags |
| VK_FILTER_NEAREST, // VkFilter magFilter |
| VK_FILTER_NEAREST, // VkFilter minFilter |
| VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW |
| 0.0f, // float mipLodBias |
| VK_FALSE, // VkBool32 anisotropyEnable |
| 1.0f, // float maxAnisotropy |
| DE_FALSE, // VkBool32 compareEnable |
| VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp |
| 0.0f, // float minLod |
| 0.0f, // float maxLod |
| VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor |
| VK_FALSE, // VkBool32 unnormalizedCoords |
| }; |
| return createSampler(vk, device, &samplerInfo); |
| } |
| |
| Move<VkDescriptorSetLayout> NoneStageTestInstance::buildDescriptorSetLayout(VkDescriptorType descriptorType) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| return |
| DescriptorSetLayoutBuilder() |
| .addSingleSamplerBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL) |
| .build(vk, device); |
| } |
| |
| Move<VkDescriptorPool> NoneStageTestInstance::buildDescriptorPool(VkDescriptorType descriptorType) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| return |
| DescriptorPoolBuilder() |
| .addType(descriptorType, 1u) |
| .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); |
| } |
| |
| Move<VkDescriptorSet> NoneStageTestInstance::buildDescriptorSet(VkDescriptorPool descriptorPool, |
| VkDescriptorSetLayout descriptorSetLayout, |
| VkDescriptorType descriptorType, |
| VkImageView inputView, |
| VkImageLayout inputLayout, |
| const VkSampler* sampler) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| |
| const VkDescriptorImageInfo inputImageInfo = makeDescriptorImageInfo(sampler ? *sampler : 0u, inputView, inputLayout); |
| Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout); |
| |
| DescriptorSetUpdateBuilder() |
| .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &inputImageInfo) |
| .update(vk, device); |
| |
| return descriptorSet; |
| } |
| |
| Move<VkPipeline> NoneStageTestInstance::buildPipeline(deUint32 subpass, |
| VkImageAspectFlags resultAspect, |
| VkPipelineLayout pipelineLayout, |
| VkShaderModule vertShaderModule, |
| VkShaderModule fragShaderModule, |
| VkRenderPass renderPass) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| const std::vector<VkViewport> viewports { makeViewport(m_imageExtent) }; |
| const std::vector<VkRect2D> scissors { makeRect2D(m_imageExtent) }; |
| const bool useDepth = resultAspect & VK_IMAGE_ASPECT_DEPTH_BIT; |
| const bool useStencil = resultAspect & VK_IMAGE_ASPECT_STENCIL_BIT; |
| |
| const VkStencilOpState stencilOpState = makeStencilOpState( |
| VK_STENCIL_OP_REPLACE, // stencil fail |
| VK_STENCIL_OP_REPLACE, // depth & stencil pass |
| VK_STENCIL_OP_REPLACE, // depth only fail |
| VK_COMPARE_OP_ALWAYS, // compare op |
| 1u, // compare mask |
| 1u, // write mask |
| 1u); // reference |
| |
| const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags |
| useDepth, // VkBool32 depthTestEnable |
| useDepth, // VkBool32 depthWriteEnable |
| VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp |
| VK_FALSE, // VkBool32 depthBoundsTestEnable |
| useStencil, // VkBool32 stencilTestEnable |
| stencilOpState, // VkStencilOpState front |
| stencilOpState, // VkStencilOpState back |
| 0.0f, // float minDepthBounds |
| 1.0f, // float maxDepthBounds |
| }; |
| |
| return makeGraphicsPipeline( |
| vk, // DeviceInterface& vk |
| device, // VkDevice device |
| pipelineLayout, // VkPipelineLayout pipelineLayout |
| vertShaderModule, // VkShaderModule vertexShaderModule |
| DE_NULL, // VkShaderModule tessellationControlModule |
| DE_NULL, // VkShaderModule tessellationEvalModule |
| DE_NULL, // VkShaderModule geometryShaderModule |
| fragShaderModule, // VkShaderModule fragmentShaderModule |
| renderPass, // VkRenderPass renderPass |
| viewports, // std::vector<VkViewport>& viewports |
| scissors, // std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology |
| subpass, // deUint32 subpass |
| 0u, // deUint32 patchControlPoints |
| DE_NULL, // VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| DE_NULL, // VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| DE_NULL, // VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| &depthStencilStateCreateInfo); // VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo |
| } |
| |
| tcu::TestStatus NoneStageTestInstance::iterate(void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice& device = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| VkQueue queue = m_context.getUniversalQueue(); |
| Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); |
| Move<VkCommandBuffer> cmdBuffer = makeCommandBuffer(vk, device, *cmdPool); |
| const VkDeviceSize vertexBufferOffset = 0; |
| ImageWrapper* transitionImagePtr = &m_referenceImage; |
| ImageWrapper* imageToVerifyPtr = &m_referenceImage; |
| const deUint32 imageSizeInBytes = m_imageExtent.width * m_imageExtent.height * 4; |
| SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_testParams.type, vk, false); |
| const VkRect2D renderArea = makeRect2D(0, 0, m_imageExtent.width, m_imageExtent.height); |
| const VkBufferImageCopy transitionCopyRegion = buildCopyRegion(m_imageExtent, m_transitionImageAspect); |
| const VkBufferImageCopy colorCopyRegion = buildCopyRegion(m_imageExtent, VK_IMAGE_ASPECT_COLOR_BIT); |
| |
| // create image that will have gradient (without data atm) |
| m_referenceImage.create(m_context, m_alloc, m_referenceImageFormat, m_imageExtent, m_referenceImageUsage); |
| |
| // create buffer used for gradient data source |
| BufferWrapper srcBuffer; |
| srcBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| // generate gradient |
| std::vector<deUint32> referenceData (m_imageExtent.width * m_imageExtent.height); |
| tcu::TextureFormat referenceFormat (mapVkFormat(m_referenceImageFormat)); |
| PixelBufferAccess referencePBA (referenceFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, referenceData.data()); |
| fillWithComponentGradients(referencePBA, tcu::Vec4(0.0f), tcu::Vec4(1.0f)); |
| deMemcpy(srcBuffer.memory->getHostPtr(), referenceData.data(), static_cast<size_t>(imageSizeInBytes)); |
| flushAlloc(vk, device, *srcBuffer.memory); |
| |
| // create buffer for result transfer |
| BufferWrapper dstBuffer; |
| tcu::TextureFormat resultFormat (mapVkFormat(m_readImageFormat)); |
| dstBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| if (m_usePipelineToWrite || m_usePipelineToRead) |
| { |
| buildVertexBuffer(); |
| |
| // create image view for reference image (its always at index 0) |
| m_attachmentViews.push_back(buildImageView(*m_referenceImage.handle, m_referenceImageFormat, m_referenceSubresourceRange)); |
| |
| // create graphics pipeline used to write image data |
| if (m_usePipelineToWrite) |
| { |
| // create image that will be used as attachment to write to |
| m_imageToWrite.create(m_context, m_alloc, m_transitionImageFormat, m_imageExtent, m_imageToWriteUsage); |
| m_attachmentViews.push_back(buildImageView(*m_imageToWrite.handle, m_transitionImageFormat, m_transitionSubresourceRange)); |
| |
| m_writeVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0); |
| m_writeFragShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragShaderName), 0); |
| |
| if (m_useStencilDuringWrite) |
| { |
| // this is used only for cases where writable layout is VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL |
| // in this case generated gradient is only used for verification |
| m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout, VK_ATTACHMENT_LOAD_OP_CLEAR); |
| m_writePipelineLayout = makePipelineLayout(vk, device, DE_NULL); |
| m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout, |
| *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass); |
| m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get()); |
| } |
| else |
| { |
| m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout); |
| m_writeSampler = buildSampler(); |
| m_writeDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); |
| m_writeDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); |
| m_writeDescriptorSet = buildDescriptorSet(*m_writeDescriptorPool, *m_writeDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| *m_attachmentViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, &m_writeSampler.get()); |
| m_writePipelineLayout = makePipelineLayout(vk, device, *m_writeDescriptorSetLayout); |
| m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout, |
| *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass); |
| m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get()); |
| } |
| |
| transitionImagePtr = &m_imageToWrite; |
| imageToVerifyPtr = &m_imageToWrite; |
| } |
| |
| // create graphics pipeline used to read image data |
| if (m_usePipelineToRead) |
| { |
| m_imageToRead.create(m_context, m_alloc, m_readImageFormat, m_imageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); |
| m_attachmentViews.push_back(buildImageView(*m_imageToRead.handle, m_readImageFormat, m_readSubresourceRange)); |
| imageToVerifyPtr = &m_imageToRead; |
| |
| m_readVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0); |
| m_readFragShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragShaderName), 0); |
| |
| if (m_useInputAttachmentToRead) |
| { |
| m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); |
| m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); |
| m_readDescriptorSet = buildDescriptorSet(*m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, |
| *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout); |
| m_readRenderPass = buildComplexRenderPass(m_transitionImageFormat, m_testParams.readLayout, |
| m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite].get(), |
| &m_attachmentViews[m_usePipelineToWrite+1].get()); |
| m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout); |
| m_readPipeline = buildPipeline(0u, VK_IMAGE_ASPECT_COLOR_BIT, *m_readPipelineLayout, |
| *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass); |
| } |
| else |
| { |
| m_readSampler = buildSampler(); |
| m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); |
| m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); |
| m_readDescriptorSet = buildDescriptorSet(*m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout, &m_readSampler.get()); |
| m_readRenderPass = buildBasicRenderPass(m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite + 1].get()); |
| m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout); |
| m_readPipeline = buildPipeline(0u, m_transitionImageAspect, *m_readPipelineLayout, |
| *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass); |
| } |
| } |
| } |
| |
| beginCommandBuffer(vk, *cmdBuffer); |
| |
| // write data from buffer with gradient to image (for stencil_attachment cases we dont need to do that) |
| if (!m_useStencilDuringWrite) |
| { |
| // wait for reference data to be in buffer |
| const VkBufferMemoryBarrier2KHR preBufferMemoryBarrier2 = makeBufferMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| getAccessFlag(VK_ACCESS_2_HOST_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask |
| *srcBuffer.handle, // VkBuffer buffer |
| 0u, // VkDeviceSize offset |
| imageSizeInBytes // VkDeviceSize size |
| ); |
| |
| VkImageLayout copyBufferToImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| if(m_testParams.writeLayout == VK_IMAGE_LAYOUT_GENERAL) |
| copyBufferToImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| // change image layout so that we can copy to it data from buffer |
| const VkImageMemoryBarrier2KHR preImageMemoryBarrier2 = makeImageMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR dstAccessMask |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout |
| copyBufferToImageLayout, // VkImageLayout newLayout |
| *m_referenceImage.handle, // VkImage image |
| m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange |
| ); |
| VkDependencyInfoKHR buffDependencyInfo = makeCommonDependencyInfo(DE_NULL, &preBufferMemoryBarrier2, &preImageMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &buffDependencyInfo); |
| |
| const VkBufferImageCopy* copyRegion = m_usePipelineToWrite ? &colorCopyRegion : &transitionCopyRegion; |
| vk.cmdCopyBufferToImage(*cmdBuffer, *srcBuffer.handle, *m_referenceImage.handle, copyBufferToImageLayout, 1u, copyRegion); |
| } |
| |
| if (m_usePipelineToWrite) |
| { |
| // wait till data is transfered to image (in all cases except when stencil_attachment is tested) |
| if (!m_useStencilDuringWrite) |
| { |
| const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout |
| *m_referenceImage.handle, // VkImage image |
| m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange |
| ); |
| VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo); |
| } |
| |
| beginRenderPass(vk, *cmdBuffer, *m_writeRenderPass, *m_writeFramebuffer, renderArea, tcu::Vec4(0.0f ,0.0f, 0.0f, 1.0f)); |
| |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipeline); |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset); |
| if (m_useStencilDuringWrite) |
| { |
| // when writing to stencil buffer draw single triangle (to simulate gradient over 1bit) |
| vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); |
| } |
| else |
| { |
| vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipelineLayout, 0, 1, &m_writeDescriptorSet.get(), 0, DE_NULL); |
| vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u); |
| } |
| |
| endRenderPass(vk, *cmdBuffer); |
| } |
| |
| // use none stage to wait till data is transfered to image |
| { |
| const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2( |
| m_srcStageToNoneStageMask, // VkPipelineStageFlags2KHR srcStageMask |
| m_srcAccessToNoneAccessMask, // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_NONE_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR dstAccessMask |
| m_testParams.writeLayout, // VkImageLayout oldLayout |
| m_testParams.writeLayout, // VkImageLayout newLayout |
| *transitionImagePtr->handle, // VkImage image |
| m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange |
| ); |
| VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo); |
| } |
| |
| // use all commands stage to change image layout |
| { |
| const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR srcAccessMask |
| m_dstStageFromNoneStageMask, // VkPipelineStageFlags2KHR dstStageMask |
| m_dstAccessFromNoneAccessMask, // VkAccessFlags2KHR dstAccessMask |
| m_testParams.writeLayout, // VkImageLayout oldLayout |
| m_testParams.readLayout, // VkImageLayout newLayout |
| *transitionImagePtr->handle, // VkImage image |
| m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange |
| ); |
| VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo); |
| } |
| |
| VkImageLayout copyImageToBufferLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| if (m_testParams.readLayout == VK_IMAGE_LAYOUT_GENERAL) |
| copyImageToBufferLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| if (m_usePipelineToRead) |
| { |
| beginRenderPass(vk, *cmdBuffer, *m_readRenderPass, *m_readFramebuffer, renderArea); |
| |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipeline); |
| vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipelineLayout, 0, 1, &m_readDescriptorSet.get(), 0, DE_NULL); |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset); |
| vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u); |
| |
| endRenderPass(vk, *cmdBuffer); |
| |
| // wait till data is transfered to image |
| const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout |
| copyImageToBufferLayout, // VkImageLayout newLayout |
| *imageToVerifyPtr->handle, // VkImage image |
| m_readSubresourceRange // VkImageSubresourceRange subresourceRange |
| ); |
| VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo); |
| } |
| |
| // read back image |
| { |
| const VkBufferImageCopy* copyRegion = m_usePipelineToRead ? &colorCopyRegion : &transitionCopyRegion; |
| vk.cmdCopyImageToBuffer(*cmdBuffer, *imageToVerifyPtr->handle, copyImageToBufferLayout, *dstBuffer.handle, 1u, copyRegion); |
| |
| const VkBufferMemoryBarrier2KHR postBufferMemoryBarrier2 = makeBufferMemoryBarrier2( |
| VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask |
| getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask |
| VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask |
| getAccessFlag(VK_ACCESS_2_HOST_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask |
| *dstBuffer.handle, // VkBuffer buffer |
| 0u, // VkDeviceSize offset |
| imageSizeInBytes // VkDeviceSize size |
| ); |
| VkDependencyInfoKHR bufDependencyInfo = makeCommonDependencyInfo(DE_NULL, &postBufferMemoryBarrier2); |
| synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &bufDependencyInfo); |
| } |
| |
| endCommandBuffer(vk, *cmdBuffer); |
| |
| Move<VkFence> fence = createFence(vk, device); |
| VkCommandBufferSubmitInfoKHR cmdBuffersInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer); |
| synchronizationWrapper->addSubmitInfo(0u, DE_NULL, 1u, &cmdBuffersInfo, 0u, DE_NULL); |
| VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence)); |
| VK_CHECK(vk.waitForFences(device, 1, &fence.get(), VK_TRUE, ~0ull)); |
| |
| // read image data |
| invalidateAlloc(vk, device, *dstBuffer.memory); |
| PixelBufferAccess resultPBA(resultFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, dstBuffer.memory->getHostPtr()); |
| |
| // if result/reference is depth-stencil format then focus only on depth component |
| if (isCombinedDepthStencilType(referenceFormat.type)) |
| referencePBA = getEffectiveDepthStencilAccess(referencePBA, tcu::Sampler::MODE_DEPTH); |
| if (isCombinedDepthStencilType(resultFormat.type)) |
| resultPBA = getEffectiveDepthStencilAccess(resultPBA, tcu::Sampler::MODE_DEPTH); |
| |
| if (verifyResult(referencePBA, resultPBA)) |
| return TestStatus::pass("Pass"); |
| return TestStatus::fail("Fail"); |
| } |
| |
| bool NoneStageTestInstance::verifyResult(const PixelBufferAccess& reference, const PixelBufferAccess& result) |
| { |
| TestLog& log = m_context.getTestContext().getLog(); |
| |
| if (isIntFormat(m_referenceImageFormat) || isUintFormat(m_referenceImageFormat)) |
| { |
| // special case for stencil (1bit gradient - top-left of image is 0, bottom-right is 1) |
| |
| bool isResultCorrect = true; |
| TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), |
| m_imageExtent.width, m_imageExtent.height, 1); |
| PixelBufferAccess errorMask = errorMaskStorage.getAccess(); |
| |
| for (deUint32 y = 0; y < m_imageExtent.height; y++) |
| for (deUint32 x = 0; x < m_imageExtent.width; x++) |
| { |
| // skip textels on diagonal (gradient lights texels on diagonal and stencil operation in test does not) |
| if ((x + y) == (m_imageExtent.width - 1)) |
| { |
| errorMask.setPixel(IVec4(0, 0xff, 0, 0xff), x, y, 0); |
| continue; |
| } |
| |
| IVec4 refPix = reference.getPixelInt(x, y, 0); |
| IVec4 cmpPix = result.getPixelInt(x, y, 0); |
| bool isOk = (refPix[0] == cmpPix[0]); |
| errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, 0); |
| isResultCorrect &= isOk; |
| } |
| |
| Vec4 pixelBias(0.0f); |
| Vec4 pixelScale(1.0f); |
| if (isResultCorrect) |
| { |
| log << TestLog::ImageSet("Image comparison", "") |
| << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << TestLog::EndImageSet; |
| return true; |
| } |
| |
| log << TestLog::ImageSet("Image comparison", "") |
| << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) |
| << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) |
| << TestLog::Image("ErrorMask", "Error mask", errorMask) |
| << TestLog::EndImageSet; |
| return false; |
| } |
| |
| return floatThresholdCompare(log, "Image comparison", "", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT); |
| } |
| |
| class NoneStageTestCase : public vkt::TestCase |
| { |
| public: |
| NoneStageTestCase (tcu::TestContext& testContext, |
| const std::string& name, |
| const TestParams& testParams); |
| ~NoneStageTestCase (void) = default; |
| |
| void initPrograms (SourceCollections& sourceCollections) const override; |
| TestInstance* createInstance (Context& context) const override; |
| void checkSupport (Context& context) const override; |
| |
| private: |
| const TestParams m_testParams; |
| }; |
| |
| NoneStageTestCase::NoneStageTestCase(tcu::TestContext& testContext, const std::string& name, const TestParams& testParams) |
| : vkt::TestCase (testContext, name, "") |
| , m_testParams (testParams) |
| { |
| } |
| |
| void NoneStageTestCase::initPrograms(SourceCollections& sourceCollections) const |
| { |
| const auto writeLayout = m_testParams.writeLayout; |
| const auto writeAspect = m_testParams.writeAspect; |
| const auto readLayout = m_testParams.readLayout; |
| const auto readAspect = m_testParams.readAspect; |
| |
| // for tests that use only transfer and general layouts we don't create pipeline |
| if (((writeLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) || (readLayout == VK_IMAGE_LAYOUT_GENERAL)) && |
| ((writeLayout == VK_IMAGE_LAYOUT_GENERAL) || (readLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL))) |
| return; |
| |
| sourceCollections.glslSources.add("vert") << glu::VertexSource( |
| "#version 450\n" |
| "layout(location = 0) in vec4 inPosition;\n" |
| "layout(location = 0) out vec2 outUV;\n" |
| "void main(void)\n" |
| "{\n" |
| " outUV = vec2(inPosition.x * 0.5 + 0.5, inPosition.y * 0.5 + 0.5);\n" |
| " gl_Position = inPosition;\n" |
| "}\n" |
| ); |
| |
| sourceCollections.glslSources.add("frag-color") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(binding = 0) uniform sampler2D u_sampler;\n" |
| "layout(location = 0) in vec2 inUV;\n" |
| "layout(location = 0) out vec4 fragColor;\n" |
| "void main(void)\n" |
| "{\n" |
| " fragColor = texture(u_sampler, inUV);\n" |
| "}\n" |
| ); |
| |
| if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT) |
| { |
| sourceCollections.glslSources.add("frag-color-to-depth") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(binding = 0) uniform sampler2D u_sampler;\n" |
| "layout(location = 0) in vec2 inUV;\n" |
| "void main(void)\n" |
| "{\n" |
| " gl_FragDepth = texture(u_sampler, inUV).r;\n" |
| "}\n" |
| ); |
| } |
| |
| if (writeAspect & VK_IMAGE_ASPECT_STENCIL_BIT) |
| { |
| sourceCollections.glslSources.add("frag-color-to-stencil") << glu::FragmentSource( |
| "#version 450\n" |
| "void main(void)\n" |
| "{\n" |
| "}\n" |
| ); |
| |
| if ((readLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) || |
| ((readLayout == VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR) && (readAspect == IMAGE_ASPECT_ALL))) |
| { |
| // use usampler2D and uvec4 for color |
| sourceCollections.glslSources.add("frag-stencil-to-color") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(binding = 0) uniform usampler2D u_sampler;\n" |
| "layout(location = 0) in vec2 inUV;\n" |
| "layout(location = 0) out uvec4 fragColor;\n" |
| "void main(void)\n" |
| "{\n" |
| " fragColor = texture(u_sampler, inUV);\n" |
| "}\n" |
| ); |
| } |
| } |
| |
| if (readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) |
| { |
| // for stencil only cases we need to use usubpassInput (for depth and depth_stencil we need to use subpassInput) |
| const bool readDepth = readAspect & VK_IMAGE_ASPECT_DEPTH_BIT; |
| const std::map<std::string, std::string> specializations |
| { |
| { "SUBPASS_INPUT", (readDepth ? "subpassInput" : "usubpassInput") }, |
| { "VALUE_TYPE", (readDepth ? "float" : "uint") } |
| }; |
| |
| std::string source = |
| "#version 450\n" |
| "layout (input_attachment_index = 0, binding = 0) uniform ${SUBPASS_INPUT} depthOrStencilInput;\n" |
| "layout(location = 0) in vec2 inUV;\n" |
| "layout(location = 0) out ${VALUE_TYPE} fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = subpassLoad(depthOrStencilInput).x;\n" |
| "}\n"; |
| sourceCollections.glslSources.add("frag-depth-or-stencil-to-color") |
| << glu::FragmentSource(tcu::StringTemplate(source).specialize(specializations)); |
| } |
| } |
| |
| TestInstance* NoneStageTestCase::createInstance(Context& context) const |
| { |
| return new NoneStageTestInstance(context, m_testParams); |
| } |
| |
| void NoneStageTestCase::checkSupport(Context& context) const |
| { |
| context.requireDeviceFunctionality("VK_KHR_synchronization2"); |
| |
| const auto writeAspect = m_testParams.writeAspect; |
| const auto readAspect = m_testParams.readAspect; |
| |
| // check whether implementation supports separate depth/stencil layouts |
| if (((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) && (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) || |
| ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) && (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))) |
| { |
| if(!context.getSeparateDepthStencilLayoutsFeatures().separateDepthStencilLayouts) |
| TCU_THROW(NotSupportedError, "Implementation does not support separateDepthStencilLayouts"); |
| } |
| |
| const auto writeLayout = m_testParams.writeLayout; |
| const auto readLayout = m_testParams.readLayout; |
| bool usePipelineToWrite = (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL); |
| bool usePipelineToRead = (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL); |
| |
| if (!usePipelineToWrite && !usePipelineToRead) |
| return; |
| |
| VkFormat transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM; |
| if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) |
| transitionImageFormat = VK_FORMAT_D32_SFLOAT; |
| else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT)) |
| transitionImageFormat = VK_FORMAT_S8_UINT; |
| else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL)) |
| transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT; |
| |
| struct FormatToCheck |
| { |
| VkFormat format; |
| VkImageUsageFlags usage; |
| }; |
| std::vector<FormatToCheck> formatsToCheck |
| { |
| // reference image |
| { transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_DST_BIT }, |
| |
| // image to write |
| { transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_SRC_BIT } |
| }; |
| |
| // note: conditions here are analogic to conditions in test case constructor |
| // everything not needed was cout out leaving only logic related to |
| // m_referenceImage and m_imageToWrite |
| if (usePipelineToWrite) |
| { |
| if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) |
| { |
| if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT) |
| { |
| formatsToCheck[0].format = VK_FORMAT_R32_SFLOAT; |
| formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| } |
| else |
| formatsToCheck[0].usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| |
| formatsToCheck[1].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| } |
| else |
| { |
| formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| formatsToCheck[1].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| } |
| } |
| |
| if (usePipelineToRead) |
| { |
| // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read |
| if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) && (readAspect != IMAGE_ASPECT_DEPTH_STENCIL)) |
| { |
| formatsToCheck[1].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| |
| if (!usePipelineToWrite) |
| formatsToCheck[0].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| } |
| else // use image sampler for color and depth_stencil layouts |
| { |
| formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| // for depth_stencil layouts we need to have depth_stencil_attachment usage |
| if (!usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT)) |
| formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| } |
| } |
| |
| // it simplifies logic to pop image to write then to add conditions everywhere above |
| if (!usePipelineToWrite) |
| formatsToCheck.pop_back(); |
| |
| for (const auto& formatData : formatsToCheck) |
| { |
| VkImageFormatProperties properties; |
| const vk::InstanceInterface& vki = context.getInstanceInterface(); |
| if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), |
| formatData.format, |
| VK_IMAGE_TYPE_2D, |
| VK_IMAGE_TILING_OPTIMAL, |
| formatData.usage, |
| 0, |
| &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| std::string error = std::string("Format (") + |
| vk::getFormatName(formatData.format) + ") doesn't support required capabilities."; |
| TCU_THROW(NotSupportedError, error.c_str()); |
| } |
| } |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createNoneStageTests(tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> noneStageTests(new tcu::TestCaseGroup(testCtx, "none_stage", "")); |
| |
| struct LayoutData |
| { |
| VkImageLayout token; |
| VkImageAspectFlags aspect; |
| std::string name; |
| }; |
| |
| const std::vector<LayoutData> writableLayoutsData |
| { |
| { VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_dst" }, |
| { VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general" }, |
| { VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, "color_attachment" }, |
| { VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_attachment" }, |
| { VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_attachment" }, |
| { VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_attachment" }, |
| { VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_COLOR_BIT, "generic_color_attachment" }, |
| { VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_attachment" }, |
| { VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_attachment" }, |
| { VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_attachment" }, |
| }; |
| const std::vector<LayoutData> readableLayoutsData |
| { |
| { VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_src" }, |
| { VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general" }, |
| { VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, IMAGE_ASPECT_ALL, "shader_read" }, |
| { VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_read" }, |
| { VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_read_stencil_attachment" }, |
| { VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_attachment_stencil_read" }, |
| { VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_read" }, |
| { VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_read" }, |
| { VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_ALL, "generic_color_read" }, |
| { VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_read" }, |
| { VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_read" }, |
| { VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_read" }, |
| }; |
| |
| struct SynchronizationData |
| { |
| SynchronizationType type; |
| std::string casePrefix; |
| bool useGenericAccessFlags; |
| }; |
| std::vector<SynchronizationData> synchronizationData |
| { |
| { SynchronizationType::SYNCHRONIZATION2, "", true }, |
| { SynchronizationType::SYNCHRONIZATION2, "old_access_", false }, |
| |
| // using legacy synchronization structures with NONE_STAGE |
| { SynchronizationType::LEGACY, "legacy_", false } |
| }; |
| |
| for (const auto& syncData : synchronizationData) |
| { |
| for (const auto& writeData : writableLayoutsData) |
| { |
| for (const auto& readData : readableLayoutsData) |
| { |
| if (readData.aspect && writeData.aspect && |
| (readData.aspect != writeData.aspect)) |
| continue; |
| |
| const std::string name = syncData.casePrefix + writeData.name + "_to_" + readData.name; |
| noneStageTests->addChild(new NoneStageTestCase(testCtx, name, { |
| syncData.type, |
| syncData.useGenericAccessFlags, |
| writeData.token, |
| writeData.aspect, |
| readData.token, |
| readData.aspect |
| })); |
| } |
| } |
| } |
| |
| return noneStageTests.release(); |
| } |
| |
| } // synchronization |
| } // vkt |