Test unused shader stages with graphics pipeline libraries
authorRicardo Garcia <rgarcia@igalia.com>
Tue, 22 Nov 2022 16:29:58 +0000 (17:29 +0100)
committerPiotr Byszewski <piotr.byszewski@mobica.com>
Mon, 19 Dec 2022 10:38:03 +0000 (10:38 +0000)
Test pStages is properly ignored when creating graphics pipeline
libraries that do not need shading stages, like for vertex input state
and for fragment output state.

New tests:
dEQP-VK.pipeline.*.misc.unused_shader_stages*

Components: Vulkan
VK-GL-CTS issue: 4007

Change-Id: I3453fb48a422e135fc394ffc7d4ad006f1739a1f

android/cts/main/vk-master-2022-03-01/pipeline.txt
android/cts/main/vk-master/pipeline/fast-linked-library.txt
android/cts/main/vk-master/pipeline/pipeline-library.txt
external/vulkancts/modules/vulkan/pipeline/vktPipelineMiscTests.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineMiscTests.hpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp
external/vulkancts/mustpass/main/vk-default/pipeline/fast-linked-library.txt
external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt

index fa88f06..dc87a77 100644 (file)
@@ -287622,6 +287622,10 @@ dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachm
 dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess_include_geom
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.4
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_1111
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_112
@@ -700368,3 +700372,7 @@ dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.atta
 dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess_include_geom
index fef7bc3..a50e85e 100644 (file)
@@ -287622,3 +287622,7 @@ dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.atta
 dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess_include_geom
index d207596..bb837a0 100644 (file)
@@ -287622,6 +287622,10 @@ dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachm
 dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess_include_geom
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.4
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_1111
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_112
index 585f31f..771a696 100644 (file)
@@ -409,20 +409,664 @@ tcu::TestStatus ImplicitPrimitiveIDPassthroughInstance::iterate ()
        return tcu::TestStatus::pass("Pass");
 }
 
