1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2019 Google LLC 6 * Copyright (c) 2019 The Khronos Group Inc. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Miscellaneous pipeline tests. 25 *//*--------------------------------------------------------------------*/ 26 27#include <string> 28#include <memory> 29#include <vector> 30#include <algorithm> 31#include <array> 32#include <numeric> 33#include <memory> 34 35#include "vkPipelineConstructionUtil.hpp" 36#include "vktTestGroupUtil.hpp" 37#include "vktAmberTestCase.hpp" 38#include "vktPipelineMiscTests.hpp" 39 40#include "vkDefs.hpp" 41#include "tcuImageCompare.hpp" 42#include "vkImageUtil.hpp" 43#include "deStringUtil.hpp" 44#include "vktTestCaseUtil.hpp" 45#include "vkTypeUtil.hpp" 46#include "vkCmdUtil.hpp" 47#include "vkObjUtil.hpp" 48#include "vkImageWithMemory.hpp" 49#include "vkBarrierUtil.hpp" 50#include "vkBufferWithMemory.hpp" 51#include "vkBuilderUtil.hpp" 52#include "vktPipelineReferenceRenderer.hpp" 53#include "vkBuilderUtil.hpp" 54 55namespace vkt 56{ 57namespace pipeline 58{ 59 60using namespace vk; 61 62namespace 63{ 64 65enum AmberFeatureBits 66{ 67 AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS = (1 << 0), 68 AMBER_FEATURE_TESSELATION_SHADER = (1 << 1), 69 AMBER_FEATURE_GEOMETRY_SHADER = (1 << 2), 70}; 71 72using AmberFeatureFlags = deUint32; 73 74#ifndef CTS_USES_VULKANSC 75std::vector<std::string> getFeatureList (AmberFeatureFlags flags) 76{ 77 std::vector<std::string> requirements; 78 79 if (flags & AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) 80 requirements.push_back("Features.vertexPipelineStoresAndAtomics"); 81 82 if (flags & AMBER_FEATURE_TESSELATION_SHADER) 83 requirements.push_back("Features.tessellationShader"); 84 85 if (flags & AMBER_FEATURE_GEOMETRY_SHADER) 86 requirements.push_back("Features.geometryShader"); 87 88 return requirements; 89} 90#endif // CTS_USES_VULKANSC 91 92void addMonolithicAmberTests (tcu::TestCaseGroup* tests) 93{ 94#ifndef CTS_USES_VULKANSC 95 tcu::TestContext& testCtx = tests->getTestContext(); 96 97 // Shader test files are saved in <path>/external/vulkancts/data/vulkan/amber/pipeline/<basename>.amber 98 struct Case { 99 const char* basename; 100 AmberFeatureFlags flags; 101 }; 102 103 const Case cases[] = 104 { 105 { 106 "position_to_ssbo", 107 (AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS), 108 }, 109 { 110 "primitive_id_from_tess", 111 (AMBER_FEATURE_TESSELATION_SHADER | AMBER_FEATURE_GEOMETRY_SHADER), 112 }, 113 }; 114 for (unsigned i = 0; i < DE_LENGTH_OF_ARRAY(cases) ; ++i) 115 { 116 std::string file = std::string(cases[i].basename) + ".amber"; 117 std::vector<std::string> requirements = getFeatureList(cases[i].flags); 118 cts_amber::AmberTestCase *testCase = cts_amber::createAmberTestCase(testCtx, cases[i].basename, "pipeline", file, requirements); 119 120 tests->addChild(testCase); 121 } 122#else 123 DE_UNREF(tests); 124#endif 125} 126 127class ImplicitPrimitiveIDPassthroughCase : public vkt::TestCase 128{ 129public: 130 ImplicitPrimitiveIDPassthroughCase (tcu::TestContext& testCtx, 131 const std::string& name, 132 const PipelineConstructionType pipelineConstructionType, 133 bool withTessellation) 134 : vkt::TestCase(testCtx, name) 135 , m_pipelineConstructionType(pipelineConstructionType) 136 , m_withTessellationPassthrough(withTessellation) 137 { 138 } 139 ~ImplicitPrimitiveIDPassthroughCase (void) {} 140 void initPrograms (SourceCollections& programCollection) const override; 141 void checkSupport (Context& context) const override; 142 TestInstance* createInstance (Context& context) const override; 143 144 const PipelineConstructionType m_pipelineConstructionType; 145private: 146 bool m_withTessellationPassthrough; 147}; 148 149class ImplicitPrimitiveIDPassthroughInstance : public vkt::TestInstance 150{ 151public: 152 ImplicitPrimitiveIDPassthroughInstance (Context& context, 153 const PipelineConstructionType pipelineConstructionType, 154 bool withTessellation) 155 : vkt::TestInstance (context) 156 , m_pipelineConstructionType (pipelineConstructionType) 157 , m_renderSize (2, 2) 158 , m_extent(makeExtent3D (m_renderSize.x(), m_renderSize.y(), 1u)) 159 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType) 160 , m_withTessellationPassthrough (withTessellation) 161 { 162 } 163 ~ImplicitPrimitiveIDPassthroughInstance (void) {} 164 tcu::TestStatus iterate (void) override; 165 166private: 167 PipelineConstructionType m_pipelineConstructionType; 168 const tcu::UVec2 m_renderSize; 169 const VkExtent3D m_extent; 170 const VkFormat m_format = VK_FORMAT_R8G8B8A8_UNORM; 171 GraphicsPipelineWrapper m_graphicsPipeline; 172 bool m_withTessellationPassthrough; 173}; 174 175TestInstance* ImplicitPrimitiveIDPassthroughCase::createInstance (Context& context) const 176{ 177 return new ImplicitPrimitiveIDPassthroughInstance(context, m_pipelineConstructionType, m_withTessellationPassthrough); 178} 179 180void ImplicitPrimitiveIDPassthroughCase::checkSupport (Context &context) const 181{ 182 if (m_withTessellationPassthrough) 183 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER); 184 185 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); 186 187 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType); 188} 189 190void ImplicitPrimitiveIDPassthroughCase::initPrograms(SourceCollections& sources) const 191{ 192 std::ostringstream vert; 193 // Generate a vertically split framebuffer, filled with red on the 194 // left, and a green on the right. 195 vert 196 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 197 << "void main ()\n" 198 << "{\n" 199 << " switch (gl_VertexIndex) {\n" 200 << " case 0:\n" 201 << " gl_Position = vec4(-3.0, -1.0, 0.0, 1.0);\n" 202 << " break;\n" 203 << " case 1:\n" 204 << " gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n" 205 << " break;\n" 206 << " case 2:\n" 207 << " gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 208 << " break;\n" 209 << " case 3:\n" 210 << " gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 211 << " break;\n" 212 << " case 4:\n" 213 << " gl_Position = vec4(3.0, -1.0, 0.0, 1.0);\n" 214 << " break;\n" 215 << " case 5:\n" 216 << " gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n" 217 << " break;\n" 218 << " }\n" 219 << "}\n" 220 ; 221 sources.glslSources.add("vert") << glu::VertexSource(vert.str()); 222 223 if (m_withTessellationPassthrough) { 224 std::ostringstream tsc; 225 tsc 226 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 227 << "layout (vertices = 3) out;\n" 228 << "\n" 229 << "void main ()\n" 230 << "{\n" 231 << " if (gl_InvocationID == 0) {\n" 232 << " gl_TessLevelInner[0] = 1.0;\n" 233 << " gl_TessLevelInner[1] = 1.0;\n" 234 << " gl_TessLevelOuter[0] = 1.0;\n" 235 << " gl_TessLevelOuter[1] = 1.0;\n" 236 << " gl_TessLevelOuter[2] = 1.0;\n" 237 << " gl_TessLevelOuter[3] = 1.0;\n" 238 << " }\n" 239 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 240 << "}\n"; 241 sources.glslSources.add("tsc") << glu::TessellationControlSource(tsc.str()); 242 243 std::ostringstream tse; 244 tse 245 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 246 << "layout (triangles, equal_spacing, cw) in;\n" 247 << "\n" 248 << "void main ()\n" 249 << "{\n" 250 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n" 251 << " gl_in[1].gl_Position * gl_TessCoord.y +\n" 252 << " gl_in[2].gl_Position * gl_TessCoord.z;\n" 253 << "}\n" 254 ; 255 sources.glslSources.add("tse") << glu::TessellationEvaluationSource(tse.str()); 256 } 257 258 std::ostringstream frag; 259 frag 260 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 261 << "layout (location=0) out vec4 outColor;\n" 262 << "\n" 263 << "void main ()\n" 264 << "{\n" 265 << " const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 266 << " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 267 << " outColor = (gl_PrimitiveID % 2 == 0) ? red : green;\n" 268 << "}\n" 269 ; 270 sources.glslSources.add("frag") << glu::FragmentSource(frag.str()); 271} 272 273tcu::TestStatus ImplicitPrimitiveIDPassthroughInstance::iterate () 274{ 275 const auto& vkd = m_context.getDeviceInterface(); 276 const auto device = m_context.getDevice(); 277 auto& alloc = m_context.getDefaultAllocator(); 278 const auto qIndex = m_context.getUniversalQueueFamilyIndex(); 279 const auto queue = m_context.getUniversalQueue(); 280 const auto tcuFormat = mapVkFormat(m_format); 281 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 282 const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; 283 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); 284 285 // Color attachment. 286 const VkImageCreateInfo colorBufferInfo = 287 { 288 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 289 nullptr, // const void* pNext; 290 0u, // VkImageCreateFlags flags; 291 VK_IMAGE_TYPE_2D, // VkImageType imageType; 292 m_format, // VkFormat format; 293 m_extent, // VkExtent3D extent; 294 1u, // uint32_t mipLevels; 295 1u, // uint32_t arrayLayers; 296 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 297 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 298 colorUsage, // VkImageUsageFlags usage; 299 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 300 0u, // uint32_t queueFamilyIndexCount; 301 nullptr, // const uint32_t* pQueueFamilyIndices; 302 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 303 }; 304 ImageWithMemory colorBuffer (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any); 305 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 306 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u); 307 const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR); 308 309 // Verification buffer. 310 const auto verifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height; 311 const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage); 312 BufferWithMemory verifBuffer (vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible); 313 auto& verifBufferAlloc = verifBuffer.getAllocation(); 314 315 // Render pass and framebuffer. 316 RenderPassWrapper renderPass (m_pipelineConstructionType, vkd, device, m_format); 317 renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width, m_extent.height); 318 319 // Shader modules. 320 const auto& binaries = m_context.getBinaryCollection(); 321 const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert")); 322 const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag")); 323 ShaderWrapper tscModule; 324 ShaderWrapper tseModule; 325 326 if (m_withTessellationPassthrough) { 327 tscModule = ShaderWrapper(vkd, device, binaries.get("tsc")); 328 tseModule = ShaderWrapper(vkd, device, binaries.get("tse")); 329 } 330 331 // Viewports and scissors. 332 const std::vector<VkViewport> viewports (1u, makeViewport(m_extent)); 333 const std::vector<VkRect2D> scissors (1u, makeRect2D(m_extent)); 334 335 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure(); 336 const VkPipelineRasterizationStateCreateInfo rasterizationState = 337 { 338 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 339 DE_NULL, // const void* pNext; 340 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 341 VK_FALSE, // VkBool32 depthClampEnable; 342 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 343 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 344 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 345 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace; 346 VK_FALSE, // VkBool32 depthBiasEnable; 347 0.0f, // float depthBiasConstantFactor; 348 0.0f, // float depthBiasClamp; 349 0.0f, // float depthBiasSlopeFactor; 350 1.0f, // float lineWidth; 351 }; 352 353 // Pipeline layout and graphics pipeline. 354 const PipelineLayoutWrapper pipelineLayout (m_pipelineConstructionType, vkd, device); 355 356 const auto topology = m_withTessellationPassthrough ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 357 m_graphicsPipeline.setDefaultRasterizationState() 358 .setDefaultTopology(topology) 359 .setupVertexInputState(&vertexInputState) 360 .setDefaultDepthStencilState() 361 .setDefaultMultisampleState() 362 .setDefaultColorBlendState() 363 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, &rasterizationState, tscModule, tseModule) 364 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule) 365 .setupFragmentOutputState(*renderPass) 366 .setMonolithicPipelineLayout(pipelineLayout) 367 .buildPipeline(); 368 369 // Command pool and buffer. 370 const auto cmdPool = makeCommandPool(vkd, device, qIndex); 371 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); 372 const auto cmdBuffer = cmdBufferPtr.get(); 373 374 beginCommandBuffer(vkd, cmdBuffer); 375 376 // Draw. 377 renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor); 378 m_graphicsPipeline.bind(cmdBuffer); 379 vkd.cmdDraw(cmdBuffer, 6, 1u, 0u, 0u); 380 renderPass.end(vkd, cmdBuffer); 381 382 // Copy to verification buffer. 383 const auto copyRegion = makeBufferImageCopy(m_extent, colorSRL); 384 const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); 385 const auto color2Transfer = makeImageMemoryBarrier( 386 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 387 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 388 colorBuffer.get(), colorSRR); 389 390 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer); 391 vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, ©Region); 392 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host); 393 394 endCommandBuffer(vkd, cmdBuffer); 395 396 // Submit and validate result. 397 submitCommandsAndWait(vkd, device, queue, cmdBuffer); 398 399 auto& log = m_context.getTestContext().getLog(); 400 const tcu::IVec3 iExtent (static_cast<int>(m_extent.width), static_cast<int>(m_extent.height), static_cast<int>(m_extent.depth)); 401 void* verifBufferData = verifBufferAlloc.getHostPtr(); 402 const tcu::ConstPixelBufferAccess verifAccess (tcuFormat, iExtent, verifBufferData); 403 invalidateAlloc(vkd, device, verifBufferAlloc); 404 405 const auto red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 406 const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 407 408 for (int x = 0; x < iExtent.x(); ++x) 409 for (int y = 0; y < iExtent.y(); ++y) { 410 const auto resultColor = verifAccess.getPixel(x, y); 411 const auto expectedColor = (x < iExtent.x() / 2) ? red : green; 412 if (resultColor != expectedColor) { 413 log << tcu::TestLog::ImageSet("Result image", "Expect left side of framebuffer red, and right side green") 414 << tcu::TestLog::Image("Result", "Verification buffer", verifAccess) 415 << tcu::TestLog::EndImageSet; 416 TCU_FAIL("Expected a vertically split framebuffer, filled with red on the left and green the right; see the log for the unexpected result"); 417 } 418 } 419 420 return tcu::TestStatus::pass("Pass"); 421} 422 423#ifndef CTS_USES_VULKANSC 424struct UnusedShaderStageParams 425{ 426 PipelineConstructionType pipelineConstructionType; 427 bool useTessShaders; 428 bool useGeomShader; 429}; 430 431class UnusedShaderStagesCase : public vkt::TestCase 432{ 433public: 434 UnusedShaderStagesCase (tcu::TestContext& testCtx, const std::string& name, const UnusedShaderStageParams& params) 435 : vkt::TestCase (testCtx, name) 436 , m_params (params) 437 {} 438 virtual ~UnusedShaderStagesCase (void) {} 439 440 void initPrograms (vk::SourceCollections& programCollection) const override; 441 TestInstance* createInstance (Context& context) const override; 442 void checkSupport (Context& context) const override; 443 444protected: 445 UnusedShaderStageParams m_params; 446}; 447 448class UnusedShaderStagesInstance : public vkt::TestInstance 449{ 450public: 451 UnusedShaderStagesInstance (Context& context, const UnusedShaderStageParams& params) 452 : vkt::TestInstance (context) 453 , m_params (params) 454 {} 455 virtual ~UnusedShaderStagesInstance (void) {} 456 tcu::TestStatus iterate (void) override; 457 458protected: 459 UnusedShaderStageParams m_params; 460}; 461 462void UnusedShaderStagesCase::initPrograms (vk::SourceCollections &programCollection) const 463{ 464 // Shaders that produce bad results. 465 { 466 std::ostringstream vert; 467 vert 468 << "#version 460\n" 469 << "out gl_PerVertex {\n" 470 << " vec4 gl_Position;\n" 471 << "};\n" 472 << "void main (void) {\n" 473 << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 474 << "}\n" 475 ; 476 programCollection.glslSources.add("bad_vert") << glu::VertexSource(vert.str()); 477 478 std::ostringstream tesc; 479 tesc 480 << "#version 460\n" 481 << "layout (vertices=3) out;\n" 482 << "in gl_PerVertex {\n" 483 << " vec4 gl_Position;\n" 484 << "} gl_in[gl_MaxPatchVertices];\n" 485 << "out gl_PerVertex {\n" 486 << " vec4 gl_Position;\n" 487 << "} gl_out[];\n" 488 << "void main (void) {\n" 489 << " gl_TessLevelInner[0] = 1.0;\n" 490 << " gl_TessLevelInner[1] = 1.0;\n" 491 << " gl_TessLevelOuter[0] = 1.0;\n" 492 << " gl_TessLevelOuter[1] = 1.0;\n" 493 << " gl_TessLevelOuter[2] = 1.0;\n" 494 << " gl_TessLevelOuter[3] = 1.0;\n" 495 << " gl_out[gl_InvocationID].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 496 << "}\n" 497 ; 498 programCollection.glslSources.add("bad_tesc") << glu::TessellationControlSource(tesc.str()); 499 500 std::ostringstream tese; 501 tese 502 << "#version 460\n" 503 << "layout (triangles, fractional_odd_spacing, cw) in;\n" 504 << "in gl_PerVertex {\n" 505 << " vec4 gl_Position;\n" 506 << "} gl_in[gl_MaxPatchVertices];\n" 507 << "out gl_PerVertex {\n" 508 << " vec4 gl_Position;\n" 509 << "};\n" 510 << "void main() {\n" 511 << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 512 << "}\n" 513 ; 514 programCollection.glslSources.add("bad_tese") << glu::TessellationEvaluationSource(tese.str()); 515 516 std::ostringstream geom; 517 geom 518 << "#version 460\n" 519 << "layout (triangles) in;\n" 520 << "layout (triangle_strip, max_vertices=3) out;\n" 521 << "in gl_PerVertex {\n" 522 << " vec4 gl_Position;\n" 523 << "} gl_in[3];\n" 524 << "out gl_PerVertex {\n" 525 << " vec4 gl_Position;\n" 526 << "};\n" 527 << "void main() {\n" 528 // Avoid emitting any vertices. 529 << "}\n" 530 ; 531 programCollection.glslSources.add("bad_geom") << glu::GeometrySource(geom.str()); 532 533 std::ostringstream frag; 534 frag 535 << "#version 460\n" 536 << "layout (location=0) out vec4 outColor;\n" 537 << "void main (void) {\n" 538 << " outColor = vec4(0.0, 0.0, 0.0, 1.0);\n" 539 << "}\n" 540 ; 541 programCollection.glslSources.add("bad_frag") << glu::FragmentSource(frag.str()); 542 } 543 544 // Shaders that produce the expected results. 545 { 546 std::ostringstream vert; 547 vert 548 << "#version 460\n" 549 << "out gl_PerVertex {\n" 550 << " vec4 gl_Position;\n" 551 << "};\n" 552 << "vec2 positions[3] = vec2[](\n" 553 << " vec2(-1.0, -1.0),\n" 554 << " vec2(-1.0, 3.0),\n" 555 << " vec2( 3.0, -1.0)\n" 556 << ");\n" 557 << "void main (void) {\n" 558 << " gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n" 559 << "}\n" 560 ; 561 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str()); 562 563 std::ostringstream tesc; 564 tesc 565 << "#version 460\n" 566 << "layout (vertices=3) out;\n" 567 << "in gl_PerVertex {\n" 568 << " vec4 gl_Position;\n" 569 << "} gl_in[gl_MaxPatchVertices];\n" 570 << "out gl_PerVertex {\n" 571 << " vec4 gl_Position;\n" 572 << "} gl_out[];\n" 573 << "void main (void) {\n" 574 << " gl_TessLevelInner[0] = 1.0;\n" 575 << " gl_TessLevelInner[1] = 1.0;\n" 576 << " gl_TessLevelOuter[0] = 1.0;\n" 577 << " gl_TessLevelOuter[1] = 1.0;\n" 578 << " gl_TessLevelOuter[2] = 1.0;\n" 579 << " gl_TessLevelOuter[3] = 1.0;\n" 580 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 581 << "}\n" 582 ; 583 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str()); 584 585 std::ostringstream tese; 586 tese 587 << "#version 460\n" 588 << "layout (triangles, fractional_odd_spacing, cw) in;\n" 589 << "in gl_PerVertex {\n" 590 << " vec4 gl_Position;\n" 591 << "} gl_in[gl_MaxPatchVertices];\n" 592 << "out gl_PerVertex {\n" 593 << " vec4 gl_Position;\n" 594 << "};\n" 595 << "void main() {\n" 596 << " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n" 597 << " (gl_TessCoord.y * gl_in[1].gl_Position) +\n" 598 << " (gl_TessCoord.z * gl_in[2].gl_Position);\n" 599 << "}\n" 600 ; 601 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str()); 602 603 std::ostringstream geom; 604 geom 605 << "#version 460\n" 606 << "layout (triangles) in;\n" 607 << "layout (triangle_strip, max_vertices=3) out;\n" 608 << "in gl_PerVertex {\n" 609 << " vec4 gl_Position;\n" 610 << "} gl_in[3];\n" 611 << "out gl_PerVertex {\n" 612 << " vec4 gl_Position;\n" 613 << "};\n" 614 << "void main() {\n" 615 << " gl_Position = gl_in[0].gl_Position; EmitVertex();\n" 616 << " gl_Position = gl_in[1].gl_Position; EmitVertex();\n" 617 << " gl_Position = gl_in[2].gl_Position; EmitVertex();\n" 618 << "}\n" 619 ; 620 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str()); 621 622 std::ostringstream frag; 623 frag 624 << "#version 460\n" 625 << "layout (location=0) out vec4 outColor;\n" 626 << "void main (void) {\n" 627 << " outColor = vec4(0.0, 1.0, 0.0, 1.0);\n" // Blue instead of black. 628 << "}\n" 629 ; 630 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str()); 631 } 632} 633 634TestInstance* UnusedShaderStagesCase::createInstance (Context &context) const 635{ 636 return new UnusedShaderStagesInstance(context, m_params); 637} 638 639void UnusedShaderStagesCase::checkSupport (Context &context) const 640{ 641 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 642 643 if (m_params.useTessShaders) 644 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER); 645 646 if (m_params.useGeomShader) 647 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); 648} 649 650tcu::TestStatus UnusedShaderStagesInstance::iterate () 651{ 652 const auto& vkd = m_context.getDeviceInterface(); 653 const auto device = m_context.getDevice(); 654 auto& alloc = m_context.getDefaultAllocator(); 655 const auto queue = m_context.getUniversalQueue(); 656 const auto queueIndex = m_context.getUniversalQueueFamilyIndex(); 657 658 const bool isOptimized = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY); 659 const auto colorExtent = makeExtent3D(1u, 1u, 1u); 660 const tcu::IVec3 colorExtentVec (static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth)); 661 const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 662 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 663 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 664 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u); 665 const auto tcuFormat = mapVkFormat(colorFormat); 666 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f); 667 const tcu::Vec4 expectedColor (0.0f, 1.0f, 0.0f, 1.0f); // Must match the good frag shader. 668 669 // Good and bad shader modules. 670 const auto& binaries = m_context.getBinaryCollection(); 671 672 const auto goodVertModule = createShaderModule(vkd, device, binaries.get("vert")); 673 const auto goodTescModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("tesc")) : Move<VkShaderModule>()); 674 const auto goodTeseModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("tese")) : Move<VkShaderModule>()); 675 const auto goodGeomModule = (m_params.useGeomShader ? createShaderModule(vkd, device, binaries.get("geom")) : Move<VkShaderModule>()); 676 const auto goodFragModule = createShaderModule(vkd, device, binaries.get("frag")); 677 678 const auto goodVertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, goodVertModule.get()); 679 const auto goodTescShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, goodTescModule.get()); 680 const auto goodTeseShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, goodTeseModule.get()); 681 const auto goodGeomShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, goodGeomModule.get()); 682 const auto goodFragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, goodFragModule.get()); 683 684 const auto badVertModule = createShaderModule(vkd, device, binaries.get("bad_vert")); 685 const auto badTescModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("bad_tesc")) : Move<VkShaderModule>()); 686 const auto badTeseModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("bad_tese")) : Move<VkShaderModule>()); 687 const auto badGeomModule = (m_params.useGeomShader ? createShaderModule(vkd, device, binaries.get("bad_geom")) : Move<VkShaderModule>()); 688 const auto badFragModule = createShaderModule(vkd, device, binaries.get("bad_frag")); 689 690 const auto badVertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, badVertModule.get()); 691 const auto badTescShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, badTescModule.get()); 692 const auto badTeseShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, badTeseModule.get()); 693 const auto badGeomShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, badGeomModule.get()); 694 const auto badFragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, badFragModule.get()); 695 696 // Color attachment. 697 const VkImageCreateInfo colorAttachmentCreateInfo = 698 { 699 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 700 nullptr, // const void* pNext; 701 0u, // VkImageCreateFlags flags; 702 VK_IMAGE_TYPE_2D, // VkImageType imageType; 703 colorFormat, // VkFormat format; 704 colorExtent, // VkExtent3D extent; 705 1u, // uint32_t mipLevels; 706 1u, // uint32_t arrayLayers; 707 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 708 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 709 colorUsage, // VkImageUsageFlags usage; 710 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 711 0u, // uint32_t queueFamilyIndexCount; 712 nullptr, // const uint32_t* pQueueFamilyIndices; 713 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 714 }; 715 ImageWithMemory colorAttachment (vkd, device, alloc, colorAttachmentCreateInfo, MemoryRequirement::Any); 716 717 // Color attachment view. 718 const auto colorAttachmentView = makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR); 719 720 // Verification buffer. 721 const auto verificationBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * colorExtent.width * colorExtent.height * colorExtent.depth; 722 const auto verificationBufferCreateInfo = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 723 BufferWithMemory verificationBuffer (vkd, device, alloc, verificationBufferCreateInfo, MemoryRequirement::HostVisible); 724 auto& verificationBufferAlloc = verificationBuffer.getAllocation(); 725 726 // Render pass and framebuffer. 727 RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, colorFormat); 728 renderPass.createFramebuffer(vkd, device, *colorAttachment, colorAttachmentView.get(), colorExtent.width, colorExtent.height); 729 730 // Pipeline layout. 731 const auto pipelineLayout = makePipelineLayout(vkd, device); 732 733 // Pipeline state. 734 735 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure(); 736 737 const auto primitiveTopology = (m_params.useTessShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); 738 739 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = 740 { 741 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 742 nullptr, // const void* pNext; 743 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 744 primitiveTopology, // VkPrimitiveTopology topology; 745 VK_FALSE, // VkBool32 primitiveRestartEnable; 746 }; 747 748 const VkPipelineTessellationStateCreateInfo tessellationStateInfo = 749 { 750 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 751 nullptr, // const void* pNext; 752 0u, // VkPipelineTessellationStateCreateFlags flags; 753 3u, // uint32_t patchControlPoints; 754 }; 755 756 const std::vector<VkViewport> viewports (1u, makeViewport(colorExtent)); 757 const std::vector<VkRect2D> scissors (1u, makeRect2D(colorExtent)); 758 759 const VkPipelineViewportStateCreateInfo viewportStateInfo = 760 { 761 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 762 nullptr, // const void* pNext; 763 0u, // VkPipelineViewportStateCreateFlags flags; 764 de::sizeU32(viewports), // uint32_t viewportCount; 765 de::dataOrNull(viewports), // const VkViewport* pViewports; 766 de::sizeU32(scissors), // uint32_t scissorCount; 767 de::dataOrNull(scissors), // const VkRect2D* pScissors; 768 }; 769 770 const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = 771 { 772 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 773 nullptr, // const void* pNext; 774 0u, // VkPipelineRasterizationStateCreateFlags flags; 775 VK_FALSE, // VkBool32 depthClampEnable; 776 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 777 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 778 VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode; 779 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 780 VK_FALSE, // VkBool32 depthBiasEnable; 781 0.0f, // float depthBiasConstantFactor; 782 0.0f, // float depthBiasClamp; 783 0.0f, // float depthBiasSlopeFactor; 784 1.0f, // float lineWidth; 785 }; 786 787 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 788 { 789 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 790 nullptr, // const void* pNext; 791 0u, // VkPipelineMultisampleStateCreateFlags flags; 792 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 793 VK_FALSE, // VkBool32 sampleShadingEnable; 794 1.0f, // float minSampleShading; 795 nullptr, // const VkSampleMask* pSampleMask; 796 VK_FALSE, // VkBool32 alphaToCoverageEnable; 797 VK_FALSE, // VkBool32 alphaToOneEnable; 798 }; 799 800 const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure(); 801 802 const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT); 803 804 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 805 { 806 VK_FALSE, // VkBool32 blendEnable; 807 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor; 808 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 809 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 810 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor; 811 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 812 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 813 colorComponentFlags, // VkColorComponentFlags colorWriteMask; 814 }; 815 816 const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = 817 { 818 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 819 nullptr, // const void* pNext; 820 0u, // VkPipelineColorBlendStateCreateFlags flags; 821 VK_FALSE, // VkBool32 logicOpEnable; 822 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp; 823 1u, // uint32_t attachmentCount; 824 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 825 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 826 }; 827 828 // Make a few vectors with the wrong shader modules. 829 std::vector<VkPipelineShaderStageCreateInfo> badPreRasterStages; 830 badPreRasterStages.push_back(badVertShaderInfo); 831 if (m_params.useTessShaders) 832 { 833 badPreRasterStages.push_back(badTescShaderInfo); 834 badPreRasterStages.push_back(badTeseShaderInfo); 835 } 836 if (m_params.useGeomShader) 837 badPreRasterStages.push_back(badGeomShaderInfo); 838 839 std::vector<VkPipelineShaderStageCreateInfo> allBadStages (badPreRasterStages); 840 allBadStages.push_back(badFragShaderInfo); 841 842 // Make a few vectors with the right shader modules. 843 std::vector<VkPipelineShaderStageCreateInfo> goodPreRasterStages; 844 goodPreRasterStages.push_back(goodVertShaderInfo); 845 if (m_params.useTessShaders) 846 { 847 goodPreRasterStages.push_back(goodTescShaderInfo); 848 goodPreRasterStages.push_back(goodTeseShaderInfo); 849 } 850 if (m_params.useGeomShader) 851 goodPreRasterStages.push_back(goodGeomShaderInfo); 852 853 std::vector<VkPipelineShaderStageCreateInfo> allGoodStages (goodPreRasterStages); 854 allGoodStages.push_back(goodFragShaderInfo); 855 856 // Build the different pipeline pieces. 857 Move<VkPipeline> vertexInputLib; 858 Move<VkPipeline> preRasterShaderLib; 859 Move<VkPipeline> fragShaderLib; 860 Move<VkPipeline> fragOutputLib; 861 862 VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; 863 VkPipelineCreateFlags linkFlags = 0u; 864 865 if (isOptimized) 866 { 867 libCreationFlags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; 868 linkFlags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT; 869 } 870 871 // Vertex input state library. 872 { 873 VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructure(); 874 vertexInputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; 875 876 VkGraphicsPipelineCreateInfo vertexInputPipelineInfo = initVulkanStructure(&vertexInputLibInfo); 877 vertexInputPipelineInfo.flags = libCreationFlags; 878 vertexInputPipelineInfo.pVertexInputState = &vertexInputStateInfo; 879 vertexInputPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo; 880 881 // Add all bad shaders (they should be ignored). 882 vertexInputPipelineInfo.stageCount = de::sizeU32(allBadStages); 883 vertexInputPipelineInfo.pStages = de::dataOrNull(allBadStages); 884 885 vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputPipelineInfo); 886 } 887 888 // Pre-rasterization shader state library. 889 { 890 VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo = initVulkanStructure(); 891 preRasterShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT; 892 893 VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo = initVulkanStructure(&preRasterShaderLibInfo); 894 preRasterShaderPipelineInfo.flags = libCreationFlags; 895 preRasterShaderPipelineInfo.layout = pipelineLayout.get(); 896 preRasterShaderPipelineInfo.pViewportState = &viewportStateInfo; 897 preRasterShaderPipelineInfo.pRasterizationState = &rasterizationStateInfo; 898 if (m_params.useTessShaders) 899 { 900 preRasterShaderPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo; 901 preRasterShaderPipelineInfo.pTessellationState = &tessellationStateInfo; 902 } 903 preRasterShaderPipelineInfo.renderPass = renderPass.get(); 904 905 // All good pre-rasterization stages. 906 auto preRasterStagesVec = goodPreRasterStages; 907 // The bad fragment shader state cannot be added here due to VUID-VkGraphicsPipelineCreateInfo-pStages-06894. 908 //preRasterStagesVec.push_back(badFragShaderInfo); 909 910 preRasterShaderPipelineInfo.stageCount = de::sizeU32(preRasterStagesVec); 911 preRasterShaderPipelineInfo.pStages = de::dataOrNull(preRasterStagesVec); 912 913 preRasterShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRasterShaderPipelineInfo); 914 } 915 916 // Fragment shader stage library. 917 { 918 VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructure(); 919 fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; 920 921 VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo); 922 fragShaderPipelineInfo.flags = libCreationFlags; 923 fragShaderPipelineInfo.layout = pipelineLayout.get(); 924 fragShaderPipelineInfo.pMultisampleState = &multisampleStateInfo; 925 fragShaderPipelineInfo.pDepthStencilState = &depthStencilStateInfo; 926 fragShaderPipelineInfo.renderPass = renderPass.get(); 927 928 // The good fragment shader stage. 929 std::vector<VkPipelineShaderStageCreateInfo> fragShaderStagesVec; 930 // We cannot add the bad pre-rasterization shader stages due to VUID-VkGraphicsPipelineCreateInfo-pStages-06895. 931 //fragShaderStagesVec.insert(fragShaderStagesVec.end(), badPreRasterStages.begin(), badPreRasterStages.end()) 932 fragShaderStagesVec.push_back(goodFragShaderInfo); 933 934 fragShaderPipelineInfo.stageCount = de::sizeU32(fragShaderStagesVec); 935 fragShaderPipelineInfo.pStages = de::dataOrNull(fragShaderStagesVec); 936 937 fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderPipelineInfo); 938 } 939 940 // Fragment output library. 941 { 942 VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo = initVulkanStructure(); 943 fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; 944 945 VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo); 946 fragOutputPipelineInfo.flags = libCreationFlags; 947 fragOutputPipelineInfo.pColorBlendState = &colorBlendStateInfo; 948 fragOutputPipelineInfo.renderPass = renderPass.get(); 949 fragOutputPipelineInfo.pMultisampleState = &multisampleStateInfo; 950 951 // Add all bad shaders (they should be ignored). 952 fragOutputPipelineInfo.stageCount = de::sizeU32(allBadStages); 953 fragOutputPipelineInfo.pStages = de::dataOrNull(allBadStages); 954 955 fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputPipelineInfo); 956 } 957 958 // Linked pipeline. 959 const std::vector<VkPipeline> libraryHandles 960 { 961 vertexInputLib.get(), 962 preRasterShaderLib.get(), 963 fragShaderLib.get(), 964 fragOutputLib.get(), 965 }; 966 967 VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure(); 968 linkedPipelineLibraryInfo.libraryCount = de::sizeU32(libraryHandles); 969 linkedPipelineLibraryInfo.pLibraries = de::dataOrNull(libraryHandles); 970 971 VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo); 972 linkedPipelineInfo.flags = linkFlags; 973 linkedPipelineInfo.layout = pipelineLayout.get(); 974 linkedPipelineInfo.stageCount = de::sizeU32(allBadStages); 975 linkedPipelineInfo.pStages = de::dataOrNull(allBadStages); 976 977 const auto pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &linkedPipelineInfo); 978 979 // Command pool, command buffer and draw. 980 const auto cmdPool = makeCommandPool(vkd, device, queueIndex); 981 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); 982 const auto cmdBuffer = cmdBufferPtr.get(); 983 984 beginCommandBuffer(vkd, cmdBuffer); 985 renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor); 986 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get()); 987 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); 988 renderPass.end(vkd, cmdBuffer); 989 990 // Copy color attachment to verification buffer. 991 const auto preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 992 VK_ACCESS_TRANSFER_READ_BIT, 993 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 994 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 995 colorAttachment.get(), colorSRR); 996 const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL); 997 const auto postCopyBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); 998 999 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preCopyBarrier); 1000 vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, ©Region); 1001 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyBarrier); 1002 1003 endCommandBuffer(vkd, cmdBuffer); 1004 1005 submitCommandsAndWait(vkd, device, queue, cmdBuffer); 1006 1007 // Verify pixel contents. 1008 invalidateAlloc(vkd, device, verificationBufferAlloc); 1009 tcu::PixelBufferAccess resultAccess (tcuFormat, colorExtentVec, verificationBufferAlloc.getHostPtr()); 1010 1011 for (int z = 0; z < colorExtentVec.z(); ++z) 1012 for (int y = 0; y < colorExtentVec.y(); ++y) 1013 for (int x = 0; x < colorExtentVec.x(); ++x) 1014 { 1015 const auto resultColor = resultAccess.getPixel(x, y, z); 1016 if (resultColor != expectedColor) 1017 { 1018 const tcu::IVec3 position(x, y, z); 1019 std::ostringstream msg; 1020 msg << "Bad color found at pixel " << position << ": expected " << expectedColor << " but found " << resultColor; 1021 TCU_FAIL(msg.str()); 1022 } 1023 } 1024 1025 return tcu::TestStatus::pass("Pass"); 1026} 1027#endif // CTS_USES_VULKANSC 1028 1029#ifndef CTS_USES_VULKANSC 1030class PipelineLibraryInterpolateAtSampleTestCase : public vkt::TestCase 1031{ 1032public: 1033 PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name); 1034 void initPrograms (vk::SourceCollections& programCollection) const override; 1035 TestInstance* createInstance (Context& context) const override; 1036 void checkSupport (Context& context) const override; 1037 //there are 4 sample points, which may have a shader invocation each, each of them writes 5 values 1038 //and we render a 2x2 grid. 1039 static constexpr uint32_t width = 2; 1040 static constexpr uint32_t height = 2; 1041 static constexpr VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT; 1042 static constexpr uint32_t ResultCount = (sampleCount + 1) * sampleCount * width * height; 1043}; 1044 1045class PipelineLibraryInterpolateAtSampleTestInstance : public vkt::TestInstance 1046{ 1047public: 1048 PipelineLibraryInterpolateAtSampleTestInstance(Context& context); 1049 void runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type); 1050 virtual tcu::TestStatus iterate(void); 1051}; 1052 1053PipelineLibraryInterpolateAtSampleTestCase::PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name): 1054 vkt::TestCase(context, name) { } 1055 1056void PipelineLibraryInterpolateAtSampleTestCase::checkSupport(Context& context) const 1057{ 1058 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"); 1059 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS); 1060 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY); 1061} 1062 1063void PipelineLibraryInterpolateAtSampleTestCase::initPrograms(vk::SourceCollections& collection) const 1064{ 1065 { 1066 std::ostringstream src; 1067 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1068 << "vec2 positions[6] = vec2[](\n" 1069 << " vec2(1.0, 1.0)," 1070 << " vec2(-1.0, 1.0)," 1071 << " vec2(-1.0, -1.0)," 1072 << " vec2(-1.0, -1.0)," 1073 << " vec2(1.0, -1.0)," 1074 << " vec2(1.0, 1.0)" 1075 << ");\n" 1076 << "float values[6] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};\n" 1077 << "layout (location=0) out float verify;" 1078 << "void main() {\n" 1079 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n" 1080 << " verify = values[gl_VertexIndex];\n" 1081 << "}"; 1082 collection.glslSources.add("vert") << glu::VertexSource(src.str()); 1083 } 1084 1085 { 1086 std::ostringstream src; 1087 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1088 << "layout(location = 0) out vec4 outColor;\n" 1089 << "layout (location=0) in float verify;" 1090 << "layout(std430, binding = 0) buffer Index {" 1091 << " uint writeIndex;" 1092 << "} index;\n" 1093 << "layout(std430, binding = 1) buffer Values {" 1094 << " float num[" << PipelineLibraryInterpolateAtSampleTestCase::ResultCount << "];" 1095 << "} values;\n" 1096 << "void main() {\n" 1097 << " uint index = atomicAdd(index.writeIndex, 5);" 1098 << " float iSample1 = interpolateAtSample(verify, 0);\n" 1099 << " float iSample2 = interpolateAtSample(verify, 1);\n" 1100 << " float iSample3 = interpolateAtSample(verify, 2);\n" 1101 << " float iSample4 = interpolateAtSample(verify, 3);\n" 1102 << " values.num[index] = verify;" 1103 << " values.num[index + 1] = iSample1;" 1104 << " values.num[index + 2] = iSample2;" 1105 << " values.num[index + 3] = iSample3;" 1106 << " values.num[index + 4] = iSample4;" 1107 << " outColor = vec4(1.0, 1.0, 0.0, 1.0);\n" 1108 << "}"; 1109 collection.glslSources.add("frag") << glu::FragmentSource(src.str()); 1110 } 1111} 1112 1113TestInstance* PipelineLibraryInterpolateAtSampleTestCase::createInstance(Context& context) const 1114{ 1115 return new PipelineLibraryInterpolateAtSampleTestInstance(context); 1116} 1117 1118PipelineLibraryInterpolateAtSampleTestInstance::PipelineLibraryInterpolateAtSampleTestInstance(Context& context) : vkt::TestInstance(context) { } 1119 1120void PipelineLibraryInterpolateAtSampleTestInstance::runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type) 1121{ 1122 const auto& vki = m_context.getInstanceInterface(); 1123 const auto& vkd = m_context.getDeviceInterface(); 1124 const auto physDevice = m_context.getPhysicalDevice(); 1125 const auto device = m_context.getDevice(); 1126 auto& alloc = m_context.getDefaultAllocator(); 1127 auto imageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; 1128 auto imageExtent = vk::makeExtent3D(2, 2, 1u); 1129 1130 const std::vector<vk::VkViewport> viewports { makeViewport(imageExtent) }; 1131 const std::vector<vk::VkRect2D> scissors { makeRect2D(imageExtent) }; 1132 1133 de::MovePtr<vk::ImageWithMemory> colorAttachment; 1134 1135 vk::GraphicsPipelineWrapper pipeline1(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), type); 1136 const auto qIndex = m_context.getUniversalQueueFamilyIndex(); 1137 1138 const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 1139 const auto imageUsage = static_cast<vk::VkImageUsageFlags>(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 1140 const vk::VkImageCreateInfo imageCreateInfo = 1141 { 1142 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1143 nullptr, // const void* pNext; 1144 0u, // VkImageCreateFlags flags; 1145 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1146 imageFormat, // VkFormat format; 1147 imageExtent, // VkExtent3D extent; 1148 1u, // deUint32 mipLevels; 1149 1u, // deUint32 arrayLayers; 1150 vk::VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples; 1151 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1152 imageUsage, // VkImageUsageFlags usage; 1153 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1154 1u, // deUint32 queueFamilyIndexCount; 1155 &qIndex, // const deUint32* pQueueFamilyIndices; 1156 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1157 }; 1158 1159 colorAttachment = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any)); 1160 auto colorAttachmentView = vk::makeImageView(vkd, device, colorAttachment->get(), vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange); 1161 1162 vk::DescriptorSetLayoutBuilder layoutBuilder; 1163 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT); 1164 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT); 1165 1166 auto descriptorSetLayout = layoutBuilder.build(vkd, device); 1167 vk::PipelineLayoutWrapper graphicsPipelineLayout (type, vkd, device, descriptorSetLayout.get()); 1168 1169 DescriptorPoolBuilder poolBuilder; 1170 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1171 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1172 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 1173 const auto descriptorSetBuffer = makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); 1174 1175 // Update descriptor sets. 1176 DescriptorSetUpdateBuilder updater; 1177 1178 const auto indexBufferInfo = makeDescriptorBufferInfo(index.get(), 0ull, sizeof(uint32_t)); 1179 const auto valueBufferInfo = makeDescriptorBufferInfo(values.get(), 0ull, bufferSize); 1180 updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indexBufferInfo); 1181 updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &valueBufferInfo); 1182 1183 updater.update(vkd, device); 1184 1185 auto vtxshader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert")); 1186 auto frgshader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag")); 1187 1188 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = 1189 { 1190 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType 1191 nullptr, // const void* pNext 1192 0u, // VkPipelineVertexInputStateCreateFlags flags 1193 0u, // deUint32 vertexBindingDescriptionCount 1194 nullptr, // const VkVertexInputBindingDescription* pVertexBindingDescriptions 1195 0u, // deUint32 vertexAttributeDescriptionCount 1196 nullptr, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions 1197 }; 1198 1199 VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure(); 1200 multisampling.sampleShadingEnable = VK_FALSE; 1201 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; 1202 multisampling.minSampleShading = 1.0f; // Optional 1203 multisampling.pSampleMask = NULL; // Optional 1204 multisampling.alphaToCoverageEnable = VK_FALSE; // Optional 1205 multisampling.alphaToOneEnable = VK_FALSE; // Optional 1206 1207 pipeline1.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) 1208 .setDefaultRasterizationState() 1209 .setDefaultDepthStencilState() 1210 .setDefaultColorBlendState() 1211 .setupVertexInputState(&vertexInputState) 1212 .setupPreRasterizationShaderState( 1213 viewports, 1214 scissors, 1215 graphicsPipelineLayout, 1216 DE_NULL, 1217 0u, 1218 vtxshader) 1219 .setupFragmentShaderState(graphicsPipelineLayout, DE_NULL, 0u, 1220 frgshader) 1221 .setupFragmentOutputState(DE_NULL, 0u, DE_NULL, &multisampling) 1222 .setMonolithicPipelineLayout(graphicsPipelineLayout).buildPipeline(); 1223 1224 auto commandPool = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex); 1225 auto commandBuffer = vk::allocateCommandBuffer(vkd, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1226 1227 const auto clearValueColor = vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 1228 1229 const vk::VkRect2D renderArea = 1230 { 1231 { 0u, 0u }, 1232 { imageExtent.width, imageExtent.height } 1233 }; 1234 1235 const vk::VkRenderingAttachmentInfoKHR colorAttachments = { 1236 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType; 1237 DE_NULL, // const void* pNext; 1238 colorAttachmentView.get(), // VkImageView imageView; 1239 vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout imageLayout; 1240 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode; 1241 DE_NULL, // VkImageView resolveImageView; 1242 vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout resolveImageLayout; 1243 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 1244 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1245 clearValueColor // VkClearValue clearValue; 1246 }; 1247 const VkRenderingInfoKHR render_info = { 1248 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, 1249 0, 1250 0, 1251 renderArea, 1252 1, 1253 0, 1254 1, 1255 &colorAttachments, 1256 DE_NULL, 1257 DE_NULL 1258 }; 1259 1260 vk::beginCommandBuffer(vkd, commandBuffer.get()); 1261 vk::VkImageMemoryBarrier initialBarrier = makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, 1262 (*colorAttachment).get(), subresourceRange); 1263 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, nullptr, 1264 0, nullptr, 1, &initialBarrier); 1265 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr); 1266 1267 vkd.cmdBeginRendering(*commandBuffer, &render_info); 1268 pipeline1.bind(commandBuffer.get()); 1269 vkd.cmdSetPatchControlPointsEXT(commandBuffer.get(), 3); 1270 vkd.cmdDraw(commandBuffer.get(), 6, 1, 0, 0); 1271 vkd.cmdEndRendering(*commandBuffer); 1272 1273 const VkBufferMemoryBarrier indexBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, index.get(), 0ull, sizeof(uint32_t)); 1274 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 1275 0u, 0, nullptr, 1, &indexBufferBarrier, 0, nullptr); 1276 1277 const VkBufferMemoryBarrier valueBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, values.get(), 0ull, bufferSize); 1278 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 1279 0u, 0, nullptr, 1, &valueBufferBarrier, 0, nullptr); 1280 1281 vk::endCommandBuffer(vkd, commandBuffer.get()); 1282 vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get()); 1283} 1284 1285tcu::TestStatus PipelineLibraryInterpolateAtSampleTestInstance::iterate(void) 1286{ 1287 const auto& vkd = m_context.getDeviceInterface(); 1288 const auto device = m_context.getDevice(); 1289 auto& alloc = m_context.getDefaultAllocator(); 1290 1291 struct ValueBuffer { 1292 float values[PipelineLibraryInterpolateAtSampleTestCase::ResultCount]; 1293 }; 1294 1295 size_t resultSize = PipelineLibraryInterpolateAtSampleTestCase::ResultCount; 1296 1297 const auto indexBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t)); 1298 const auto valueBufferSize = static_cast<VkDeviceSize>(sizeof(ValueBuffer)); 1299 1300 auto indexCreateInfo = makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1301 auto valuesCreateInfo = makeBufferCreateInfo(valueBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1302 1303 BufferWithMemory indexBufferMonolithic (vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible); 1304 BufferWithMemory valuesBufferMonolithic (vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible); 1305 BufferWithMemory indexBufferGPL (vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible); 1306 BufferWithMemory valuesBufferGPL (vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible); 1307 1308 auto& indexBufferMonolithicAlloc = indexBufferMonolithic.getAllocation(); 1309 auto& valuesBufferMonolithicAlloc = valuesBufferMonolithic.getAllocation(); 1310 auto& indexBufferGPLAlloc = indexBufferGPL.getAllocation(); 1311 auto& valuesBufferGPLAlloc = valuesBufferGPL.getAllocation(); 1312 1313 void* indexBufferMonolithicData = indexBufferMonolithicAlloc.getHostPtr(); 1314 void* valuesBufferMonolithicData = valuesBufferMonolithicAlloc.getHostPtr(); 1315 void* indexBufferGPLData = indexBufferGPLAlloc.getHostPtr(); 1316 void* valuesBufferGPLData = valuesBufferGPLAlloc.getHostPtr(); 1317 1318 deMemset(indexBufferMonolithicData, 0, sizeof(uint32_t)); 1319 deMemset(valuesBufferMonolithicData, 0, sizeof(ValueBuffer)); 1320 deMemset(indexBufferGPLData, 0, sizeof(uint32_t)); 1321 deMemset(valuesBufferGPLData, 0, sizeof(ValueBuffer)); 1322 1323 flushAlloc(vkd, device, indexBufferMonolithicAlloc); 1324 flushAlloc(vkd, device, valuesBufferMonolithicAlloc); 1325 flushAlloc(vkd, device, indexBufferGPLAlloc); 1326 flushAlloc(vkd, device, valuesBufferGPLAlloc); 1327 1328 runTest(indexBufferMonolithic, valuesBufferMonolithic, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC); 1329 runTest(indexBufferGPL, valuesBufferGPL, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY); 1330 1331 invalidateAlloc(vkd, device, indexBufferMonolithicAlloc); 1332 invalidateAlloc(vkd, device, valuesBufferMonolithicAlloc); 1333 invalidateAlloc(vkd, device, indexBufferGPLAlloc); 1334 invalidateAlloc(vkd, device, valuesBufferGPLAlloc); 1335 1336 uint32_t monolithicIndex; 1337 uint32_t GPLIndex; 1338 struct ValueBuffer monolithicResult = ValueBuffer(); 1339 struct ValueBuffer GPLResult = ValueBuffer(); 1340 memcpy((void*)&monolithicIndex, indexBufferMonolithicData, sizeof(uint32_t)); 1341 memcpy((void*)&GPLIndex, indexBufferGPLData, sizeof(uint32_t)); 1342 memcpy((void*)&monolithicResult, valuesBufferMonolithicData, sizeof(ValueBuffer)); 1343 memcpy((void*)&GPLResult, valuesBufferGPLData, sizeof(ValueBuffer)); 1344 1345 //we can't know which order the shaders will run in 1346 std::sort(monolithicResult.values, monolithicResult.values + resultSize); 1347 std::sort(GPLResult.values, GPLResult.values + resultSize); 1348 1349 //check that the atomic counters are at enough for the number of invocations 1350 constexpr int expected = (PipelineLibraryInterpolateAtSampleTestCase::sampleCount + 1) * 1351 PipelineLibraryInterpolateAtSampleTestCase::width * PipelineLibraryInterpolateAtSampleTestCase::height; 1352 1353 if (monolithicIndex < expected && GPLIndex < expected) { 1354 return tcu::TestStatus::fail("Atomic counter value lower than expected"); 1355 } 1356 1357 for (uint32_t i = 1; i < PipelineLibraryInterpolateAtSampleTestCase::ResultCount; i++) { 1358 if (monolithicResult.values[i] != monolithicResult.values[i]) { 1359 return tcu::TestStatus::fail("Comparison failed"); 1360 } 1361 } 1362 1363 return tcu::TestStatus::pass("Pass"); 1364} 1365#endif 1366 1367struct BindingTestConfig { 1368 PipelineConstructionType construction; 1369 bool backwardsBinding; 1370 bool holes; 1371}; 1372 1373/* 1374 * Test the following behaviours: 1375 * Descriptor sets updated/bound in backwards order 1376 * Descriptor sets with index holes updated/bound/used 1377 */ 1378class PipelineLayoutBindingTestCases : public vkt::TestCase 1379{ 1380public: 1381 PipelineLayoutBindingTestCases (tcu::TestContext& testCtx, 1382 const std::string& name, 1383 const BindingTestConfig& config) 1384 : vkt::TestCase(testCtx, name) 1385 , m_config(config) 1386 { 1387 } 1388 ~PipelineLayoutBindingTestCases (void) {} 1389 void initPrograms (SourceCollections& programCollection) const override; 1390 void checkSupport (Context& context) const override; 1391 TestInstance* createInstance (Context& context) const override; 1392 1393 const BindingTestConfig m_config; 1394}; 1395 1396class PipelineLayoutBindingTestInstance : public vkt::TestInstance 1397{ 1398public: 1399 PipelineLayoutBindingTestInstance (Context& context, 1400 const BindingTestConfig& config) 1401 : vkt::TestInstance (context) 1402 , m_renderSize (2, 2) 1403 , m_extent (makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u)) 1404 , m_format (VK_FORMAT_R8G8B8A8_UNORM) 1405 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), config.construction) 1406 , m_config (config) 1407 { 1408 } 1409 ~PipelineLayoutBindingTestInstance (void) {} 1410 tcu::TestStatus iterate (void) override; 1411 1412private: 1413 const tcu::UVec2 m_renderSize; 1414 const VkExtent3D m_extent; 1415 const VkFormat m_format; 1416 GraphicsPipelineWrapper m_graphicsPipeline; 1417 const BindingTestConfig m_config; 1418}; 1419 1420TestInstance* PipelineLayoutBindingTestCases::createInstance (Context& context) const 1421{ 1422 return new PipelineLayoutBindingTestInstance(context, m_config); 1423} 1424 1425void PipelineLayoutBindingTestCases::checkSupport (Context &context) const 1426{ 1427 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_config.construction); 1428} 1429 1430void PipelineLayoutBindingTestCases::initPrograms(SourceCollections& sources) const 1431{ 1432 std::ostringstream src; 1433 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1434 << "vec2 positions[3] = vec2[](\n" 1435 << " vec2(-1.0, -1.0)," 1436 << " vec2(3.0, -1.0)," 1437 << " vec2(-1.0, 3.0)" 1438 << ");\n" 1439 << "void main() {\n" 1440 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n" 1441 << "}"; 1442 sources.glslSources.add("vert") << glu::VertexSource(src.str()); 1443 1444 std::ostringstream frag; 1445 frag 1446 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1447 << "layout (location=0) out vec4 outColor;\n" 1448 << "layout(set = 0, binding = 0) uniform Output0 {" 1449 << " uint data;" 1450 << "} buf0;\n"; 1451 if (!m_config.holes) { 1452 frag 1453 << "layout(set = 1, binding = 0) uniform Output1 {" 1454 << " uint data;" 1455 << "} buf1;\n" 1456 << "layout(set = 2, binding = 0) uniform Output2 {" 1457 << " uint data;" 1458 << "} buf2;\n" 1459 << "\n"; 1460 } 1461 frag 1462 << "layout(set = 3, binding = 0) uniform Output3 {" 1463 << " uint data;" 1464 << "} buf3;\n" 1465 << "void main ()\n" 1466 << "{\n" 1467 << " const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 1468 << " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"; 1469 if (!m_config.holes) { 1470 frag 1471 << " outColor = ((buf0.data == 0) && (buf1.data == 1) && (buf2.data == 2) && (buf3.data == 3)) ? green : red;\n"; 1472 } else { 1473 frag 1474 << " outColor = ((buf0.data == 0) && (buf3.data == 3)) ? green : red;\n"; 1475 } 1476 frag << "}\n"; 1477 sources.glslSources.add("frag") << glu::FragmentSource(frag.str()); 1478} 1479 1480tcu::TestStatus PipelineLayoutBindingTestInstance::iterate () 1481{ 1482 const auto& vkd = m_context.getDeviceInterface(); 1483 const auto device = m_context.getDevice(); 1484 auto& alloc = m_context.getDefaultAllocator(); 1485 const auto qIndex = m_context.getUniversalQueueFamilyIndex(); 1486 const auto queue = m_context.getUniversalQueue(); 1487 const auto tcuFormat = mapVkFormat(m_format); 1488 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 1489 const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; 1490 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); 1491 1492 // Color attachment. 1493 const VkImageCreateInfo colorBufferInfo = 1494 { 1495 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1496 nullptr, // const void* pNext; 1497 0u, // VkImageCreateFlags flags; 1498 VK_IMAGE_TYPE_2D, // VkImageType imageType; 1499 m_format, // VkFormat format; 1500 m_extent, // VkExtent3D extent; 1501 1u, // uint32_t mipLevels; 1502 1u, // uint32_t arrayLayers; 1503 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 1504 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1505 colorUsage, // VkImageUsageFlags usage; 1506 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1507 0u, // uint32_t queueFamilyIndexCount; 1508 nullptr, // const uint32_t* pQueueFamilyIndices; 1509 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1510 }; 1511 ImageWithMemory colorBuffer (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any); 1512 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 1513 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u); 1514 const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR); 1515 1516 // Verification buffer. 1517 const auto verifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height; 1518 const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage); 1519 BufferWithMemory verifBuffer (vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible); 1520 auto& verifBufferAlloc = verifBuffer.getAllocation(); 1521 1522 // Render pass and framebuffer. 1523 RenderPassWrapper renderPass (m_config.construction, vkd, device, m_format); 1524 renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width, m_extent.height); 1525 1526 // Shader modules. 1527 const auto& binaries = m_context.getBinaryCollection(); 1528 const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert")); 1529 const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag")); 1530 1531 // Viewports and scissors. 1532 const std::vector<VkViewport> viewports (1u, makeViewport(m_extent)); 1533 const std::vector<VkRect2D> scissors (1u, makeRect2D(m_extent)); 1534 1535 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure(); 1536 const VkPipelineRasterizationStateCreateInfo rasterizationState = 1537 { 1538 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 1539 DE_NULL, // const void* pNext; 1540 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 1541 VK_FALSE, // VkBool32 depthClampEnable; 1542 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 1543 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 1544 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 1545 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace; 1546 VK_FALSE, // VkBool32 depthBiasEnable; 1547 0.0f, // float depthBiasConstantFactor; 1548 0.0f, // float depthBiasClamp; 1549 0.0f, // float depthBiasSlopeFactor; 1550 1.0f, // float lineWidth; 1551 }; 1552 1553 std::array<int, 4> tmpIndices = {}; 1554 std::array<int, 4> indices = {}; 1555 std::iota(tmpIndices.begin(), tmpIndices.end(), 0); 1556 if (m_config.backwardsBinding) { 1557 std::copy(tmpIndices.rbegin(), tmpIndices.rend(), indices.begin()); 1558 } else { 1559 std::copy(tmpIndices.begin(), tmpIndices.end(), indices.begin()); 1560 } 1561 1562 vk::DescriptorSetLayoutBuilder layoutBuilder; 1563 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT); 1564 1565 std::vector<vk::Move<VkDescriptorSetLayout>> descriptorSetLayouts = {}; 1566 1567 for (size_t i = 0; i < indices.size(); i++) { 1568 descriptorSetLayouts.emplace_back(layoutBuilder.build(vkd, device)); 1569 } 1570 1571 // Pipeline layout and graphics pipeline. 1572 uint32_t setAndDescriptorCount = de::sizeU32(indices); 1573 const vk::PipelineLayoutWrapper pipelineLayout (m_config.construction, vkd, device, descriptorSetLayouts); 1574 DescriptorPoolBuilder poolBuilder; 1575 poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, setAndDescriptorCount); 1576 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setAndDescriptorCount); 1577 std::vector<vk::Move<VkDescriptorSet>> descriptorSetsWrap = {}; 1578 std::vector<VkDescriptorSet> descriptorSets = {}; 1579 1580 for (const auto& setLayout : descriptorSetLayouts) { 1581 descriptorSetsWrap.emplace_back(makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get())); 1582 } 1583 1584 for (size_t i = 0; i < indices.size(); i++) { 1585 descriptorSets.emplace_back(descriptorSetsWrap[i].get()); 1586 } 1587 1588 const auto bufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t)); 1589 std::vector<std::unique_ptr<BufferWithMemory>> buffers; 1590 //create uniform buffers 1591 for (size_t i = 0; i < indices.size(); i++) { 1592 auto outBufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); 1593 auto buffer = std::unique_ptr<vk::BufferWithMemory>(new vk::BufferWithMemory(vkd, device, alloc, outBufferInfo, vk::MemoryRequirement::HostVisible)); 1594 auto& bufferAlloc = buffer->getAllocation(); 1595 uint32_t* bufferData = (uint32_t*)bufferAlloc.getHostPtr(); 1596 *bufferData = (uint32_t)i; 1597 flushAlloc(vkd, device, bufferAlloc); 1598 buffers.push_back(std::move(buffer)); 1599 } 1600 1601 DescriptorSetUpdateBuilder updater; 1602 1603 for (auto i : indices) { 1604 const auto bufferInfo = makeDescriptorBufferInfo(buffers[i]->get(), 0ull, bufferSize); 1605 updater.writeSingle(descriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo); 1606 updater.update(vkd, device); 1607 } 1608 1609 const auto topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1610 m_graphicsPipeline.setDefaultRasterizationState() 1611 .setDefaultTopology(topology) 1612 .setupVertexInputState(&vertexInputState) 1613 .setDefaultDepthStencilState() 1614 .setDefaultMultisampleState() 1615 .setDefaultColorBlendState() 1616 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, &rasterizationState) 1617 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule) 1618 .setupFragmentOutputState(*renderPass) 1619 .setMonolithicPipelineLayout(pipelineLayout) 1620 .buildPipeline(); 1621 1622 // Command pool and buffer. 1623 const auto cmdPool = makeCommandPool(vkd, device, qIndex); 1624 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1625 const auto cmdBuffer = cmdBufferPtr.get(); 1626 1627 beginCommandBuffer(vkd, cmdBuffer); 1628 1629 // Draw. 1630 renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor); 1631 for (auto i : indices) { 1632 if (m_config.holes && ((i == 1) || (i == 2))) { 1633 continue; 1634 } 1635 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), i, 1, &descriptorSets[i], 0u, nullptr); 1636 } 1637 m_graphicsPipeline.bind(cmdBuffer); 1638 vkd.cmdDraw(cmdBuffer, 3, 1u, 0u, 0u); 1639 renderPass.end(vkd, cmdBuffer); 1640 1641 // Copy to verification buffer. 1642 const auto copyRegion = makeBufferImageCopy(m_extent, colorSRL); 1643 const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); 1644 const auto color2Transfer = makeImageMemoryBarrier( 1645 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 1646 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1647 colorBuffer.get(), colorSRR); 1648 1649 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer); 1650 vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, ©Region); 1651 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host); 1652 1653 endCommandBuffer(vkd, cmdBuffer); 1654 1655 // Submit and validate result. 1656 submitCommandsAndWait(vkd, device, queue, cmdBuffer); 1657 1658 const tcu::IVec3 iExtent (static_cast<int>(m_extent.width), static_cast<int>(m_extent.height), static_cast<int>(m_extent.depth)); 1659 void* verifBufferData = verifBufferAlloc.getHostPtr(); 1660 const tcu::ConstPixelBufferAccess verifAccess (tcuFormat, iExtent, verifBufferData); 1661 invalidateAlloc(vkd, device, verifBufferAlloc); 1662 1663 const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 1664 tcu::TextureLevel referenceLevel(mapVkFormat(m_format), m_extent.height, m_extent.height); 1665 tcu::PixelBufferAccess reference = referenceLevel.getAccess(); 1666 tcu::clear(reference, green); 1667 1668 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference, verifAccess, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR)) 1669 return tcu::TestStatus::fail("Image comparison failed"); 1670 1671 return tcu::TestStatus::pass("Pass"); 1672} 1673 1674} // anonymous 1675 1676tcu::TestCaseGroup* createMiscTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1677{ 1678 de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc")); 1679 1680 // Location of the Amber script files under the data/vulkan/amber source tree. 1681 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 1682 addMonolithicAmberTests(miscTests.get()); 1683 1684 // Verify implicit access to gl_PrimtiveID works 1685 miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", pipelineConstructionType, false)); 1686 // Verify implicit access to gl_PrimtiveID works with a tessellation shader 1687 miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation", pipelineConstructionType, true)); 1688 #ifndef CTS_USES_VULKANSC 1689 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY) { 1690 // Check if interpolateAtSample works as expected when using a pipeline library and null MSAA state in the fragment shader" 1691 miscTests->addChild(new PipelineLibraryInterpolateAtSampleTestCase(testCtx, "interpolate_at_sample_no_sample_shading")); 1692 } 1693 #endif 1694 1695#ifndef CTS_USES_VULKANSC 1696 if (isConstructionTypeLibrary(pipelineConstructionType)) 1697 { 1698 for (int useTessIdx = 0; useTessIdx < 2; ++useTessIdx) 1699 for (int useGeomIdx = 0; useGeomIdx < 2; ++useGeomIdx) 1700 { 1701 const bool useTess = (useTessIdx > 0); 1702 const bool useGeom = (useGeomIdx > 0); 1703 1704 std::string testName = "unused_shader_stages"; 1705 1706 if (useTess) 1707 testName += "_include_tess"; 1708 1709 if (useGeom) 1710 testName += "_include_geom"; 1711 1712 const UnusedShaderStageParams params { pipelineConstructionType, useTess, useGeom }; 1713 miscTests->addChild(new UnusedShaderStagesCase(testCtx, testName, params)); 1714 } 1715 } 1716#endif // CTS_USES_VULKANSC 1717 1718 BindingTestConfig config0 = {pipelineConstructionType, true, false}; 1719 BindingTestConfig config1 = {pipelineConstructionType, false, true}; 1720 BindingTestConfig config2 = {pipelineConstructionType, true, true}; 1721 1722 // Verify implicit access to gl_PrimtiveID works with a tessellation shader 1723 miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards", config0)); 1724 // Verify implicit access to gl_PrimtiveID works with a tessellation shader 1725 miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_holes", config1)); 1726 // Verify implicit access to gl_PrimtiveID works with a tessellation shader 1727 miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards_holes", config2)); 1728 1729 return miscTests.release(); 1730} 1731 1732} // pipeline 1733} // vkt 1734