mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 19:20:05 +00:00
Allow arrays of out per-primitive builtins for mesh shaders (#2617)
- PrimitiveID, Layer, ViewportIndex * Add validation tests for mesh builtins
This commit is contained in:
parent
07a1019717
commit
b8fe7211c4
@ -353,6 +353,13 @@ class BuiltInsValidator {
|
||||
spv_result_t ValidateI32Arr(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag);
|
||||
spv_result_t ValidateOptionalArrayedI32(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag);
|
||||
spv_result_t ValidateI32Helper(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag,
|
||||
uint32_t underlying_type);
|
||||
spv_result_t ValidateF32(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag);
|
||||
@ -533,6 +540,30 @@ spv_result_t BuiltInsValidator::ValidateI32(
|
||||
return error;
|
||||
}
|
||||
|
||||
return ValidateI32Helper(decoration, inst, diag, underlying_type);
|
||||
}
|
||||
|
||||
spv_result_t BuiltInsValidator::ValidateOptionalArrayedI32(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag) {
|
||||
uint32_t underlying_type = 0;
|
||||
if (spv_result_t error =
|
||||
GetUnderlyingType(_, decoration, inst, &underlying_type)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// Strip the array, if present.
|
||||
if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
|
||||
underlying_type = _.FindDef(underlying_type)->word(2u);
|
||||
}
|
||||
|
||||
return ValidateI32Helper(decoration, inst, diag, underlying_type);
|
||||
}
|
||||
|
||||
spv_result_t BuiltInsValidator::ValidateI32Helper(
|
||||
const Decoration& decoration, const Instruction& inst,
|
||||
const std::function<spv_result_t(const std::string& message)>& diag,
|
||||
uint32_t underlying_type) {
|
||||
if (!_.IsIntScalarType(underlying_type)) {
|
||||
return diag(GetDefinitionDesc(decoration, inst) + " is not an int scalar.");
|
||||
}
|
||||
@ -1716,15 +1747,31 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference(
|
||||
spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtDefinition(
|
||||
const Decoration& decoration, const Instruction& inst) {
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
if (spv_result_t error = ValidateI32(
|
||||
decoration, inst,
|
||||
[this, &inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "According to the Vulkan spec BuiltIn PrimitiveId "
|
||||
"variable needs to be a 32-bit int scalar. "
|
||||
<< message;
|
||||
})) {
|
||||
return error;
|
||||
// PrimitiveId can be a per-primitive variable for mesh shader stage.
|
||||
// In such cases variable will have an array of 32-bit integers.
|
||||
if (decoration.struct_member_index() != Decoration::kInvalidMember) {
|
||||
// This must be a 32-bit int scalar.
|
||||
if (spv_result_t error = ValidateI32(
|
||||
decoration, inst,
|
||||
[this, &inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "According to the Vulkan spec BuiltIn PrimitiveId "
|
||||
"variable needs to be a 32-bit int scalar. "
|
||||
<< message;
|
||||
})) {
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
if (spv_result_t error = ValidateOptionalArrayedI32(
|
||||
decoration, inst,
|
||||
[this, &inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "According to the Vulkan spec BuiltIn PrimitiveId "
|
||||
"variable needs to be a 32-bit int scalar. "
|
||||
<< message;
|
||||
})) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2331,17 +2378,37 @@ spv_result_t BuiltInsValidator::ValidateVertexIndexAtReference(
|
||||
spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtDefinition(
|
||||
const Decoration& decoration, const Instruction& inst) {
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
if (spv_result_t error = ValidateI32(
|
||||
decoration, inst,
|
||||
[this, &decoration,
|
||||
&inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "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;
|
||||
// This can be a per-primitive variable for mesh shader stage.
|
||||
// In such cases variable will have an array of 32-bit integers.
|
||||
if (decoration.struct_member_index() != Decoration::kInvalidMember) {
|
||||
// This must be a 32-bit int scalar.
|
||||
if (spv_result_t error = ValidateI32(
|
||||
decoration, inst,
|
||||
[this, &decoration,
|
||||
&inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "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;
|
||||
}
|
||||
} else {
|
||||
if (spv_result_t error = ValidateOptionalArrayedI32(
|
||||
decoration, inst,
|
||||
[this, &decoration,
|
||||
&inst](const std::string& message) -> spv_result_t {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< "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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2785,6 +2785,85 @@ OpMemberDecorate %input_type 0 BuiltIn InstanceId
|
||||
"AnyHitNV execution models"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, ValidBuiltinsForMeshShader) {
|
||||
CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
|
||||
generator.capabilities_ += R"(
|
||||
OpCapability MeshShadingNV
|
||||
)";
|
||||
|
||||
generator.extensions_ = R"(
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
)";
|
||||
|
||||
generator.before_types_ = R"(
|
||||
OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
|
||||
OpDecorate %gl_PrimitiveID PerPrimitiveNV
|
||||
OpDecorate %gl_Layer BuiltIn Layer
|
||||
OpDecorate %gl_Layer PerPrimitiveNV
|
||||
OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex
|
||||
OpDecorate %gl_ViewportIndex PerPrimitiveNV
|
||||
)";
|
||||
|
||||
generator.after_types_ = R"(
|
||||
%u32_81 = OpConstant %u32 81
|
||||
%_arr_int_uint_81 = OpTypeArray %i32 %u32_81
|
||||
%_ptr_Output__arr_int_uint_81 = OpTypePointer Output %_arr_int_uint_81
|
||||
%gl_PrimitiveID = OpVariable %_ptr_Output__arr_int_uint_81 Output
|
||||
%gl_Layer = OpVariable %_ptr_Output__arr_int_uint_81 Output
|
||||
%gl_ViewportIndex = OpVariable %_ptr_Output__arr_int_uint_81 Output
|
||||
)";
|
||||
|
||||
EntryPoint entry_point;
|
||||
entry_point.name = "main_d_r";
|
||||
entry_point.execution_model = "MeshNV";
|
||||
entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex";
|
||||
generator.entry_points_.push_back(std::move(entry_point));
|
||||
|
||||
CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, InvalidBuiltinsForMeshShader) {
|
||||
CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
|
||||
generator.capabilities_ += R"(
|
||||
OpCapability MeshShadingNV
|
||||
)";
|
||||
|
||||
generator.extensions_ = R"(
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
)";
|
||||
|
||||
generator.before_types_ = R"(
|
||||
OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
|
||||
OpDecorate %gl_PrimitiveID PerPrimitiveNV
|
||||
OpDecorate %gl_Layer BuiltIn Layer
|
||||
OpDecorate %gl_Layer PerPrimitiveNV
|
||||
OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex
|
||||
OpDecorate %gl_ViewportIndex PerPrimitiveNV
|
||||
)";
|
||||
|
||||
generator.after_types_ = R"(
|
||||
%u32_81 = OpConstant %u32 81
|
||||
%_arr_float_uint_81 = OpTypeArray %f32 %u32_81
|
||||
%_ptr_Output__arr_float_uint_81 = OpTypePointer Output %_arr_float_uint_81
|
||||
%gl_PrimitiveID = OpVariable %_ptr_Output__arr_float_uint_81 Output
|
||||
%gl_Layer = OpVariable %_ptr_Output__arr_float_uint_81 Output
|
||||
%gl_ViewportIndex = OpVariable %_ptr_Output__arr_float_uint_81 Output
|
||||
)";
|
||||
|
||||
EntryPoint entry_point;
|
||||
entry_point.name = "main_d_r";
|
||||
entry_point.execution_model = "MeshNV";
|
||||
entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex";
|
||||
generator.entry_points_.push_back(std::move(entry_point));
|
||||
|
||||
CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("needs to be a 32-bit int scalar"));
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr("is not an int scalar"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -46,6 +46,8 @@ std::string GetDefaultShaderTypes() {
|
||||
%bool = OpTypeBool
|
||||
%f32 = OpTypeFloat 32
|
||||
%f64 = OpTypeFloat 64
|
||||
%i32 = OpTypeInt 32 1
|
||||
%i64 = OpTypeInt 64 1
|
||||
%u32 = OpTypeInt 32 0
|
||||
%u64 = OpTypeInt 64 0
|
||||
%f32vec2 = OpTypeVector %f32 2
|
||||
|
Loading…
Reference in New Issue
Block a user