+#ifndef CTS_USES_VULKANSC
+struct UnusedShaderStageParams
+{
+       PipelineConstructionType        pipelineConstructionType;
+       bool                                            useTessShaders;
+       bool                                            useGeomShader;
+};
+
+class UnusedShaderStagesCase : public vkt::TestCase
+{
+public:
+                                       UnusedShaderStagesCase  (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const UnusedShaderStageParams& params)
+                                               : vkt::TestCase (testCtx, name, description)
+                                               , m_params              (params)
+                                               {}
+       virtual                 ~UnusedShaderStagesCase (void) {}
+
+       void                    initPrograms                    (vk::SourceCollections& programCollection) const override;
+       TestInstance*   createInstance                  (Context& context) const override;
+       void                    checkSupport                    (Context& context) const override;
+
+protected:
+       UnusedShaderStageParams m_params;
+};
+
+class UnusedShaderStagesInstance : public vkt::TestInstance
+{
+public:
+                                               UnusedShaderStagesInstance      (Context& context, const UnusedShaderStageParams& params)
+                                                       : vkt::TestInstance     (context)
+                                                       , m_params                      (params)
+                                                       {}
+       virtual                         ~UnusedShaderStagesInstance     (void) {}
+       tcu::TestStatus         iterate                                         (void) override;
+
+protected:
+       UnusedShaderStageParams m_params;
+};
+
+void UnusedShaderStagesCase::initPrograms (vk::SourceCollections &programCollection) const
+{
+       // Shaders that produce bad results.
+       {
+               std::ostringstream vert;
+               vert
+                       << "#version 460\n"
+                       << "out gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "};\n"
+                       << "void main (void) {\n"
+                       << "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("bad_vert") << glu::VertexSource(vert.str());
+
+               std::ostringstream tesc;
+               tesc
+                       << "#version 460\n"
+                       << "layout (vertices=3) out;\n"
+                       << "in gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_in[gl_MaxPatchVertices];\n"
+                       << "out gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_out[];\n"
+                       << "void main (void) {\n"
+                       << "    gl_TessLevelInner[0] = 1.0;\n"
+                       << "    gl_TessLevelInner[1] = 1.0;\n"
+                       << "    gl_TessLevelOuter[0] = 1.0;\n"
+                       << "    gl_TessLevelOuter[1] = 1.0;\n"
+                       << "    gl_TessLevelOuter[2] = 1.0;\n"
+                       << "    gl_TessLevelOuter[3] = 1.0;\n"
+                       << "    gl_out[gl_InvocationID].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("bad_tesc") << glu::TessellationControlSource(tesc.str());
+
+               std::ostringstream tese;
+               tese
+                       << "#version 460\n"
+                       << "layout (triangles, fractional_odd_spacing, cw) in;\n"
+                       << "in gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_in[gl_MaxPatchVertices];\n"
+                       << "out gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "};\n"
+                       << "void main() {\n"
+                       << "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("bad_tese") << glu::TessellationEvaluationSource(tese.str());
+
+               std::ostringstream geom;
+               geom
+                       << "#version 460\n"
+                       << "layout (triangles) in;\n"
+                       << "layout (triangle_strip, max_vertices=3) out;\n"
+                       << "in gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "} gl_in[3];\n"
+                       << "out gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "};\n"
+                       << "void main() {\n"
+                       // Avoid emitting any vertices.
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("bad_geom") << glu::GeometrySource(geom.str());
+
+               std::ostringstream frag;
+               frag
+                       << "#version 460\n"
+                       << "layout (location=0) out vec4 outColor;\n"
+                       << "void main (void) {\n"
+                       << "    outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("bad_frag") << glu::FragmentSource(frag.str());
+       }
+
+       // Shaders that produce the expected results.
+       {
+               std::ostringstream vert;
+               vert
+                       << "#version 460\n"
+                       << "out gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "};\n"
+                       << "vec2 positions[3] = vec2[](\n"
+                       << "    vec2(-1.0, -1.0),\n"
+                       << "    vec2(-1.0,  3.0),\n"
+                       << "    vec2( 3.0, -1.0)\n"
+                       << ");\n"
+                       << "void main (void) {\n"
+                       << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
+
+               std::ostringstream tesc;
+               tesc
+                       << "#version 460\n"
+                       << "layout (vertices=3) out;\n"
+                       << "in gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_in[gl_MaxPatchVertices];\n"
+                       << "out gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_out[];\n"
+                       << "void main (void) {\n"
+                       << "    gl_TessLevelInner[0] = 1.0;\n"
+                       << "    gl_TessLevelInner[1] = 1.0;\n"
+                       << "    gl_TessLevelOuter[0] = 1.0;\n"
+                       << "    gl_TessLevelOuter[1] = 1.0;\n"
+                       << "    gl_TessLevelOuter[2] = 1.0;\n"
+                       << "    gl_TessLevelOuter[3] = 1.0;\n"
+                       << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
+
+               std::ostringstream tese;
+               tese
+                       << "#version 460\n"
+                       << "layout (triangles, fractional_odd_spacing, cw) in;\n"
+                       << "in gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "} gl_in[gl_MaxPatchVertices];\n"
+                       << "out gl_PerVertex {\n"
+                       << "  vec4 gl_Position;\n"
+                       << "};\n"
+                       << "void main() {\n"
+                       << "    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
+                       << "                  (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
+                       << "                  (gl_TessCoord.z * gl_in[2].gl_Position);\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
+
+               std::ostringstream geom;
+               geom
+                       << "#version 460\n"
+                       << "layout (triangles) in;\n"
+                       << "layout (triangle_strip, max_vertices=3) out;\n"
+                       << "in gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "} gl_in[3];\n"
+                       << "out gl_PerVertex {\n"
+                       << "    vec4 gl_Position;\n"
+                       << "};\n"
+                       << "void main() {\n"
+                       << "    gl_Position = gl_in[0].gl_Position; EmitVertex();\n"
+                       << "    gl_Position = gl_in[1].gl_Position; EmitVertex();\n"
+                       << "    gl_Position = gl_in[2].gl_Position; EmitVertex();\n"
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
+
+               std::ostringstream frag;
+               frag
+                       << "#version 460\n"
+                       << "layout (location=0) out vec4 outColor;\n"
+                       << "void main (void) {\n"
+                       << "    outColor = vec4(0.0, 1.0, 0.0, 1.0);\n" // Blue instead of black.
+                       << "}\n"
+                       ;
+               programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+       }
+}
+
+TestInstance* UnusedShaderStagesCase::createInstance (Context &context) const
+{
+       return new UnusedShaderStagesInstance(context, m_params);
+}
+
+void UnusedShaderStagesCase::checkSupport (Context &context) const
+{
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
+
+       if (m_params.useTessShaders)
+               context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
+
+       if (m_params.useGeomShader)
+               context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
+}
+
+VkPipelineShaderStageCreateInfo makePipelineShaderStageCreateInfo (VkShaderStageFlagBits stage, VkShaderModule module)
+{
+       const VkPipelineShaderStageCreateInfo stageInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineShaderStageCreateFlags        flags;
+               stage,                                                                                                  //      VkShaderStageFlagBits                           stage;
+               module,                                                                                                 //      VkShaderModule                                          module;
+               "main",                                                                                                 //      const char*                                                     pName;
+               nullptr,                                                                                                //      const VkSpecializationInfo*                     pSpecializationInfo;
+       };
+       return stageInfo;
+}
+
+tcu::TestStatus UnusedShaderStagesInstance::iterate ()
+{
+       const auto&                     vkd                             = m_context.getDeviceInterface();
+       const auto                      device                  = m_context.getDevice();
+       auto&                           alloc                   = m_context.getDefaultAllocator();
+       const auto                      queue                   = m_context.getUniversalQueue();
+       const auto                      queueIndex              = m_context.getUniversalQueueFamilyIndex();
+
+       const bool                      isOptimized             = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
+       const auto                      colorExtent             = makeExtent3D(1u, 1u, 1u);
+       const tcu::IVec3        colorExtentVec  (static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
+       const auto                      colorFormat             = VK_FORMAT_R8G8B8A8_UNORM;
+       const auto                      colorUsage              = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+       const auto                      colorSRR                = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+       const auto                      colorSRL                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
+       const auto                      tcuFormat               = mapVkFormat(colorFormat);
+       const tcu::Vec4         clearColor              (0.0f, 0.0f, 0.0f, 0.0f);
+       const tcu::Vec4         expectedColor   (0.0f, 1.0f, 0.0f, 1.0f); // Must match the good frag shader.
+
+       // Good and bad shader modules.
+       const auto&     binaries                        = m_context.getBinaryCollection();
+
+       const auto      goodVertModule          = createShaderModule(vkd, device, binaries.get("vert"));
+       const auto      goodTescModule          = (m_params.useTessShaders ?    createShaderModule(vkd, device, binaries.get("tesc")) : Move<VkShaderModule>());
+       const auto      goodTeseModule          = (m_params.useTessShaders ?    createShaderModule(vkd, device, binaries.get("tese")) : Move<VkShaderModule>());
+       const auto      goodGeomModule          = (m_params.useGeomShader ?             createShaderModule(vkd, device, binaries.get("geom")) : Move<VkShaderModule>());
+       const auto      goodFragModule          = createShaderModule(vkd, device, binaries.get("frag"));
+
+       const auto      goodVertShaderInfo      = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, goodVertModule.get());
+       const auto      goodTescShaderInfo      = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, goodTescModule.get());
+       const auto      goodTeseShaderInfo      = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, goodTeseModule.get());
+       const auto      goodGeomShaderInfo      = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, goodGeomModule.get());
+       const auto      goodFragShaderInfo      = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, goodFragModule.get());
+
+       const auto      badVertModule           = createShaderModule(vkd, device, binaries.get("bad_vert"));
+       const auto      badTescModule           = (m_params.useTessShaders ?    createShaderModule(vkd, device, binaries.get("bad_tesc")) : Move<VkShaderModule>());
+       const auto      badTeseModule           = (m_params.useTessShaders ?    createShaderModule(vkd, device, binaries.get("bad_tese")) : Move<VkShaderModule>());
+       const auto      badGeomModule           = (m_params.useGeomShader ?             createShaderModule(vkd, device, binaries.get("bad_geom")) : Move<VkShaderModule>());
+       const auto      badFragModule           = createShaderModule(vkd, device, binaries.get("bad_frag"));
+
+       const auto      badVertShaderInfo       = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, badVertModule.get());
+       const auto      badTescShaderInfo       = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, badTescModule.get());
+       const auto      badTeseShaderInfo       = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, badTeseModule.get());
+       const auto      badGeomShaderInfo       = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, badGeomModule.get());
+       const auto      badFragShaderInfo       = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, badFragModule.get());
+
+       // Color attachment.
+       const VkImageCreateInfo colorAttachmentCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //      VkStructureType                 sType;
+               nullptr,                                                                //      const void*                             pNext;
+               0u,                                                                             //      VkImageCreateFlags              flags;
+               VK_IMAGE_TYPE_2D,                                               //      VkImageType                             imageType;
+               colorFormat,                                                    //      VkFormat                                format;
+               colorExtent,                                                    //      VkExtent3D                              extent;
+               1u,                                                                             //      uint32_t                                mipLevels;
+               1u,                                                                             //      uint32_t                                arrayLayers;
+               VK_SAMPLE_COUNT_1_BIT,                                  //      VkSampleCountFlagBits   samples;
+               VK_IMAGE_TILING_OPTIMAL,                                //      VkImageTiling                   tiling;
+               colorUsage,                                                             //      VkImageUsageFlags               usage;
+               VK_SHARING_MODE_EXCLUSIVE,                              //      VkSharingMode                   sharingMode;
+               0u,                                                                             //      uint32_t                                queueFamilyIndexCount;
+               nullptr,                                                                //      const uint32_t*                 pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED,                              //      VkImageLayout                   initialLayout;
+       };
+       ImageWithMemory colorAttachment (vkd, device, alloc, colorAttachmentCreateInfo, MemoryRequirement::Any);
+
+       // Color attachment view.
+       const auto colorAttachmentView = makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
+
+       // Verification buffer.
+       const auto                      verificationBufferSize                  = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * colorExtent.width * colorExtent.height * colorExtent.depth;
+       const auto                      verificationBufferCreateInfo    = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       BufferWithMemory        verificationBuffer                              (vkd, device, alloc, verificationBufferCreateInfo, MemoryRequirement::HostVisible);
+       auto&                           verificationBufferAlloc                 = verificationBuffer.getAllocation();
+
+       // Render pass and framebuffer.
+       const auto renderPass   = makeRenderPass(vkd, device, colorFormat);
+       const auto framebuffer  = makeFramebuffer(vkd, device, renderPass.get(), colorAttachmentView.get(), colorExtent.width, colorExtent.height);
+
+       // Pipeline layout.
+       const auto pipelineLayout = makePipelineLayout(vkd, device);
+
+       // Pipeline state.
+
+       const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
+
+       const auto primitiveTopology = (m_params.useTessShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
+
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    //      VkStructureType                                                 sType;
+               nullptr,                                                                                                                //      const void*                                                             pNext;
+               0u,                                                                                                                             //      VkPipelineInputAssemblyStateCreateFlags flags;
+               primitiveTopology,                                                                                              //      VkPrimitiveTopology                                             topology;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                primitiveRestartEnable;
+       };
+
+       const VkPipelineTessellationStateCreateInfo tessellationStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,      //      VkStructureType                                                 sType;
+               nullptr,                                                                                                        //      const void*                                                             pNext;
+               0u,                                                                                                                     //      VkPipelineTessellationStateCreateFlags  flags;
+               3u,                                                                                                                     //      uint32_t                                                                patchControlPoints;
+       };
+
+       const std::vector<VkViewport>   viewports       (1u, makeViewport(colorExtent));
+       const std::vector<VkRect2D>             scissors        (1u, makeRect2D(colorExtent));
+
+       const VkPipelineViewportStateCreateInfo viewportStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineViewportStateCreateFlags      flags;
+               de::sizeU32(viewports),                                                                 //      uint32_t                                                        viewportCount;
+               de::dataOrNull(viewports),                                                              //      const VkViewport*                                       pViewports;
+               de::sizeU32(scissors),                                                                  //      uint32_t                                                        scissorCount;
+               de::dataOrNull(scissors),                                                               //      const VkRect2D*                                         pScissors;
+       };
+
+       const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //      VkStructureType                                                 sType;
+               nullptr,                                                                                                                //      const void*                                                             pNext;
+               0u,                                                                                                                             //      VkPipelineRasterizationStateCreateFlags flags;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthClampEnable;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                rasterizerDiscardEnable;
+               VK_POLYGON_MODE_FILL,                                                                                   //      VkPolygonMode                                                   polygonMode;
+               VK_CULL_MODE_BACK_BIT,                                                                                  //      VkCullModeFlags                                                 cullMode;
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //      VkFrontFace                                                             frontFace;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthBiasEnable;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasConstantFactor;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasClamp;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasSlopeFactor;
+               1.0f,                                                                                                                   //      float                                                                   lineWidth;
+       };
+
+       const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       //      VkStructureType                                                 sType;
+               nullptr,                                                                                                        //      const void*                                                             pNext;
+               0u,                                                                                                                     //      VkPipelineMultisampleStateCreateFlags   flags;
+               VK_SAMPLE_COUNT_1_BIT,                                                                          //      VkSampleCountFlagBits                                   rasterizationSamples;
+               VK_FALSE,                                                                                                       //      VkBool32                                                                sampleShadingEnable;
+               1.0f,                                                                                                           //      float                                                                   minSampleShading;
+               nullptr,                                                                                                        //      const VkSampleMask*                                             pSampleMask;
+               VK_FALSE,                                                                                                       //      VkBool32                                                                alphaToCoverageEnable;
+               VK_FALSE,                                                                                                       //      VkBool32                                                                alphaToOneEnable;
+       };
+
+       const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
+
+       const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
+
+       const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+       {
+               VK_FALSE,                               //      VkBool32                                blendEnable;
+               VK_BLEND_FACTOR_ZERO,   //      VkBlendFactor                   srcColorBlendFactor;
+               VK_BLEND_FACTOR_ZERO,   //      VkBlendFactor                   dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                //      VkBlendOp                               colorBlendOp;
+               VK_BLEND_FACTOR_ZERO,   //      VkBlendFactor                   srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ZERO,   //      VkBlendFactor                   dstAlphaBlendFactor;
+               VK_BLEND_OP_ADD,                //      VkBlendOp                               alphaBlendOp;
+               colorComponentFlags,    //      VkColorComponentFlags   colorWriteMask;
+       };
+
+       const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       //      VkStructureType                                                         sType;
+               nullptr,                                                                                                        //      const void*                                                                     pNext;
+               0u,                                                                                                                     //      VkPipelineColorBlendStateCreateFlags            flags;
+               VK_FALSE,                                                                                                       //      VkBool32                                                                        logicOpEnable;
+               VK_LOGIC_OP_CLEAR,                                                                                      //      VkLogicOp                                                                       logicOp;
+               1u,                                                                                                                     //      uint32_t                                                                        attachmentCount;
+               &colorBlendAttachmentState,                                                                     //      const VkPipelineColorBlendAttachmentState*      pAttachments;
+               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     //      float                                                                           blendConstants[4];
+       };
+
+       // Make a few vectors with the wrong shader modules.
+       std::vector<VkPipelineShaderStageCreateInfo> badPreRasterStages;
+       badPreRasterStages.push_back(badVertShaderInfo);
+       if (m_params.useTessShaders)
+       {
+               badPreRasterStages.push_back(badTescShaderInfo);
+               badPreRasterStages.push_back(badTeseShaderInfo);
+       }
+       if (m_params.useGeomShader)
+               badPreRasterStages.push_back(badGeomShaderInfo);
+
+       std::vector<VkPipelineShaderStageCreateInfo> allBadStages (badPreRasterStages);
+       allBadStages.push_back(badFragShaderInfo);
+
+       // Make a few vectors with the right shader modules.
+       std::vector<VkPipelineShaderStageCreateInfo> goodPreRasterStages;
+       goodPreRasterStages.push_back(goodVertShaderInfo);
+       if (m_params.useTessShaders)
+       {
+               goodPreRasterStages.push_back(goodTescShaderInfo);
+               goodPreRasterStages.push_back(goodTeseShaderInfo);
+       }
+       if (m_params.useGeomShader)
+               goodPreRasterStages.push_back(goodGeomShaderInfo);
+
+       std::vector<VkPipelineShaderStageCreateInfo> allGoodStages (goodPreRasterStages);
+       allGoodStages.push_back(goodFragShaderInfo);
+
+       // Build the different pipeline pieces.
+       Move<VkPipeline> vertexInputLib;
+       Move<VkPipeline> preRasterShaderLib;
+       Move<VkPipeline> fragShaderLib;
+       Move<VkPipeline> fragOutputLib;
+
+       VkPipelineCreateFlags libCreationFlags  = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
+       VkPipelineCreateFlags linkFlags                 = 0u;
+
+       if (isOptimized)
+       {
+               libCreationFlags        |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
+               linkFlags                       |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
+       }
+
+       // Vertex input state library.
+       {
+               VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo       = initVulkanStructure();
+               vertexInputLibInfo.flags                                                                        |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
+
+               VkGraphicsPipelineCreateInfo vertexInputPipelineInfo    = initVulkanStructure(&vertexInputLibInfo);
+               vertexInputPipelineInfo.flags                                                   = libCreationFlags;
+               vertexInputPipelineInfo.pVertexInputState                               = &vertexInputStateInfo;
+               vertexInputPipelineInfo.pInputAssemblyState                             = &inputAssemblyStateInfo;
+
+               // Add all bad shaders (they should be ignored).
+               vertexInputPipelineInfo.stageCount      = de::sizeU32(allBadStages);
+               vertexInputPipelineInfo.pStages         = de::dataOrNull(allBadStages);
+
+               vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputPipelineInfo);
+       }
+
+       // Pre-rasterization shader state library.
+       {
+               VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo   = initVulkanStructure();
+               preRasterShaderLibInfo.flags                                                                    |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
+
+               VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo        = initVulkanStructure(&preRasterShaderLibInfo);
+               preRasterShaderPipelineInfo.flags                                                       = libCreationFlags;
+               preRasterShaderPipelineInfo.layout                                                      = pipelineLayout.get();
+               preRasterShaderPipelineInfo.pViewportState                                      = &viewportStateInfo;
+               preRasterShaderPipelineInfo.pRasterizationState                         = &rasterizationStateInfo;
+               if (m_params.useTessShaders)
+               {
+                       preRasterShaderPipelineInfo.pInputAssemblyState                 = &inputAssemblyStateInfo;
+                       preRasterShaderPipelineInfo.pTessellationState                  = &tessellationStateInfo;
+               }
+               preRasterShaderPipelineInfo.renderPass                                          = renderPass.get();
+
+               // All good pre-rasterization stages.
+               auto preRasterStagesVec = goodPreRasterStages;
+               // The bad fragment shader state cannot be added here due to VUID-VkGraphicsPipelineCreateInfo-pStages-06894.
+               //preRasterStagesVec.push_back(badFragShaderInfo);
+
+               preRasterShaderPipelineInfo.stageCount  = de::sizeU32(preRasterStagesVec);
+               preRasterShaderPipelineInfo.pStages             = de::dataOrNull(preRasterStagesVec);
+
+               preRasterShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRasterShaderPipelineInfo);
+       }
+
+       // Fragment shader stage library.
+       {
+               VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo        = initVulkanStructure();
+               fragShaderLibInfo.flags                                                                         |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
+
+               VkGraphicsPipelineCreateInfo fragShaderPipelineInfo     = initVulkanStructure(&fragShaderLibInfo);
+               fragShaderPipelineInfo.flags                                            = libCreationFlags;
+               fragShaderPipelineInfo.layout                                           = pipelineLayout.get();
+               fragShaderPipelineInfo.pMultisampleState                        = &multisampleStateInfo;
+               fragShaderPipelineInfo.pDepthStencilState                       = &depthStencilStateInfo;
+               fragShaderPipelineInfo.renderPass                                       = renderPass.get();
+
+               // The good fragment shader stage.
+               std::vector<VkPipelineShaderStageCreateInfo> fragShaderStagesVec;
+               // We cannot add the bad pre-rasterization shader stages due to VUID-VkGraphicsPipelineCreateInfo-pStages-06895.
+               //fragShaderStagesVec.insert(fragShaderStagesVec.end(), badPreRasterStages.begin(), badPreRasterStages.end())
+               fragShaderStagesVec.push_back(goodFragShaderInfo);
+
+               fragShaderPipelineInfo.stageCount       = de::sizeU32(fragShaderStagesVec);
+               fragShaderPipelineInfo.pStages          = de::dataOrNull(fragShaderStagesVec);
+
+               fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderPipelineInfo);
+       }
+
+       // Fragment output library.
+       {
+               VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo        = initVulkanStructure();
+               fragOutputLibInfo.flags                                                                         |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
+
+               VkGraphicsPipelineCreateInfo fragOutputPipelineInfo     = initVulkanStructure(&fragOutputLibInfo);
+               fragOutputPipelineInfo.flags                                            = libCreationFlags;
+               fragOutputPipelineInfo.pColorBlendState                         = &colorBlendStateInfo;
+               fragOutputPipelineInfo.renderPass                                       = renderPass.get();
+               fragOutputPipelineInfo.pMultisampleState                        = &multisampleStateInfo;
+
+               // Add all bad shaders (they should be ignored).
+               fragOutputPipelineInfo.stageCount       = de::sizeU32(allBadStages);
+               fragOutputPipelineInfo.pStages          = de::dataOrNull(allBadStages);
+
+               fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputPipelineInfo);
+       }
+
+       // Linked pipeline.
+       const std::vector<VkPipeline> libraryHandles
+       {
+               vertexInputLib.get(),
+               preRasterShaderLib.get(),
+               fragShaderLib.get(),
+               fragOutputLib.get(),
+       };
+
+       VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo        = initVulkanStructure();
+       linkedPipelineLibraryInfo.libraryCount                                          = de::sizeU32(libraryHandles);
+       linkedPipelineLibraryInfo.pLibraries                                            = de::dataOrNull(libraryHandles);
+
+       VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
+       linkedPipelineInfo.flags                                                = linkFlags;
+       linkedPipelineInfo.stageCount                                   = de::sizeU32(allBadStages);
+       linkedPipelineInfo.pStages                                              = de::dataOrNull(allBadStages);
+
+       const auto pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &linkedPipelineInfo);
+
+       // Command pool, command buffer and draw.
+       const auto cmdPool              = makeCommandPool(vkd, device, queueIndex);
+       const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       const auto cmdBuffer    = cmdBufferPtr.get();
+
+       beginCommandBuffer(vkd, cmdBuffer);
+       beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
+       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+       vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
+       endRenderPass(vkd, cmdBuffer);
+
+       // Copy color attachment to verification buffer.
+       const auto preCopyBarrier       = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                                                                                                                VK_ACCESS_TRANSFER_READ_BIT,
+                                                                                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                                                                                                                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                                                                                                                colorAttachment.get(), colorSRR);
+       const auto copyRegion           = makeBufferImageCopy(colorExtent, colorSRL);
+       const auto postCopyBarrier      = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+
+       cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preCopyBarrier);
+       vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
+       cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyBarrier);
+
+       endCommandBuffer(vkd, cmdBuffer);
+
+       submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+       // Verify pixel contents.
+       invalidateAlloc(vkd, device, verificationBufferAlloc);
+       tcu::PixelBufferAccess resultAccess (tcuFormat, colorExtentVec, verificationBufferAlloc.getHostPtr());
+
+       for (int z = 0; z < colorExtentVec.z(); ++z)
+               for (int y = 0; y < colorExtentVec.y(); ++y)
+                       for (int x = 0; x < colorExtentVec.x(); ++x)
+                       {
+                               const auto resultColor = resultAccess.getPixel(x, y, z);
+                               if (resultColor != expectedColor)
+                               {
+                                       const tcu::IVec3 position(x, y, z);
+                                       std::ostringstream msg;
+                                       msg << "Bad color found at pixel " << position << ": expected " << expectedColor << " but found " << resultColor;
+                                       TCU_FAIL(msg.str());
+                               }
+                       }
+
+       return tcu::TestStatus::pass("Pass");
+}
+#endif // CTS_USES_VULKANSC
+
 } // anonymous
 
 
