mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 00:40:14 +00:00
Disallow array-of-arrays with DescriptorSets when validating. (#1586)
* Disallow array-of-arrays with DescriptorSets when validating. This CL adds validation to disallow using an array-of-arrays when attached to a DescriptorSet. Fixes #1522
This commit is contained in:
parent
a1f9e1342e
commit
e3f1f3bda5
@ -180,6 +180,44 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t CheckDescriptorSetArrayOfArrays(ValidationState_t& vstate) {
|
||||
for (const auto& def : vstate.all_definitions()) {
|
||||
const auto inst = def.second;
|
||||
if (SpvOpVariable != inst->opcode()) continue;
|
||||
|
||||
// Verify this variable is a DescriptorSet
|
||||
bool has_descriptor_set = false;
|
||||
for (const auto& decoration : vstate.id_decorations(def.first)) {
|
||||
if (SpvDecorationDescriptorSet == decoration.dec_type()) {
|
||||
has_descriptor_set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_descriptor_set) continue;
|
||||
|
||||
const auto& words = inst->words();
|
||||
const auto* ptrInst = vstate.FindDef(words[1]);
|
||||
assert(SpvOpTypePointer == ptrInst->opcode());
|
||||
|
||||
// Check for a first level array
|
||||
const auto typePtr = vstate.FindDef(ptrInst->words()[3]);
|
||||
if (SpvOpTypeRuntimeArray != typePtr->opcode() &&
|
||||
SpvOpTypeArray != typePtr->opcode()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for a second level array
|
||||
const auto secondaryTypePtr = vstate.FindDef(typePtr->words()[2]);
|
||||
if (SpvOpTypeRuntimeArray == secondaryTypePtr->opcode() ||
|
||||
SpvOpTypeArray == secondaryTypePtr->opcode()) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID)
|
||||
<< "Only a single level of array is allowed for descriptor "
|
||||
"set variables";
|
||||
}
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace libspirv {
|
||||
@ -189,6 +227,7 @@ spv_result_t ValidateDecorations(ValidationState_t& vstate) {
|
||||
if (auto error = CheckImportedVariableInitialization(vstate)) return error;
|
||||
if (auto error = CheckDecorationsOfEntryPoints(vstate)) return error;
|
||||
if (auto error = CheckLinkageAttrOfFunctions(vstate)) return error;
|
||||
if (auto error = CheckDescriptorSetArrayOfArrays(vstate)) return error;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
using libspirv::Decoration;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using ValidateDecorations = spvtest::ValidateBase<bool>;
|
||||
|
||||
@ -548,4 +548,181 @@ OpFunctionEnd
|
||||
"Component decorations"));
|
||||
}
|
||||
|
||||
// #version 440
|
||||
// #extension GL_EXT_nonuniform_qualifier : enable
|
||||
// layout(binding = 1) uniform sampler2D s2d[];
|
||||
// layout(location = 0) in nonuniformEXT int i;
|
||||
// void main()
|
||||
// {
|
||||
// vec4 v = texture(s2d[i], vec2(0.3));
|
||||
// }
|
||||
TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) {
|
||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability ShaderNonUniformEXT
|
||||
OpCapability RuntimeDescriptorArrayEXT
|
||||
OpCapability SampledImageArrayNonUniformIndexingEXT
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %i
|
||||
OpSource GLSL 440
|
||||
OpSourceExtension "GL_EXT_nonuniform_qualifier"
|
||||
OpName %main "main"
|
||||
OpName %v "v"
|
||||
OpName %s2d "s2d"
|
||||
OpName %i "i"
|
||||
OpDecorate %s2d DescriptorSet 0
|
||||
OpDecorate %s2d Binding 1
|
||||
OpDecorate %i Location 0
|
||||
OpDecorate %i NonUniformEXT
|
||||
OpDecorate %18 NonUniformEXT
|
||||
OpDecorate %21 NonUniformEXT
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %10
|
||||
%_runtimearr_11 = OpTypeRuntimeArray %11
|
||||
%_ptr_UniformConstant__runtimearr_11 = OpTypePointer UniformConstant %_runtimearr_11
|
||||
%s2d = OpVariable %_ptr_UniformConstant__runtimearr_11 UniformConstant
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%i = OpVariable %_ptr_Input_int Input
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%v2float = OpTypeVector %float 2
|
||||
%float_0_300000012 = OpConstant %float 0.300000012
|
||||
%24 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
|
||||
%float_0 = OpConstant %float 0
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%18 = OpLoad %int %i
|
||||
%20 = OpAccessChain %_ptr_UniformConstant_11 %s2d %18
|
||||
%21 = OpLoad %11 %20
|
||||
%26 = OpImageSampleExplicitLod %v4float %21 %24 Lod %float_0
|
||||
OpStore %v %26
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
|
||||
}
|
||||
|
||||
// #version 440
|
||||
// #extension GL_EXT_nonuniform_qualifier : enable
|
||||
// layout(binding = 1) uniform sampler2D s2d[][2];
|
||||
// layout(location = 0) in nonuniformEXT int i;
|
||||
// void main()
|
||||
// {
|
||||
// vec4 v = texture(s2d[i][i], vec2(0.3));
|
||||
// }
|
||||
TEST_F(ValidateDecorations, RuntimeArrayOfArraysOfDescriptorSetsIsDisallowed) {
|
||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability ShaderNonUniformEXT
|
||||
OpCapability RuntimeDescriptorArrayEXT
|
||||
OpCapability SampledImageArrayNonUniformIndexingEXT
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %i
|
||||
OpSource GLSL 440
|
||||
OpSourceExtension "GL_EXT_nonuniform_qualifier"
|
||||
OpName %main "main"
|
||||
OpName %v "v"
|
||||
OpName %s2d "s2d"
|
||||
OpName %i "i"
|
||||
OpDecorate %s2d DescriptorSet 0
|
||||
OpDecorate %s2d Binding 1
|
||||
OpDecorate %i Location 0
|
||||
OpDecorate %i NonUniformEXT
|
||||
OpDecorate %21 NonUniformEXT
|
||||
OpDecorate %22 NonUniformEXT
|
||||
OpDecorate %25 NonUniformEXT
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %10
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_arr_11_uint_2 = OpTypeArray %11 %uint_2
|
||||
%_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2
|
||||
%_ptr_UniformConstant__runtimearr__arr_11_uint_2 = OpTypePointer UniformConstant %_runtimearr__arr_11_uint_2
|
||||
%s2d = OpVariable %_ptr_UniformConstant__runtimearr__arr_11_uint_2 UniformConstant
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%i = OpVariable %_ptr_Input_int Input
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%v2float = OpTypeVector %float 2
|
||||
%float_0_300000012 = OpConstant %float 0.300000012
|
||||
%28 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
|
||||
%float_0 = OpConstant %float 0
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%21 = OpLoad %int %i
|
||||
%22 = OpLoad %int %i
|
||||
%24 = OpAccessChain %_ptr_UniformConstant_11 %s2d %21 %22
|
||||
%25 = OpLoad %11 %24
|
||||
%30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0
|
||||
OpStore %v %30
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(spirv, env);
|
||||
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Only a single level of array is allowed for "
|
||||
"descriptor set variables"));
|
||||
}
|
||||
|
||||
// #version 440
|
||||
// layout (set=1, binding=1) uniform sampler2D variableName[2][2];
|
||||
// void main() {
|
||||
// }
|
||||
TEST_F(ValidateDecorations, ArrayOfArraysOfDescriptorSetsIsDisallowed) {
|
||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main"
|
||||
OpSource GLSL 440
|
||||
OpName %main "main"
|
||||
OpName %variableName "variableName"
|
||||
OpDecorate %variableName DescriptorSet 1
|
||||
OpDecorate %variableName Binding 1
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%8 = OpTypeSampledImage %7
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_arr_8_uint_2 = OpTypeArray %8 %uint_2
|
||||
%_arr__arr_8_uint_2_uint_2 = OpTypeArray %_arr_8_uint_2 %uint_2
|
||||
%_ptr_UniformConstant__arr__arr_8_uint_2_uint_2 = OpTypePointer UniformConstant %_arr__arr_8_uint_2_uint_2
|
||||
%variableName = OpVariable %_ptr_UniformConstant__arr__arr_8_uint_2_uint_2 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(spirv, env);
|
||||
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Only a single level of array is allowed for "
|
||||
"descriptor set variables"));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user