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, ©Region);
+ 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