summaryrefslogtreecommitdiffstats
path: root/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp')
-rw-r--r--3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp186
1 files changed, 170 insertions, 16 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp
index 39f00fedc73..b9831941646 100644
--- a/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp
+++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_function.cpp
@@ -12,18 +12,47 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "source/val/validate.h"
-
#include <algorithm>
#include "source/opcode.h"
#include "source/val/instruction.h"
+#include "source/val/validate.h"
#include "source/val/validation_state.h"
namespace spvtools {
namespace val {
namespace {
+// Returns true if |a| and |b| are instructions defining pointers that point to
+// types logically match and the decorations that apply to |b| are a subset
+// of the decorations that apply to |a|.
+bool DoPointeesLogicallyMatch(val::Instruction* a, val::Instruction* b,
+ ValidationState_t& _) {
+ if (a->opcode() != SpvOpTypePointer || b->opcode() != SpvOpTypePointer) {
+ return false;
+ }
+
+ const auto& dec_a = _.id_decorations(a->id());
+ const auto& dec_b = _.id_decorations(b->id());
+ for (const auto& dec : dec_b) {
+ if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
+ return false;
+ }
+ }
+
+ uint32_t a_type = a->GetOperandAs<uint32_t>(2);
+ uint32_t b_type = b->GetOperandAs<uint32_t>(2);
+
+ if (a_type == b_type) {
+ return true;
+ }
+
+ Instruction* a_type_inst = _.FindDef(a_type);
+ Instruction* b_type_inst = _.FindDef(b_type);
+
+ return _.LogicallyMatch(a_type_inst, b_type_inst, true);
+}
+
spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
const auto function_type_id = inst->GetOperandAs<uint32_t>(3);
const auto function_type = _.FindDef(function_type_id);
@@ -41,18 +70,22 @@ spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
<< _.getIdName(return_id) << "'.";
}
+ const std::vector<SpvOp> acceptable = {
+ SpvOpDecorate,
+ SpvOpEnqueueKernel,
+ SpvOpEntryPoint,
+ SpvOpExecutionMode,
+ SpvOpExecutionModeId,
+ SpvOpFunctionCall,
+ SpvOpGetKernelNDrangeSubGroupCount,
+ SpvOpGetKernelNDrangeMaxSubGroupSize,
+ SpvOpGetKernelWorkGroupSize,
+ SpvOpGetKernelPreferredWorkGroupSizeMultiple,
+ SpvOpGetKernelLocalSizeForSubgroupCount,
+ SpvOpGetKernelMaxNumSubgroups,
+ SpvOpName};
for (auto& pair : inst->uses()) {
const auto* use = pair.first;
- const std::vector<SpvOp> acceptable = {
- SpvOpFunctionCall,
- SpvOpEntryPoint,
- SpvOpEnqueueKernel,
- SpvOpGetKernelNDrangeSubGroupCount,
- SpvOpGetKernelNDrangeMaxSubGroupSize,
- SpvOpGetKernelWorkGroupSize,
- SpvOpGetKernelPreferredWorkGroupSizeMultiple,
- SpvOpGetKernelLocalSizeForSubgroupCount,
- SpvOpGetKernelMaxNumSubgroups};
if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) ==
acceptable.end()) {
return _.diag(SPV_ERROR_INVALID_ID, use)
@@ -111,6 +144,79 @@ spv_result_t ValidateFunctionParameter(ValidationState_t& _,
<< "' does not match the OpTypeFunction parameter "
"type of the same index.";
}
+
+ // Validate that PhysicalStorageBufferEXT have one of Restrict, Aliased,
+ // RestrictPointerEXT, or AliasedPointerEXT.
+ auto param_nonarray_type_id = param_type->id();
+ while (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypeArray) {
+ param_nonarray_type_id =
+ _.FindDef(param_nonarray_type_id)->GetOperandAs<uint32_t>(1u);
+ }
+ if (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypePointer) {
+ auto param_nonarray_type = _.FindDef(param_nonarray_type_id);
+ if (param_nonarray_type->GetOperandAs<uint32_t>(1u) ==
+ SpvStorageClassPhysicalStorageBufferEXT) {
+ // check for Aliased or Restrict
+ const auto& decorations = _.id_decorations(inst->id());
+
+ bool foundAliased = std::any_of(
+ decorations.begin(), decorations.end(), [](const Decoration& d) {
+ return SpvDecorationAliased == d.dec_type();
+ });
+
+ bool foundRestrict = std::any_of(
+ decorations.begin(), decorations.end(), [](const Decoration& d) {
+ return SpvDecorationRestrict == d.dec_type();
+ });
+
+ if (!foundAliased && !foundRestrict) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "OpFunctionParameter " << inst->id()
+ << ": expected Aliased or Restrict for PhysicalStorageBufferEXT "
+ "pointer.";
+ }
+ if (foundAliased && foundRestrict) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "OpFunctionParameter " << inst->id()
+ << ": can't specify both Aliased and Restrict for "
+ "PhysicalStorageBufferEXT pointer.";
+ }
+ } else {
+ const auto pointee_type_id =
+ param_nonarray_type->GetOperandAs<uint32_t>(2);
+ const auto pointee_type = _.FindDef(pointee_type_id);
+ if (SpvOpTypePointer == pointee_type->opcode() &&
+ pointee_type->GetOperandAs<uint32_t>(1u) ==
+ SpvStorageClassPhysicalStorageBufferEXT) {
+ // check for AliasedPointerEXT/RestrictPointerEXT
+ const auto& decorations = _.id_decorations(inst->id());
+
+ bool foundAliased = std::any_of(
+ decorations.begin(), decorations.end(), [](const Decoration& d) {
+ return SpvDecorationAliasedPointerEXT == d.dec_type();
+ });
+
+ bool foundRestrict = std::any_of(
+ decorations.begin(), decorations.end(), [](const Decoration& d) {
+ return SpvDecorationRestrictPointerEXT == d.dec_type();
+ });
+
+ if (!foundAliased && !foundRestrict) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "OpFunctionParameter " << inst->id()
+ << ": expected AliasedPointerEXT or RestrictPointerEXT for "
+ "PhysicalStorageBufferEXT pointer.";
+ }
+ if (foundAliased && foundRestrict) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "OpFunctionParameter " << inst->id()
+ << ": can't specify both AliasedPointerEXT and "
+ "RestrictPointerEXT for PhysicalStorageBufferEXT pointer.";
+ }
+ }
+ }
+ }
+
return SPV_SUCCESS;
}
@@ -169,10 +275,58 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
function_type->GetOperandAs<uint32_t>(param_index);
const auto parameter_type = _.FindDef(parameter_type_id);
if (!parameter_type || argument_type->id() != parameter_type->id()) {
- return _.diag(SPV_ERROR_INVALID_ID, inst)
- << "OpFunctionCall Argument <id> '" << _.getIdName(argument_id)
- << "'s type does not match Function <id> '"
- << _.getIdName(parameter_type_id) << "'s parameter type.";
+ if (!_.options()->before_hlsl_legalization ||
+ !DoPointeesLogicallyMatch(argument_type, parameter_type, _)) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "OpFunctionCall Argument <id> '" << _.getIdName(argument_id)
+ << "'s type does not match Function <id> '"
+ << _.getIdName(parameter_type_id) << "'s parameter type.";
+ }
+ }
+
+ if (_.addressing_model() == SpvAddressingModelLogical) {
+ if (parameter_type->opcode() == SpvOpTypePointer &&
+ !_.options()->relax_logical_pointer) {
+ SpvStorageClass sc = parameter_type->GetOperandAs<SpvStorageClass>(1u);
+ // Validate which storage classes can be pointer operands.
+ switch (sc) {
+ case SpvStorageClassUniformConstant:
+ case SpvStorageClassFunction:
+ case SpvStorageClassPrivate:
+ case SpvStorageClassWorkgroup:
+ case SpvStorageClassAtomicCounter:
+ // These are always allowed.
+ break;
+ case SpvStorageClassStorageBuffer:
+ if (!_.features().variable_pointers_storage_buffer) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "StorageBuffer pointer operand "
+ << _.getIdName(argument_id)
+ << " requires a variable pointers capability";
+ }
+ break;
+ default:
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Invalid storage class for pointer operand "
+ << _.getIdName(argument_id);
+ }
+
+ // Validate memory object declaration requirements.
+ if (argument->opcode() != SpvOpVariable &&
+ argument->opcode() != SpvOpFunctionParameter) {
+ const bool ssbo_vptr =
+ _.features().variable_pointers_storage_buffer &&
+ sc == SpvStorageClassStorageBuffer;
+ const bool wg_vptr =
+ _.features().variable_pointers && sc == SpvStorageClassWorkgroup;
+ const bool uc_ptr = sc == SpvStorageClassUniformConstant;
+ if (!ssbo_vptr && !wg_vptr && !uc_ptr) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Pointer operand " << _.getIdName(argument_id)
+ << " must be a memory object declaration";
+ }
+ }
+ }
}
}
return SPV_SUCCESS;