From a1439604eac013b2ad08c54783ec54cb75cc52ca Mon Sep 17 00:00:00 2001 From: Alejandro Lopez Date: Tue, 4 Dec 2018 10:05:41 -0500 Subject: [PATCH] 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 --- source/val/validate_decorations.cpp | 78 +++++- test/val/val_decoration_test.cpp | 377 +++++++++++++++++++++++++++- test/val/val_image_test.cpp | 31 +++ test/val/val_memory_test.cpp | 6 + 4 files changed, 477 insertions(+), 15 deletions(-) diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp index 96dd33d16..7d78225f2 100644 --- a/source/val/validate_decorations.cpp +++ b/source/val/validate_decorations.cpp @@ -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."; } diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp index abf315f90..751e98110 100644 --- a/test/val/val_decoration_test.cpp +++ b/test/val/val_decoration_test.cpp @@ -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. diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp index 6697cb1eb..79aecb25b 100644 --- a/test/val/val_image_test.cpp +++ b/test/val/val_image_test.cpp @@ -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 diff --git a/test/val/val_memory_test.cpp b/test/val/val_memory_test.cpp index 0cb892c1b..296ea4385 100644 --- a/test/val/val_memory_test.cpp +++ b/test/val/val_memory_test.cpp @@ -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