-void createMiscTests (tcu::TestCaseGroup* miscTests, PipelineConstructionType pipelineConstructionType)
+tcu::TestCaseGroup* createMiscTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
 {
+       de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc", ""));
+
        // Location of the Amber script files under the data/vulkan/amber source tree.
-       if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) {
-               addMonolithicAmberTests(miscTests);
-       }
+       if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
+               addMonolithicAmberTests(miscTests.get());
 
-       tcu::TestContext& testCtx = miscTests->getTestContext();
        miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", "Verify implicit access to gl_PrimtiveID works", pipelineConstructionType, false));
        miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation", "Verify implicit access to gl_PrimtiveID works with a tessellation shader", pipelineConstructionType, true));
 
+#ifndef CTS_USES_VULKANSC
+       if (pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
+       {
+               for (int useTessIdx = 0; useTessIdx < 2; ++useTessIdx)
+                       for (int useGeomIdx = 0; useGeomIdx < 2; ++useGeomIdx)
+                       {
+                               const bool useTess = (useTessIdx > 0);
+                               const bool useGeom = (useGeomIdx > 0);
+
+                               std::string testName = "unused_shader_stages";
+
+                               if (useTess)
+                                       testName += "_include_tess";
+
+                               if (useGeom)
+                                       testName += "_include_geom";
+
+                               const UnusedShaderStageParams params { pipelineConstructionType, useTess, useGeom };
+                               miscTests->addChild(new UnusedShaderStagesCase(testCtx, testName, "", params));
+                       }
+       }
+#endif // CTS_USES_VULKANSC
+
+       return miscTests.release();
 }
 
 } // pipeline
