mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 19:20:05 +00:00
Check binding annotations in resource variables (#2151)
Fixes #2007 Add checks that all uniform, uniform constant and storage buffer variables have descriptor set and binding decorations
This commit is contained in:
parent
17cba4695c
commit
a1439604ea
@ -520,15 +520,18 @@ spv_result_t checkLayout(uint32_t struct_id, const char* storage_class_str,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns true if structure id has given decoration. Handles also nested
|
||||
// structures.
|
||||
bool hasDecoration(uint32_t struct_id, SpvDecoration decoration,
|
||||
// Returns true if variable or structure id has given decoration. Handles also
|
||||
// nested structures.
|
||||
bool hasDecoration(uint32_t id, SpvDecoration decoration,
|
||||
ValidationState_t& vstate) {
|
||||
for (auto& dec : vstate.id_decorations(struct_id)) {
|
||||
for (auto& dec : vstate.id_decorations(id)) {
|
||||
if (decoration == dec.dec_type()) return true;
|
||||
}
|
||||
for (auto id : getStructMembers(struct_id, SpvOpTypeStruct, vstate)) {
|
||||
if (hasDecoration(id, decoration, vstate)) {
|
||||
if (SpvOpTypeStruct != vstate.FindDef(id)->opcode()) {
|
||||
return false;
|
||||
}
|
||||
for (auto member_id : getStructMembers(id, SpvOpTypeStruct, vstate)) {
|
||||
if (hasDecoration(member_id, decoration, vstate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -781,12 +784,39 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
|
||||
for (const auto& inst : vstate.ordered_instructions()) {
|
||||
const auto& words = inst.words();
|
||||
if (SpvOpVariable == inst.opcode()) {
|
||||
const auto var_id = inst.id();
|
||||
// For storage class / decoration combinations, see Vulkan 14.5.4 "Offset
|
||||
// and Stride Assignment".
|
||||
const auto storageClass = words[3];
|
||||
const bool uniform = storageClass == SpvStorageClassUniform;
|
||||
const bool uniform_constant =
|
||||
storageClass == SpvStorageClassUniformConstant;
|
||||
const bool push_constant = storageClass == SpvStorageClassPushConstant;
|
||||
const bool storage_buffer = storageClass == SpvStorageClassStorageBuffer;
|
||||
|
||||
// Vulkan 14.5.2: Check DescriptorSet and Binding decoration for
|
||||
// UniformConstant which cannot be a struct.
|
||||
if (spvIsVulkanEnv(vstate.context()->target_env)) {
|
||||
if (uniform_constant) {
|
||||
if (!hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
|
||||
<< "UniformConstant id '" << var_id
|
||||
<< "' is missing DescriptorSet decoration.\n"
|
||||
<< "From Vulkan spec, section 14.5.2:\n"
|
||||
<< "These variables must have DescriptorSet and Binding "
|
||||
"decorations specified";
|
||||
}
|
||||
if (!hasDecoration(var_id, SpvDecorationBinding, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
|
||||
<< "UniformConstant id '" << var_id
|
||||
<< "' is missing Binding decoration.\n"
|
||||
<< "From Vulkan spec, section 14.5.2:\n"
|
||||
<< "These variables must have DescriptorSet and Binding "
|
||||
"decorations specified";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uniform || push_constant || storage_buffer) {
|
||||
const auto ptrInst = vstate.FindDef(words[1]);
|
||||
assert(SpvOpTypePointer == ptrInst->opcode());
|
||||
@ -795,9 +825,13 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
|
||||
MemberConstraints constraints;
|
||||
ComputeMemberConstraintsForStruct(&constraints, id, LayoutConstraints(),
|
||||
vstate);
|
||||
// Prepare for messages
|
||||
const char* sc_str =
|
||||
uniform ? "Uniform"
|
||||
: (push_constant ? "PushConstant" : "StorageBuffer");
|
||||
|
||||
// Vulkan 14.5.1: Check Block annotation for PushConstant variables.
|
||||
if (spvIsVulkanEnv(vstate.context()->target_env)) {
|
||||
// Vulkan 14.5.1: Check Block decoration for PushConstant variables.
|
||||
if (push_constant && !hasDecoration(id, SpvDecorationBlock, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
|
||||
<< "PushConstant id '" << id
|
||||
@ -806,12 +840,28 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
|
||||
<< "Such variables must be identified with a Block "
|
||||
"decoration";
|
||||
}
|
||||
// Vulkan 14.5.2: Check DescriptorSet and Binding decoration for
|
||||
// Uniform and StorageBuffer variables.
|
||||
if (uniform || storage_buffer) {
|
||||
if (!hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
|
||||
<< sc_str << " id '" << var_id
|
||||
<< "' is missing DescriptorSet decoration.\n"
|
||||
<< "From Vulkan spec, section 14.5.2:\n"
|
||||
<< "These variables must have DescriptorSet and Binding "
|
||||
"decorations specified";
|
||||
}
|
||||
if (!hasDecoration(var_id, SpvDecorationBinding, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
|
||||
<< sc_str << " id '" << var_id
|
||||
<< "' is missing Binding decoration.\n"
|
||||
<< "From Vulkan spec, section 14.5.2:\n"
|
||||
<< "These variables must have DescriptorSet and Binding "
|
||||
"decorations specified";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for messages
|
||||
const char* sc_str =
|
||||
uniform ? "Uniform"
|
||||
: (push_constant ? "PushConstant" : "StorageBuffer");
|
||||
for (const auto& dec : vstate.id_decorations(id)) {
|
||||
const bool blockDeco = SpvDecorationBlock == dec.dec_type();
|
||||
const bool bufferDeco = SpvDecorationBufferBlock == dec.dec_type();
|
||||
@ -825,7 +875,8 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
|
||||
if (isMissingOffsetInStruct(id, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
|
||||
<< "Structure id " << id << " decorated as " << deco_str
|
||||
<< " must be explicitly laid out with Offset decorations.";
|
||||
<< " must be explicitly laid out with Offset "
|
||||
"decorations.";
|
||||
} else if (hasDecoration(id, SpvDecorationGLSLShared, vstate)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
|
||||
<< "Structure id " << id << " decorated as " << deco_str
|
||||
@ -946,7 +997,8 @@ spv_result_t CheckDecorationsOfConversions(ValidationState_t& vstate) {
|
||||
vstate.GetBitWidth(half_float_id) != 16) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "FPRoundingMode decoration can be applied only to the "
|
||||
"Object operand of an OpStore storing through a pointer to "
|
||||
"Object operand of an OpStore storing through a pointer "
|
||||
"to "
|
||||
"a 16-bit floating-point scalar or vector object.";
|
||||
}
|
||||
|
||||
|
@ -2013,6 +2013,8 @@ TEST_F(ValidateDecorations, BlockArrayBadAlignmentWithRelaxedLayoutStillBad) {
|
||||
OpEntryPoint Vertex %main "main"
|
||||
OpSource GLSL 450
|
||||
OpDecorate %_arr_float_uint_2 ArrayStride 16
|
||||
OpDecorate %u DescriptorSet 0
|
||||
OpDecorate %u Binding 0
|
||||
OpMemberDecorate %S 0 Offset 0
|
||||
OpMemberDecorate %S 1 Offset 8
|
||||
OpDecorate %S Block
|
||||
@ -2039,7 +2041,7 @@ TEST_F(ValidateDecorations, BlockArrayBadAlignmentWithRelaxedLayoutStillBad) {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"Structure id 3 decorated as Block for variable in Uniform "
|
||||
"Structure id 4 decorated as Block for variable in Uniform "
|
||||
"storage class must follow standard uniform buffer layout rules: "
|
||||
"member 1 at offset 8 is not aligned to 16"));
|
||||
}
|
||||
@ -2053,6 +2055,8 @@ TEST_F(ValidateDecorations, BlockArrayBadAlignmentWithVulkan1_1StillBad) {
|
||||
OpEntryPoint Vertex %main "main"
|
||||
OpSource GLSL 450
|
||||
OpDecorate %_arr_float_uint_2 ArrayStride 16
|
||||
OpDecorate %u DescriptorSet 0
|
||||
OpDecorate %u Binding 0
|
||||
OpMemberDecorate %S 0 Offset 0
|
||||
OpMemberDecorate %S 1 Offset 8
|
||||
OpDecorate %S Block
|
||||
@ -2078,7 +2082,7 @@ TEST_F(ValidateDecorations, BlockArrayBadAlignmentWithVulkan1_1StillBad) {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"Structure id 3 decorated as Block for variable in Uniform "
|
||||
"Structure id 4 decorated as Block for variable in Uniform "
|
||||
"storage class must follow relaxed uniform buffer layout rules: "
|
||||
"member 1 at offset 8 is not aligned to 16"));
|
||||
}
|
||||
@ -2279,6 +2283,375 @@ TEST_F(ValidateDecorations, VulkanPushConstantMissingBlockBad) {
|
||||
"decoration"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct Block
|
||||
OpMemberDecorate %struct 0 Offset 0
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer Uniform %struct
|
||||
%var = OpVariable %ptr Uniform
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct Block
|
||||
OpMemberDecorate %struct 0 Offset 0
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer Uniform %struct
|
||||
%var = OpVariable %ptr Uniform
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Uniform id '3' is missing Binding decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%sampler = OpTypeSampler
|
||||
%ptr = OpTypePointer UniformConstant %sampler
|
||||
%var = OpVariable %ptr UniformConstant
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%sampler = OpTypeSampler
|
||||
%ptr = OpTypePointer UniformConstant %sampler
|
||||
%var = OpVariable %ptr UniformConstant
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("UniformConstant id '2' is missing Binding decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct BufferBlock
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer StorageBuffer %struct
|
||||
%var = OpVariable %ptr StorageBuffer
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct BufferBlock
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer StorageBuffer %struct
|
||||
%var = OpVariable %ptr StorageBuffer
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n"
|
||||
"From Vulkan spec, section 14.5.2:\n"
|
||||
"These variables must have DescriptorSet and Binding "
|
||||
"decorations specified"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct Block
|
||||
OpMemberDecorate %struct 0 Offset 0
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer Uniform %struct
|
||||
%var = OpVariable %ptr Uniform
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, UniformMissingBindingGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct Block
|
||||
OpMemberDecorate %struct 0 Offset 0
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer Uniform %struct
|
||||
%var = OpVariable %ptr Uniform
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%sampler = OpTypeSampler
|
||||
%ptr = OpTypePointer UniformConstant %sampler
|
||||
%var = OpVariable %ptr UniformConstant
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%sampler = OpTypeSampler
|
||||
%ptr = OpTypePointer UniformConstant %sampler
|
||||
%var = OpVariable %ptr UniformConstant
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct BufferBlock
|
||||
OpDecorate %var Binding 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer StorageBuffer %struct
|
||||
%var = OpVariable %ptr StorageBuffer
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
|
||||
OpDecorate %struct BufferBlock
|
||||
OpDecorate %var DescriptorSet 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %float
|
||||
%ptr = OpTypePointer StorageBuffer %struct
|
||||
%var = OpVariable %ptr StorageBuffer
|
||||
|
||||
%1 = OpFunction %void None %voidfn
|
||||
%label = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
|
||||
<< getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) {
|
||||
// Spot check buffer rules when using StorageBuffer storage class with Block
|
||||
// decoration.
|
||||
|
@ -61,6 +61,37 @@ OpCapability ImageBuffer
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
if (env == SPV_ENV_VULKAN_1_0) {
|
||||
ss << R"(
|
||||
OpDecorate %uniform_image_f32_1d_0001 DescriptorSet 0
|
||||
OpDecorate %uniform_image_f32_1d_0001 Binding 0
|
||||
OpDecorate %uniform_image_f32_1d_0002_rgba32f DescriptorSet 0
|
||||
OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1
|
||||
OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0
|
||||
OpDecorate %uniform_image_f32_2d_0001 Binding 2
|
||||
OpDecorate %uniform_image_f32_2d_0010 DescriptorSet 0
|
||||
OpDecorate %uniform_image_f32_2d_0010 Binding 3
|
||||
OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1
|
||||
OpDecorate %uniform_image_u32_2d_0001 Binding 0
|
||||
OpDecorate %uniform_image_u32_2d_0000 DescriptorSet 1
|
||||
OpDecorate %uniform_image_u32_2d_0000 Binding 1
|
||||
OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1
|
||||
OpDecorate %uniform_image_s32_3d_0001 Binding 2
|
||||
OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1
|
||||
OpDecorate %uniform_image_f32_2d_0002 Binding 3
|
||||
OpDecorate %uniform_image_f32_spd_0002 DescriptorSet 2
|
||||
OpDecorate %uniform_image_f32_spd_0002 Binding 0
|
||||
OpDecorate %uniform_image_f32_3d_0111 DescriptorSet 2
|
||||
OpDecorate %uniform_image_f32_3d_0111 Binding 1
|
||||
OpDecorate %uniform_image_f32_cube_0101 DescriptorSet 2
|
||||
OpDecorate %uniform_image_f32_cube_0101 Binding 2
|
||||
OpDecorate %uniform_image_f32_cube_0102_rgba32f DescriptorSet 2
|
||||
OpDecorate %uniform_image_f32_cube_0102_rgba32f Binding 3
|
||||
OpDecorate %uniform_sampler DescriptorSet 3
|
||||
OpDecorate %uniform_sampler Binding 0
|
||||
)";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
|
@ -64,6 +64,8 @@ OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
OpDecorate %2 DescriptorSet 0
|
||||
OpDecorate %2 Binding 0
|
||||
%sampler = OpTypeSampler
|
||||
%sampler_ptr = OpTypePointer UniformConstant %sampler
|
||||
%2 = OpVariable %sampler_ptr UniformConstant
|
||||
@ -115,6 +117,8 @@ OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
OpDecorate %2 DescriptorSet 0
|
||||
OpDecorate %2 Binding 0
|
||||
%sampler = OpTypeSampler
|
||||
%uint = OpTypeInt 32 0
|
||||
%array_size = OpConstant %uint 5
|
||||
@ -138,6 +142,8 @@ OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
OpDecorate %2 DescriptorSet 0
|
||||
OpDecorate %2 Binding 0
|
||||
%sampler = OpTypeSampler
|
||||
%uint = OpTypeInt 32 0
|
||||
%array = OpTypeRuntimeArray %sampler
|
||||
|
Loading…
Reference in New Issue
Block a user