1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 Valve Corporation.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 * \brief VK_EXT_shader_module_identifier tests
23 *//*--------------------------------------------------------------------*/
24 #include "vktPipelineShaderModuleIdentifierTests.hpp"
25 #include "vktTestCase.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkImageWithMemory.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRayTracingUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkPipelineConstructionUtil.hpp"
40 #include "vkBarrierUtil.hpp"
42 #include "tcuMaybe.hpp"
43 #include "tcuCommandLine.hpp"
44 #include "tcuFormatUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTestLog.hpp"
48 #include "deUniquePtr.hpp"
49 #include "deRandom.hpp"
69 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
70 using StringVec = std::vector<std::string>;
73 using ShaderModuleId = std::vector<uint8_t>;
74 using ShaderModuleIdPtr = std::unique_ptr<ShaderModuleId>;
75 using ShaderStageIdPtr = std::unique_ptr<VkPipelineShaderStageModuleIdentifierCreateInfoEXT>;
77 // Helper function to create a shader module identifier from a VkShaderModuleIdentifierEXT structure.
78 ShaderModuleId makeShaderModuleId (const VkShaderModuleIdentifierEXT& idExt)
80 if (idExt.identifierSize == 0u || idExt.identifierSize > VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT)
81 TCU_FAIL("Invalid identifierSize returned");
83 ShaderModuleId identifier(idExt.identifier, idExt.identifier + idExt.identifierSize);
87 // Helper function to obtain the shader module identifier for a VkShaderModule as a return value.
88 ShaderModuleId getShaderModuleIdentifier (const DeviceInterface& vkd, const VkDevice device, const VkShaderModule module)
90 VkShaderModuleIdentifierEXT idExt = initVulkanStructure();
91 vkd.getShaderModuleIdentifierEXT(device, module, &idExt);
92 return makeShaderModuleId(idExt);
95 // Helper function to obtain the shader module identifier from a VkShaderModuleCreateInfo structure as a return value.
96 ShaderModuleId getShaderModuleIdentifier (const DeviceInterface& vkd, const VkDevice device, const VkShaderModuleCreateInfo& createInfo)
98 VkShaderModuleIdentifierEXT idExt = initVulkanStructure();
99 vkd.getShaderModuleCreateInfoIdentifierEXT(device, &createInfo, &idExt);
100 return makeShaderModuleId(idExt);
103 // Helper function to create a VkShaderModuleCreateInfo structure.
104 VkShaderModuleCreateInfo makeShaderModuleCreateInfo (size_t codeSize, const uint32_t* pCode, const VkShaderModuleCreateFlags createFlags = 0u, const void* pNext = nullptr)
106 const VkShaderModuleCreateInfo moduleCreateInfo =
108 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
109 pNext, // const void* pNext;
110 createFlags, // VkShaderModuleCreateFlags flags;
111 codeSize, // size_t codeSize;
112 pCode, // const uint32_t* pCode;
114 return moduleCreateInfo;
117 // On the actual pipeline in use, will we use module IDs or other data?
118 enum class UseModuleCase
122 ZERO_LEN_ID_NULL_PTR,
123 ZERO_LEN_ID_GARBAGE_PTR,
129 bool isZeroLen (UseModuleCase usage)
131 bool zeroLen = false;
135 case UseModuleCase::ZERO_LEN_ID:
136 case UseModuleCase::ZERO_LEN_ID_NULL_PTR:
137 case UseModuleCase::ZERO_LEN_ID_GARBAGE_PTR:
147 bool expectCacheMiss (UseModuleCase usage)
153 case UseModuleCase::ALL_ZEROS:
154 case UseModuleCase::ALL_ONES:
155 case UseModuleCase::PSEUDORANDOM_ID:
165 // Modify a shader module id according to the type of use.
166 void maybeMangleShaderModuleId (ShaderModuleId& moduleId, UseModuleCase moduleUse, de::Random& rnd)
168 if (moduleUse == UseModuleCase::ALL_ZEROS || moduleUse == UseModuleCase::ALL_ONES)
170 deMemset(moduleId.data(), ((moduleUse == UseModuleCase::ALL_ZEROS) ? 0 : 0xFF), de::dataSize(moduleId));
172 else if (moduleUse == UseModuleCase::PSEUDORANDOM_ID)
174 for (auto& byte : moduleId)
175 byte = rnd.getUint8();
179 // Helper function to create a VkPipelineShaderStageModuleIdentifierCreateInfoEXT structure.
180 ShaderStageIdPtr makeShaderStageModuleIdentifierCreateInfo (const ShaderModuleId& moduleId, UseModuleCase moduleUse, de::Random* rnd = nullptr)
182 ShaderStageIdPtr createInfo(new VkPipelineShaderStageModuleIdentifierCreateInfoEXT(initVulkanStructure()));
184 createInfo->identifierSize = (isZeroLen(moduleUse) ? 0u : de::sizeU32(moduleId));
188 case UseModuleCase::ID:
189 case UseModuleCase::ZERO_LEN_ID:
190 case UseModuleCase::ALL_ZEROS: // For this one and below, the module id will have been modified outside.
191 case UseModuleCase::ALL_ONES:
192 case UseModuleCase::PSEUDORANDOM_ID:
193 createInfo->pIdentifier = de::dataOrNull(moduleId);
195 case UseModuleCase::ZERO_LEN_ID_NULL_PTR:
196 break; // Already null as part of initVulkanStructure().
197 case UseModuleCase::ZERO_LEN_ID_GARBAGE_PTR:
201 // Fill pointer with random bytes.
202 auto pIdentifierPtr = reinterpret_cast<uint8_t*>(&(createInfo->pIdentifier));
204 for (size_t i = 0; i < sizeof(createInfo->pIdentifier); ++i)
205 pIdentifierPtr[i] = rnd->getUint8();
216 VkShaderModule retUsedModule (VkShaderModule module, UseModuleCase moduleUse)
218 return (isZeroLen(moduleUse) ? module : DE_NULL);
221 enum class PipelineType
228 enum class GraphicsShaderType
237 enum class RayTracingShaderType
247 using GraphicsShaderVec = std::vector<GraphicsShaderType>;
248 using RTShaderVec = std::vector<RayTracingShaderType>;
250 std::ostream& operator<<(std::ostream& out, GraphicsShaderType type)
254 case GraphicsShaderType::VERTEX: out << "vert"; break;
255 case GraphicsShaderType::TESS_CONTROL: out << "tesc"; break;
256 case GraphicsShaderType::TESS_EVAL: out << "tese"; break;
257 case GraphicsShaderType::GEOMETRY: out << "geom"; break;
258 case GraphicsShaderType::FRAG: out << "frag"; break;
266 std::ostream& operator<<(std::ostream& out, RayTracingShaderType type)
270 case RayTracingShaderType::RAY_GEN: out << "rgen"; break;
271 case RayTracingShaderType::CLOSEST_HIT: out << "chit"; break;
272 case RayTracingShaderType::ANY_HIT: out << "ahit"; break;
273 case RayTracingShaderType::INTERSECTION: out << "isec"; break;
274 case RayTracingShaderType::MISS: out << "miss"; break;
275 case RayTracingShaderType::CALLABLE: out << "call"; break;
284 std::string toString(const std::vector<T>& vec)
286 std::ostringstream out;
287 for (size_t i = 0; i < vec.size(); ++i)
288 out << ((i == 0) ? "" : "_") << vec.at(i);
292 // Pipeline executable properties helpers.
293 struct PipelineExecutableStat
295 PipelineExecutableStat (std::string name_, std::string description_, VkPipelineExecutableStatisticFormatKHR format_, VkPipelineExecutableStatisticValueKHR value_)
296 : name (std::move(name_))
297 , description (std::move(description_))
302 const std::string name;
303 const std::string description;
304 const VkPipelineExecutableStatisticFormatKHR format;
305 const VkPipelineExecutableStatisticValueKHR value;
308 struct PipelineExecutableInternalRepresentation
310 PipelineExecutableInternalRepresentation (std::string name_, std::string description_, bool isText_, const std::vector<uint8_t>& data)
311 : name (std::move(name_))
312 , description (std::move(description_))
318 m_text = std::string(reinterpret_cast<const char*>(data.data()));
323 const std::string name;
324 const std::string description;
326 bool isText (void) const { return m_isText; }
327 const std::string& getText (void) const { DE_ASSERT(isText()); return m_text; }
328 const std::vector<uint8_t>& getBytes (void) const { DE_ASSERT(!isText()); return m_bytes; }
333 std::vector<uint8_t> m_bytes;
336 struct PipelineExecutableProperty
338 PipelineExecutableProperty (VkShaderStageFlags stageFlags_, std::string name_, std::string description_, uint32_t subgroupSize_)
339 : stageFlags (stageFlags_)
340 , name (std::move(name_))
341 , description (std::move(description_))
342 , subgroupSize (subgroupSize_)
347 const VkShaderStageFlags stageFlags;
348 const std::string name;
349 const std::string description;
350 const uint32_t subgroupSize;
352 void addStat (const PipelineExecutableStat& stat) { m_stats.emplace_back(stat); }
353 void addIR (const PipelineExecutableInternalRepresentation& ir) { m_irs.emplace_back(ir); }
355 const std::vector<PipelineExecutableStat>& getStats (void) const { return m_stats; }
356 const std::vector<PipelineExecutableInternalRepresentation>& getIRs (void) const { return m_irs; }
359 std::vector<PipelineExecutableStat> m_stats;
360 std::vector<PipelineExecutableInternalRepresentation> m_irs;
363 // This will NOT compare stats and IRs, only flags, name, description and subgroup sizes.
364 bool operator== (const PipelineExecutableProperty& a, const PipelineExecutableProperty& b)
366 return (a.stageFlags == b.stageFlags && a.name == b.name && a.description == b.description && a.subgroupSize == b.subgroupSize);
369 // For sorting if used as a map key or in a set. Based on the property name.
370 bool operator< (const PipelineExecutableProperty& a, const PipelineExecutableProperty& b)
372 return (a.name < b.name);
375 std::ostream& operator<< (std::ostream& out, const PipelineExecutableProperty& prop)
377 out << "PipelineExecutableProperty("
378 << "stageFlags=\"" << prop.stageFlags << "\", "
379 << "name=\"" << prop.name << "\", "
380 << "description=\"" << prop.description << "\", "
381 << "subgroupSize=\"" << prop.subgroupSize << "\")";
385 // What to capture from a pipeline.
386 enum class CapturedPropertiesBits
392 using CapturedPropertiesFlags = uint32_t;
394 VkPipelineCreateFlags getPipelineCreateFlags (CapturedPropertiesFlags capturedProperties)
396 VkPipelineCreateFlags createFlags = 0u;
398 if (capturedProperties & static_cast<int>(CapturedPropertiesBits::STATS))
399 createFlags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
401 if (capturedProperties & static_cast<int>(CapturedPropertiesBits::IRS))
402 createFlags |= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
407 VkPipelineInfoKHR makePipelineInfo (VkPipeline pipeline)
409 VkPipelineInfoKHR pipelineInfo = initVulkanStructure();
410 pipelineInfo.pipeline = pipeline;
414 VkPipelineExecutableInfoKHR makePipelineExecutableInfo (VkPipeline pipeline, size_t executableIndex)
416 VkPipelineExecutableInfoKHR info = initVulkanStructure();
417 info.pipeline = pipeline;
418 info.executableIndex = static_cast<uint32_t>(executableIndex);
422 using PipelineExecutablePropertyVec = std::vector<PipelineExecutableProperty>;
424 std::ostream& operator<< (std::ostream& out, const PipelineExecutablePropertyVec& vec)
428 for (const auto& prop : vec)
430 out << (first ? "" : ", ") << prop;
437 PipelineExecutablePropertyVec getPipelineExecutableProperties (const DeviceInterface& vkd, VkDevice device, VkPipeline pipeline, CapturedPropertiesFlags captureFlags)
439 PipelineExecutablePropertyVec properties;
440 const auto pipelineInfo = makePipelineInfo(pipeline);
441 uint32_t executableCount = 0u;
443 std::vector<VkPipelineExecutablePropertiesKHR> propertiesKHR;
444 VK_CHECK(vkd.getPipelineExecutablePropertiesKHR(device, &pipelineInfo, &executableCount, nullptr));
447 if (executableCount == 0u)
450 propertiesKHR.resize(executableCount, initVulkanStructure());
451 VK_CHECK(vkd.getPipelineExecutablePropertiesKHR(device, &pipelineInfo, &executableCount, propertiesKHR.data()));
453 // Make a property with every result structure.
454 properties.reserve(propertiesKHR.size());
455 for (const auto& prop : propertiesKHR)
456 properties.emplace_back(prop.stages, prop.name, prop.description, prop.subgroupSize);
458 // Query stats if requested.
459 if (captureFlags & static_cast<int>(CapturedPropertiesBits::STATS))
461 for (size_t exeIdx = 0; exeIdx < properties.size(); ++exeIdx)
463 uint32_t statCount = 0u;
464 std::vector<VkPipelineExecutableStatisticKHR> statsKHR;
465 const auto executableInfo = makePipelineExecutableInfo(pipeline, exeIdx);
467 VK_CHECK(vkd.getPipelineExecutableStatisticsKHR(device, &executableInfo, &statCount, nullptr));
472 statsKHR.resize(statCount, initVulkanStructure());
473 VK_CHECK(vkd.getPipelineExecutableStatisticsKHR(device, &executableInfo, &statCount, statsKHR.data()));
475 for (const auto& stat : statsKHR)
476 properties[exeIdx].addStat(PipelineExecutableStat(stat.name, stat.description, stat.format, stat.value));
480 // Query IRs if requested.
481 if (captureFlags & static_cast<int>(CapturedPropertiesBits::IRS))
483 for (size_t exeIdx = 0; exeIdx < properties.size(); ++exeIdx)
485 uint32_t irsCount = 0u;
486 std::vector<VkPipelineExecutableInternalRepresentationKHR> irsKHR;
487 std::vector<std::vector<uint8_t>> irsData;
488 const auto executableInfo = makePipelineExecutableInfo(pipeline, exeIdx);
491 VK_CHECK(vkd.getPipelineExecutableInternalRepresentationsKHR(device, &executableInfo, &irsCount, nullptr));
497 irsData.resize(irsCount);
498 irsKHR.resize(irsCount, initVulkanStructure());
499 VK_CHECK(vkd.getPipelineExecutableInternalRepresentationsKHR(device, &executableInfo, &irsCount, irsKHR.data()));
502 for (size_t irIdx = 0; irIdx < irsKHR.size(); ++irIdx)
504 auto& dataBuffer = irsData[irIdx];
505 auto& irKHR = irsKHR[irIdx];
507 dataBuffer.resize(irKHR.dataSize);
508 irKHR.pData = dataBuffer.data();
510 VK_CHECK(vkd.getPipelineExecutableInternalRepresentationsKHR(device, &executableInfo, &irsCount, irsKHR.data()));
512 // Append IRs to property.
513 for (size_t irIdx = 0; irIdx < irsKHR.size(); ++irIdx)
515 const auto& ir = irsKHR[irIdx];
516 properties[exeIdx].addIR(PipelineExecutableInternalRepresentation(ir.name, ir.description, ir.isText, irsData[irIdx]));
526 const PipelineType pipelineType;
527 GraphicsShaderVec graphicsShaders;
528 RTShaderVec rtShaders;
529 const uint8_t pipelineCount;
530 const tcu::Maybe<uint8_t> pipelineToRun;
531 const bool useSpecializationConstants;
534 BaseParams (PipelineType pipelineType_,
535 GraphicsShaderVec graphicsShaders_,
536 RTShaderVec rtShaders_,
537 uint8_t pipelineCount_,
538 const tcu::Maybe<uint8_t>& pipelineToRun_,
541 : pipelineType (pipelineType_)
542 , graphicsShaders (std::move(graphicsShaders_))
543 , rtShaders (std::move(rtShaders_))
544 , pipelineCount (pipelineCount_)
545 , pipelineToRun (pipelineToRun_)
546 , useSpecializationConstants (useSCs_)
547 , useCache (useCache_)
549 if (pipelineType != PipelineType::GRAPHICS)
550 DE_ASSERT(graphicsShaders.empty());
551 else if (pipelineType != PipelineType::RAY_TRACING)
552 DE_ASSERT(rtShaders.empty());
554 if (static_cast<bool>(pipelineToRun))
555 DE_ASSERT(pipelineToRun.get() < pipelineCount);
557 // We'll use one descriptor set per pipeline, so we only want a few pipelines.
558 DE_ASSERT(static_cast<uint32_t>(pipelineCount) <= 4u);
561 // Make the class polymorphic, needed below.
562 virtual ~BaseParams () {}
564 size_t stageCountPerPipeline (void) const
566 size_t stageCount = 0;
568 switch (pipelineType)
570 case PipelineType::COMPUTE: stageCount = 1u; break;
571 case PipelineType::GRAPHICS: stageCount = graphicsShaders.size(); break;
572 case PipelineType::RAY_TRACING: stageCount = rtShaders.size(); break;
582 bool hasGraphicsStage (GraphicsShaderType stage) const
584 if (pipelineType != PipelineType::GRAPHICS)
586 return de::contains(begin(graphicsShaders), end(graphicsShaders), stage);
589 bool hasRTStage (RayTracingShaderType stage) const
591 if (pipelineType != PipelineType::RAY_TRACING)
593 return de::contains(begin(rtShaders), end(rtShaders), stage);
597 bool hasGeom (void) const
599 return hasGraphicsStage(GraphicsShaderType::GEOMETRY);
602 bool hasTess (void) const
604 return (hasGraphicsStage(GraphicsShaderType::TESS_CONTROL) || hasGraphicsStage(GraphicsShaderType::TESS_EVAL));
607 bool hasVertexPipelineStage (void) const
609 return (hasGraphicsStage(GraphicsShaderType::VERTEX) || hasTess() || hasGeom());
612 bool hasFrag (void) const
614 return hasGraphicsStage(GraphicsShaderType::FRAG);
617 bool hasRayTracing (void) const
619 return (pipelineType == PipelineType::RAY_TRACING);
622 bool hasHit (void) const
624 return (hasRTStage(RayTracingShaderType::ANY_HIT) || hasRTStage(RayTracingShaderType::CLOSEST_HIT) || hasRTStage(RayTracingShaderType::INTERSECTION));
627 bool hasISec (void) const
629 return hasRTStage(RayTracingShaderType::INTERSECTION);
632 bool hasMiss (void) const
634 return hasRTStage(RayTracingShaderType::MISS);
637 VkPipelineStageFlags getPipelineStageFlags (void) const
639 if (pipelineType == PipelineType::COMPUTE)
640 return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
642 if (pipelineType == PipelineType::RAY_TRACING)
643 return VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
645 if (pipelineType == PipelineType::GRAPHICS)
647 VkPipelineStageFlags stageFlags = 0u;
649 for (const auto& stage : graphicsShaders)
653 case GraphicsShaderType::VERTEX: stageFlags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; break;
654 case GraphicsShaderType::TESS_CONTROL: stageFlags |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT; break;
655 case GraphicsShaderType::TESS_EVAL: stageFlags |= VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; break;
656 case GraphicsShaderType::GEOMETRY: stageFlags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; break;
657 case GraphicsShaderType::FRAG: stageFlags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break;
671 VkShaderStageFlags getShaderStageFlags (void) const
673 if (pipelineType == PipelineType::COMPUTE)
674 return VK_SHADER_STAGE_COMPUTE_BIT;
676 if (pipelineType == PipelineType::RAY_TRACING)
678 VkShaderStageFlags stageFlags = 0u;
680 for (const auto& stage : rtShaders)
684 case RayTracingShaderType::RAY_GEN: stageFlags |= VK_SHADER_STAGE_RAYGEN_BIT_KHR; break;
685 case RayTracingShaderType::CLOSEST_HIT: stageFlags |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; break;
686 case RayTracingShaderType::ANY_HIT: stageFlags |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR; break;
687 case RayTracingShaderType::INTERSECTION: stageFlags |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR; break;
688 case RayTracingShaderType::MISS: stageFlags |= VK_SHADER_STAGE_MISS_BIT_KHR; break;
689 case RayTracingShaderType::CALLABLE: stageFlags |= VK_SHADER_STAGE_CALLABLE_BIT_KHR; break;
699 if (pipelineType == PipelineType::GRAPHICS)
701 VkShaderStageFlags stageFlags = 0u;
703 for (const auto& stage : graphicsShaders)
707 case GraphicsShaderType::VERTEX: stageFlags |= VK_SHADER_STAGE_VERTEX_BIT; break;
708 case GraphicsShaderType::TESS_CONTROL: stageFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
709 case GraphicsShaderType::TESS_EVAL: stageFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
710 case GraphicsShaderType::GEOMETRY: stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT; break;
711 case GraphicsShaderType::FRAG: stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT; break;
726 using BaseParamsPtr = std::unique_ptr<BaseParams>;
728 void checkShaderModuleIdentifierSupport (Context& context)
730 context.requireDeviceFunctionality("VK_EXT_shader_module_identifier");
733 void getTwoShaderIdentifierProperties (Context& context,
734 VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT* properties1,
735 VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT* properties2)
737 *properties1 = initVulkanStructure();
738 *properties2 = initVulkanStructure();
740 const auto& vki = context.getInstanceInterface();
741 const auto physicalDevice = context.getPhysicalDevice();
742 VkPhysicalDeviceProperties2 main = initVulkanStructure(properties1);
744 vki.getPhysicalDeviceProperties2(physicalDevice, &main);
745 main.pNext = properties2;
746 vki.getPhysicalDeviceProperties2(physicalDevice, &main);
749 tcu::TestStatus constantAlgorithmUUIDCase (Context& context)
751 VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT properties1, properties2;
752 getTwoShaderIdentifierProperties(context, &properties1, &properties2);
754 const auto uuidSize = static_cast<size_t>(VK_UUID_SIZE);
756 if (deMemCmp(properties1.shaderModuleIdentifierAlgorithmUUID, properties2.shaderModuleIdentifierAlgorithmUUID, uuidSize) != 0)
757 return tcu::TestStatus::fail("shaderModuleIdentifierAlgorithmUUID not constant accross calls");
759 uint8_t nullUUID[uuidSize];
760 deMemset(nullUUID, 0, uuidSize);
762 if (deMemCmp(properties1.shaderModuleIdentifierAlgorithmUUID, nullUUID, uuidSize) == 0)
763 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "shaderModuleIdentifierAlgorithmUUID is all zeros");
765 return tcu::TestStatus::pass("Pass");
768 std::vector<uint32_t> generateShaderConstants (PipelineType pipelineType, uint8_t pipelineCount, size_t stageCount)
770 std::vector<uint32_t> shaderConstants;
772 for (uint8_t pipelineIdx = 0; pipelineIdx < pipelineCount; ++pipelineIdx)
773 for (size_t stageIdx = 0; stageIdx < stageCount; ++stageIdx)
774 shaderConstants.push_back(0xEB000000u
775 | ((static_cast<uint32_t>(pipelineType) & 0xFFu) << 16)
776 | ((static_cast<uint32_t>(pipelineIdx) & 0xFFu) << 8)
777 | ((static_cast<uint32_t>(stageIdx) & 0xFFu) )
780 return shaderConstants;
783 size_t getShaderIdx (uint8_t pipelineIdx, size_t stageIdx, size_t stageCount)
785 const auto pIdx = static_cast<size_t>(pipelineIdx);
786 return (pIdx * stageCount + stageIdx);
789 void generateSources (SourceCollections& programCollection, const BaseParams* params_)
791 const auto& params = *params_;
792 const auto stageCount = params.stageCountPerPipeline();
793 const auto constantValues = generateShaderConstants(params.pipelineType, params.pipelineCount, stageCount);
795 StringVec constantDecls; // Per pipeline and stage.
796 StringVec pipelineAdds; // Per pipeline.
797 StringVec stageStores; // Per stage.
799 std::string ssboDecl; // Universal.
800 std::string uboDecls; // Universal.
801 std::string outValueDecl = " uint outValue = stageConstant;\n"; // Universal.
803 // Each stage in each pipeline will have one specific constant value.
805 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
806 for (size_t stageIdx = 0; stageIdx < stageCount; ++stageIdx)
808 constantDecls.push_back(params.useSpecializationConstants
809 ? "layout (constant_id=0) const uint stageConstant = 0u;\n"
810 : "const uint stageConstant = " + std::to_string(constantValues.at(getShaderIdx(pipelineIdx, stageIdx, stageCount))) + "u;\n");
814 // Each pipeline will have slightly different code by adding more values to the constant in each shader.
815 // The values will come from UBOs and, in practice, will contain zeros.
817 pipelineAdds.reserve(params.pipelineCount);
819 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
821 std::string additions;
822 const auto addCount = static_cast<size_t>(pipelineIdx + 1);
824 for (size_t addIdx = 0; addIdx < addCount; ++addIdx)
826 const auto uboId = addIdx + 1;
827 additions += " outValue += ubo_" + std::to_string(uboId) + ".value;\n";
830 pipelineAdds.push_back(additions);
834 // Each stage will write the output value to an SSBO position.
836 stageStores.reserve(stageCount);
838 for (size_t stageIdx = 0; stageIdx < stageCount; ++stageIdx)
840 const auto stageStore = " ssbo.values[" + std::to_string(stageIdx) + "] = outValue;\n";
841 stageStores.push_back(stageStore);
845 // The SSBO declaration is constant.
846 ssboDecl = "layout (set=0, binding=0, std430) buffer SSBOBlock { uint values[]; } ssbo;\n";
848 // The UBO declarations are constant. We need one UBO per pipeline, but all pipelines declare them all.
850 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
852 const auto uboId = pipelineIdx + 1;
853 const auto idStr = std::to_string(uboId);
854 uboDecls += "layout (set=0, binding=" + idStr + ") uniform UBOBlock" + idStr + " { uint value; } ubo_" + idStr + ";\n";
858 if (params.pipelineType == PipelineType::COMPUTE)
860 const std::string localSize = (params.useSpecializationConstants
861 ? "layout (local_size_x_id=1, local_size_y_id=2, local_size_z_id=3) in;\n"
862 : "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n");
864 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
866 const auto plIdxSz = static_cast<size_t>(pipelineIdx);
867 const std::string shaderName = "comp_" + std::to_string(plIdxSz);
868 const auto shaderIdx = getShaderIdx(pipelineIdx, 0, stageCount);
870 std::ostringstream comp;
876 << constantDecls.at(shaderIdx)
877 << "void main (void) {\n"
879 << pipelineAdds.at(plIdxSz)
880 << " if (gl_LocalInvocationIndex == 0u) {\n"
885 programCollection.glslSources.add(shaderName) << glu::ComputeSource(comp.str());
888 else if (params.pipelineType == PipelineType::GRAPHICS)
890 bool hasVertex = false;
891 bool hasTessControl = false;
892 bool hasTessEval = false;
893 bool hasGeom = false;
894 bool hasFrag = false;
896 // Assign a unique index to each active shader type.
897 size_t vertShaderIdx = 0u;
898 size_t tescShaderIdx = 0u;
899 size_t teseShaderIdx = 0u;
900 size_t geomShaderIdx = 0u;
901 size_t fragShaderIdx = 0u;
902 size_t curShaderIdx = 0u;
904 const std::set<GraphicsShaderType> uniqueStages (begin(params.graphicsShaders), end(params.graphicsShaders));
906 for (const auto& stage : uniqueStages)
910 case GraphicsShaderType::VERTEX: hasVertex = true; vertShaderIdx = curShaderIdx++; break;
911 case GraphicsShaderType::TESS_CONTROL: hasTessControl = true; tescShaderIdx = curShaderIdx++; break;
912 case GraphicsShaderType::TESS_EVAL: hasTessEval = true; teseShaderIdx = curShaderIdx++; break;
913 case GraphicsShaderType::GEOMETRY: hasGeom = true; geomShaderIdx = curShaderIdx++; break;
914 case GraphicsShaderType::FRAG: hasFrag = true; fragShaderIdx = curShaderIdx++; break;
915 default: DE_ASSERT(false); break;
919 const bool hasTess = (hasTessControl || hasTessEval);
921 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
923 const auto plIdxSz = static_cast<size_t>(pipelineIdx);
927 const std::string shaderName = "vert_" + std::to_string(plIdxSz);
928 const auto shaderIdx = getShaderIdx(pipelineIdx, vertShaderIdx, stageCount);
930 std::ostringstream vert;
933 << "out gl_PerVertex\n"
935 << " vec4 gl_Position;\n"
936 << (hasTess ? "" : " float gl_PointSize;\n")
943 << "vec2 vertexPositions[3] = vec2[](\n"
944 << " vec2( 0.0, -0.5),\n"
945 << " vec2( 0.5, 0.5),\n"
946 << " vec2(-0.5, 0.5)\n"
954 << constantDecls.at(shaderIdx)
955 << "void main (void) {\n"
957 << pipelineAdds.at(plIdxSz)
958 << stageStores.at(vertShaderIdx)
963 vert << " gl_Position = vec4(vertexPositions[gl_VertexIndex], 0.0, 1.0);\n";
968 << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
969 << " gl_PointSize = 1.0;\n"
975 programCollection.glslSources.add(shaderName) << glu::VertexSource(vert.str());
980 const std::string shaderName = "frag_" + std::to_string(plIdxSz);
981 const auto shaderIdx = getShaderIdx(pipelineIdx, fragShaderIdx, stageCount);
983 std::ostringstream frag;
986 << "layout (location=0) out vec4 outColor;\n"
989 << constantDecls.at(shaderIdx)
990 << "void main (void) {\n"
992 << pipelineAdds.at(plIdxSz)
993 << stageStores.at(fragShaderIdx)
994 << " outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
997 programCollection.glslSources.add(shaderName) << glu::FragmentSource(frag.str());
1002 const std::string shaderName = "tesc_" + std::to_string(plIdxSz);
1003 const auto shaderIdx = getShaderIdx(pipelineIdx, tescShaderIdx, stageCount);
1005 std::ostringstream tesc;
1008 << "layout (vertices=3) out;\n"
1009 << "in gl_PerVertex\n"
1011 << " vec4 gl_Position;\n"
1012 << "} gl_in[gl_MaxPatchVertices];\n"
1013 << "out gl_PerVertex\n"
1015 << " vec4 gl_Position;\n"
1019 << constantDecls.at(shaderIdx)
1020 << "void main (void) {\n"
1022 << pipelineAdds.at(plIdxSz)
1023 << stageStores.at(tescShaderIdx)
1024 << " gl_TessLevelInner[0] = 1.0;\n"
1025 << " gl_TessLevelInner[1] = 1.0;\n"
1026 << " gl_TessLevelOuter[0] = 1.0;\n"
1027 << " gl_TessLevelOuter[1] = 1.0;\n"
1028 << " gl_TessLevelOuter[2] = 1.0;\n"
1029 << " gl_TessLevelOuter[3] = 1.0;\n"
1030 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1033 programCollection.glslSources.add(shaderName) << glu::TessellationControlSource(tesc.str());
1038 const std::string shaderName = "tese_" + std::to_string(plIdxSz);
1039 const auto shaderIdx = getShaderIdx(pipelineIdx, teseShaderIdx, stageCount);
1041 std::ostringstream tese;
1044 << "layout (triangles, fractional_odd_spacing, cw) in;\n"
1045 << "in gl_PerVertex\n"
1047 << " vec4 gl_Position;\n"
1048 << "} gl_in[gl_MaxPatchVertices];\n"
1049 << "out gl_PerVertex\n"
1051 << " vec4 gl_Position;\n"
1055 << constantDecls.at(shaderIdx)
1056 << "void main (void) {\n"
1058 << pipelineAdds.at(plIdxSz)
1059 << stageStores.at(teseShaderIdx)
1060 << " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
1061 << " (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
1062 << " (gl_TessCoord.z * gl_in[2].gl_Position);\n"
1065 programCollection.glslSources.add(shaderName) << glu::TessellationEvaluationSource(tese.str());
1070 const std::string shaderName = "geom_" + std::to_string(plIdxSz);
1071 const auto shaderIdx = getShaderIdx(pipelineIdx, geomShaderIdx, stageCount);
1072 const auto inputPrim = (hasTess ? "triangles" : "points");
1073 const auto outputPrim = (hasTess ? "triangle_strip" : "points");
1074 const auto vertexCount = (hasTess ? 3u : 1u);
1076 std::ostringstream geom;
1079 << "layout (" << inputPrim << ") in;\n"
1080 << "layout (" << outputPrim << ", max_vertices=" << vertexCount << ") out;\n"
1081 << "in gl_PerVertex\n"
1083 << " vec4 gl_Position;\n"
1084 << (hasTess ? "" : " float gl_PointSize;\n")
1085 << "} gl_in[" << vertexCount << "];\n"
1086 << "out gl_PerVertex\n"
1088 << " vec4 gl_Position;\n"
1089 << (hasTess ? "" : " float gl_PointSize;\n")
1093 << constantDecls.at(shaderIdx)
1094 << "void main (void) {\n"
1096 << pipelineAdds.at(plIdxSz)
1097 << stageStores.at(geomShaderIdx)
1100 for (uint32_t i = 0; i < vertexCount; ++i)
1103 << " gl_Position = gl_in[" << i << "].gl_Position;\n"
1104 << (hasTess ? "" : " gl_PointSize = gl_in[" + std::to_string(i) + "].gl_PointSize;\n")
1105 << " EmitVertex();\n"
1111 programCollection.glslSources.add(shaderName) << glu::GeometrySource(geom.str());
1115 else if (params.pipelineType == PipelineType::RAY_TRACING)
1117 bool hasRayGen = false;
1118 bool hasAnyHit = false;
1119 bool hasClosestHit = false;
1120 bool hasIntersection = false;
1121 bool hasMiss = false;
1122 bool hasCallable = false;
1124 // Assign a unique index to each active shader type.
1125 size_t rgenShaderIdx = 0u;
1126 size_t ahitShaderIdx = 0u;
1127 size_t chitShaderIdx = 0u;
1128 size_t isecShaderIdx = 0u;
1129 size_t missShaderIdx = 0u;
1130 size_t callShaderIdx = 0u;
1131 size_t curShaderIdx = 0u;
1133 const std::set<RayTracingShaderType> uniqueStages (begin(params.rtShaders), end(params.rtShaders));
1135 for (const auto& stage : uniqueStages)
1139 case RayTracingShaderType::RAY_GEN: hasRayGen = true; rgenShaderIdx = curShaderIdx++; break;
1140 case RayTracingShaderType::ANY_HIT: hasAnyHit = true; ahitShaderIdx = curShaderIdx++; break;
1141 case RayTracingShaderType::CLOSEST_HIT: hasClosestHit = true; chitShaderIdx = curShaderIdx++; break;
1142 case RayTracingShaderType::INTERSECTION: hasIntersection = true; isecShaderIdx = curShaderIdx++; break;
1143 case RayTracingShaderType::MISS: hasMiss = true; missShaderIdx = curShaderIdx++; break;
1144 case RayTracingShaderType::CALLABLE: hasCallable = true; callShaderIdx = curShaderIdx++; break;
1145 default: DE_ASSERT(false); break;
1149 const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true/* allow SPIR-V 1.4 */);
1150 const bool needsRayTraced = (hasAnyHit || hasClosestHit || hasIntersection || hasMiss);
1152 for (uint8_t pipelineIdx = 0; pipelineIdx < params.pipelineCount; ++pipelineIdx)
1154 const auto plIdxSz = static_cast<size_t>(pipelineIdx);
1158 const std::string shaderName = "rgen_" + std::to_string(plIdxSz);
1159 const auto shaderIdx = getShaderIdx(pipelineIdx, rgenShaderIdx, stageCount);
1161 std::ostringstream rgen;
1164 << "#extension GL_EXT_ray_tracing : require\n"
1165 << (needsRayTraced ? "layout (location=0) rayPayloadEXT vec3 hitValue;\n" : "")
1166 << (hasCallable ? "layout (location=0) callableDataEXT float unused;\n" : "")
1167 // Ray tracing pipelines will use a separate set for the acceleration structure.
1168 << "layout (set=1, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
1171 << constantDecls.at(shaderIdx)
1172 << "void main (void) {\n"
1174 << pipelineAdds.at(plIdxSz)
1175 << " if (gl_LaunchIDEXT.x == 0u) {\n"
1176 << stageStores.at(rgenShaderIdx)
1178 << " uint rayFlags = 0;\n"
1179 << " uint cullMask = 0xFF;\n"
1180 << " float tmin = 0.0;\n"
1181 << " float tmax = 10.0;\n"
1182 // Rays will be traced towards +Z and geometry should be in the [0, 1] range in both X and Y, possibly at Z=5.
1183 // If a hit and a miss shader are used, a second ray will be traced starting at X=1.5, which should result in a miss.
1184 << " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, 0.5, 0.0);\n"
1185 << " vec3 direct = vec3(0.0, 0.0, 1.0);\n"
1186 << (needsRayTraced ? " traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n" : "")
1187 << (hasCallable ? " executeCallableEXT(0, 0);\n" : "")
1190 programCollection.glslSources.add(shaderName) << glu::RaygenSource(rgen.str()) << buildOptions;
1195 const std::string shaderName = "ahit_" + std::to_string(plIdxSz);
1196 const auto shaderIdx = getShaderIdx(pipelineIdx, ahitShaderIdx, stageCount);
1198 // VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR should be used.
1199 std::stringstream ahit;
1202 << "#extension GL_EXT_ray_tracing : require\n"
1203 << "layout (location=0) rayPayloadInEXT vec3 hitValue;\n"
1204 << "hitAttributeEXT vec3 attribs;\n"
1207 << constantDecls.at(shaderIdx)
1211 << pipelineAdds.at(plIdxSz)
1212 << stageStores.at(ahitShaderIdx)
1216 programCollection.glslSources.add(shaderName) << glu::AnyHitSource(ahit.str()) << buildOptions;
1221 const std::string shaderName = "chit_" + std::to_string(plIdxSz);
1222 const auto shaderIdx = getShaderIdx(pipelineIdx, chitShaderIdx, stageCount);
1224 std::stringstream chit;
1227 << "#extension GL_EXT_ray_tracing : require\n"
1228 << "layout (location=0) rayPayloadInEXT vec3 hitValue;\n"
1229 << "hitAttributeEXT vec3 attribs;\n"
1232 << constantDecls.at(shaderIdx)
1236 << pipelineAdds.at(plIdxSz)
1237 << stageStores.at(chitShaderIdx)
1241 programCollection.glslSources.add(shaderName) << glu::ClosestHitSource(chit.str()) << buildOptions;
1244 if (hasIntersection)
1246 const std::string shaderName = "isec_" + std::to_string(plIdxSz);
1247 const auto shaderIdx = getShaderIdx(pipelineIdx, isecShaderIdx, stageCount);
1249 std::stringstream isec;
1252 << "#extension GL_EXT_ray_tracing : require\n"
1253 << "hitAttributeEXT vec3 hitAttribute;\n"
1256 << constantDecls.at(shaderIdx)
1260 << pipelineAdds.at(plIdxSz)
1261 << stageStores.at(isecShaderIdx)
1262 << " hitAttribute = vec3(0.0, 0.0, 0.0);\n"
1263 << " reportIntersectionEXT(5.0, 0);\n"
1267 programCollection.glslSources.add(shaderName) << glu::IntersectionSource(isec.str()) << buildOptions;
1272 const std::string shaderName = "miss_" + std::to_string(plIdxSz);
1273 const auto shaderIdx = getShaderIdx(pipelineIdx, missShaderIdx, stageCount);
1275 std::stringstream miss;
1278 << "#extension GL_EXT_ray_tracing : require\n"
1279 << "layout (location=0) rayPayloadInEXT vec3 hitValue;\n"
1282 << constantDecls.at(shaderIdx)
1286 << pipelineAdds.at(plIdxSz)
1287 << stageStores.at(missShaderIdx)
1291 programCollection.glslSources.add(shaderName) << glu::MissSource(miss.str()) << buildOptions;
1296 const std::string shaderName = "call_" + std::to_string(plIdxSz);
1297 const auto shaderIdx = getShaderIdx(pipelineIdx, callShaderIdx, stageCount);
1299 std::stringstream call;
1302 << "#extension GL_EXT_ray_tracing : require\n"
1303 << "layout (location=0) callableDataInEXT float unused;\n"
1306 << constantDecls.at(shaderIdx)
1310 << pipelineAdds.at(plIdxSz)
1311 << stageStores.at(callShaderIdx)
1315 programCollection.glslSources.add(shaderName) << glu::CallableSource(call.str()) << buildOptions;
1323 // Virtual base class that uses the functions above to generate sources and check for support.
1324 class SourcesAndSupportFromParamsBase : public vkt::TestCase
1327 SourcesAndSupportFromParamsBase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BaseParamsPtr&& params)
1328 : vkt::TestCase(testCtx, name, description)
1329 , m_params(std::move(params))
1331 virtual ~SourcesAndSupportFromParamsBase (void) {}
1332 void initPrograms (vk::SourceCollections& programCollection) const override;
1333 void checkSupport (Context& context) const override;
1336 const BaseParamsPtr m_params;
1339 void SourcesAndSupportFromParamsBase::initPrograms (vk::SourceCollections &programCollection) const
1341 generateSources(programCollection, m_params.get());
1344 void SourcesAndSupportFromParamsBase::checkSupport (Context &context) const
1346 checkShaderModuleIdentifierSupport(context);
1348 if (m_params->hasVertexPipelineStage())
1349 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1351 if (m_params->hasFrag())
1352 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1354 if (m_params->hasTess())
1355 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1357 if (m_params->hasGeom())
1358 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1360 if (m_params->hasRayTracing())
1362 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1363 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1367 // Check shader module identifiers are constant across different API calls.
1368 class ConstantModuleIdentifiersInstance : public vkt::TestInstance
1371 enum class APICall { MODULE = 0, CREATE_INFO, BOTH };
1373 struct Params : public BaseParams
1376 bool differentDevices;
1378 Params (PipelineType pipelineType_,
1379 GraphicsShaderVec graphicsShaders_,
1380 RTShaderVec rtShaders_,
1381 uint8_t pipelineCount_,
1382 const tcu::Maybe<uint8_t>& pipelineToRun_,
1386 bool differentDevices_)
1387 : BaseParams (pipelineType_, graphicsShaders_, rtShaders_, pipelineCount_, pipelineToRun_, useSCs_, useCache_)
1388 , apiCall (apiCall_)
1389 , differentDevices (differentDevices_)
1392 virtual ~Params () {}
1394 bool needsVkModule (void) const
1396 return (apiCall != APICall::CREATE_INFO);
1400 using ParamsPtr = std::unique_ptr<Params>;
1402 ConstantModuleIdentifiersInstance (Context& context, const Params* params)
1403 : vkt::TestInstance(context)
1406 virtual ~ConstantModuleIdentifiersInstance (void) {}
1407 tcu::TestStatus runTest (const DeviceInterface& vkd1, const VkDevice device1,
1408 const DeviceInterface& vkd2, const VkDevice device2);
1409 tcu::TestStatus iterate (void) override;
1412 const Params* m_params;
1415 tcu::TestStatus ConstantModuleIdentifiersInstance::runTest (const DeviceInterface& vkd1, const VkDevice device1,
1416 const DeviceInterface& vkd2, const VkDevice device2)
1418 const auto& binaries = m_context.getBinaryCollection();
1419 DE_ASSERT(!binaries.empty());
1421 std::set<ShaderModuleId> uniqueIds;
1423 size_t binaryCount = 0u;
1425 for (const auto& binary : binaries)
1430 const auto binSize = binary.getSize();
1431 const auto binData = reinterpret_cast<const uint32_t*>(binary.getBinary());
1432 const auto shaderModule = (m_params->needsVkModule() ? createShaderModule(vkd1, device1, binary) : Move<VkShaderModule>());
1434 // The first one will be a VkShaderModule if needed.
1435 const auto id1 = (m_params->needsVkModule()
1436 ? getShaderModuleIdentifier(vkd1, device1, shaderModule.get())
1437 : getShaderModuleIdentifier(vkd1, device1, makeShaderModuleCreateInfo(binSize, binData)));
1439 // The second one will be a VkShaderModule only when comparing shader modules.
1440 const auto id2 = ((m_params->apiCall == APICall::MODULE)
1441 ? getShaderModuleIdentifier(vkd2, device2, shaderModule.get())
1442 : getShaderModuleIdentifier(vkd2, device2, makeShaderModuleCreateInfo(binSize, binData)));
1447 uniqueIds.insert(id1);
1451 return tcu::TestStatus::fail("The same shader module returned different identifiers");
1453 if (uniqueIds.size() != binaryCount)
1454 return tcu::TestStatus::fail("Different modules share the same identifier");
1456 return tcu::TestStatus::pass("Pass");
1459 // Helper to create a new device supporting shader module identifiers.
1462 Move<VkDevice> device;
1463 std::unique_ptr<DeviceDriver> vkd;
1464 deUint32 queueFamilyIndex;
1466 std::unique_ptr<SimpleAllocator> allocator;
1468 // Forbid copy and assignment.
1469 DeviceHelper (const DeviceHelper&) = delete;
1470 DeviceHelper& operator= (const DeviceHelper& other) = delete;
1472 DeviceHelper (Context& context, bool enableRayTracing = false)
1474 const auto& vkp = context.getPlatformInterface();
1475 const auto& vki = context.getInstanceInterface();
1476 const auto instance = context.getInstance();
1477 const auto physicalDevice = context.getPhysicalDevice();
1479 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1481 // Get device features (these have to be checked in the test case).
1482 VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT shaderIdFeatures = initVulkanStructure();
1483 VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT cacheControlFeatures = initVulkanStructure(&shaderIdFeatures);
1485 VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptorIdxFeatures = initVulkanStructure(&cacheControlFeatures);
1486 VkPhysicalDeviceBufferDeviceAddressFeaturesKHR deviceAddressFeatures = initVulkanStructure(&descriptorIdxFeatures);
1488 VkPhysicalDeviceFeatures2 deviceFeatures = initVulkanStructure(enableRayTracing
1489 ? reinterpret_cast<void*>(&deviceAddressFeatures)
1490 : reinterpret_cast<void*>(&cacheControlFeatures));
1492 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
1494 // Make sure robust buffer access is disabled as in the default device.
1495 deviceFeatures.features.robustBufferAccess = VK_FALSE;
1497 const auto queuePriority = 1.0f;
1498 const VkDeviceQueueCreateInfo queueInfo
1500 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
1501 nullptr, // const void* pNext;
1502 0u, // VkDeviceQueueCreateFlags flags;
1503 queueFamilyIndex, // deUint32 queueFamilyIndex;
1504 1u, // deUint32 queueCount;
1505 &queuePriority, // const float* pQueuePriorities;
1508 // Required extensions. Note: many of these require VK_KHR_get_physical_device_properties2, which is an instance extension.
1509 std::vector<const char*> requiredExtensions
1511 "VK_EXT_pipeline_creation_cache_control",
1512 "VK_EXT_shader_module_identifier",
1515 if (enableRayTracing)
1517 requiredExtensions.push_back("VK_KHR_maintenance3");
1518 requiredExtensions.push_back("VK_EXT_descriptor_indexing");
1519 requiredExtensions.push_back("VK_KHR_buffer_device_address");
1520 requiredExtensions.push_back("VK_KHR_deferred_host_operations");
1521 requiredExtensions.push_back("VK_KHR_acceleration_structure");
1522 requiredExtensions.push_back("VK_KHR_shader_float_controls");
1523 requiredExtensions.push_back("VK_KHR_spirv_1_4");
1524 requiredExtensions.push_back("VK_KHR_ray_tracing_pipeline");
1527 const VkDeviceCreateInfo createInfo
1529 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
1530 deviceFeatures.pNext, // const void* pNext;
1531 0u, // VkDeviceCreateFlags flags;
1532 1u, // deUint32 queueCreateInfoCount;
1533 &queueInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
1534 0u, // deUint32 enabledLayerCount;
1535 nullptr, // const char* const* ppEnabledLayerNames;
1536 de::sizeU32(requiredExtensions), // deUint32 enabledExtensionCount;
1537 de::dataOrNull(requiredExtensions), // const char* const* ppEnabledExtensionNames;
1538 &deviceFeatures.features, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
1541 // Create custom device and related objects
1542 device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &createInfo);
1543 vkd.reset(new DeviceDriver(vkp, instance, device.get()));
1544 queue = getDeviceQueue(*vkd, *device, queueFamilyIndex, 0u);
1545 allocator.reset(new SimpleAllocator(*vkd, device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
1549 tcu::TestStatus ConstantModuleIdentifiersInstance::iterate (void)
1551 // The second device may be the one from the context or a new device for the cases that require different devices.
1552 const auto& vkd = m_context.getDeviceInterface();
1553 const auto device = m_context.getDevice();
1554 const std::unique_ptr<DeviceHelper> helper (m_params->differentDevices ? new DeviceHelper(m_context) : nullptr);
1556 const auto& di1 = vkd;
1557 const auto dev1 = device;
1558 const auto& di2 = (m_params->differentDevices ? *helper->vkd : vkd);
1559 const auto dev2 = (m_params->differentDevices ? helper->device.get() : device);
1561 return runTest(di1, dev1, di2, dev2);
1564 class ConstantModuleIdentifiersCase : public SourcesAndSupportFromParamsBase
1567 using Params = ConstantModuleIdentifiersInstance::Params;
1568 using ParamsPtr = ConstantModuleIdentifiersInstance::ParamsPtr;
1570 ConstantModuleIdentifiersCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr&& params)
1571 : SourcesAndSupportFromParamsBase(testCtx, name, description, BaseParamsPtr(static_cast<BaseParams*>(params.release())))
1573 virtual ~ConstantModuleIdentifiersCase (void) {}
1574 TestInstance* createInstance (Context& context) const override;
1577 TestInstance* ConstantModuleIdentifiersCase::createInstance (Context &context) const
1579 const auto paramsPtr = dynamic_cast<Params*>(m_params.get());
1580 DE_ASSERT(paramsPtr);
1582 return new ConstantModuleIdentifiersInstance(context, paramsPtr);
1585 // Tests that create one or more pipelines using several shaders, obtain the shader ids from one of the pipelines and use them to
1586 // attempt creation of a new pipeline to be used normally.
1587 class CreateAndUseIdsInstance : public vkt::TestInstance
1590 using RndGenPtr = std::shared_ptr<de::Random>;
1592 struct Params : public BaseParams
1594 PipelineConstructionType constructionType;
1595 bool useRTLibraries; // Use ray tracing libraries? For monolithic builds only.
1596 UseModuleCase moduleUseCase;
1597 CapturedPropertiesFlags capturedProperties; // For UseModuleCase::ID only.
1600 Params (PipelineType pipelineType_,
1601 GraphicsShaderVec graphicsShaders_,
1602 RTShaderVec rtShaders_,
1603 uint8_t pipelineCount_,
1604 const tcu::Maybe<uint8_t>& pipelineToRun_,
1607 PipelineConstructionType constructionType_,
1608 bool useRTLibraries_,
1609 UseModuleCase moduleUseCase_,
1610 CapturedPropertiesFlags capturedProperties_)
1611 : BaseParams (pipelineType_, graphicsShaders_, rtShaders_, pipelineCount_, pipelineToRun_, useSCs_, useCache_)
1612 , constructionType (constructionType_)
1613 , useRTLibraries (useRTLibraries_)
1614 , moduleUseCase (moduleUseCase_)
1615 , capturedProperties(capturedProperties_)
1618 DE_ASSERT(!useRTLibraries || hasRayTracing());
1619 DE_ASSERT(!useRTLibraries || constructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1620 DE_ASSERT(capturedProperties == 0u || moduleUseCase == UseModuleCase::ID);
1622 // We will only be capturing properties if using one pipeline that will be run later.
1623 DE_ASSERT(capturedProperties == 0u || (pipelineCount == uint8_t{1} && static_cast<bool>(pipelineToRun)));
1626 virtual ~Params () {}
1628 // Convenience helper method.
1629 de::Random& getRndGen (void) const
1634 // Copy parameters resetting the random number generator with a new seed.
1635 BaseParamsPtr copy (uint32_t newSeed)
1637 std::unique_ptr<Params> clone (new Params(*this));
1638 clone->rnd.reset(new de::Random(newSeed));
1639 return BaseParamsPtr(clone.release());
1643 using ParamsPtr = std::unique_ptr<Params>;
1645 CreateAndUseIdsInstance (Context& context, const Params* params)
1646 : vkt::TestInstance (context)
1649 virtual ~CreateAndUseIdsInstance (void) {}
1651 tcu::TestStatus iterate (void) override;
1654 const Params* m_params;
1657 class CreateAndUseIdsCase : public SourcesAndSupportFromParamsBase
1660 CreateAndUseIdsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BaseParamsPtr&& params)
1661 : SourcesAndSupportFromParamsBase (testCtx, name, description, std::move(params))
1662 , m_createAndUseIdsParams (dynamic_cast<const CreateAndUseIdsInstance::Params*>(m_params.get()))
1664 DE_ASSERT(m_createAndUseIdsParams);
1666 virtual ~CreateAndUseIdsCase (void) {}
1667 void checkSupport (Context& context) const override;
1668 TestInstance* createInstance (Context& context) const override;
1671 const CreateAndUseIdsInstance::Params* m_createAndUseIdsParams;
1674 void CreateAndUseIdsCase::checkSupport (Context &context) const
1676 SourcesAndSupportFromParamsBase::checkSupport(context);
1678 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_createAndUseIdsParams->constructionType);
1680 if (m_createAndUseIdsParams->useRTLibraries)
1681 context.requireDeviceFunctionality("VK_KHR_pipeline_library");
1683 if (m_createAndUseIdsParams->capturedProperties != 0u)
1684 context.requireDeviceFunctionality("VK_KHR_pipeline_executable_properties");
1687 TestInstance* CreateAndUseIdsCase::createInstance (Context &context) const
1689 return new CreateAndUseIdsInstance(context, m_createAndUseIdsParams);
1692 using SpecInfoPtr = std::unique_ptr<VkSpecializationInfo>;
1693 using SCMapEntryVec = std::vector<VkSpecializationMapEntry>;
1695 SpecInfoPtr maybeMakeSpecializationInfo (bool makeIt, const VkSpecializationMapEntry* entry, std::vector<uint32_t>::const_iterator& iter)
1701 SpecInfoPtr info (new VkSpecializationInfo);
1703 info->mapEntryCount = 1u;
1704 info->pMapEntries = entry;
1705 info->dataSize = sizeof(uint32_t);
1706 info->pData = &(*(iter++));
1711 VkPipelineRasterizationStateCreateInfo makeRasterizationState (bool rasterizationDisabled)
1713 VkPipelineRasterizationStateCreateInfo state = initVulkanStructure();
1714 state.rasterizerDiscardEnable = (rasterizationDisabled ? VK_TRUE : VK_FALSE);
1715 state.lineWidth = 1.0f;
1719 class PipelineStageInfo
1722 VkShaderModule m_module;
1723 ShaderModuleId m_moduleId;
1724 ShaderStageIdPtr m_moduleIdCreateInfo;
1725 SpecInfoPtr m_specInfo;
1728 PipelineStageInfo ()
1729 : m_module (DE_NULL)
1731 , m_moduleIdCreateInfo ()
1735 void setModule (const DeviceInterface &vkd, const VkDevice device, const VkShaderModule module, UseModuleCase moduleUse, de::Random& rnd)
1739 m_moduleId = getShaderModuleIdentifier(vkd, device, module);
1740 maybeMangleShaderModuleId(m_moduleId, moduleUse, rnd);
1742 m_moduleIdCreateInfo = makeShaderStageModuleIdentifierCreateInfo(m_moduleId, moduleUse, &rnd);
1745 void setSpecInfo (SpecInfoPtr&& specInfo)
1747 m_specInfo = std::move(specInfo);
1750 VkShaderModule getModule (void) const
1755 VkShaderModule getUsedModule (UseModuleCase moduleUse)
1757 return retUsedModule(m_module, moduleUse);
1760 const VkPipelineShaderStageModuleIdentifierCreateInfoEXT* getModuleIdCreateInfo (void) const
1762 return m_moduleIdCreateInfo.get();
1765 const VkSpecializationInfo* getSpecInfo (void) const
1767 return m_specInfo.get();
1770 // Forbid copy and assignment. This would break the relationship between moduleId and moduleIdCreateInfo.
1771 PipelineStageInfo (const PipelineStageInfo&) = delete;
1772 PipelineStageInfo& operator=(const PipelineStageInfo&) = delete;
1775 std::vector<uint32_t> makeComputeSpecConstants (uint32_t stageConstant)
1777 return std::vector<uint32_t>{stageConstant, 1u, 1u, 1u};
1780 SCMapEntryVec makeComputeSpecMapEntries (void)
1782 const auto kNumEntries = 4u; // Matches the vector above.
1783 const auto entrySizeSz = sizeof(uint32_t);
1784 const auto entrySize = static_cast<uint32_t>(entrySizeSz);
1785 SCMapEntryVec entries;
1787 entries.reserve(kNumEntries);
1788 for (uint32_t i = 0u; i < kNumEntries; ++i)
1790 const VkSpecializationMapEntry entry =
1792 i, // uint32_t constantID;
1793 (entrySize * i), // uint32_t offset;
1794 entrySizeSz, // size_t size;
1796 entries.push_back(entry);
1802 SpecInfoPtr makeComputeSpecInfo (const SCMapEntryVec& scEntries, const std::vector<uint32_t>& scData)
1804 SpecInfoPtr scInfo (new VkSpecializationInfo);
1806 scInfo->mapEntryCount = de::sizeU32(scEntries);
1807 scInfo->pMapEntries = de::dataOrNull(scEntries);
1808 scInfo->dataSize = de::dataSize(scData);
1809 scInfo->pData = de::dataOrNull(scData);
1814 tcu::TestStatus CreateAndUseIdsInstance::iterate (void)
1816 const auto& vkd = m_context.getDeviceInterface();
1817 const auto device = m_context.getDevice();
1818 auto& alloc = m_context.getDefaultAllocator();
1819 const auto queue = m_context.getUniversalQueue();
1820 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1821 const auto& vki = m_context.getInstanceInterface();
1822 const auto physicalDevice = m_context.getPhysicalDevice();
1824 const auto pipelineStages = m_params->getPipelineStageFlags();
1825 const auto shaderStages = m_params->getShaderStageFlags();
1826 const auto captureFlags = getPipelineCreateFlags(m_params->capturedProperties);
1827 const bool needsCapture = (captureFlags != 0u);
1828 const auto isGraphics = (m_params->pipelineType == PipelineType::GRAPHICS);
1829 const auto isCompute = (m_params->pipelineType == PipelineType::COMPUTE);
1830 const auto fbFormat = VK_FORMAT_R8G8B8A8_UNORM;
1831 const auto tcuFbFormat = mapVkFormat(fbFormat);
1832 const auto pixelSize = tcu::getPixelSize(tcuFbFormat);
1833 const auto fbExtent = makeExtent3D(1u, 1u, 1u);
1834 const tcu::IVec3 iExtent (static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(fbExtent.depth));
1835 const auto isRT = m_params->hasRayTracing();
1836 const auto hasHit = m_params->hasHit();
1837 const auto hasHitAndMiss = hasHit && m_params->hasMiss();
1838 const auto stagesCount = m_params->stageCountPerPipeline();
1839 const auto pipelineCount32 = static_cast<uint32_t>(m_params->pipelineCount);
1840 const auto hasTess = m_params->hasTess();
1841 const auto topology = (hasTess ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1842 const auto patchCPs = (hasTess ? 3u : 0u);
1843 const auto useSCs = m_params->useSpecializationConstants;
1844 const auto shaderConstants = generateShaderConstants(m_params->pipelineType, m_params->pipelineCount, stagesCount);
1845 const auto runOnePipeline = static_cast<bool>(m_params->pipelineToRun);
1846 const bool reqCacheMiss = expectCacheMiss(m_params->moduleUseCase);
1847 const bool qualityWarn = (m_params->useCache && !needsCapture);
1848 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
1849 const tcu::Vec4 blueColor (0.0f, 0.0f, 1.0f, 1.0f); // Must match fragment shader above.
1851 // Used when capturing pipeline executable properties.
1852 PipelineExecutablePropertyVec classicExeProps;
1853 PipelineExecutablePropertyVec identifierExeProps;
1855 // Command pool and buffer.
1856 const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
1857 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1858 const auto cmdBuffer = cmdBufferPtr.get();
1860 // Begin command buffer. We may need it below for RT.
1861 beginCommandBuffer(vkd, cmdBuffer);
1863 // Descriptor set layouts. Typically 1 but ray tracing tests use a separate set for the acceleration structure.
1864 std::vector<VkDescriptorSetLayout> setLayouts;
1866 DescriptorSetLayoutBuilder setLayoutBuilder;
1867 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, shaderStages);
1868 for (uint8_t i = 0; i < m_params->pipelineCount; ++i)
1869 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, shaderStages);
1870 const auto mainSetLayout = setLayoutBuilder.build(vkd, device);
1871 setLayouts.push_back(mainSetLayout.get());
1873 const auto auxSetLayout = (isRT
1874 ? DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, shaderStages).build(vkd, device)
1875 : Move<VkDescriptorSetLayout>());
1877 setLayouts.push_back(auxSetLayout.get());
1880 const auto pipelineLayout = makePipelineLayout(vkd, device, de::sizeU32(setLayouts), de::dataOrNull(setLayouts));
1883 DescriptorPoolBuilder poolBuilder;
1884 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1885 poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pipelineCount32);
1887 poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
1888 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, de::sizeU32(setLayouts));
1890 // Descriptor buffers.
1891 const auto storageBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t) * stagesCount);
1892 const auto storageBufferInfo = makeBufferCreateInfo(storageBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1893 BufferWithMemory storageBuffer (vkd, device, alloc, storageBufferInfo, MemoryRequirement::HostVisible);
1894 auto& storageBufferAlloc = storageBuffer.getAllocation();
1895 void* storageBufferData = storageBufferAlloc.getHostPtr();
1897 // For the uniform buffers we'll use a single allocation.
1898 const auto deviceProperties = getPhysicalDeviceProperties(vki, physicalDevice);
1899 const auto minBlock = de::roundUp(static_cast<VkDeviceSize>(sizeof(uint32_t)), deviceProperties.limits.minUniformBufferOffsetAlignment);
1900 const auto uniformBufferSize = minBlock * pipelineCount32;
1901 const auto uniformBufferInfo = makeBufferCreateInfo(uniformBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1902 BufferWithMemory uniformBuffer (vkd, device, alloc, uniformBufferInfo, MemoryRequirement::HostVisible);
1903 auto& uniformBufferAlloc = uniformBuffer.getAllocation();
1904 void* uniformBufferData = uniformBufferAlloc.getHostPtr();
1906 deMemset(storageBufferData, 0, static_cast<size_t>(storageBufferSize));
1907 deMemset(uniformBufferData, 0, static_cast<size_t>(uniformBufferSize));
1908 flushAlloc(vkd, device, storageBufferAlloc);
1909 flushAlloc(vkd, device, uniformBufferAlloc);
1911 // Acceleration structures if needed.
1912 using TLASPtr = de::MovePtr<TopLevelAccelerationStructure>;
1913 using BLASPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
1920 tlas = makeTopLevelAccelerationStructure();
1921 blas = BLASPtr(makeBottomLevelAccelerationStructure().release());
1923 // If we don't want hits we move the geometry way off in the X axis.
1924 // If we want hits and misses we launch 2 rays (see raygen shader).
1925 const float xOffset = (hasHit ? 0.0f : 100.0f);
1927 if (m_params->hasISec())
1929 // AABB around (0.5, 0.5, 5).
1930 const std::vector<tcu::Vec3> geometry
1932 tcu::Vec3(0.0f + xOffset, 0.0f, 4.0f),
1933 tcu::Vec3(1.0f + xOffset, 1.0f, 6.0f),
1936 blas->addGeometry(geometry, false/*isTriangles*/, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
1940 // Triangle surrounding (0.5, 0.5, 5).
1941 const std::vector<tcu::Vec3> geometry
1943 tcu::Vec3(0.25f + xOffset, 0.25f, 5.0f),
1944 tcu::Vec3(0.75f + xOffset, 0.25f, 5.0f),
1945 tcu::Vec3(0.5f + xOffset, 0.75f, 5.0f),
1948 blas->addGeometry(geometry, true/*isTriangles*/, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
1950 blas->createAndBuild(vkd, device, cmdBuffer, alloc);
1951 tlas->setInstanceCount(1u);
1952 tlas->addInstance(blas, identityMatrix3x4, 0u, 0xFFu, 0u, VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR);
1954 tlas->createAndBuild(vkd, device, cmdBuffer, alloc);
1957 // Graphics pipeline data if needed.
1958 std::unique_ptr<ImageWithMemory> colorAtt;
1959 VkImageSubresourceRange colorSRR;
1960 VkImageSubresourceLayers colorSRL;
1961 Move<VkImageView> colorAttView;
1962 Move<VkRenderPass> renderPass;
1963 Move<VkFramebuffer> framebuffer;
1964 std::unique_ptr<BufferWithMemory> verifBuffer;
1965 std::vector<VkViewport> viewports;
1966 std::vector<VkRect2D> scissors;
1968 // This is constant for all shader stages.
1969 const VkSpecializationMapEntry scMapEntry =
1971 0u, // uint32_t constantID;
1972 0u, // uint32_t offset;
1973 sizeof(uint32_t), // size_t size;
1978 const VkImageCreateInfo colorAttCreateInfo =
1980 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1981 nullptr, // const void* pNext;
1982 0u, // VkImageCreateFlags flags;
1983 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1984 fbFormat, // VkFormat format;
1985 fbExtent, // VkExtent3D extent;
1986 1u, // uint32_t mipLevels;
1987 1u, // uint32_t arrayLayers;
1988 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1989 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1990 (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // VkImageUsageFlags usage;
1991 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1992 0u, // uint32_t queueFamilyIndexCount;
1993 nullptr, // const uint32_t* pQueueFamilyIndices;
1994 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1997 colorAtt .reset(new ImageWithMemory(vkd, device, alloc, colorAttCreateInfo, MemoryRequirement::Any));
1998 colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1999 colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2000 colorAttView = makeImageView(vkd, device, colorAtt->get(), VK_IMAGE_VIEW_TYPE_2D, fbFormat, colorSRR);
2001 renderPass = makeRenderPass(vkd, device, fbFormat);
2002 framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorAttView.get(), fbExtent.width, fbExtent.height);
2004 DE_ASSERT(fbExtent.width == 1u && fbExtent.height == 1u && fbExtent.depth == 1u);
2005 const auto verifBufferSize = static_cast<VkDeviceSize>(pixelSize);
2006 const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2007 verifBuffer.reset(new BufferWithMemory(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible));
2009 viewports.push_back(makeViewport(fbExtent));
2010 scissors.push_back(makeRect2D(fbExtent));
2014 const auto mainDescriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), mainSetLayout.get());
2015 const auto auxDescriptorSet = (isRT ? makeDescriptorSet(vkd, device, descriptorPool.get(), auxSetLayout.get()) : Move<VkDescriptorSet>());
2017 std::vector<VkDescriptorSet> rawDescriptorSets;
2018 rawDescriptorSets.push_back(mainDescriptorSet.get());
2020 rawDescriptorSets.push_back(auxDescriptorSet.get());
2022 // Update descriptor sets.
2023 DescriptorSetUpdateBuilder updateBuilder;
2025 const auto storageDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), 0ull, storageBufferSize);
2026 updateBuilder.writeSingle(mainDescriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageDescInfo);
2028 for (uint32_t uboIdx = 0u; uboIdx < pipelineCount32; ++uboIdx)
2030 const auto uboDescInfo = makeDescriptorBufferInfo(uniformBuffer.get(), minBlock * uboIdx, minBlock);
2031 updateBuilder.writeSingle(mainDescriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(uboIdx + 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboDescInfo);
2035 const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
2037 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
2040 tlas.get()->getPtr(),
2043 updateBuilder.writeSingle(auxDescriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
2045 updateBuilder.update(vkd, device);
2048 using ModuleVec = std::vector<Move<VkShaderModule>>;
2049 using PipelinePtrVec = std::vector<Move<VkPipeline>>;
2050 using PipelineVec = std::vector<VkPipeline>;
2051 using WrapperVec = std::vector<std::unique_ptr<GraphicsPipelineWrapper>>;
2052 using BufferPtr = de::MovePtr<BufferWithMemory>;
2054 ModuleVec vertModules;
2055 ModuleVec tescModules;
2056 ModuleVec teseModules;
2057 ModuleVec geomModules;
2058 ModuleVec fragModules;
2060 ModuleVec compModules;
2062 ModuleVec rgenModules;
2063 ModuleVec ahitModules;
2064 ModuleVec chitModules;
2065 ModuleVec isecModules;
2066 ModuleVec missModules;
2067 ModuleVec callModules;
2074 VkStridedDeviceAddressRegionKHR rgenRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0ull, 0ull);
2075 VkStridedDeviceAddressRegionKHR xhitRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0ull, 0ull);
2076 VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0ull, 0ull);
2077 VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0ull, 0ull);
2079 WrapperVec pipelineWrappers; // For graphics pipelines.
2080 PipelinePtrVec pipelinePtrs; // For other pipelines.
2081 PipelineVec pipelines;
2082 Move<VkPipelineCache> pipelineCache;
2084 if (m_params->useCache)
2086 const VkPipelineCacheCreateInfo cacheCreateInfo = initVulkanStructure();
2087 pipelineCache = createPipelineCache(vkd, device, &cacheCreateInfo);
2090 const auto& binaries = m_context.getBinaryCollection();
2094 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2095 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
2097 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
2098 nullptr, // const void* pNext;
2099 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
2100 topology, // VkPrimitiveTopology topology;
2101 VK_FALSE, // VkBool32 primitiveRestartEnable;
2103 const VkPipelineDepthStencilStateCreateInfo depthStencilState = initVulkanStructure();
2104 VkPipelineMultisampleStateCreateInfo multisampleState = initVulkanStructure();
2105 multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
2106 VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
2107 deMemset(&colorBlendAttachmentState, 0, sizeof(colorBlendAttachmentState));
2108 colorBlendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
2109 const VkPipelineColorBlendStateCreateInfo colorBlendState =
2111 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
2112 nullptr, // const void* pNext
2113 0u, // VkPipelineColorBlendStateCreateFlags flags
2114 VK_FALSE, // VkBool32 logicOpEnable
2115 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
2116 1u, // deUint32 attachmentCount
2117 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
2118 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
2121 auto shaderConstIt = shaderConstants.begin();
2123 // In case we have to run a pipeline.
2124 PipelineStageInfo vertToRun;
2125 PipelineStageInfo tescToRun;
2126 PipelineStageInfo teseToRun;
2127 PipelineStageInfo geomToRun;
2128 PipelineStageInfo fragToRun;
2130 for (uint32_t i = 0; i < pipelineCount32; ++i)
2132 const auto runThis = (runOnePipeline && static_cast<uint32_t>(m_params->pipelineToRun.get()) == i);
2133 const auto suffix = "_" + std::to_string(i);
2134 const auto vertName = "vert" + suffix;
2135 const auto tescName = "tesc" + suffix;
2136 const auto teseName = "tese" + suffix;
2137 const auto geomName = "geom" + suffix;
2138 const auto fragName = "frag" + suffix;
2140 pipelineWrappers.emplace_back(new GraphicsPipelineWrapper(vkd, device, m_params->constructionType, captureFlags));
2141 auto& wrapper = *pipelineWrappers.back();
2143 VkShaderModule vertModule = DE_NULL;
2144 VkShaderModule tescModule = DE_NULL;
2145 VkShaderModule teseModule = DE_NULL;
2146 VkShaderModule geomModule = DE_NULL;
2147 VkShaderModule fragModule = DE_NULL;
2149 SpecInfoPtr vertSpecInfo;
2150 SpecInfoPtr tescSpecInfo;
2151 SpecInfoPtr teseSpecInfo;
2152 SpecInfoPtr geomSpecInfo;
2153 SpecInfoPtr fragSpecInfo;
2155 vertModules .push_back(createShaderModule(vkd, device, binaries.get(vertName)));
2156 vertModule = vertModules.back().get();
2157 vertSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2159 if (binaries.contains(tescName))
2161 tescModules .push_back(createShaderModule(vkd, device, binaries.get(tescName)));
2162 tescModule = tescModules.back().get();
2163 tescSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2166 if (binaries.contains(teseName))
2168 teseModules .push_back(createShaderModule(vkd, device, binaries.get(teseName)));
2169 teseModule = teseModules.back().get();
2170 teseSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2173 if (binaries.contains(geomName))
2175 geomModules .push_back(createShaderModule(vkd, device, binaries.get(geomName)));
2176 geomModule = geomModules.back().get();
2177 geomSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2180 if (binaries.contains(fragName))
2182 fragModules .push_back(createShaderModule(vkd, device, binaries.get(fragName)));
2183 fragModule = fragModules.back().get();
2184 fragSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2187 const auto rasterizationState = makeRasterizationState(fragModule == DE_NULL);
2189 wrapper .setDefaultPatchControlPoints(patchCPs)
2190 .setupVertexInputStete(&vertexInputState, &inputAssemblyState, pipelineCache.get())
2191 .setupPreRasterizationShaderState2(
2194 pipelineLayout.get(),
2198 &rasterizationState,
2207 pipelineCache.get())
2208 .setupFragmentShaderState(
2209 pipelineLayout.get(),
2217 pipelineCache.get())
2218 .setupFragmentOutputState(*renderPass, 0u, &colorBlendState, &multisampleState, pipelineCache.get())
2219 .setMonolithicPipelineLayout(pipelineLayout.get())
2220 .buildPipeline(pipelineCache.get());
2222 pipelines.push_back(wrapper.getPipeline());
2224 // Capture properties if needed.
2226 classicExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2230 vertToRun.setModule(vkd, device, vertModule, m_params->moduleUseCase, m_params->getRndGen());
2231 vertToRun.setSpecInfo(std::move(vertSpecInfo));
2233 if (tescModule != DE_NULL)
2235 tescToRun.setModule(vkd, device, tescModule, m_params->moduleUseCase, m_params->getRndGen());
2236 tescToRun.setSpecInfo(std::move(tescSpecInfo));
2239 if (teseModule != DE_NULL)
2241 teseToRun.setModule(vkd, device, teseModule, m_params->moduleUseCase, m_params->getRndGen());
2242 teseToRun.setSpecInfo(std::move(teseSpecInfo));
2245 if (geomModule != DE_NULL)
2247 geomToRun.setModule(vkd, device, geomModule, m_params->moduleUseCase, m_params->getRndGen());
2248 geomToRun.setSpecInfo(std::move(geomSpecInfo));
2251 if (fragModule != DE_NULL)
2253 fragToRun.setModule(vkd, device, fragModule, m_params->moduleUseCase, m_params->getRndGen());
2254 fragToRun.setSpecInfo(std::move(fragSpecInfo));
2261 // Append the pipeline to run at the end of the vector.
2262 pipelineWrappers.emplace_back(new GraphicsPipelineWrapper(vkd, device, m_params->constructionType, captureFlags));
2263 auto& wrapper = *pipelineWrappers.back();
2265 const auto fragModule = fragToRun.getModule();
2266 const auto rasterizationState = makeRasterizationState(fragModule == DE_NULL);
2270 wrapper .setDefaultPatchControlPoints(patchCPs)
2271 .setupVertexInputStete(&vertexInputState, &inputAssemblyState, pipelineCache.get())
2272 .setupPreRasterizationShaderState3(
2275 pipelineLayout.get(),
2278 vertToRun.getUsedModule(m_params->moduleUseCase),
2279 vertToRun.getModuleIdCreateInfo(),
2280 &rasterizationState,
2281 tescToRun.getUsedModule(m_params->moduleUseCase),
2282 tescToRun.getModuleIdCreateInfo(),
2283 teseToRun.getUsedModule(m_params->moduleUseCase),
2284 teseToRun.getModuleIdCreateInfo(),
2285 geomToRun.getUsedModule(m_params->moduleUseCase),
2286 geomToRun.getModuleIdCreateInfo(),
2287 vertToRun.getSpecInfo(),
2288 tescToRun.getSpecInfo(),
2289 teseToRun.getSpecInfo(),
2290 geomToRun.getSpecInfo(),
2292 pipelineCache.get())
2293 .setupFragmentShaderState2(
2294 pipelineLayout.get(),
2297 fragToRun.getUsedModule(m_params->moduleUseCase),
2298 fragToRun.getModuleIdCreateInfo(),
2302 fragToRun.getSpecInfo(),
2303 pipelineCache.get())
2304 .setupFragmentOutputState(*renderPass, 0u, &colorBlendState, &multisampleState, pipelineCache.get())
2305 .setMonolithicPipelineLayout(pipelineLayout.get())
2306 .buildPipeline(pipelineCache.get());
2309 TCU_FAIL("Cache miss expected");
2311 catch (const PipelineCompileRequiredError& err)
2314 return tcu::TestStatus::pass("Pass");
2317 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "VK_PIPELINE_COMPILE_REQUIRED despite passing a pipeline cache");
2318 return tcu::TestStatus::pass("VK_PIPELINE_COMPILE_REQUIRED"); // ;_;
2321 pipelines.push_back(wrapper.getPipeline());
2324 identifierExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2329 const auto invalidPipelineIdx = std::numeric_limits<uint32_t>::max();
2330 auto idxToRun = invalidPipelineIdx;
2332 for (uint32_t i = 0; i < pipelineCount32; ++i)
2334 const auto runThis = (runOnePipeline && static_cast<uint32_t>(m_params->pipelineToRun.get()) == i);
2335 const auto suffix = "_" + std::to_string(i);
2336 const auto compName = "comp" + suffix;
2338 const auto scData = (useSCs ? makeComputeSpecConstants(shaderConstants.at(i)) : std::vector<uint32_t>());
2339 const auto scEntries = (useSCs ? makeComputeSpecMapEntries() : std::vector<VkSpecializationMapEntry>());
2340 const auto scInfo = (useSCs ? makeComputeSpecInfo(scEntries, scData) : nullptr);
2342 compModules.push_back(createShaderModule(vkd, device, binaries.get(compName)));
2343 pipelinePtrs.push_back(makeComputePipeline(vkd, device, pipelineLayout.get(), captureFlags, compModules.back().get(), 0u, scInfo.get(), pipelineCache.get()));
2344 pipelines.push_back(pipelinePtrs.back().get());
2350 classicExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2353 if (idxToRun != invalidPipelineIdx)
2355 const auto compModule = compModules.at(idxToRun).get();
2356 auto moduleId = getShaderModuleIdentifier(vkd, device, compModule);
2358 maybeMangleShaderModuleId(moduleId, m_params->moduleUseCase, m_params->getRndGen());
2360 const auto modInfo = makeShaderStageModuleIdentifierCreateInfo(moduleId, m_params->moduleUseCase, &(m_params->getRndGen()));
2361 const auto scData = (useSCs ? makeComputeSpecConstants(shaderConstants.at(idxToRun)) : std::vector<uint32_t>());
2362 const auto scEntries = (useSCs ? makeComputeSpecMapEntries() : std::vector<VkSpecializationMapEntry>());
2363 const auto scInfo = (useSCs ? makeComputeSpecInfo(scEntries, scData) : nullptr);
2365 // Append the pipeline to run at the end of the vector.
2367 const auto pipelineFlags = (VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT | captureFlags);
2369 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
2371 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2372 modInfo.get(), // const void* pNext;
2373 0u, // VkPipelineShaderStageCreateFlags flags;
2374 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
2375 retUsedModule(compModule, m_params->moduleUseCase), // VkShaderModule module;
2376 "main", // const char* pName;
2377 scInfo.get(), // const VkSpecializationInfo* pSpecializationInfo;
2380 const VkComputePipelineCreateInfo pipelineCreateInfo =
2382 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2383 nullptr, // const void* pNext;
2384 pipelineFlags, // VkPipelineCreateFlags flags;
2385 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
2386 pipelineLayout.get(), // VkPipelineLayout layout;
2387 DE_NULL, // VkPipeline basePipelineHandle;
2388 0, // deInt32 basePipelineIndex;
2391 VkPipeline pipeline;
2392 VkResult creationResult = vkd.createComputePipelines(device, pipelineCache.get(), 1u, &pipelineCreateInfo, nullptr, &pipeline);
2394 if (creationResult == VK_PIPELINE_COMPILE_REQUIRED)
2397 return tcu::TestStatus::pass("Pass");
2400 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "VK_PIPELINE_COMPILE_REQUIRED despite passing a pipeline cache");
2401 return tcu::TestStatus::pass("VK_PIPELINE_COMPILE_REQUIRED"); // ;_;
2403 VK_CHECK(creationResult);
2406 TCU_FAIL("Cache miss expected");
2408 Move<VkPipeline> pipelinePtr(check<VkPipeline>(pipeline), Deleter<VkPipeline>(vkd, device, nullptr));
2409 pipelinePtrs.emplace_back(pipelinePtr);
2410 pipelines.push_back(pipeline);
2413 identifierExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2419 // Get some ray tracing properties and constants.
2420 const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
2421 const auto shaderGroupHandleSize = rayTracingPropertiesKHR->getShaderGroupHandleSize();
2422 const auto shaderGroupBaseAlignment = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
2423 const auto vec3Size = static_cast<uint32_t>(sizeof(tcu::Vec3));
2425 // Empty pipeline vector, needed in a couple places.
2426 const std::vector<VkPipeline> emptyPipelinesVec;
2428 auto shaderConstIt = shaderConstants.begin();
2430 // In case we have to run a pipeline.
2431 PipelineStageInfo rgenToRun;
2432 PipelineStageInfo chitToRun;
2433 PipelineStageInfo ahitToRun;
2434 PipelineStageInfo isecToRun;
2435 PipelineStageInfo missToRun;
2436 PipelineStageInfo callToRun;
2438 for (uint32_t i = 0; i < pipelineCount32; ++i)
2440 const auto runThis = (runOnePipeline && static_cast<uint32_t>(m_params->pipelineToRun.get()) == i);
2441 const auto suffix = "_" + std::to_string(i);
2442 const auto rgenName = "rgen" + suffix;
2443 const auto chitName = "chit" + suffix;
2444 const auto ahitName = "ahit" + suffix;
2445 const auto isecName = "isec" + suffix;
2446 const auto missName = "miss" + suffix;
2447 const auto callName = "call" + suffix;
2449 VkShaderModule rgenModule = DE_NULL;
2450 VkShaderModule chitModule = DE_NULL;
2451 VkShaderModule ahitModule = DE_NULL;
2452 VkShaderModule isecModule = DE_NULL;
2453 VkShaderModule missModule = DE_NULL;
2454 VkShaderModule callModule = DE_NULL;
2456 SpecInfoPtr rgenSpecInfo;
2457 SpecInfoPtr chitSpecInfo;
2458 SpecInfoPtr ahitSpecInfo;
2459 SpecInfoPtr isecSpecInfo;
2460 SpecInfoPtr missSpecInfo;
2461 SpecInfoPtr callSpecInfo;
2463 uint32_t groupCount = 1u;
2464 const uint32_t rgenGroup = 0u;
2465 tcu::Maybe<uint32_t> xhitGroup;
2466 tcu::Maybe<uint32_t> missGroup;
2467 tcu::Maybe<uint32_t> callGroup;
2469 rgenModules .push_back(createShaderModule(vkd, device, binaries.get(rgenName)));
2470 rgenModule = rgenModules.back().get();
2471 rgenSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2473 if (binaries.contains(chitName))
2475 chitModules .push_back(createShaderModule(vkd, device, binaries.get(chitName)));
2476 chitModule = chitModules.back().get();
2477 chitSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2478 xhitGroup = (static_cast<bool>(xhitGroup) ? xhitGroup : tcu::just(groupCount++));
2481 if (binaries.contains(ahitName))
2483 ahitModules .push_back(createShaderModule(vkd, device, binaries.get(ahitName)));
2484 ahitModule = ahitModules.back().get();
2485 ahitSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2486 xhitGroup = (static_cast<bool>(xhitGroup) ? xhitGroup : tcu::just(groupCount++));
2489 if (binaries.contains(isecName))
2491 isecModules .push_back(createShaderModule(vkd, device, binaries.get(isecName)));
2492 isecModule = isecModules.back().get();
2493 isecSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2494 xhitGroup = (static_cast<bool>(xhitGroup) ? xhitGroup : tcu::just(groupCount++));
2497 if (binaries.contains(missName))
2499 missModules .push_back(createShaderModule(vkd, device, binaries.get(missName)));
2500 missModule = missModules.back().get();
2501 missSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2502 missGroup = tcu::just(groupCount++);
2505 if (binaries.contains(callName))
2507 callModules .push_back(createShaderModule(vkd, device, binaries.get(callName)));
2508 callModule = callModules.back().get();
2509 callSpecInfo = maybeMakeSpecializationInfo(useSCs, &scMapEntry, shaderConstIt);
2510 callGroup = tcu::just(groupCount++);
2514 const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
2516 // These have to match the shaders.
2517 rayTracingPipeline->setMaxPayloadSize(vec3Size);
2518 rayTracingPipeline->setMaxAttributeSize(vec3Size);
2520 // Make it a library if we are using libraries.
2521 rayTracingPipeline->setCreateFlags(captureFlags | (m_params->useRTLibraries ? VK_PIPELINE_CREATE_LIBRARY_BIT_KHR : 0));
2523 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, rgenGroup, rgenSpecInfo.get());
2525 if (chitModule != DE_NULL)
2526 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, xhitGroup.get(), chitSpecInfo.get());
2528 if (ahitModule != DE_NULL)
2529 rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR, ahitModule, xhitGroup.get(), ahitSpecInfo.get());
2531 if (isecModule != DE_NULL)
2532 rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR, isecModule, xhitGroup.get(), isecSpecInfo.get());
2534 if (missModule != DE_NULL)
2535 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missModule, missGroup.get(), missSpecInfo.get());
2537 if (callModule != DE_NULL)
2538 rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, callModule, callGroup.get(), callSpecInfo.get());
2540 pipelinePtrs.emplace_back(rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get(), emptyPipelinesVec, pipelineCache.get()));
2541 pipelines.push_back(pipelinePtrs.back().get());
2543 // We may need to link the pipeline just like we'll do with shader module identifiers below.
2544 if (m_params->useRTLibraries)
2546 const auto linkedPipeline = de::newMovePtr<RayTracingPipeline>();
2548 linkedPipeline->setMaxPayloadSize(vec3Size);
2549 linkedPipeline->setMaxAttributeSize(vec3Size);
2550 linkedPipeline->setCreateFlags(captureFlags);
2552 const std::vector<VkPipeline> rawPipelines(1u, pipelines.back());
2553 pipelinePtrs.emplace_back(linkedPipeline->createPipeline(vkd, device, pipelineLayout.get(), rawPipelines, pipelineCache.get()));
2554 pipelines.push_back(pipelinePtrs.back().get());
2558 classicExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2563 rgenToRun.setModule(vkd, device, rgenModule, m_params->moduleUseCase, m_params->getRndGen());
2564 rgenToRun.setSpecInfo(std::move(rgenSpecInfo));
2566 if (chitModule != DE_NULL)
2568 chitToRun.setModule(vkd, device, chitModule, m_params->moduleUseCase, m_params->getRndGen());
2569 chitToRun.setSpecInfo(std::move(chitSpecInfo));
2572 if (ahitModule != DE_NULL)
2574 ahitToRun.setModule(vkd, device, ahitModule, m_params->moduleUseCase, m_params->getRndGen());
2575 ahitToRun.setSpecInfo(std::move(ahitSpecInfo));
2578 if (isecModule != DE_NULL)
2580 isecToRun.setModule(vkd, device, isecModule, m_params->moduleUseCase, m_params->getRndGen());
2581 isecToRun.setSpecInfo(std::move(isecSpecInfo));
2584 if (missModule != DE_NULL)
2586 missToRun.setModule(vkd, device, missModule, m_params->moduleUseCase, m_params->getRndGen());
2587 missToRun.setSpecInfo(std::move(missSpecInfo));
2590 if (callModule != DE_NULL)
2592 callToRun.setModule(vkd, device, callModule, m_params->moduleUseCase, m_params->getRndGen());
2593 callToRun.setSpecInfo(std::move(callSpecInfo));
2600 uint32_t groupCount = 1u;
2601 const uint32_t rgenGroup = 0u;
2602 tcu::Maybe<uint32_t> xhitGroup;
2603 tcu::Maybe<uint32_t> missGroup;
2604 tcu::Maybe<uint32_t> callGroup;
2606 const auto rgenModule = rgenToRun.getModule(); DE_UNREF(rgenModule);
2607 const auto chitModule = chitToRun.getModule();
2608 const auto ahitModule = ahitToRun.getModule();
2609 const auto isecModule = isecToRun.getModule();
2610 const auto missModule = missToRun.getModule();
2611 const auto callModule = callToRun.getModule();
2613 if (chitModule != DE_NULL)
2614 xhitGroup = (xhitGroup ? xhitGroup : tcu::just(groupCount++));
2615 if (ahitModule != DE_NULL)
2616 xhitGroup = (xhitGroup ? xhitGroup : tcu::just(groupCount++));
2617 if (isecModule != DE_NULL)
2618 xhitGroup = (xhitGroup ? xhitGroup : tcu::just(groupCount++));
2620 if (missModule != DE_NULL)
2621 missGroup = tcu::just(groupCount++);
2623 if (callModule != DE_NULL)
2624 callGroup = tcu::just(groupCount++);
2626 const auto shaderOwningPipelinePtr = makeVkSharedPtr(de::newMovePtr<RayTracingPipeline>());
2627 const auto shaderOwningPipeline = shaderOwningPipelinePtr->get();
2629 de::SharedPtr<de::MovePtr<RayTracingPipeline>> auxiliaryPipelinePtr;
2630 RayTracingPipeline* auxiliaryPipeline = nullptr;
2632 if (m_params->useRTLibraries)
2634 // The shader-owning pipeline will be a library and auxiliaryPipeline will be the bound pipeline helper.
2635 auxiliaryPipelinePtr = makeVkSharedPtr(de::newMovePtr<RayTracingPipeline>());
2636 auxiliaryPipeline = auxiliaryPipelinePtr->get();
2639 // The bound pipeline is the shader-owning pipeline if not using libraries, or the auxiliary pipeline otherwise.
2640 RayTracingPipeline* boundPipeline = (m_params->useRTLibraries ? auxiliaryPipeline : shaderOwningPipeline);
2642 shaderOwningPipeline->setMaxPayloadSize(vec3Size);
2643 shaderOwningPipeline->setMaxAttributeSize(vec3Size);
2645 VkPipelineCreateFlags creationFlags = (VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT | captureFlags);
2646 if (m_params->useRTLibraries)
2647 creationFlags |= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
2648 shaderOwningPipeline->setCreateFlags(creationFlags);
2651 shaderOwningPipeline->addShader(
2652 VK_SHADER_STAGE_RAYGEN_BIT_KHR,
2653 rgenToRun.getUsedModule(m_params->moduleUseCase),
2655 rgenToRun.getSpecInfo(), 0,
2656 rgenToRun.getModuleIdCreateInfo());
2658 if (chitModule != DE_NULL)
2660 shaderOwningPipeline->addShader(
2661 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
2662 chitToRun.getUsedModule(m_params->moduleUseCase),
2664 chitToRun.getSpecInfo(), 0,
2665 chitToRun.getModuleIdCreateInfo());
2668 if (ahitModule != DE_NULL)
2670 shaderOwningPipeline->addShader(
2671 VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
2672 ahitToRun.getUsedModule(m_params->moduleUseCase),
2674 ahitToRun.getSpecInfo(), 0,
2675 ahitToRun.getModuleIdCreateInfo());
2678 if (isecModule != DE_NULL)
2680 shaderOwningPipeline->addShader(
2681 VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
2682 isecToRun.getUsedModule(m_params->moduleUseCase),
2684 isecToRun.getSpecInfo(), 0,
2685 isecToRun.getModuleIdCreateInfo());
2688 if (missModule != DE_NULL)
2690 shaderOwningPipeline->addShader(
2691 VK_SHADER_STAGE_MISS_BIT_KHR,
2692 missToRun.getUsedModule(m_params->moduleUseCase),
2694 missToRun.getSpecInfo(), 0,
2695 missToRun.getModuleIdCreateInfo());
2698 if (callModule != DE_NULL)
2700 shaderOwningPipeline->addShader(
2701 VK_SHADER_STAGE_CALLABLE_BIT_KHR,
2702 callToRun.getUsedModule(m_params->moduleUseCase),
2704 callToRun.getSpecInfo(), 0,
2705 callToRun.getModuleIdCreateInfo());
2708 // Append the pipeline, SBTs and regions to use at the end of their vectors.
2711 pipelinePtrs.emplace_back(shaderOwningPipeline->createPipeline(vkd, device, pipelineLayout.get(), emptyPipelinesVec, pipelineCache.get()));
2712 pipelines.push_back(pipelinePtrs.back().get());
2714 catch (const RayTracingPipeline::CompileRequiredError& err)
2717 return tcu::TestStatus::pass("Pass");
2720 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "VK_PIPELINE_COMPILE_REQUIRED despite passing a pipeline cache");
2721 return tcu::TestStatus::pass("VK_PIPELINE_COMPILE_REQUIRED"); // ;_;
2724 if (m_params->useRTLibraries)
2726 // Create a new pipeline using the library created above, and use it as the active pipeline.
2727 auxiliaryPipeline->setMaxPayloadSize(vec3Size);
2728 auxiliaryPipeline->setMaxAttributeSize(vec3Size);
2729 auxiliaryPipeline->setCreateFlags(VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT | captureFlags);
2733 const std::vector<VkPipeline> rawPipelines(1u, pipelines.back());
2734 pipelinePtrs.emplace_back(auxiliaryPipeline->createPipeline(vkd, device, pipelineLayout.get(), rawPipelines, pipelineCache.get()));
2735 pipelines.push_back(pipelinePtrs.back().get());
2738 TCU_FAIL("Cache miss expected");
2740 catch (const RayTracingPipeline::CompileRequiredError& err)
2743 return tcu::TestStatus::pass("Pass");
2746 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "VK_PIPELINE_COMPILE_REQUIRED on library use despite passing a pipeline cache");
2747 return tcu::TestStatus::pass("VK_PIPELINE_COMPILE_REQUIRED on library use"); // ;_;
2750 else if (reqCacheMiss)
2751 TCU_FAIL("Cache miss expected");
2754 identifierExeProps = getPipelineExecutableProperties(vkd, device, pipelines.back(), m_params->capturedProperties);
2756 const auto pipeline = pipelines.back();
2758 rgenSBT = boundPipeline->createShaderBindingTable(vkd, device, pipeline, alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, rgenGroup, 1u);
2759 rgenRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, rgenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2763 xhitSBT = boundPipeline->createShaderBindingTable(vkd, device, pipeline, alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, xhitGroup.get(), 1u);
2764 xhitRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, xhitSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2769 missSBT = boundPipeline->createShaderBindingTable(vkd, device, pipeline, alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, missGroup.get(), 1u);
2770 missRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2775 callSBT = boundPipeline->createShaderBindingTable(vkd, device, pipeline, alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, callGroup.get(), 1u);
2776 callRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2785 // Early exit if we don't need to run any pipeline.
2786 if (!runOnePipeline)
2787 return tcu::TestStatus::pass("Pass (not using any pipeline)");
2789 // Compare executable properties if captured.
2792 using PipelineExecutablePropertySet = std::set<PipelineExecutableProperty>;
2794 const PipelineExecutablePropertySet classicProps (begin(classicExeProps), end(classicExeProps));
2795 const PipelineExecutablePropertySet identifierProps (begin(identifierExeProps), end(identifierExeProps));
2797 if (classicProps != identifierProps)
2799 auto& log = m_context.getTestContext().getLog();
2801 log << tcu::TestLog::Message << "Properties without identifiers: " << classicExeProps << tcu::TestLog::EndMessage;
2802 log << tcu::TestLog::Message << "Properties with identifiers: " << identifierExeProps << tcu::TestLog::EndMessage;
2804 TCU_FAIL("Pipeline executable properties differ (check log for details)");
2810 const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
2811 const auto vertexCount = (m_params->hasTess() ? 3u : 1u);
2813 beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2814 vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, pipelineLayout.get(), 0u, de::sizeU32(rawDescriptorSets), de::dataOrNull(rawDescriptorSets), 0u, nullptr);
2815 vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipelines.back());
2816 vkd.cmdDraw(cmdBuffer, vertexCount, 1u, 0u, 0u);
2817 endRenderPass(vkd, cmdBuffer);
2819 const auto copyRegion = makeBufferImageCopy(fbExtent, colorSRL);
2820 const auto preHostBarrier = makeMemoryBarrier((VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT), VK_ACCESS_HOST_READ_BIT);
2821 const auto postRenderBarrier = makeImageMemoryBarrier(
2822 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2823 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2824 colorAtt->get(), colorSRR);
2826 // Copy color attachment to verification buffer.
2827 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postRenderBarrier);
2828 vkd.cmdCopyImageToBuffer(cmdBuffer, colorAtt->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer->get(), 1u, ©Region);
2830 // Synchronize SSBO and verification buffer reads from the host.
2831 cmdPipelineMemoryBarrier(vkd, cmdBuffer, (VK_PIPELINE_STAGE_TRANSFER_BIT | pipelineStages), VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
2835 const auto bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
2836 const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2838 vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, pipelineLayout.get(), 0u, de::sizeU32(rawDescriptorSets), de::dataOrNull(rawDescriptorSets), 0u, nullptr);
2839 vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipelines.back());
2840 vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
2841 cmdPipelineMemoryBarrier(vkd, cmdBuffer, pipelineStages, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
2845 const auto bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2846 const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2847 const auto rayCount = (hasHitAndMiss ? 2u : 1u);
2849 vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, pipelineLayout.get(), 0u, de::sizeU32(rawDescriptorSets), de::dataOrNull(rawDescriptorSets), 0u, nullptr);
2850 vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipelines.back());
2851 vkd.cmdTraceRaysKHR(cmdBuffer, &rgenRegion, &missRegion, &xhitRegion, &callRegion, rayCount, 1u, 1u);
2852 cmdPipelineMemoryBarrier(vkd, cmdBuffer, pipelineStages, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
2859 // Finish and submit command buffer.
2860 endCommandBuffer(vkd, cmdBuffer);
2861 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2863 // Verify framebuffer if used.
2866 auto& verifBufferAlloc = verifBuffer->getAllocation();
2867 void* verifBufferData = verifBufferAlloc.getHostPtr();
2869 invalidateAlloc(vkd, device, verifBufferAlloc);
2871 tcu::ConstPixelBufferAccess resultAccess (tcuFbFormat, iExtent, verifBufferData);
2872 const tcu::Vec4 expectedColor = (m_params->hasFrag() ? blueColor : clearColor);
2873 const auto resultColor = resultAccess.getPixel(0, 0);
2875 if (resultColor != expectedColor)
2877 std::ostringstream msg;
2878 msg << "Unexpected color found in Framebuffer: expected " << expectedColor << " but found " << resultColor;
2879 TCU_FAIL(msg.str());
2883 // Verify SSBO data.
2885 invalidateAlloc(vkd, device, storageBufferAlloc);
2886 std::vector<uint32_t> outputData(stagesCount, 0u);
2887 deMemcpy(outputData.data(), storageBufferData, de::dataSize(outputData));
2889 for (size_t stageIdx = 0u; stageIdx < stagesCount; ++stageIdx)
2891 const auto& expected = shaderConstants.at(getShaderIdx(m_params->pipelineToRun.get(), stageIdx, stagesCount));
2892 const auto& result = outputData.at(stageIdx);
2894 if (expected != result)
2896 std::ostringstream msg;
2897 msg << "Unexpected data found for stage " << stageIdx << std::hex << ": expected 0x" << expected << " but found 0x" << result;
2898 TCU_FAIL(msg.str());
2903 return tcu::TestStatus::pass("Pass");
2912 enum class Partitioning
2918 std::ostream& operator<<(std::ostream& out, Winding w)
2920 return (out << ((w == Winding::CW) ? "triangle_cw" : "triangle_ccw"));
2923 std::ostream& operator<<(std::ostream& out, Partitioning p)
2925 return (out << ((p == Partitioning::INTEGER) ? "integer" : "fractional_odd"));
2928 class HLSLTessellationInstance : public vkt::TestInstance
2931 HLSLTessellationInstance (Context& context, PipelineConstructionType constructionType)
2932 : vkt::TestInstance (context)
2933 , m_constructionType (constructionType)
2935 virtual ~HLSLTessellationInstance (void) {}
2937 tcu::TestStatus iterate (void) override;
2940 const PipelineConstructionType m_constructionType;
2943 class HLSLTessellationCase : public vkt::TestCase
2946 HLSLTessellationCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, PipelineConstructionType constructionType)
2947 : vkt::TestCase (testCtx, name, description)
2948 , m_constructionType (constructionType)
2950 virtual ~HLSLTessellationCase (void) {}
2952 void checkSupport (Context& context) const override;
2953 void initPrograms (vk::SourceCollections& programCollection) const override;
2954 TestInstance* createInstance (Context& context) const override { return new HLSLTessellationInstance(context, m_constructionType); }
2956 static std::vector<tcu::Vec4> getOutputColors (void);
2959 const PipelineConstructionType m_constructionType;
2962 std::vector<tcu::Vec4> HLSLTessellationCase::getOutputColors (void)
2964 std::vector<tcu::Vec4> outColors
2966 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2967 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2968 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2969 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
2975 void HLSLTessellationCase::checkSupport (Context &context) const
2977 const auto& vki = context.getInstanceInterface();
2978 const auto physicalDevice = context.getPhysicalDevice();
2980 checkPipelineLibraryRequirements(vki, physicalDevice, m_constructionType);
2981 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
2982 checkShaderModuleIdentifierSupport(context);
2985 void HLSLTessellationCase::initPrograms (vk::SourceCollections &programCollection) const
2989 // Full-screen triangle.
2990 std::ostringstream vert;
2993 << "out gl_PerVertex\n"
2995 << " vec4 gl_Position;\n"
2997 << "vec2 vertexPositions[3] = vec2[](\n"
2998 << " vec2(-1.0, -1.0),\n"
2999 << " vec2( 3.0, -1.0),\n"
3000 << " vec2(-1.0, 3.0)\n"
3002 << "void main (void) {\n"
3003 << " gl_Position = vec4(vertexPositions[gl_VertexIndex], 0.0, 1.0);\n"
3007 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
3010 // Fragment shader, which outputs the color from the previous stages.
3012 std::ostringstream frag;
3015 << "layout (location=0) in vec4 inColor;\n"
3016 << "layout (location=0) out vec4 outColor;\n"
3017 << "void main (void) {\n"
3018 << " outColor = inColor;\n"
3022 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
3025 // Tessellation evaluation shader (AKA domain shader) in HLSL, common for every pipeline.
3026 // Contrary to GLSL, HLSL allows us to omit execution modes in the "tese" shader and specify them on the "tesc" shader.
3028 std::ostringstream tese;
3030 << "struct HullShaderOutput\n"
3032 << " float4 Position : SV_Position;\n"
3033 << " [[vk::location(0)]] float4 Color : COLOR0;\n"
3036 << "struct HullShaderConstantOutput\n"
3038 << " float TessLevelOuter[4] : SV_TessFactor;\n"
3039 << " float TessLevelInner[2] : SV_InsideTessFactor;\n"
3042 << "struct DomainShaderOutput\n"
3044 << " float4 Position : SV_Position;\n"
3045 << " [[vk::location(0)]] float4 Color : COLOR0;\n"
3048 << "DomainShaderOutput main (HullShaderConstantOutput input, float3 TessCoord : SV_DomainLocation, const OutputPatch<HullShaderOutput, 3> patch)\n"
3050 << " DomainShaderOutput output = (DomainShaderOutput)0;\n"
3052 << " output.Position = (TessCoord.x * patch[0].Position) +\n"
3053 << " (TessCoord.y * patch[1].Position) +\n"
3054 << " (TessCoord.z * patch[2].Position);\n"
3056 << " output.Color = (TessCoord.x * patch[0].Color) +\n"
3057 << " (TessCoord.y * patch[1].Color) +\n"
3058 << " (TessCoord.z * patch[2].Color);\n"
3060 << " return output;\n"
3064 programCollection.hlslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
3067 // Tessellation control shaders. Create 4 combinations with different execution modes. Each combination will also assign a different color to the vertices.
3068 // We will later run each pipeline to draw a pixel in a framebuffer (using viewports and scissors) to end up with 4 distinct colors.
3070 const auto outColors = getOutputColors();
3071 size_t colorIdx = 0;
3073 const Winding windings[] = { Winding::CW, Winding::CCW };
3074 const Partitioning partitionings[] = { Partitioning::INTEGER, Partitioning::FRACTIONAL_ODD };
3076 for (const auto& winding : windings)
3077 for (const auto& partitioning : partitionings)
3079 std::ostringstream tesc;
3081 << "struct VertexShaderOutput\n"
3083 << " float4 Position : SV_Position;\n"
3086 << "struct HullShaderOutput\n"
3088 << " float4 Position : SV_Position;\n"
3089 << " [[vk::location(0)]] float4 Color : COLOR0;\n"
3092 << "struct HullShaderConstantOutput\n"
3094 << " float TessLevelOuter[4] : SV_TessFactor;\n"
3095 << " float TessLevelInner[2] : SV_InsideTessFactor;\n"
3098 << "[domain(\"tri\")]\n"
3099 << "[partitioning(\"" << partitioning << "\")]\n"
3100 << "[outputtopology(\"" << winding << "\")]\n"
3101 << "[outputcontrolpoints(3)]\n"
3102 << "[patchconstantfunc(\"PCF\")]\n"
3103 << "HullShaderOutput main (InputPatch<VertexShaderOutput, 3> patch, uint InvocationID : SV_OutputControlPointID)\n"
3105 << " HullShaderOutput output = (HullShaderOutput)0;\n"
3106 << " output.Position = patch[InvocationID].Position;\n"
3107 << " output.Color = float4" << outColors.at(colorIdx) << ";\n"
3108 << " return output;\n"
3111 << "HullShaderConstantOutput PCF (InputPatch<VertexShaderOutput, 3> patch, uint InvocationID : SV_PrimitiveID)\n"
3113 << " HullShaderConstantOutput output = (HullShaderConstantOutput)0;\n"
3115 << " output.TessLevelOuter[0] = 1;\n"
3116 << " output.TessLevelOuter[1] = 1;\n"
3117 << " output.TessLevelOuter[2] = 1;\n"
3118 << " output.TessLevelOuter[3] = 1;\n"
3120 << " output.TessLevelInner[0] = 1;\n"
3121 << " output.TessLevelInner[1] = 1;\n"
3123 << " return output;\n"
3127 const auto idxStr = std::to_string(colorIdx);
3128 programCollection.hlslSources.add("tesc" + idxStr) << glu::TessellationControlSource(tesc.str());
3135 tcu::TestStatus HLSLTessellationInstance::iterate (void)
3137 const auto& vkd = m_context.getDeviceInterface();
3138 const auto device = m_context.getDevice();
3139 auto& alloc = m_context.getDefaultAllocator();
3140 const auto queue = m_context.getUniversalQueue();
3141 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
3143 const auto fbFormat = VK_FORMAT_R8G8B8A8_UNORM;
3144 const auto fbExtent = makeExtent3D(2u, 2u, 1u);
3145 const tcu::IVec3 iExtent (static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(fbExtent.depth));
3146 const auto tcuFbFormat = mapVkFormat(fbFormat);
3147 const auto pixelSize = tcu::getPixelSize(tcuFbFormat);
3148 const auto topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
3149 const auto patchCPs = 3u;
3150 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
3151 const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
3153 const std::vector<VkViewport> rpViewports (1u, makeViewport(fbExtent));
3154 const std::vector<VkRect2D> rpScissors (1u, makeRect2D(fbExtent));
3156 // Color attachment.
3157 const VkImageCreateInfo colorAttCreateInfo =
3159 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
3160 nullptr, // const void* pNext;
3161 0u, // VkImageCreateFlags flags;
3162 VK_IMAGE_TYPE_2D, // VkImageType imageType;
3163 fbFormat, // VkFormat format;
3164 fbExtent, // VkExtent3D extent;
3165 1u, // uint32_t mipLevels;
3166 1u, // uint32_t arrayLayers;
3167 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
3168 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
3169 (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // VkImageUsageFlags usage;
3170 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3171 0u, // uint32_t queueFamilyIndexCount;
3172 nullptr, // const uint32_t* pQueueFamilyIndices;
3173 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
3176 ImageWithMemory colorAtt (vkd, device, alloc, colorAttCreateInfo, MemoryRequirement::Any);
3177 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3178 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
3179 const auto colorAttView = makeImageView(vkd, device, colorAtt.get(), VK_IMAGE_VIEW_TYPE_2D, fbFormat, colorSRR);
3180 const auto renderPass = makeRenderPass(vkd, device, fbFormat);
3181 const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorAttView.get(), fbExtent.width, fbExtent.height);
3183 // Verification buffer.
3184 DE_ASSERT(fbExtent.depth == 1u);
3185 const auto verifBufferSize = static_cast<VkDeviceSize>(pixelSize) * fbExtent.width * fbExtent.height;
3186 const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3187 BufferWithMemory verifBuffer (vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
3189 // Create shader modules, obtain IDs and verify all of them differ.
3190 const auto& binaries = m_context.getBinaryCollection();
3191 const auto vertModule = createShaderModule(vkd, device, binaries.get("vert"));
3192 const auto fragModule = createShaderModule(vkd, device, binaries.get("frag"));
3193 const auto teseModule = createShaderModule(vkd, device, binaries.get("tese"));
3195 std::vector<Move<VkShaderModule>> tescModules;
3201 const auto shaderName = "tesc" + std::to_string(tescIdx);
3202 if (!binaries.contains(shaderName))
3204 tescModules.emplace_back(createShaderModule(vkd, device, binaries.get(shaderName)));
3210 const auto vertId = getShaderModuleIdentifier(vkd, device, vertModule.get());
3211 const auto fragId = getShaderModuleIdentifier(vkd, device, fragModule.get());
3212 const auto teseId = getShaderModuleIdentifier(vkd, device, teseModule.get());
3213 std::vector<ShaderModuleId> tescIds;
3214 for (const auto& mod : tescModules)
3215 tescIds.emplace_back(getShaderModuleIdentifier(vkd, device, mod.get()));
3217 // Verify all of them are unique.
3219 std::vector<ShaderModuleId> allIds;
3220 allIds.emplace_back(vertId);
3221 allIds.emplace_back(fragId);
3222 allIds.emplace_back(teseId);
3223 for (const auto& id : tescIds)
3224 allIds.emplace_back(id);
3226 std::set<ShaderModuleId> uniqueIds (begin(allIds), end(allIds));
3228 if (allIds.size() != uniqueIds.size())
3229 TCU_FAIL("Not every module has a unique ID");
3232 // Constant structures used when creating pipelines.
3233 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
3234 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
3236 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
3237 nullptr, // const void* pNext;
3238 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
3239 topology, // VkPrimitiveTopology topology;
3240 VK_FALSE, // VkBool32 primitiveRestartEnable;
3242 const VkPipelineDepthStencilStateCreateInfo depthStencilState = initVulkanStructure();
3243 VkPipelineMultisampleStateCreateInfo multisampleState = initVulkanStructure();
3244 multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
3245 VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
3246 deMemset(&colorBlendAttachmentState, 0, sizeof(colorBlendAttachmentState));
3247 colorBlendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
3248 const VkPipelineColorBlendStateCreateInfo colorBlendState =
3250 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
3251 nullptr, // const void* pNext
3252 0u, // VkPipelineColorBlendStateCreateFlags flags
3253 VK_FALSE, // VkBool32 logicOpEnable
3254 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
3255 1u, // deUint32 attachmentCount
3256 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
3257 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
3259 const auto rasterizationState = makeRasterizationState(false/*rasterizationDisabled*/);
3262 const VkPipelineCacheCreateInfo cacheCreateInfo = initVulkanStructure();
3263 const auto pipelineCache = createPipelineCache(vkd, device, &cacheCreateInfo);
3265 // Empty pipeline layout.
3266 const auto pipelineLayout = makePipelineLayout(vkd, device);
3268 using GraphicsPipelineWrapperPtr = std::unique_ptr<GraphicsPipelineWrapper>;
3270 // Create temporary pipelines with them to prime the cache.
3272 for (const auto& tescModule : tescModules)
3274 GraphicsPipelineWrapperPtr wrapper (new GraphicsPipelineWrapper(vkd, device, m_constructionType));
3278 wrapper->setDefaultPatchControlPoints(patchCPs)
3279 .setupVertexInputStete(&vertexInputState, &inputAssemblyState, pipelineCache.get())
3280 .setupPreRasterizationShaderState2(
3283 pipelineLayout.get(),
3287 &rasterizationState,
3296 pipelineCache.get())
3297 .setupFragmentShaderState(
3298 pipelineLayout.get(),
3306 pipelineCache.get())
3307 .setupFragmentOutputState(
3312 pipelineCache.get())
3313 .setMonolithicPipelineLayout(pipelineLayout.get())
3314 .buildPipeline(pipelineCache.get());
3316 catch (const PipelineCompileRequiredError& err)
3318 TCU_FAIL("PipelineCompileRequiredError received while priming pipeline cache");
3323 // Create pipelines using shader module ids. These will actually be run. Note the changing viewports and scissors.
3324 std::vector<GraphicsPipelineWrapperPtr> pipelineWrappers;
3325 std::vector<VkViewport> viewports;
3326 std::vector<VkRect2D> scissors;
3328 const auto vertIdInfo = makeShaderStageModuleIdentifierCreateInfo(vertId, UseModuleCase::ID);
3329 const auto fragIdInfo = makeShaderStageModuleIdentifierCreateInfo(fragId, UseModuleCase::ID);
3330 const auto teseIdInfo = makeShaderStageModuleIdentifierCreateInfo(teseId, UseModuleCase::ID);
3331 std::vector<ShaderStageIdPtr> tescIdInfos;
3332 for (const auto& tescId : tescIds)
3333 tescIdInfos.emplace_back(makeShaderStageModuleIdentifierCreateInfo(tescId, UseModuleCase::ID));
3335 for (size_t tescIdx = 0; tescIdx < tescModules.size(); ++tescIdx)
3337 const auto row = tescIdx / fbExtent.width;
3338 const auto col = tescIdx % fbExtent.width;
3340 viewports.emplace_back(makeViewport(static_cast<float>(col), static_cast<float>(row), 1.0f, 1.0f, 0.0f, 1.0f));
3341 scissors.emplace_back(makeRect2D(static_cast<int32_t>(col), static_cast<int32_t>(row), 1u, 1u));
3342 pipelineWrappers.emplace_back(new GraphicsPipelineWrapper(vkd, device, m_constructionType));
3344 const auto& wrapper = pipelineWrappers.back();
3348 wrapper->setDefaultPatchControlPoints(patchCPs)
3349 .setupVertexInputStete(&vertexInputState, &inputAssemblyState, pipelineCache.get())
3350 .setupPreRasterizationShaderState3(
3351 std::vector<VkViewport>(1u, viewports.back()),
3352 std::vector<VkRect2D>(1u, scissors.back()),
3353 pipelineLayout.get(),
3358 &rasterizationState,
3360 tescIdInfos.at(tescIdx).get(),
3370 pipelineCache.get())
3371 .setupFragmentShaderState2(
3372 pipelineLayout.get(),
3381 pipelineCache.get())
3382 .setupFragmentOutputState(
3387 pipelineCache.get())
3388 .setMonolithicPipelineLayout(pipelineLayout.get())
3389 .buildPipeline(pipelineCache.get());
3391 catch (const PipelineCompileRequiredError& err)
3393 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "PipelineCompileRequiredError received despite using pipeline cache");
3397 // Use pipelines in a render pass.
3398 const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
3399 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3400 const auto cmdBuffer = cmdBufferPtr.get();
3402 beginCommandBuffer(vkd, cmdBuffer);
3403 beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), rpScissors.at(0u), clearColor);
3404 for (const auto& wrapper : pipelineWrappers)
3406 vkd.cmdBindPipeline(cmdBuffer, bindPoint, wrapper->getPipeline());
3407 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
3409 endRenderPass(vkd, cmdBuffer);
3411 // Transfer color attachment to verification buffer.
3412 const auto copyRegion = makeBufferImageCopy(fbExtent, colorSRL);
3413 const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
3414 const auto postRenderBarrier = makeImageMemoryBarrier(
3415 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
3416 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3417 colorAtt.get(), colorSRR);
3419 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postRenderBarrier);
3420 vkd.cmdCopyImageToBuffer(cmdBuffer, colorAtt.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, ©Region);
3421 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
3423 endCommandBuffer(vkd, cmdBuffer);
3424 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3428 auto& log = m_context.getTestContext().getLog();
3429 const auto outColors = HLSLTessellationCase::getOutputColors();
3430 auto& verifBufferAlloc = verifBuffer.getAllocation();
3431 void* verifBufferData = verifBufferAlloc.getHostPtr();
3433 invalidateAlloc(vkd, device, verifBufferAlloc);
3435 tcu::ConstPixelBufferAccess resultAccess (tcuFbFormat, iExtent, verifBufferData);
3436 tcu::TextureLevel referenceLevel (tcuFbFormat, iExtent.x(), iExtent.y());
3437 const auto referenceAccess = referenceLevel.getAccess();
3438 const tcu::Vec4 threshold (0.0f, 0.0f, 0.0f, 0.0f);
3440 for (int x = 0; x < iExtent.x(); ++x)
3441 for (int y = 0; y < iExtent.y(); ++y)
3442 referenceAccess.setPixel(outColors.at(y*iExtent.x() + x), x, y);
3444 tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold, tcu::COMPARE_LOG_EVERYTHING);
3447 return tcu::TestStatus::pass("Pass");
3450 } // anonymous namespace
3452 tcu::TestCaseGroup* createShaderModuleIdentifierTests (tcu::TestContext& testCtx, vk::PipelineConstructionType constructionType)
3454 // No pipelines are actually constructed in some of these variants, so adding them to a single group is fine.
3455 GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "shader_module_identifier", "Tests for VK_EXT_shader_module_identifier"));
3457 if (constructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3460 GroupPtr propertiesGroup (new tcu::TestCaseGroup(testCtx, "properties", "Test shader module identifier extension properties"));
3462 addFunctionCase(propertiesGroup.get(), "constant_algorithm_uuid", "", checkShaderModuleIdentifierSupport, constantAlgorithmUUIDCase);
3464 mainGroup->addChild(propertiesGroup.release());
3469 PipelineType pipelineType;
3470 bool useRTLibraries;
3472 } pipelineTypeCases[] =
3474 { PipelineType::COMPUTE, false, "compute" },
3475 { PipelineType::GRAPHICS, false, "graphics" },
3476 { PipelineType::RAY_TRACING, false, "ray_tracing" },
3477 { PipelineType::RAY_TRACING, true, "ray_tracing_libs" },
3480 const uint8_t pipelineCountCases[] = { uint8_t{1}, uint8_t{4} };
3482 const std::vector<GraphicsShaderVec> graphicsShadersCases
3484 { GraphicsShaderType::VERTEX },
3485 { GraphicsShaderType::VERTEX, GraphicsShaderType::FRAG },
3486 { GraphicsShaderType::VERTEX, GraphicsShaderType::TESS_CONTROL, GraphicsShaderType::TESS_EVAL, GraphicsShaderType::FRAG },
3487 { GraphicsShaderType::VERTEX, GraphicsShaderType::GEOMETRY, GraphicsShaderType::FRAG },
3488 { GraphicsShaderType::VERTEX, GraphicsShaderType::TESS_CONTROL, GraphicsShaderType::TESS_EVAL, GraphicsShaderType::GEOMETRY, GraphicsShaderType::FRAG },
3491 const std::vector<RTShaderVec> rtShadersCases
3493 { RayTracingShaderType::RAY_GEN, RayTracingShaderType::MISS },
3494 { RayTracingShaderType::RAY_GEN, RayTracingShaderType::CLOSEST_HIT, RayTracingShaderType::MISS },
3495 { RayTracingShaderType::RAY_GEN, RayTracingShaderType::ANY_HIT, RayTracingShaderType::CLOSEST_HIT, RayTracingShaderType::MISS },
3496 { RayTracingShaderType::RAY_GEN, RayTracingShaderType::INTERSECTION, RayTracingShaderType::ANY_HIT, RayTracingShaderType::CLOSEST_HIT, RayTracingShaderType::MISS },
3497 { RayTracingShaderType::RAY_GEN, RayTracingShaderType::CALLABLE },
3506 { false, "no_spec_constants" },
3507 { true, "use_spec_constants" },
3510 // Tests checking the identifiers are constant.
3511 if (constructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3513 // Constant and unique module identifier tests.
3514 GroupPtr constantIdsGroup (new tcu::TestCaseGroup(testCtx, "constant_identifiers", "Test shader modules have constant and unique identifiers"));
3518 ConstantModuleIdentifiersInstance::APICall apiCall;
3522 { ConstantModuleIdentifiersInstance::APICall::MODULE, "module_id" },
3523 { ConstantModuleIdentifiersInstance::APICall::CREATE_INFO, "create_info_id" },
3524 { ConstantModuleIdentifiersInstance::APICall::BOTH, "both_ids" },
3529 bool differentDevice;
3531 } differentDeviceCases[] =
3533 { false, "same_device" },
3534 { true, "different_devices" },
3537 for (const auto& pipelineTypeCase : pipelineTypeCases)
3539 // Skip this case for constant module identifiers.
3540 if (pipelineTypeCase.useRTLibraries)
3543 GroupPtr pipelineTypeGroup (new tcu::TestCaseGroup(testCtx, pipelineTypeCase.name, ""));
3545 for (const auto& pipelineCountCase : pipelineCountCases)
3547 const auto countGroupName = std::to_string(static_cast<int>(pipelineCountCase)) + "_variants";
3549 GroupPtr pipelineCountGroup (new tcu::TestCaseGroup(testCtx, countGroupName.c_str(), ""));
3551 for (const auto& useSCCase : useSCCases)
3553 GroupPtr useSCGroup (new tcu::TestCaseGroup(testCtx, useSCCase.name, ""));
3555 for (const auto& apiCallCase : apiCallCases)
3557 GroupPtr apiCallGroup (new tcu::TestCaseGroup(testCtx, apiCallCase.name, ""));
3559 for (const auto& differentDeviceCase : differentDeviceCases)
3561 GroupPtr differentDeviceGroup (new tcu::TestCaseGroup(testCtx, differentDeviceCase.name, ""));
3563 using Params = ConstantModuleIdentifiersInstance::Params;
3565 Params commonParams(
3566 pipelineTypeCase.pipelineType,
3567 {}, {}, pipelineCountCase, tcu::Nothing,
3568 useSCCase.useSCs, false, apiCallCase.apiCall, differentDeviceCase.differentDevice);
3570 if (pipelineTypeCase.pipelineType == PipelineType::GRAPHICS)
3572 for (const auto& graphicsShadersCase : graphicsShadersCases)
3574 std::unique_ptr<Params> params (new Params(commonParams));
3575 params->graphicsShaders = graphicsShadersCase;
3576 differentDeviceGroup->addChild(new ConstantModuleIdentifiersCase(testCtx, toString(graphicsShadersCase), "", std::move(params)));
3579 else if (pipelineTypeCase.pipelineType == PipelineType::RAY_TRACING)
3581 for (const auto& rtShadersCase : rtShadersCases)
3583 std::unique_ptr<Params> params (new Params(commonParams));
3584 params->rtShaders = rtShadersCase;
3585 differentDeviceGroup->addChild(new ConstantModuleIdentifiersCase(testCtx, toString(rtShadersCase), "", std::move(params)));
3590 std::unique_ptr<Params> params (new Params(commonParams));
3591 differentDeviceGroup->addChild(new ConstantModuleIdentifiersCase(testCtx, "comp", "", std::move(params)));
3594 apiCallGroup->addChild(differentDeviceGroup.release());
3597 useSCGroup->addChild(apiCallGroup.release());
3600 pipelineCountGroup->addChild(useSCGroup.release());
3603 pipelineTypeGroup->addChild(pipelineCountGroup.release());
3606 constantIdsGroup->addChild(pipelineTypeGroup.release());
3609 mainGroup->addChild(constantIdsGroup.release());
3612 // Tests creating pipelines using the module id extension structures.
3616 bool useVkPipelineCache;
3618 } pipelineCacheCases[] =
3620 { false, "no_pipeline_cache" },
3621 { true, "use_pipeline_cache" },
3626 UseModuleCase moduleUse;
3628 } moduleUsageCases[] =
3630 { UseModuleCase::ID, "use_id" },
3631 { UseModuleCase::ZERO_LEN_ID, "zero_len_id" },
3632 { UseModuleCase::ZERO_LEN_ID_NULL_PTR, "zero_len_id_null_ptr" },
3633 { UseModuleCase::ZERO_LEN_ID_GARBAGE_PTR, "zero_len_id_garbage_ptr" },
3634 { UseModuleCase::ALL_ZEROS, "all_zeros_id" },
3635 { UseModuleCase::ALL_ONES, "all_ones_id" },
3636 { UseModuleCase::PSEUDORANDOM_ID, "pseudorandom_id" },
3641 CapturedPropertiesBits capturedProperties;
3643 } capturingCases[] =
3645 { CapturedPropertiesBits::NONE, "no_exec_properties" },
3646 { CapturedPropertiesBits::STATS, "capture_stats" },
3647 { CapturedPropertiesBits::IRS, "capture_irs" },
3650 uint32_t rndSeed = 1651848014u;
3652 // Tests using pipelines created using shader identifiers.
3653 GroupPtr pipelineFromIdsGroup (new tcu::TestCaseGroup(testCtx, "pipeline_from_id", "Test creating and using pipelines from shader module identifiers"));
3655 for (const auto& pipelineTypeCase : pipelineTypeCases)
3657 if (pipelineTypeCase.pipelineType != PipelineType::GRAPHICS && constructionType != PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3660 GroupPtr pipelineTypeGroup (new tcu::TestCaseGroup(testCtx, pipelineTypeCase.name, ""));
3662 for (const auto& pipelineCountCase : pipelineCountCases)
3664 const auto countGroupName = std::to_string(static_cast<int>(pipelineCountCase)) + "_variants";
3666 GroupPtr pipelineCountGroup (new tcu::TestCaseGroup(testCtx, countGroupName.c_str(), ""));
3668 for (const auto& useSCCase : useSCCases)
3670 GroupPtr useSCGroup (new tcu::TestCaseGroup(testCtx, useSCCase.name, ""));
3672 for (const auto& pipelineCacheCase : pipelineCacheCases)
3674 GroupPtr pipelineCacheGroup (new tcu::TestCaseGroup(testCtx, pipelineCacheCase.name, ""));
3676 for (const auto& moduleUsageCase : moduleUsageCases)
3678 GroupPtr moduleUsageGroup (new tcu::TestCaseGroup(testCtx, moduleUsageCase.name, ""));
3680 for (const auto& capturingCase : capturingCases)
3682 // We are only going to attempt to capture properties in a specific subset of the tests.
3683 if (capturingCase.capturedProperties != CapturedPropertiesBits::NONE &&
3684 (pipelineCountCase > 1u || moduleUsageCase.moduleUse != UseModuleCase::ID))
3687 GroupPtr captureGroup (new tcu::TestCaseGroup(testCtx, capturingCase.name, ""));
3689 DE_ASSERT(pipelineCountCase > 0u);
3690 const uint8_t pipelineToRun = (pipelineCountCase == 1u ? uint8_t{0} : static_cast<uint8_t>(pipelineCountCase - 2u));
3692 CreateAndUseIdsInstance::Params baseParams(
3693 pipelineTypeCase.pipelineType,
3694 {}, {}, pipelineCountCase, tcu::just(pipelineToRun),
3695 useSCCase.useSCs, pipelineCacheCase.useVkPipelineCache,
3696 constructionType, pipelineTypeCase.useRTLibraries,
3697 moduleUsageCase.moduleUse,
3698 static_cast<CapturedPropertiesFlags>(capturingCase.capturedProperties));
3700 if (pipelineTypeCase.pipelineType == PipelineType::GRAPHICS)
3702 for (const auto& graphicsShadersCase : graphicsShadersCases)
3704 BaseParamsPtr params = baseParams.copy(rndSeed++);
3705 params->graphicsShaders = graphicsShadersCase;
3706 captureGroup->addChild(new CreateAndUseIdsCase(testCtx, toString(graphicsShadersCase), "", std::move(params)));
3709 else if (pipelineTypeCase.pipelineType == PipelineType::RAY_TRACING)
3711 for (const auto& rtShadersCase : rtShadersCases)
3713 BaseParamsPtr params = baseParams.copy(rndSeed++);
3714 params->rtShaders = rtShadersCase;
3715 captureGroup->addChild(new CreateAndUseIdsCase(testCtx, toString(rtShadersCase), "", std::move(params)));
3720 BaseParamsPtr params = baseParams.copy(rndSeed++);
3721 captureGroup->addChild(new CreateAndUseIdsCase(testCtx, "comp", "", std::move(params)));
3724 moduleUsageGroup->addChild(captureGroup.release());
3727 pipelineCacheGroup->addChild(moduleUsageGroup.release());
3730 useSCGroup->addChild(pipelineCacheGroup.release());
3733 pipelineCountGroup->addChild(useSCGroup.release());
3736 pipelineTypeGroup->addChild(pipelineCountGroup.release());
3739 pipelineFromIdsGroup->addChild(pipelineTypeGroup.release());
3742 mainGroup->addChild(pipelineFromIdsGroup.release());
3745 // HLSL tessellation test.
3747 GroupPtr hlslTessGroup (new tcu::TestCaseGroup(testCtx, "hlsl_tessellation", "Tests checking HLSL tessellation shaders with module identifiers"));
3748 hlslTessGroup->addChild(new HLSLTessellationCase(testCtx, "test", "", constructionType));
3749 mainGroup->addChild(hlslTessGroup.release());
3752 return mainGroup.release();