Support SPV_KHR_fragment_shading_rate (#3943)
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index 16ea7ff..a0114c3 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -176,12 +176,13 @@
// Set 5: Operands that are a single word bitmask.
// Sometimes a set bit indicates the instruction requires still more operands.
- SPV_OPERAND_TYPE_IMAGE, // SPIR-V Sec 3.14
- SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, // SPIR-V Sec 3.15
- SPV_OPERAND_TYPE_SELECTION_CONTROL, // SPIR-V Sec 3.22
- SPV_OPERAND_TYPE_LOOP_CONTROL, // SPIR-V Sec 3.23
- SPV_OPERAND_TYPE_FUNCTION_CONTROL, // SPIR-V Sec 3.24
- SPV_OPERAND_TYPE_MEMORY_ACCESS, // SPIR-V Sec 3.26
+ SPV_OPERAND_TYPE_IMAGE, // SPIR-V Sec 3.14
+ SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, // SPIR-V Sec 3.15
+ SPV_OPERAND_TYPE_SELECTION_CONTROL, // SPIR-V Sec 3.22
+ SPV_OPERAND_TYPE_LOOP_CONTROL, // SPIR-V Sec 3.23
+ SPV_OPERAND_TYPE_FUNCTION_CONTROL, // SPIR-V Sec 3.24
+ SPV_OPERAND_TYPE_MEMORY_ACCESS, // SPIR-V Sec 3.26
+ SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE, // SPIR-V Sec 3.FSR
// The remaining operand types are only used internally by the assembler.
// There are two categories:
diff --git a/source/operand.cpp b/source/operand.cpp
index 7b2b98f..d4b64a8 100644
--- a/source/operand.cpp
+++ b/source/operand.cpp
@@ -208,6 +208,8 @@
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
return "memory access";
+ case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
+ return "shading rate";
case SPV_OPERAND_TYPE_SCOPE_ID:
return "scope ID";
case SPV_OPERAND_TYPE_GROUP_OPERATION:
@@ -360,6 +362,7 @@
case SPV_OPERAND_TYPE_LOOP_CONTROL:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+ case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
return true;
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp
index 1d7017d..5b9eed6 100644
--- a/source/val/validate_builtins.cpp
+++ b/source/val/validate_builtins.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2018 Google LLC.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -230,6 +232,12 @@
spv_result_t ValidateComputeI32InputAtDefinition(const Decoration& decoration,
const Instruction& inst);
+ spv_result_t ValidatePrimitiveShadingRateAtDefinition(
+ const Decoration& decoration, const Instruction& inst);
+
+ spv_result_t ValidateShadingRateAtDefinition(const Decoration& decoration,
+ const Instruction& inst);
+
// The following section contains functions which are called when id defined
// by |referenced_inst| is
// 1. referenced by |referenced_from_inst|
@@ -383,6 +391,16 @@
const Instruction& referenced_inst,
const Instruction& referenced_from_inst);
+ spv_result_t ValidatePrimitiveShadingRateAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
+ spv_result_t ValidateShadingRateAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
// Validates that |built_in_inst| is not (even indirectly) referenced from
// within a function which can be called with |execution_model|.
//
@@ -3314,6 +3332,142 @@
return SPV_SUCCESS;
}
+spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtDefinition(
+ const Decoration& decoration, const Instruction& inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ if (spv_result_t error = ValidateI32(
+ decoration, inst,
+ [this, &inst,
+ &decoration](const std::string& message) -> spv_result_t {
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(4486)
+ << "According to the Vulkan spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " variable needs to be a 32-bit int scalar. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ // Seed at reference checks with this built-in.
+ return ValidatePrimitiveShadingRateAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassOutput) {
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(4485) << "Vulkan spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " to be only used for variables with Output storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ switch (execution_model) {
+ case SpvExecutionModelVertex:
+ case SpvExecutionModelGeometry:
+ case SpvExecutionModelMeshNV:
+ break;
+ default: {
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(4484) << "Vulkan spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " to be used only with Vertex, Geometry, or MeshNV "
+ "execution models. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
+ std::bind(&BuiltInsValidator::ValidatePrimitiveShadingRateAtReference,
+ this, decoration, built_in_inst, referenced_from_inst,
+ std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateShadingRateAtDefinition(
+ const Decoration& decoration, const Instruction& inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ if (spv_result_t error = ValidateI32(
+ decoration, inst,
+ [this, &inst,
+ &decoration](const std::string& message) -> spv_result_t {
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(4492)
+ << "According to the Vulkan spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " variable needs to be a 32-bit int scalar. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ // Seed at reference checks with this built-in.
+ return ValidateShadingRateAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateShadingRateAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassInput) {
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(4491) << "Vulkan spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " to be only used for variables with Input storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ if (execution_model != SpvExecutionModelFragment) {
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(4490) << "Vulkan spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ decoration.params()[0])
+ << " to be used only with the Fragment execution model. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+ &BuiltInsValidator::ValidateShadingRateAtReference, this, decoration,
+ built_in_inst, referenced_from_inst, std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
const Decoration& decoration, const Instruction& inst) {
const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
@@ -3514,6 +3668,11 @@
case SpvBuiltInRayGeometryIndexKHR: {
// No validation rules (for the moment).
break;
+
+ case SpvBuiltInPrimitiveShadingRateKHR:
+ return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
+ case SpvBuiltInShadingRateKHR:
+ return ValidateShadingRateAtDefinition(decoration, inst);
}
}
return SPV_SUCCESS;
diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp
index cc9bda6..4248caa 100644
--- a/test/val/val_builtins_test.cpp
+++ b/test/val/val_builtins_test.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2018 Google LLC.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -3723,6 +3725,108 @@
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
}
+INSTANTIATE_TEST_SUITE_P(
+ PrimitiveShadingRateOutputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("PrimitiveShadingRateKHR"), Values("Vertex", "Geometry"),
+ Values("Output"), Values("%u32"),
+ Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ PrimitiveShadingRateMeshOutputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("PrimitiveShadingRateKHR"), Values("MeshNV"),
+ Values("Output"), Values("%u32"),
+ Values("OpCapability FragmentShadingRateKHR\nOpCapability "
+ "MeshShadingNV\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\nOpExtension "
+ "\"SPV_NV_mesh_shader\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ PrimitiveShadingRateInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("PrimitiveShadingRateKHR"), Values("Fragment"), Values("Output"),
+ Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484 "),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn PrimitiveShadingRateKHR to be used "
+ "only with Vertex, Geometry, or MeshNV execution models."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ PrimitiveShadingRateInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("PrimitiveShadingRateKHR"), Values("Vertex"), Values("Input"),
+ Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485 "),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn PrimitiveShadingRateKHR to be only "
+ "used for variables with Output storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ PrimitiveShadingRateInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("PrimitiveShadingRateKHR"), Values("Vertex"), Values("Output"),
+ Values("%f32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485 "),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn PrimitiveShadingRateKHR "
+ "variable needs to be a 32-bit int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ ShadingRateInputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("ShadingRateKHR"), Values("Fragment"), Values("Input"),
+ Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ ShadingRateInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("ShadingRateKHR"), Values("Vertex"), Values("Input"),
+ Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-ShadingRateKHR-ShadingRateKHR-04490 "),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn ShadingRateKHR to be used "
+ "only with the Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ ShadingRateInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("ShadingRateKHR"), Values("Fragment"), Values("Output"),
+ Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-ShadingRateKHR-ShadingRateKHR-04491 "),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn ShadingRateKHR to be only "
+ "used for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ ShadingRateInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("ShadingRateKHR"), Values("Fragment"), Values("Input"),
+ Values("%f32"), Values("OpCapability FragmentShadingRateKHR\n"),
+ Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
+ Values("VUID-ShadingRateKHR-ShadingRateKHR-04492 "),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn ShadingRateKHR "
+ "variable needs to be a 32-bit int scalar."))));
} // namespace
} // namespace val
} // namespace spvtools