index 13f56ca..3602659 100644 (file)
@@ -33,7 +33,7 @@ namespace vkt
 namespace pipeline
 {
 
-void createMiscTests (tcu::TestCaseGroup* miscTests, vk::PipelineConstructionType pipelineConstructionType);
+tcu::TestCaseGroup* createMiscTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType);
 
 } // pipeline
 } // vkt
index 122c229..5a0dbee 100644 (file)
@@ -138,7 +138,7 @@ void createChildren (tcu::TestCaseGroup* group, PipelineConstructionType pipelin
        group->addChild(createShaderModuleIdentifierTests       (testCtx, pipelineConstructionType));
 #endif // CTS_USES_VULKANSC
        group->addChild(createColorWriteEnable2Tests            (testCtx, pipelineConstructionType));
-       group->addChild(createTestGroup                                         (testCtx, "misc", "", createMiscTests, pipelineConstructionType));
+       group->addChild(createMiscTests                                         (testCtx, pipelineConstructionType));
 
        // NOTE: all new pipeline tests should use GraphicsPipelineWrapper for pipeline creation
 
index ca9e5e6..be82604 100644 (file)
@@ -287663,3 +287663,7 @@ dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.atta
 dEQP-VK.pipeline.fast_linked_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.fast_linked_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.fast_linked_library.misc.unused_shader_stages_include_tess_include_geom
index d7817a9..68418e4 100644 (file)
@@ -287663,6 +287663,10 @@ dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachm
 dEQP-VK.pipeline.pipeline_library.color_write_enable_maxa.cwe_after_bind.attachments5_more3
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id
 dEQP-VK.pipeline.pipeline_library.misc.implicit_primitive_id_with_tessellation
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_geom
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess
+dEQP-VK.pipeline.pipeline_library.misc.unused_shader_stages_include_tess_include_geom
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.4
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_1111
 dEQP-VK.pipeline.pipeline_library.graphics_library.fast.0_112