validate_misc.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright (c) 2018 Google LLC.
  2. // Copyright (c) 2019 NVIDIA Corporation
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include "source/val/validate.h"
  16. #include "source/opcode.h"
  17. #include "source/spirv_target_env.h"
  18. #include "source/val/instruction.h"
  19. #include "source/val/validate_scopes.h"
  20. #include "source/val/validation_state.h"
  21. namespace spvtools {
  22. namespace val {
  23. namespace {
  24. spv_result_t ValidateUndef(ValidationState_t& _, const Instruction* inst) {
  25. if (_.HasCapability(SpvCapabilityShader) &&
  26. _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
  27. !_.IsPointerType(inst->type_id())) {
  28. return _.diag(SPV_ERROR_INVALID_ID, inst)
  29. << "Cannot create undefined values with 8- or 16-bit types";
  30. }
  31. if (spvIsWebGPUEnv(_.context()->target_env)) {
  32. return _.diag(SPV_ERROR_INVALID_BINARY, inst) << "OpUndef is disallowed";
  33. }
  34. return SPV_SUCCESS;
  35. }
  36. spv_result_t ValidateShaderClock(ValidationState_t& _,
  37. const Instruction* inst) {
  38. const uint32_t scope = inst->GetOperandAs<uint32_t>(2);
  39. if (auto error = ValidateScope(_, inst, scope)) {
  40. return error;
  41. }
  42. bool is_int32 = false, is_const_int32 = false;
  43. uint32_t value = 0;
  44. std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
  45. if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
  46. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  47. << "Scope must be Subgroup or Device";
  48. }
  49. // Result Type must be a 64 - bit unsigned integer type or
  50. // a vector of two - components of 32 -
  51. // bit unsigned integer type
  52. const uint32_t result_type = inst->type_id();
  53. if (!(_.IsUnsignedIntScalarType(result_type) &&
  54. _.GetBitWidth(result_type) == 64) &&
  55. !(_.IsUnsignedIntVectorType(result_type) &&
  56. _.GetDimension(result_type) == 2 && _.GetBitWidth(result_type) == 32)) {
  57. return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Expected Value to be a "
  58. "vector of two components"
  59. " of unsigned integer"
  60. " or 64bit unsigned integer";
  61. }
  62. return SPV_SUCCESS;
  63. }
  64. } // namespace
  65. spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
  66. switch (inst->opcode()) {
  67. case SpvOpUndef:
  68. if (auto error = ValidateUndef(_, inst)) return error;
  69. break;
  70. default:
  71. break;
  72. }
  73. switch (inst->opcode()) {
  74. case SpvOpBeginInvocationInterlockEXT:
  75. case SpvOpEndInvocationInterlockEXT:
  76. _.function(inst->function()->id())
  77. ->RegisterExecutionModelLimitation(
  78. SpvExecutionModelFragment,
  79. "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
  80. "require Fragment execution model");
  81. _.function(inst->function()->id())
  82. ->RegisterLimitation([](const ValidationState_t& state,
  83. const Function* entry_point,
  84. std::string* message) {
  85. const auto* execution_modes =
  86. state.GetExecutionModes(entry_point->id());
  87. auto find_interlock = [](const SpvExecutionMode& mode) {
  88. switch (mode) {
  89. case SpvExecutionModePixelInterlockOrderedEXT:
  90. case SpvExecutionModePixelInterlockUnorderedEXT:
  91. case SpvExecutionModeSampleInterlockOrderedEXT:
  92. case SpvExecutionModeSampleInterlockUnorderedEXT:
  93. case SpvExecutionModeShadingRateInterlockOrderedEXT:
  94. case SpvExecutionModeShadingRateInterlockUnorderedEXT:
  95. return true;
  96. default:
  97. return false;
  98. }
  99. };
  100. bool found = false;
  101. if (execution_modes) {
  102. auto i = std::find_if(execution_modes->begin(),
  103. execution_modes->end(), find_interlock);
  104. found = (i != execution_modes->end());
  105. }
  106. if (!found) {
  107. *message =
  108. "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
  109. "require a fragment shader interlock execution mode.";
  110. return false;
  111. }
  112. return true;
  113. });
  114. break;
  115. case SpvOpDemoteToHelperInvocationEXT:
  116. _.function(inst->function()->id())
  117. ->RegisterExecutionModelLimitation(
  118. SpvExecutionModelFragment,
  119. "OpDemoteToHelperInvocationEXT requires Fragment execution "
  120. "model");
  121. break;
  122. case SpvOpIsHelperInvocationEXT: {
  123. const uint32_t result_type = inst->type_id();
  124. _.function(inst->function()->id())
  125. ->RegisterExecutionModelLimitation(
  126. SpvExecutionModelFragment,
  127. "OpIsHelperInvocationEXT requires Fragment execution model");
  128. if (!_.IsBoolScalarType(result_type))
  129. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  130. << "Expected bool scalar type as Result Type: "
  131. << spvOpcodeString(inst->opcode());
  132. break;
  133. }
  134. case SpvOpReadClockKHR:
  135. if (auto error = ValidateShaderClock(_, inst)) {
  136. return error;
  137. }
  138. break;
  139. default:
  140. break;
  141. }
  142. return SPV_SUCCESS;
  143. }
  144. } // namespace val
  145. } // namespace spvtools