| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2021 The Khronos Group Inc. |
| * Copyright (c) 2021 Google 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 |
| * \brief Tests load and store op "none" |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktRenderPassLoadStoreOpNoneTests.hpp" |
| #include "pipeline/vktPipelineImageUtil.hpp" |
| #include "vktTestCase.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkPrograms.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkRef.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuPlatform.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "deStringUtil.hpp" |
| #include "deUniquePtr.hpp" |
| #include "deRandom.hpp" |
| #include <cstring> |
| #include <cmath> |
| #include <vector> |
| |
| namespace vkt |
| { |
| namespace renderpass |
| { |
| |
| using namespace vk; |
| |
| namespace |
| { |
| |
| enum AttachmentInit |
| { |
| ATTACHMENT_INIT_PRE = 1, |
| ATTACHMENT_INIT_CMD_CLEAR = 2 |
| }; |
| |
| enum AttachmentUsage |
| { |
| ATTACHMENT_USAGE_UNDEFINED = 0, |
| ATTACHMENT_USAGE_COLOR = 1, |
| ATTACHMENT_USAGE_DEPTH = 2, |
| ATTACHMENT_USAGE_STENCIL = 4, |
| ATTACHMENT_USAGE_INPUT = 8, |
| ATTACHMENT_USAGE_WRITE_OFF = 16, |
| ATTACHMENT_USAGE_DEPTH_STENCIL = ATTACHMENT_USAGE_DEPTH | ATTACHMENT_USAGE_STENCIL, |
| ATTACHMENT_USAGE_MULTISAMPLE = 32, |
| ATTACHMENT_USAGE_RESOLVE_TARGET = 64, |
| ATTACHMENT_USAGE_INTEGER = 128 |
| }; |
| |
| struct AttachmentParams |
| { |
| deUint32 usage; |
| VkAttachmentLoadOp loadOp; |
| VkAttachmentStoreOp storeOp; |
| deUint32 init; |
| bool verifyInner; |
| tcu::Vec4 innerRef; |
| bool verifyOuter; |
| tcu::Vec4 outerRef; |
| }; |
| |
| struct AttachmentRef |
| { |
| deUint32 idx; |
| deUint32 usage; |
| }; |
| |
| struct SubpassParams |
| { |
| std::vector<AttachmentRef> attachmentRefs; |
| deUint32 numDraws; |
| }; |
| |
| struct TestParams |
| { |
| std::vector<AttachmentParams> attachments; |
| std::vector<SubpassParams> subpasses; |
| RenderingType renderingType; |
| VkFormat depthStencilFormat; |
| bool alphaBlend; |
| }; |
| |
| struct Vertex4RGBA |
| { |
| tcu::Vec4 position; |
| tcu::Vec4 color; |
| }; |
| |
| template<typename T> |
| inline de::SharedPtr<vk::Move<T> > makeSharedPtr(vk::Move<T> move) |
| { |
| return de::SharedPtr<vk::Move<T> >(new vk::Move<T>(move)); |
| } |
| |
| std::vector<Vertex4RGBA> createQuad (void) |
| { |
| std::vector<Vertex4RGBA> vertices; |
| |
| const float size = 1.0f; |
| const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f); |
| const Vertex4RGBA lowerLeftVertexRed = {tcu::Vec4(-size, -size, 0.0f, 1.0f), red}; |
| const Vertex4RGBA lowerRightVertexRed = {tcu::Vec4(size, -size, 0.0f, 1.0f), red}; |
| const Vertex4RGBA upperLeftVertexRed = {tcu::Vec4(-size, size, 0.0f, 1.0f), red}; |
| const Vertex4RGBA upperRightVertexRed = {tcu::Vec4(size, size, 0.0f, 1.0f), red}; |
| const Vertex4RGBA lowerLeftVertexBlue = {tcu::Vec4(-size, -size, 0.0f, 1.0f), blue}; |
| const Vertex4RGBA lowerRightVertexBlue = {tcu::Vec4(size, -size, 0.0f, 1.0f), blue}; |
| const Vertex4RGBA upperLeftVertexBlue = {tcu::Vec4(-size, size, 0.0f, 1.0f), blue}; |
| const Vertex4RGBA upperRightVertexBlue = {tcu::Vec4(size, size, 0.0f, 1.0f), blue}; |
| |
| vertices.push_back(lowerLeftVertexRed); |
| vertices.push_back(lowerRightVertexRed); |
| vertices.push_back(upperLeftVertexRed); |
| vertices.push_back(upperLeftVertexRed); |
| vertices.push_back(lowerRightVertexRed); |
| vertices.push_back(upperRightVertexRed); |
| |
| vertices.push_back(lowerLeftVertexBlue); |
| vertices.push_back(lowerRightVertexBlue); |
| vertices.push_back(upperLeftVertexBlue); |
| vertices.push_back(upperLeftVertexBlue); |
| vertices.push_back(lowerRightVertexBlue); |
| vertices.push_back(upperRightVertexBlue); |
| |
| return vertices; |
| } |
| |
| deUint32 getFirstUsage (deUint32 attachmentIdx, const std::vector<SubpassParams>& subpasses) |
| { |
| for (const auto& subpass : subpasses) |
| for (const auto& ref : subpass.attachmentRefs) |
| if (ref.idx == attachmentIdx) |
| return ref.usage; |
| |
| return ATTACHMENT_USAGE_UNDEFINED; |
| } |
| |
| std::string getFormatCaseName(VkFormat format) |
| { |
| return de::toLower(de::toString(getFormatStr(format)).substr(10)); |
| } |
| |
| // Selects an image format based on the usage flags. |
| VkFormat getFormat (deUint32 usage, VkFormat depthStencilFormat) |
| { |
| if (usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| return depthStencilFormat; |
| } |
| |
| if (usage & ATTACHMENT_USAGE_INTEGER) |
| { |
| // Color attachment using integer format. |
| return VK_FORMAT_R8G8B8A8_UINT; |
| } |
| |
| return VK_FORMAT_R8G8B8A8_UNORM; |
| } |
| |
| template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo> |
| Move<VkRenderPass> createRenderPass (const DeviceInterface& vk, |
| VkDevice vkDevice, |
| const TestParams testParams) |
| { |
| const VkImageAspectFlags aspectMask = testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT; |
| std::vector<AttachmentDesc> attachmentDescriptions; |
| std::vector<SubpassDesc> subpassDescriptions; |
| |
| struct Refs |
| { |
| std::vector<AttachmentRef> colorAttachmentRefs; |
| std::vector<AttachmentRef> resolveAttachmentRefs; |
| std::vector<AttachmentRef> depthStencilAttachmentRefs; |
| std::vector<AttachmentRef> inputAttachmentRefs; |
| }; |
| |
| std::vector<Refs> subpassRefs; |
| bool hasInputAttachment = false; |
| |
| for (size_t i = 0; i < testParams.attachments.size(); i++) |
| { |
| VkImageLayout initialLayout; |
| VkImageLayout finalLayout; |
| VkFormat format = getFormat(testParams.attachments[i].usage, testParams.depthStencilFormat); |
| |
| // Search for the first reference to determine the initial layout. |
| deUint32 firstUsage = getFirstUsage((deUint32)i, testParams.subpasses); |
| |
| // No subpasses using this attachment. Use the usage flags of the attachment. |
| if (firstUsage == ATTACHMENT_USAGE_UNDEFINED) |
| firstUsage = testParams.attachments[i].usage; |
| |
| if (firstUsage & ATTACHMENT_USAGE_COLOR) |
| initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| else if (firstUsage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| else |
| { |
| DE_ASSERT(firstUsage & ATTACHMENT_USAGE_INPUT); |
| initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |
| } |
| |
| // Set final layout to transfer src if it's being verified. Otherwise |
| // just use the initial layout as it's known to be supported by |
| // the usage flags. |
| if (testParams.attachments[i].verifyInner || testParams.attachments[i].verifyOuter) |
| finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| else |
| finalLayout = initialLayout; |
| |
| const VkSampleCountFlagBits sampleCount = testParams.attachments[i].usage & ATTACHMENT_USAGE_MULTISAMPLE ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT; |
| |
| const AttachmentDesc attachmentDesc = |
| { |
| DE_NULL, // const void* pNext |
| (VkAttachmentDescriptionFlags) 0, // VkAttachmentDescriptionFlags flags |
| format, // VkFormat format |
| sampleCount, // VkSampleCountFlagBits samples |
| testParams.attachments[i].loadOp, // VkAttachmentLoadOp loadOp |
| testParams.attachments[i].storeOp, // VkAttachmentStoreOp storeOp |
| testParams.attachments[i].loadOp, // VkAttachmentLoadOp stencilLoadOp |
| testParams.attachments[i].storeOp, // VkAttachmentStoreOp stencilStoreOp |
| initialLayout, // VkImageLayout initialLayout |
| finalLayout // VkImageLayout finalLayout |
| }; |
| |
| attachmentDescriptions.push_back(attachmentDesc); |
| } |
| |
| for (const auto& subpass : testParams.subpasses) |
| { |
| subpassRefs.push_back({}); |
| auto& refs = subpassRefs.back(); |
| |
| for (const auto& ref : subpass.attachmentRefs) |
| { |
| VkImageLayout layout; |
| |
| if (ref.usage & ATTACHMENT_USAGE_RESOLVE_TARGET) |
| { |
| layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| refs.resolveAttachmentRefs.push_back({DE_NULL, ref.idx, layout, aspectMask}); |
| } |
| else if (ref.usage & ATTACHMENT_USAGE_COLOR) |
| { |
| layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| refs.colorAttachmentRefs.push_back({DE_NULL, ref.idx, layout, aspectMask}); |
| } |
| else if (ref.usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| const auto depthStencilAspectMask = testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : getImageAspectFlags(mapVkFormat(testParams.depthStencilFormat)); |
| refs.depthStencilAttachmentRefs.push_back({DE_NULL, ref.idx, layout, depthStencilAspectMask}); |
| } |
| else |
| { |
| DE_ASSERT(ref.usage & ATTACHMENT_USAGE_INPUT); |
| layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |
| refs.inputAttachmentRefs.push_back({DE_NULL, ref.idx, layout, aspectMask}); |
| hasInputAttachment = true; |
| } |
| } |
| |
| const SubpassDesc subpassDescription = |
| { |
| DE_NULL, |
| (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint |
| 0u, // deUint32 viewMask |
| (deUint32)refs.inputAttachmentRefs.size(), // deUint32 inputAttachmentCount |
| refs.inputAttachmentRefs.empty() ? DE_NULL : refs.inputAttachmentRefs.data(), // const VkAttachmentReference* pInputAttachments |
| (deUint32)refs.colorAttachmentRefs.size(), // deUint32 colorAttachmentCount |
| refs.colorAttachmentRefs.empty() ? DE_NULL : refs.colorAttachmentRefs.data(), // const VkAttachmentReference* pColorAttachments |
| refs.resolveAttachmentRefs.empty() ? DE_NULL : refs.resolveAttachmentRefs.data(), // const VkAttachmentReference* pResolveAttachments |
| refs.depthStencilAttachmentRefs.empty() ? DE_NULL : refs.depthStencilAttachmentRefs.data(), // const VkAttachmentReference* pDepthStencilAttachment |
| 0u, // deUint32 preserveAttachmentCount |
| DE_NULL // const deUint32* pPreserveAttachments |
| }; |
| |
| subpassDescriptions.push_back(subpassDescription); |
| } |
| |
| // Dependency of color attachment of subpass 0 to input attachment of subpass 1. |
| // Determined later if it's being used. |
| const SubpassDep subpassDependency = |
| { |
| DE_NULL, // const void* pNext |
| 0u, // uint32_t srcSubpass |
| 1u, // uint32_t dstSubpass |
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask |
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask |
| VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags |
| 0u // deInt32 viewOffset |
| }; |
| |
| const RenderPassCreateInfo renderPassInfo = |
| { |
| 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 |
| hasInputAttachment ? 1u : 0u, // deUint32 dependencyCount |
| hasInputAttachment ? &subpassDependency : DE_NULL, // const VkSubpassDependency* pDependencies |
| 0u, // deUint32 correlatedViewMaskCount |
| DE_NULL // const deUint32* pCorrelatedViewMasks |
| }; |
| |
| return renderPassInfo.createRenderPass(vk, vkDevice); |
| } |
| |
| class LoadStoreOpNoneTest : public vkt::TestCase |
| { |
| public: |
| LoadStoreOpNoneTest (tcu::TestContext& testContext, |
| const std::string& name, |
| const std::string& description, |
| const TestParams& testParams); |
| virtual ~LoadStoreOpNoneTest (void); |
| virtual void initPrograms (SourceCollections& sourceCollections) const; |
| virtual void checkSupport (Context& context) const; |
| virtual TestInstance* createInstance (Context& context) const; |
| private: |
| const TestParams m_testParams; |
| }; |
| |
| class LoadStoreOpNoneTestInstance : public vkt::TestInstance |
| { |
| public: |
| LoadStoreOpNoneTestInstance (Context& context, |
| const TestParams& testParams); |
| virtual ~LoadStoreOpNoneTestInstance (void); |
| virtual tcu::TestStatus iterate (void); |
| template<typename RenderpassSubpass> |
| void createCommandBuffer (const DeviceInterface& vk, |
| VkDevice vkDevice, |
| std::vector<Move<VkImageView>>& imageViews, |
| std::vector<Move<VkDescriptorSet>>& descriptorSets, |
| std::vector<Move<VkPipelineLayout>>& pipelineLayouts, |
| std::vector<Move<VkPipeline>>& pipelines); |
| private: |
| TestParams m_testParams; |
| |
| const tcu::UVec2 m_imageSize; |
| const tcu::UVec2 m_renderSize; |
| |
| Move<VkDescriptorPool> m_descriptorPool; |
| Move<VkRenderPass> m_renderPass; |
| Move<VkFramebuffer> m_framebuffer; |
| |
| Move<VkBuffer> m_vertexBuffer; |
| std::vector<Vertex4RGBA> m_vertices; |
| de::MovePtr<Allocation> m_vertexBufferAlloc; |
| |
| Move<VkCommandPool> m_cmdPool; |
| Move<VkCommandBuffer> m_cmdBuffer; |
| }; |
| |
| LoadStoreOpNoneTest::LoadStoreOpNoneTest (tcu::TestContext& testContext, |
| const std::string& name, |
| const std::string& description, |
| const TestParams& testParams) |
| : vkt::TestCase (testContext, name, description) |
| , m_testParams(testParams) |
| { |
| } |
| |
| LoadStoreOpNoneTest::~LoadStoreOpNoneTest (void) |
| { |
| } |
| |
| TestInstance* LoadStoreOpNoneTest::createInstance (Context& context) const |
| { |
| return new LoadStoreOpNoneTestInstance(context, m_testParams); |
| } |
| |
| void LoadStoreOpNoneTest::checkSupport (Context& ctx) const |
| { |
| // Check for renderpass2 extension if used. |
| if (m_testParams.renderingType == RENDERING_TYPE_RENDERPASS2) |
| ctx.requireDeviceFunctionality("VK_KHR_create_renderpass2"); |
| |
| // Check for dynamic_rendering extension if used |
| if (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) |
| ctx.requireDeviceFunctionality("VK_KHR_dynamic_rendering"); |
| |
| ctx.requireDeviceFunctionality("VK_EXT_load_store_op_none"); |
| |
| // Check depth/stencil format support. |
| for (const auto& att : m_testParams.attachments) |
| { |
| if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| const VkFormat format = getFormat(att.usage, m_testParams.depthStencilFormat); |
| VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| const auto aspectFlags = getImageAspectFlags(mapVkFormat(format)); |
| |
| if (att.usage & ATTACHMENT_USAGE_DEPTH) |
| DE_ASSERT((aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT) != 0u); |
| |
| if (att.usage & ATTACHMENT_USAGE_STENCIL) |
| DE_ASSERT((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u); |
| |
| DE_UNREF(aspectFlags); // For release builds. |
| |
| if (att.verifyInner || att.verifyOuter) |
| usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| |
| if (att.init & ATTACHMENT_INIT_PRE) |
| usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| const auto& vki = ctx.getInstanceInterface(); |
| const auto physDev = ctx.getPhysicalDevice(); |
| const auto imgType = VK_IMAGE_TYPE_2D; |
| const auto tiling = VK_IMAGE_TILING_OPTIMAL; |
| VkImageFormatProperties properties; |
| const auto result = vki.getPhysicalDeviceImageFormatProperties(physDev, format, imgType, tiling, usage, 0u, &properties); |
| |
| if (result != VK_SUCCESS) |
| TCU_THROW(NotSupportedError, "Depth-stencil format not supported"); |
| } |
| } |
| } |
| |
| void LoadStoreOpNoneTest::initPrograms (SourceCollections& sourceCollections) const |
| { |
| std::ostringstream fragmentSource; |
| |
| sourceCollections.glslSources.add("color_vert") << glu::VertexSource( |
| "#version 450\n" |
| "layout(location = 0) in highp vec4 position;\n" |
| "layout(location = 1) in highp vec4 color;\n" |
| "layout(location = 0) out highp vec4 vtxColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = position;\n" |
| " vtxColor = color;\n" |
| "}\n"); |
| |
| sourceCollections.glslSources.add("color_frag") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(location = 0) in highp vec4 vtxColor;\n" |
| "layout(location = 0) out highp vec4 fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = vtxColor;\n" |
| " gl_FragDepth = 1.0;\n" |
| "}\n"); |
| |
| sourceCollections.glslSources.add("color_frag_uint") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(location = 0) in highp vec4 vtxColor;\n" |
| "layout(location = 0) out highp uvec4 fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = uvec4(vtxColor * vec4(255));\n" |
| " gl_FragDepth = 1.0;\n" |
| "}\n"); |
| |
| sourceCollections.glslSources.add("color_frag_blend") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(location = 0) in highp vec4 vtxColor;\n" |
| "layout(location = 0) out highp vec4 fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = vec4(vtxColor.rgb, 0.5);\n" |
| " gl_FragDepth = 1.0;\n" |
| "}\n"); |
| |
| sourceCollections.glslSources.add("color_frag_input") << glu::FragmentSource( |
| "#version 450\n" |
| "layout(location = 0) in highp vec4 vtxColor;\n" |
| "layout(location = 0) out highp vec4 fragColor;\n" |
| "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = subpassLoad(inputColor) + vtxColor;\n" |
| " gl_FragDepth = 1.0;\n" |
| "}\n"); |
| } |
| |
| LoadStoreOpNoneTestInstance::LoadStoreOpNoneTestInstance (Context& context, |
| const TestParams& testParams) |
| : vkt::TestInstance (context) |
| , m_testParams (testParams) |
| , m_imageSize (32u, 32u) |
| , m_renderSize (27u, 19u) |
| , m_vertices (createQuad()) |
| { |
| } |
| |
| LoadStoreOpNoneTestInstance::~LoadStoreOpNoneTestInstance (void) |
| { |
| } |
| |
| template<typename RenderpassSubpass> |
| void LoadStoreOpNoneTestInstance::createCommandBuffer (const DeviceInterface& vk, |
| VkDevice vkDevice, |
| std::vector<Move<VkImageView>>& imageViews, |
| std::vector<Move<VkDescriptorSet>>& descriptorSets, |
| std::vector<Move<VkPipelineLayout>>& pipelineLayouts, |
| std::vector<Move<VkPipeline>>& pipelines) |
| { |
| const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE); |
| const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL); |
| |
| const VkDeviceSize vertexBufferOffset = 0; |
| |
| m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| |
| if (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) |
| { |
| std::vector<VkRenderingAttachmentInfoKHR> colorAttachments; |
| VkRenderingAttachmentInfoKHR dsAttachment |
| { |
| VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| DE_NULL, // VkImageView imageView; |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout; |
| VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode; |
| DE_NULL, // VkImageView resolveImageView; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout; |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| makeClearValueDepthStencil(0.0f, 0u) // VkClearValue clearValue; |
| }; |
| bool useDepth = false; |
| bool useStencil = false; |
| |
| for (size_t i = 0; i < imageViews.size(); i++) |
| { |
| if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_MULTISAMPLE) |
| { |
| DE_ASSERT(m_testParams.attachments[i+1].usage & ATTACHMENT_USAGE_RESOLVE_TARGET); |
| const auto resolveMode = ((m_testParams.attachments[i].usage & ATTACHMENT_USAGE_INTEGER) ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_AVERAGE_BIT); |
| colorAttachments.push_back({ |
| VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| *imageViews[i], // VkImageView imageView; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout; |
| resolveMode, // VkResolveModeFlagBits resolveMode; |
| *imageViews[i+1], // VkImageView resolveImageView; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout resolveImageLayout; |
| m_testParams.attachments[i].loadOp, // VkAttachmentLoadOp loadOp; |
| m_testParams.attachments[i].storeOp, // VkAttachmentStoreOp storeOp; |
| makeClearValueColor(tcu::Vec4(0.0f)) // VkClearValue clearValue; |
| }); |
| i += 1; |
| } |
| else if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_COLOR) |
| { |
| colorAttachments.push_back({ |
| VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| *imageViews[i], // VkImageView imageView; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout; |
| VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode; |
| DE_NULL, // VkImageView resolveImageView; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout; |
| m_testParams.attachments[i].loadOp, // VkAttachmentLoadOp loadOp; |
| m_testParams.attachments[i].storeOp, // VkAttachmentStoreOp storeOp; |
| makeClearValueColor(tcu::Vec4(0.0f)) // VkClearValue clearValue; |
| }); |
| } |
| else |
| { |
| deUint32 usage = m_testParams.attachments[i].usage; |
| useDepth = usage & ATTACHMENT_USAGE_DEPTH; |
| useStencil = usage & ATTACHMENT_USAGE_STENCIL; |
| |
| dsAttachment.imageView = *imageViews[i]; |
| dsAttachment.loadOp = m_testParams.attachments[i].loadOp; |
| dsAttachment.storeOp = m_testParams.attachments[i].storeOp; |
| } |
| } |
| |
| VkRenderingInfoKHR renderingInfo |
| { |
| VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, |
| DE_NULL, |
| 0u, // VkRenderingFlagsKHR flags; |
| makeRect2D(m_renderSize), // VkRect2D renderArea; |
| 1u, // deUint32 layerCount; |
| 0u, // deUint32 viewMask; |
| (deUint32)colorAttachments.size(), // deUint32 colorAttachmentCount; |
| de::dataOrNull(colorAttachments), // const VkRenderingAttachmentInfoKHR* pColorAttachments; |
| useDepth ? &dsAttachment : DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment; |
| useStencil ? &dsAttachment : DE_NULL // const VkRenderingAttachmentInfoKHR* pStencilAttachment; |
| }; |
| |
| vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo); |
| } |
| else |
| { |
| const VkRenderPassBeginInfo renderPassBeginInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *m_renderPass, // VkRenderPass renderPass |
| *m_framebuffer, // VkFramebuffer framebuffer |
| makeRect2D(m_renderSize), // VkRect2D renderArea |
| 0u, // uint32_t clearValueCount |
| DE_NULL // const VkClearValue* pClearValues |
| }; |
| RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo); |
| } |
| |
| // Add clear commands for selected attachments |
| std::vector<VkClearAttachment> clearAttachments; |
| deUint32 colorAttIdx = 0u; |
| for (const auto& att : m_testParams.attachments) |
| { |
| if (att.init & ATTACHMENT_INIT_CMD_CLEAR) |
| { |
| if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| clearAttachments.push_back({getImageAspectFlags(mapVkFormat(m_testParams.depthStencilFormat)), 0u, |
| makeClearValueDepthStencil(0.25, 64)}); |
| } |
| else |
| { |
| clearAttachments.push_back({VK_IMAGE_ASPECT_COLOR_BIT, colorAttIdx++, |
| makeClearValueColorF32(0.0f, 0.0f, 0.5f, 1.0f)}); |
| } |
| } |
| } |
| if (!clearAttachments.empty()) |
| { |
| VkClearRect rect = { makeRect2D(m_renderSize), 0u, 1u }; |
| vk.cmdClearAttachments(*m_cmdBuffer, (deUint32) clearAttachments.size(), clearAttachments.data(), 1u, &rect); |
| } |
| |
| vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); |
| |
| deUint32 descriptorSetIdx = 0u; |
| deUint32 vertexOffset = 0u; |
| for (size_t i = 0; i < m_testParams.subpasses.size(); i++) |
| { |
| if (i != 0) |
| { |
| vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); |
| DE_ASSERT(m_testParams.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING); // multi subpass tests should not be executed for dynamic rendering |
| } |
| |
| vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]); |
| |
| bool hasInput = false; |
| for (const auto &ref : m_testParams.subpasses[i].attachmentRefs) |
| if (ref.usage & ATTACHMENT_USAGE_INPUT) |
| hasInput = true; |
| |
| if (hasInput) |
| vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayouts[i], 0, 1, |
| &descriptorSets[descriptorSetIdx++].get(), 0, DE_NULL); |
| |
| for (deUint32 d = 0; d < m_testParams.subpasses[i].numDraws; d++) |
| { |
| vk.cmdDraw(*m_cmdBuffer, 6u, 1, vertexOffset, 0); |
| vertexOffset += 6u; |
| } |
| } |
| if (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) |
| vk.cmdEndRendering(*m_cmdBuffer); |
| else |
| RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| |
| tcu::TestStatus LoadStoreOpNoneTestInstance::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); |
| const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; |
| |
| std::vector<Move<VkImage>> attachmentImages; |
| std::vector<de::MovePtr<Allocation>> attachmentImageAllocs; |
| std::vector<Move<VkImageView>> imageViews; |
| std::vector<Move<VkPipeline>> pipelines; |
| |
| for (const auto& att : m_testParams.attachments) |
| { |
| VkFormat format = getFormat(att.usage, m_testParams.depthStencilFormat); |
| VkImageUsageFlags usage = 0; |
| VkImageAspectFlags aspectFlags; |
| |
| if (att.verifyInner || att.verifyOuter) usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| if (att.init & ATTACHMENT_INIT_PRE) usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| aspectFlags = getImageAspectFlags(mapVkFormat(format)); |
| usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| } |
| else |
| { |
| // Color and input attachments. |
| aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| if (att.usage & ATTACHMENT_USAGE_COLOR) |
| usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| if (att.usage & ATTACHMENT_USAGE_INPUT) |
| usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| } |
| |
| const VkSampleCountFlagBits sampleCount = att.usage & ATTACHMENT_USAGE_MULTISAMPLE ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT; |
| |
| const VkImageCreateInfo imageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkImageCreateFlags flags |
| VK_IMAGE_TYPE_2D, // VkImageType imageType |
| format, // VkFormat format |
| { m_imageSize.x(), m_imageSize.y(), 1u }, // VkExtent3D extent |
| 1u, // deUint32 mipLevels |
| 1u, // deUint32 arrayLayers |
| sampleCount, // VkSampleCountFlagBits samples |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling |
| usage, // VkImageUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 1u, // deUint32 queueFamilyIndexCount |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout |
| }; |
| |
| attachmentImages.push_back(createImage(vk, vkDevice, &imageParams)); |
| |
| // Allocate and bind image memory. |
| attachmentImageAllocs.push_back(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *attachmentImages.back()), MemoryRequirement::Any)); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *attachmentImages.back(), attachmentImageAllocs.back()->getMemory(), attachmentImageAllocs.back()->getOffset())); |
| |
| // Create image view. |
| const VkImageViewCreateInfo imageViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkImageViewCreateFlags flags |
| *attachmentImages.back(), // VkImage image |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType |
| format, // VkFormat format |
| componentMappingRGBA, // VkChannelMapping channels |
| { aspectFlags, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange |
| }; |
| |
| imageViews.push_back(createImageView(vk, vkDevice, &imageViewParams)); |
| |
| if (att.init & ATTACHMENT_INIT_PRE) |
| { |
| // Preinitialize image |
| deUint32 firstUsage = getFirstUsage((deUint32)attachmentImages.size() - 1, m_testParams.subpasses); |
| if (firstUsage == ATTACHMENT_USAGE_UNDEFINED) |
| firstUsage = att.usage; |
| |
| if (firstUsage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| const auto dstAccess = (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); |
| const auto dstStage = (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); |
| |
| clearDepthStencilImage(vk, vkDevice, queue, queueFamilyIndex, *attachmentImages.back(), format, 0.5f, 128u, |
| VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| dstAccess, dstStage); |
| } |
| else |
| { |
| const auto dstAccess = (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); |
| const auto dstStage = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); |
| const auto clearColor = ((att.usage & ATTACHMENT_USAGE_INTEGER) ? makeClearValueColorU32(0u, 255u, 0u, 255u).color : makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f).color); |
| const auto layout = ((firstUsage & ATTACHMENT_USAGE_COLOR) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |
| |
| clearColorImage(vk, vkDevice, queue, queueFamilyIndex, *attachmentImages.back(), clearColor, VK_IMAGE_LAYOUT_UNDEFINED, |
| layout, dstAccess, dstStage); |
| } |
| } |
| } |
| |
| if (m_testParams.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) |
| { |
| // Create render pass. |
| if (m_testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY) |
| m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, m_testParams); |
| else |
| m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, m_testParams); |
| |
| std::vector<VkImageView> views; |
| for (const auto& view : imageViews) |
| views.push_back(*view); |
| |
| // Create framebuffer. |
| const VkFramebufferCreateInfo framebufferParams = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkFramebufferCreateFlags flags |
| *m_renderPass, // VkRenderPass renderPass |
| (deUint32)views.size(), // deUint32 attachmentCount |
| views.data(), // const VkImageView* pAttachments |
| (deUint32)m_imageSize.x(), // deUint32 width |
| (deUint32)m_imageSize.y(), // deUint32 height |
| 1u // deUint32 layers |
| }; |
| |
| m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); |
| } |
| |
| // Create shader modules |
| Unique<VkShaderModule> vertexShaderModule (createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0)); |
| Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0)); |
| Unique<VkShaderModule> fragmentShaderModuleUint (createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_uint"), 0)); |
| Unique<VkShaderModule> fragmentShaderModuleBlend (createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_blend"), 0)); |
| Unique<VkShaderModule> fragmentShaderModuleInput (createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_input"), 0)); |
| |
| // Create descriptor pool. Prepare for using one input attachment at most. |
| { |
| const VkDescriptorPoolSize descriptorPoolSize = |
| { |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type |
| 1u // deUint32 descriptorCount |
| }; |
| |
| const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags |
| 1u, // deUint32 maxSets |
| 1u, // deUint32 poolSizeCount |
| &descriptorPoolSize // const VkDescriptorPoolSize* pPoolSizes |
| }; |
| |
| m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo); |
| } |
| |
| std::vector<Move<VkDescriptorSetLayout>> descriptorSetLayouts; |
| std::vector<Move<VkDescriptorSet>> descriptorSets; |
| std::vector<Move<VkPipelineLayout>> pipelineLayouts; |
| |
| for (const auto& subpass : m_testParams.subpasses) |
| { |
| deUint32 numInputAttachments = 0u; |
| bool noColorWrite = false; |
| bool depthTest = false; |
| bool stencilTest = false; |
| bool multisample = false; |
| bool uintColorBuffer = false; |
| |
| // Create pipeline layout. |
| { |
| std::vector<VkDescriptorSetLayoutBinding> layoutBindings; |
| |
| for (const auto ref : subpass.attachmentRefs) |
| { |
| if (ref.usage & ATTACHMENT_USAGE_INPUT) |
| { |
| const VkDescriptorSetLayoutBinding layoutBinding = |
| { |
| 0u, // deUint32 binding |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType |
| 1u, // deUint32 descriptorCount |
| VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags |
| DE_NULL // const VkSampler* pImmutableSamplers |
| }; |
| |
| layoutBindings.push_back(layoutBinding); |
| numInputAttachments++; |
| } |
| if (ref.usage & ATTACHMENT_USAGE_COLOR) |
| { |
| if (ref.usage & ATTACHMENT_USAGE_WRITE_OFF) |
| noColorWrite = true; |
| } |
| if (ref.usage & ATTACHMENT_USAGE_DEPTH) |
| { |
| if (!(ref.usage & ATTACHMENT_USAGE_WRITE_OFF)) |
| depthTest = true; |
| } |
| if (ref.usage & ATTACHMENT_USAGE_STENCIL) |
| { |
| if (!(ref.usage & ATTACHMENT_USAGE_WRITE_OFF)) |
| stencilTest = true; |
| } |
| if (ref.usage & ATTACHMENT_USAGE_MULTISAMPLE) |
| { |
| multisample = true; |
| } |
| if (ref.usage & ATTACHMENT_USAGE_INTEGER) |
| { |
| uintColorBuffer = true; |
| } |
| } |
| |
| const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkDescriptorSetLayoutCreateFlags flags |
| (deUint32) layoutBindings.size(), // deUint32 bindingCount |
| layoutBindings.empty() ? DE_NULL : layoutBindings.data() // const VkDescriptorSetLayoutBinding* pBindings |
| }; |
| descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams)); |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineLayoutCreateFlags flags |
| 1u, // deUint32 setLayoutCount |
| &descriptorSetLayouts.back().get(), // const VkDescriptorSetLayout* pSetLayouts |
| 0u, // deUint32 pushConstantRangeCount |
| DE_NULL // const VkPushConstantRange* pPushConstantRanges |
| }; |
| |
| pipelineLayouts.push_back(createPipelineLayout(vk, vkDevice, &pipelineLayoutParams)); |
| } |
| |
| // Update descriptor set if needed. |
| if (numInputAttachments > 0u) |
| { |
| // Assuming there's only one input attachment at most. |
| DE_ASSERT(numInputAttachments == 1u); |
| |
| const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *m_descriptorPool, // VkDescriptorPool descriptorPool |
| 1u, // deUint32 descriptorSetCount |
| &descriptorSetLayouts.back().get(), // const VkDescriptorSetLayout* pSetLayouts |
| }; |
| |
| descriptorSets.push_back(allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo)); |
| |
| for (size_t i = 0; i < imageViews.size(); i++) |
| { |
| if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_INPUT) |
| { |
| const VkDescriptorImageInfo inputImageInfo = |
| { |
| DE_NULL, // VkSampler sampler |
| *imageViews[i], // VkImageView imageView |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout |
| }; |
| |
| const VkWriteDescriptorSet descriptorWrite = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *descriptorSets.back(), // VkDescriptorSet dstSet |
| 0u, // deUint32 dstBinding |
| 0u, // deUint32 dstArrayElement |
| 1u, // deUint32 descriptorCount |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType |
| &inputImageInfo, // const VkDescriptorImageInfo* pImageInfo |
| DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo |
| DE_NULL // const VkBufferView* pTexelBufferView |
| }; |
| vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL); |
| } |
| } |
| } |
| |
| // Create pipeline. |
| { |
| const VkVertexInputBindingDescription vertexInputBindingDescription = |
| { |
| 0u, // deUint32 binding |
| (deUint32)sizeof(Vertex4RGBA), // deUint32 strideInBytes |
| VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate |
| }; |
| |
| const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = |
| { |
| { |
| 0u, // deUint32 location |
| 0u, // deUint32 binding |
| VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format |
| 0u // deUint32 offset |
| }, |
| { |
| 1u, // deUint32 location |
| 0u, // deUint32 binding |
| VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format |
| (deUint32)(sizeof(float) * 4), // deUint32 offset |
| } |
| }; |
| |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineVertexInputStateCreateFlags flags |
| 1u, // deUint32 vertexBindingDescriptionCount |
| &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions |
| 2u, // deUint32 vertexAttributeDescriptionCount |
| vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions |
| }; |
| |
| const VkColorComponentFlags writeMask = noColorWrite ? 0 : VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask |
| | VK_COLOR_COMPONENT_G_BIT |
| | VK_COLOR_COMPONENT_B_BIT |
| | VK_COLOR_COMPONENT_A_BIT; |
| |
| const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = |
| { |
| m_testParams.alphaBlend, // VkBool32 blendEnable |
| VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor |
| VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor |
| VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp |
| VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor |
| VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp |
| writeMask // VkColorComponentFlags colorWriteMask |
| }; |
| |
| const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineColorBlendStateCreateFlags flags |
| VK_FALSE, // VkBool32 logicOpEnable |
| VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp |
| 1u, // deUint32 attachmentCount |
| &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments |
| { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] |
| }; |
| |
| const VkStencilOpState stencilOpState = |
| { |
| VK_STENCIL_OP_KEEP, // VkStencilOp failOp |
| VK_STENCIL_OP_REPLACE, // VkStencilOp passOp |
| VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp |
| VK_COMPARE_OP_GREATER, // VkCompareOp compareOp |
| 0xff, // deUint32 compareMask |
| 0xff, // deUint32 writeMask |
| 0xff // deUint32 reference |
| }; |
| |
| const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineDepthStencilStateCreateFlags flags |
| depthTest, // VkBool32 depthTestEnable |
| VK_TRUE, // VkBool32 depthWriteEnable |
| VK_COMPARE_OP_GREATER, // VkCompareOp depthCompareOp |
| VK_FALSE, // VkBool32 depthBoundsTestEnable |
| stencilTest, // VkBool32 stencilTestEnable |
| stencilOpState, // VkStencilOpState front |
| stencilOpState, // VkStencilOpState back |
| 0.0f, // float minDepthBounds |
| 1.0f, // float maxDepthBounds |
| }; |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineMultisampleStateCreateFlags flags |
| multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples |
| VK_FALSE, // VkBool32 sampleShadingEnable |
| 1.0f, // float minSampleShading |
| DE_NULL, // const VkSampleMask* pSampleMask |
| VK_FALSE, // VkBool32 alphaToCoverageEnable |
| VK_FALSE // VkBool32 alphaToOneEnable |
| }; |
| |
| const std::vector<VkViewport> viewports (1, makeViewport(m_imageSize)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize)); |
| VkShaderModule fragShader = *fragmentShaderModule; |
| |
| if (numInputAttachments > 0u) |
| fragShader = *fragmentShaderModuleInput; |
| else if (uintColorBuffer) |
| fragShader = *fragmentShaderModuleUint; |
| else if (m_testParams.alphaBlend) |
| fragShader = *fragmentShaderModuleBlend; |
| |
| VkPipelineRenderingCreateInfoKHR renderingCreateInfo |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, |
| DE_NULL, |
| 0u, |
| 0u, |
| DE_NULL, |
| VK_FORMAT_UNDEFINED, |
| VK_FORMAT_UNDEFINED |
| }; |
| |
| std::vector<VkFormat> colorVector; |
| for (const auto& att : m_testParams.attachments) |
| { |
| VkFormat format = getFormat(att.usage, m_testParams.depthStencilFormat); |
| |
| if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL) |
| { |
| const auto tcuFormat = mapVkFormat(format); |
| const auto hasDepth = tcu::hasDepthComponent(tcuFormat.order); |
| const auto hasStencil = tcu::hasStencilComponent(tcuFormat.order); |
| renderingCreateInfo.depthAttachmentFormat = (hasDepth ? format : VK_FORMAT_UNDEFINED); |
| renderingCreateInfo.stencilAttachmentFormat = (hasStencil ? format : VK_FORMAT_UNDEFINED); |
| } |
| else if (!(att.usage & ATTACHMENT_USAGE_RESOLVE_TARGET)) |
| { |
| colorVector.push_back(format); |
| } |
| } |
| |
| vk::VkPipelineRenderingCreateInfoKHR* nextPtr = DE_NULL; |
| if (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) |
| { |
| renderingCreateInfo.colorAttachmentCount = static_cast<deUint32>(colorVector.size()); |
| renderingCreateInfo.pColorAttachmentFormats = colorVector.data(); |
| |
| nextPtr = &renderingCreateInfo; |
| } |
| |
| pipelines.push_back(makeGraphicsPipeline( |
| vk, // const DeviceInterface& vk |
| vkDevice, // const VkDevice device |
| *pipelineLayouts.back(), // const VkPipelineLayout pipelineLayout |
| *vertexShaderModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlModule |
| DE_NULL, // const VkShaderModule tessellationEvalModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| fragShader, // const VkShaderModule fragmentShaderModule |
| *m_renderPass, // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology |
| (deUint32)pipelines.size(), // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo |
| &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo |
| DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo |
| nextPtr)); // const void* pNext |
| } |
| } |
| |
| // Create vertex buffer. |
| { |
| const VkBufferCreateInfo vertexBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkBufferCreateFlags flags |
| (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size |
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 1u, // deUint32 queueFamilyIndexCount |
| &queueFamilyIndex // const deUint32* pQueueFamilyIndices |
| }; |
| |
| m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); |
| m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); |
| |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); |
| |
| // Upload vertex data. |
| deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); |
| flushAlloc(vk, vkDevice, *m_vertexBufferAlloc); |
| } |
| |
| // Create command pool. |
| m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); |
| |
| // Create command buffer. |
| if (m_testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY) |
| createCommandBuffer<RenderpassSubpass1>(vk, vkDevice, imageViews, descriptorSets, pipelineLayouts, pipelines); |
| else |
| createCommandBuffer<RenderpassSubpass2>(vk, vkDevice, imageViews, descriptorSets, pipelineLayouts, pipelines); |
| |
| // Submit commands. |
| submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); |
| |
| bool pass = true; |
| |
| // Verify selected attachments. |
| for (size_t i = 0; i < m_testParams.attachments.size(); i++) |
| { |
| if (m_testParams.attachments[i].verifyInner || m_testParams.attachments[i].verifyOuter) |
| { |
| de::MovePtr<tcu::TextureLevel> textureLevelResult; |
| |
| SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); |
| VkFormat format = getFormat(m_testParams.attachments[i].usage, m_testParams.depthStencilFormat); |
| |
| if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_DEPTH) |
| { |
| VkImageLayout layout = (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| textureLevelResult = pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], m_testParams.depthStencilFormat, m_imageSize, layout); |
| } |
| else if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_STENCIL) |
| { |
| VkImageLayout layout = (m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| textureLevelResult = pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], m_testParams.depthStencilFormat, m_imageSize, layout); |
| } |
| else |
| { |
| VkImageLayout layout = ((m_testParams.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| textureLevelResult = pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], format, m_imageSize, layout); |
| } |
| |
| const tcu::ConstPixelBufferAccess& access = textureLevelResult->getAccess(); |
| |
| // Log attachment contents |
| m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Attachment " + de::toString(i), "") |
| << tcu::TestLog::Image("Attachment " + de::toString(i), "", access) |
| << tcu::TestLog::EndImageSet; |
| |
| for (int y = 0; y < access.getHeight(); y++) |
| for (int x = 0; x < access.getWidth(); x++) |
| { |
| const bool inner = x < (int)m_renderSize.x() && y < (int)m_renderSize.y(); |
| |
| if (inner && !m_testParams.attachments[i].verifyInner) |
| continue; |
| if (!inner && !m_testParams.attachments[i].verifyOuter) |
| continue; |
| |
| const tcu::Vec4 ref = inner ? m_testParams.attachments[i].innerRef : m_testParams.attachments[i].outerRef; |
| const tcu::Vec4 p = access.getPixel(x, y); |
| |
| for (int c = 0; c < 4; c++) |
| if (fabs(p[c] - ref[c]) > 0.01f) |
| pass = false; |
| } |
| |
| } |
| } |
| |
| if (pass) |
| return tcu::TestStatus::pass("Pass"); |
| else |
| return tcu::TestStatus::fail("Fail"); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createRenderPassLoadStoreOpNoneTests (tcu::TestContext& testCtx, const RenderingType renderingType) |
| { |
| de::MovePtr<tcu::TestCaseGroup> opNoneTests (new tcu::TestCaseGroup(testCtx, "load_store_op_none", "")); |
| |
| const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); |
| const tcu::Vec4 magenta (1.0f, 0.0f, 1.0f, 1.0f); |
| const tcu::Vec4 darkBlue (0.0f, 0.0f, 0.5f, 1.0f); |
| const tcu::Vec4 blend (0.5f, 0.0f, 0.25f, 0.5f); |
| const tcu::Vec4 depthInit (0.5f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 depthFull (1.0f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 stencilInit (128.0f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 stencilFull (255.0f, 0.0f, 0.0f, 1.0f); |
| const tcu::Vec4 redUint (255.0f, 0.0f, 0.0f, 255.0f); |
| const tcu::Vec4 greenUint (0.0f, 255.0f, 0.0f, 255.0f); |
| |
| // Preinitialize attachments 0 and 1 to green. |
| // Subpass 0: draw a red rectangle inside attachment 0. |
| // Subpass 1: use the attachment 0 as input and add blue channel to it resulting in magenta. Write the results to |
| // attachment 1. |
| // After the render pass attachment 0 has undefined values inside the render area because of the shader writes with |
| // store op 'none', but outside should still have the preinitialized value of green. Attachment 1 should have the |
| // preinitialized green outside the render area and magenta inside. |
| if (renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_INPUT, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| false, green, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, magenta, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_INPUT}, {1u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_load_store_op_none", "", params)); |
| } |
| |
| // Preinitialize color attachment to green. Use a render pass with load and store ops none, but |
| // disable color writes using an empty color mask. The color attachment image should have the original |
| // preinitialized value after the render pass. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| true, green, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_WRITE_OFF}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_none_write_off", "", params)); |
| } |
| |
| // Preinitialize color attachment to green. Use a render pass with load and store ops none, and |
| // write a rectange to the color buffer. The render area is undefined, but the outside area should |
| // still have the preinitialized color. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| false, green, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_none", "", params)); |
| } |
| |
| // Preinitialize color attachment to green. Use a subpass with no draw calls but instead |
| // do an attachment clear command using dark blue color. Using load op none preserves the preinitialized |
| // data and store op store causes the cleared blue render area to be present after the render pass. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| true, darkBlue, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 0u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_store", "", params)); |
| } |
| |
| // Preinitialize color attachment to green. Use a subpass with a dark blue attachment clear followed |
| // by an alpha blender draw. Load op is none preserves the preinitialized data and store op store |
| // keeps the blended color inside the render area after the render pass. |
| { |
| TestParams params; |
| params.alphaBlend = true; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| true, blend, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_store_alphablend", "", params)); |
| } |
| |
| // Preinitialize attachments 0 and 1 to green. Attachment 0 contents inside render area is undefined because load op 'none'. |
| // Subpass 0: draw a red rectangle inside attachment 0 overwriting all undefined values. |
| // Subpass 1: use the attachment 0 as input and add blue to it resulting in magenta. Write the results to attachment 1. |
| // After the render pass attachment 0 contents inside the render area are undefined because of store op 'don't care', |
| // but the outside area should still have the preinitialized content. |
| // Attachment 1 should have the preinitialized green outside render area and magenta inside. |
| if (renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_INPUT, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| ATTACHMENT_INIT_PRE, |
| false, green, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, magenta, |
| true, green}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_INPUT}, {1u, ATTACHMENT_USAGE_COLOR}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_dontcare", "", params)); |
| } |
| |
| // Preinitialize color attachment to green. Use a render pass with load and store ops none for a multisample color |
| // target. Write a red rectangle and check it ends up in the resolved buffer even though the multisample attachment |
| // doesn't store the results. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_MULTISAMPLE | ATTACHMENT_USAGE_INTEGER, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| false, green, |
| false, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_RESOLVE_TARGET | ATTACHMENT_USAGE_INTEGER, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, redUint, |
| true, greenUint}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_MULTISAMPLE | ATTACHMENT_USAGE_INTEGER}, {1u, ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_RESOLVE_TARGET}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_none_resolve", "", params)); |
| } |
| |
| std::vector<VkFormat> formats = { VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT }; |
| |
| for (deUint32 f = 0; f < formats.size(); ++f) |
| { |
| const std::string formatName = getFormatCaseName(formats[f]); |
| |
| // Preinitialize attachment 0 (color) to green and attachment 1 (depth) to 0.5. |
| // Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update |
| // depth buffer to 1.0. |
| // This is followed by another draw with a blue rectangle using the same depth of 1.0. This time |
| // the depth test fails and nothing is written. |
| // After the renderpass the red color should remain inside the render area of the color buffer. |
| // Store op 'store' for depth buffer makes the written values undefined, but the pixels outside |
| // render area should still contain the original value of 0.5. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_DEPTH, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| false, depthInit, |
| true, depthInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 2u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_"+formatName+"_load_op_load_store_op_none", "", params)); |
| } |
| |
| // Preinitialize depth attachment to 0.5. Use a render pass with load and store ops none for the depth, but |
| // disable depth test which also disables depth writes. The depth attachment should have the original |
| // preinitialized value after the render pass. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_DEPTH, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| true, depthInit, |
| true, depthInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH | ATTACHMENT_USAGE_WRITE_OFF}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_none_write_off", "", params)); |
| } |
| |
| // Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25 |
| // using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update |
| // depth buffer to 1.0. After the renderpass the color buffer should have red inside the render area and depth should have the |
| // shader updated value of 1.0. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_DEPTH, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| true, depthFull, |
| true, depthInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_store", "", params)); |
| } |
| |
| // Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25 |
| // using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater' which will pass. |
| // After the renderpass the color buffer should have red inside the render area. Depth buffer contents inside render |
| // are is undefined because of store op 'don't care', but the outside should have the original value of 0.5. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_DEPTH, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| false, depthFull, |
| true, depthInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_dontcare", "", params)); |
| } |
| |
| // Preinitialize attachment 0 (color) to green and attachment 1 (stencil) to 128. |
| // Draw a red rectangle using stencil testing with compare op 'greater' and reference of 255. The stencil test |
| // will pass. This is followed by another draw with a blue rectangle using the same stencil settings. This time |
| // the stencil test fails and nothing is written. |
| // After the renderpass the red color should remain inside the render area of the color buffer. |
| // Store op 'store' for stencil buffer makes the written values undefined, but the pixels outside |
| // render area should still contain the original value of 128. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_STENCIL, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| false, stencilInit, |
| true, stencilInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 2u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_load_store_op_none", "", params)); |
| } |
| |
| // Preinitialize stencil attachment to 128. Use a render pass with load and store ops none for the stencil, but |
| // disable stencil test which also disables stencil writes. The stencil attachment should have the original |
| // preinitialized value after the render pass. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_STENCIL, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_NONE_EXT, |
| ATTACHMENT_INIT_PRE, |
| true, stencilInit, |
| true, stencilInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL | ATTACHMENT_USAGE_WRITE_OFF}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_none_write_off", "", params)); |
| } |
| |
| // Preinitialize attachment 0 (color) to green and stencil buffer to 128. During the render pass initialize attachment 1 (stencil) to 64 |
| // using cmdClearAttachments. Draw a red rectangle using stencil reference of 255 and stencil op 'greater'. Stencil test will pass and update |
| // stencil buffer to 255. After the renderpass the color buffer should have red inside the render area and stencil should have the |
| // shader updated value of 255. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_STENCIL, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| true, stencilFull, |
| true, stencilInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_store", "", params)); |
| } |
| |
| // Preinitialize attachment 0 (color) to green and stencil buffer to 128. During the render pass initialize attachment 1 (stencil) to 64 |
| // using cmdClearAttachments. Draw a red rectangle using stencil reference 255 and stencil op 'greater' which will pass. |
| // After the renderpass the color buffer should have red inside the render area. Stencil buffer contents inside render |
| // are is undefined because of store op 'don't care', but the outside should have the original value of 128. |
| { |
| TestParams params; |
| params.alphaBlend = false; |
| params.depthStencilFormat = formats[f]; |
| params.renderingType = renderingType; |
| params.attachments.push_back({ATTACHMENT_USAGE_COLOR, |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| ATTACHMENT_INIT_PRE, |
| true, red, |
| true, green}); |
| params.attachments.push_back({ATTACHMENT_USAGE_STENCIL, |
| VK_ATTACHMENT_LOAD_OP_NONE_EXT, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR, |
| false, stencilFull, |
| true, stencilInit}); |
| params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 1u}); |
| |
| opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_dontcare", "", params)); |
| } |
| } |
| |
| return opNoneTests.release(); |
| } |
| |
| } // renderpass |
| } // vkt |