@@ -107,43 +107,53 @@ class IRayTracingPipeline : public IPipeline<PipelineLayoutType>, public IRayTra
107107 return shaders[index].shader ->getStage ();
108108 };
109109
110- if (shaderGroups.raygen .index >= shaders.size ())
111- return false ;
112- if (getShaderStage (shaderGroups.raygen .index ) != ICPUShader::E_SHADER_STAGE::ESS_RAYGEN)
113- return false ;
114-
115- auto isValidShaderIndex = [this , getShaderStage](size_t index, ICPUShader::E_SHADER_STAGE expectedStage) -> bool
110+ auto isValidShaderIndex = [this , getShaderStage](size_t index, ICPUShader::E_SHADER_STAGE expectedStage, bool is_unused_shader_forbidden) -> bool
116111 {
117112 if (index == SShaderGroupsParams::SIndex::Unused)
118- return true ;
113+ return !is_unused_shader_forbidden ;
119114 if (index >= shaders.size ())
120115 return false ;
121116 if (getShaderStage (index) != expectedStage)
122117 return false ;
123118 return true ;
124119 };
125120
121+ if (isValidShaderIndex (shaderGroups.raygen .index , ICPUShader::E_SHADER_STAGE::ESS_RAYGEN, true ))
122+ {
123+ return false ;
124+ }
125+
126126 for (const auto & shaderGroup : shaderGroups.hits )
127127 {
128- if (!isValidShaderIndex (shaderGroup.anyHit , ICPUShader::E_SHADER_STAGE::ESS_ANY_HIT))
128+ // https://docs.vulkan.org/spec/latest/chapters/pipelines.html#VUID-VkRayTracingPipelineCreateInfoKHR-flags-03470
129+ if (!isValidShaderIndex (shaderGroup.anyHit ,
130+ ICPUShader::E_SHADER_STAGE::ESS_ANY_HIT,
131+ bool (flags & FLAGS::NO_NULL_ANY_HIT_SHADERS)))
129132 return false ;
130133
131- if (!isValidShaderIndex (shaderGroup.closestHit , ICPUShader::E_SHADER_STAGE::ESS_CLOSEST_HIT))
134+ // https://docs.vulkan.org/spec/latest/chapters/pipelines.html#VUID-VkRayTracingPipelineCreateInfoKHR-flags-03471
135+ if (!isValidShaderIndex (shaderGroup.closestHit ,
136+ ICPUShader::E_SHADER_STAGE::ESS_CLOSEST_HIT,
137+ bool (flags & FLAGS::NO_NULL_CLOSEST_HIT_SHADERS)))
132138 return false ;
133139
134- if (!isValidShaderIndex (shaderGroup.intersectionShader , ICPUShader::E_SHADER_STAGE::ESS_INTERSECTION))
140+ if (!isValidShaderIndex (shaderGroup.intersectionShader ,
141+ ICPUShader::E_SHADER_STAGE::ESS_INTERSECTION,
142+ false ))
135143 return false ;
136144 }
137145
138146 for (const auto & shaderGroup : shaderGroups.misses )
139147 {
140- if (!isValidShaderIndex (shaderGroup.index , ICPUShader::E_SHADER_STAGE::ESS_MISS))
148+ if (!isValidShaderIndex (shaderGroup.index ,
149+ ICPUShader::E_SHADER_STAGE::ESS_MISS,
150+ false ))
141151 return false ;
142152 }
143153
144154 for (const auto & shaderGroup : shaderGroups.callables )
145155 {
146- if (!isValidShaderIndex (shaderGroup.index , ICPUShader::E_SHADER_STAGE::ESS_CALLABLE))
156+ if (!isValidShaderIndex (shaderGroup.index , ICPUShader::E_SHADER_STAGE::ESS_CALLABLE, false ))
147157 return false ;
148158 }
149159 return true ;
@@ -163,6 +173,8 @@ class IRayTracingPipeline : public IPipeline<PipelineLayoutType>, public IRayTra
163173 std::span<const SpecInfo> shaders = {};
164174 SShaderGroupsParams shaderGroups;
165175 SCachedCreationParams cached = {};
176+ // TODO: Could guess the required flags from SPIR-V introspection of declared caps
177+ core::bitflag<FLAGS> flags = FLAGS::NONE;
166178 };
167179
168180 inline const SCachedCreationParams& getCachedCreationParams () const { return m_params; }
0 commit comments