@@ -27,6 +27,48 @@ namespace spvtools {
2727namespace val {
2828namespace {
2929
30+ // TODO - Make a common util if someone else needs it too outside this file
31+ const char * ExecutionModelToString (spv::ExecutionModel value) {
32+ switch (value) {
33+ case spv::ExecutionModel::Vertex:
34+ return " Vertex" ;
35+ case spv::ExecutionModel::TessellationControl:
36+ return " TessellationControl" ;
37+ case spv::ExecutionModel::TessellationEvaluation:
38+ return " TessellationEvaluation" ;
39+ case spv::ExecutionModel::Geometry:
40+ return " Geometry" ;
41+ case spv::ExecutionModel::Fragment:
42+ return " Fragment" ;
43+ case spv::ExecutionModel::GLCompute:
44+ return " GLCompute" ;
45+ case spv::ExecutionModel::Kernel:
46+ return " Kernel" ;
47+ case spv::ExecutionModel::TaskNV:
48+ return " TaskNV" ;
49+ case spv::ExecutionModel::MeshNV:
50+ return " MeshNV" ;
51+ case spv::ExecutionModel::RayGenerationKHR:
52+ return " RayGenerationKHR" ;
53+ case spv::ExecutionModel::IntersectionKHR:
54+ return " IntersectionKHR" ;
55+ case spv::ExecutionModel::AnyHitKHR:
56+ return " AnyHitKHR" ;
57+ case spv::ExecutionModel::ClosestHitKHR:
58+ return " ClosestHitKHR" ;
59+ case spv::ExecutionModel::MissKHR:
60+ return " MissKHR" ;
61+ case spv::ExecutionModel::CallableKHR:
62+ return " CallableKHR" ;
63+ case spv::ExecutionModel::TaskEXT:
64+ return " TaskEXT" ;
65+ case spv::ExecutionModel::MeshEXT:
66+ return " MeshEXT" ;
67+ default :
68+ return " Unknown" ;
69+ }
70+ }
71+
3072spv_result_t ValidateEntryPoint (ValidationState_t& _, const Instruction* inst) {
3173 const auto entry_point_id = inst->GetOperandAs <uint32_t >(1 );
3274 auto entry_point = _.FindDef (entry_point_id);
@@ -306,74 +348,79 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
306348 }
307349
308350 if (spvIsVulkanEnv (_.context ()->target_env )) {
309- switch (execution_model) {
310- case spv::ExecutionModel::GLCompute:
311- if (!has_mode (spv::ExecutionMode::LocalSize)) {
312- bool ok = has_workgroup_size || has_local_size_id;
313- if (!ok && _.HasCapability (spv::Capability::TileShadingQCOM)) {
314- ok = has_mode (spv::ExecutionMode::TileShadingRateQCOM);
315- }
316- if (!ok) {
317- return _.diag (SPV_ERROR_INVALID_DATA, inst)
318- << _.VkErrorID (10685 )
319- << " In the Vulkan environment, GLCompute execution model "
320- " entry points require either the "
321- << (_.HasCapability (spv::Capability::TileShadingQCOM)
322- ? " TileShadingRateQCOM, "
323- : " " )
324- << " LocalSize or LocalSizeId execution mode or an object "
325- " decorated with WorkgroupSize must be specified." ;
326- }
351+ // SPV_QCOM_tile_shading checks
352+ if (execution_model == spv::ExecutionModel::GLCompute) {
353+ if (_.HasCapability (spv::Capability::TileShadingQCOM)) {
354+ if (has_mode (spv::ExecutionMode::TileShadingRateQCOM) &&
355+ (has_mode (spv::ExecutionMode::LocalSize) ||
356+ has_mode (spv::ExecutionMode::LocalSizeId))) {
357+ return _.diag (SPV_ERROR_INVALID_DATA, inst)
358+ << " If the TileShadingRateQCOM execution mode is used, "
359+ << " LocalSize and LocalSizeId must not be specified." ;
327360 }
328-
329- if (_.HasCapability (spv::Capability::TileShadingQCOM)) {
330- if (has_mode (spv::ExecutionMode::TileShadingRateQCOM) &&
331- (has_mode (spv::ExecutionMode::LocalSize) ||
332- has_mode (spv::ExecutionMode::LocalSizeId))) {
333- return _.diag (SPV_ERROR_INVALID_DATA, inst)
334- << " If the TileShadingRateQCOM execution mode is used, "
335- << " LocalSize and LocalSizeId must not be specified." ;
336- }
337- if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
338- return _.diag (SPV_ERROR_INVALID_DATA, inst)
339- << " The NonCoherentTileAttachmentQCOM execution mode must "
340- " not be used in any stage other than fragment." ;
341- }
342- } else {
343- if (has_mode (spv::ExecutionMode::TileShadingRateQCOM)) {
344- return _.diag (SPV_ERROR_INVALID_DATA, inst)
345- << " If the TileShadingRateQCOM execution mode is used, the "
346- " TileShadingQCOM capability must be enabled." ;
347- }
361+ if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
362+ return _.diag (SPV_ERROR_INVALID_DATA, inst)
363+ << " The NonCoherentTileAttachmentQCOM execution mode must "
364+ " not be used in any stage other than fragment." ;
348365 }
349- break ;
350- default :
366+ } else {
351367 if (has_mode (spv::ExecutionMode::TileShadingRateQCOM)) {
352368 return _.diag (SPV_ERROR_INVALID_DATA, inst)
353- << " The TileShadingRateQCOM execution mode must not be used "
354- " in any stage other than compute ." ;
369+ << " If the TileShadingRateQCOM execution mode is used, the "
370+ " TileShadingQCOM capability must be enabled ." ;
355371 }
356- if (execution_model != spv::ExecutionModel::Fragment) {
357- if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
372+ }
373+ } else {
374+ if (has_mode (spv::ExecutionMode::TileShadingRateQCOM)) {
375+ return _.diag (SPV_ERROR_INVALID_DATA, inst)
376+ << " The TileShadingRateQCOM execution mode must not be used "
377+ " in any stage other than compute." ;
378+ }
379+ if (execution_model != spv::ExecutionModel::Fragment) {
380+ if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
381+ return _.diag (SPV_ERROR_INVALID_DATA, inst)
382+ << " The NonCoherentTileAttachmentQCOM execution mode must "
383+ " not be used in any stage other than fragment." ;
384+ }
385+ if (_.HasCapability (spv::Capability::TileShadingQCOM)) {
386+ return _.diag (SPV_ERROR_INVALID_CAPABILITY, inst)
387+ << " The TileShadingQCOM capability must not be enabled in "
388+ " any stage other than compute or fragment." ;
389+ }
390+ } else {
391+ if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
392+ if (!_.HasCapability (spv::Capability::TileShadingQCOM)) {
358393 return _.diag (SPV_ERROR_INVALID_DATA, inst)
359- << " The NonCoherentTileAttachmentQCOM execution mode must "
360- " not be used in any stage other than fragment." ;
361- }
362- if (_.HasCapability (spv::Capability::TileShadingQCOM)) {
363- return _.diag (SPV_ERROR_INVALID_CAPABILITY, inst)
364- << " The TileShadingQCOM capability must not be enabled in "
365- " any stage other than compute or fragment." ;
366- }
367- } else {
368- if (has_mode (spv::ExecutionMode::NonCoherentTileAttachmentReadQCOM)) {
369- if (!_.HasCapability (spv::Capability::TileShadingQCOM)) {
370- return _.diag (SPV_ERROR_INVALID_DATA, inst)
371- << " If the NonCoherentTileAttachmentReadQCOM execution "
372- " mode is used, the TileShadingQCOM capability must be "
373- " enabled." ;
374- }
394+ << " If the NonCoherentTileAttachmentReadQCOM execution "
395+ " mode is used, the TileShadingQCOM capability must be "
396+ " enabled." ;
375397 }
376398 }
399+ }
400+ }
401+
402+ switch (execution_model) {
403+ case spv::ExecutionModel::GLCompute:
404+ case spv::ExecutionModel::MeshEXT:
405+ case spv::ExecutionModel::MeshNV:
406+ case spv::ExecutionModel::TaskEXT:
407+ case spv::ExecutionModel::TaskNV:
408+ if (!has_mode (spv::ExecutionMode::LocalSize) && !has_workgroup_size &&
409+ !has_local_size_id &&
410+ !has_mode (spv::ExecutionMode::TileShadingRateQCOM)) {
411+ return _.diag (SPV_ERROR_INVALID_DATA, inst)
412+ << _.VkErrorID (10685 ) << " In the Vulkan environment, "
413+ << ExecutionModelToString (execution_model)
414+ << " execution model "
415+ " entry points require either the "
416+ << (_.HasCapability (spv::Capability::TileShadingQCOM)
417+ ? " TileShadingRateQCOM, "
418+ : " " )
419+ << " LocalSize or LocalSizeId execution mode or an object "
420+ " decorated with WorkgroupSize must be specified." ;
421+ }
422+ break ;
423+ default :
377424 break ;
378425 }
379426 }
0 commit comments