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:
Sahil Parmar 2019-05-23 12:08:59 -07:00 committed by alan-baker
parent 07a1019717
commit b8fe7211c4
3 changed files with 168 additions and 20 deletions

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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