From 5a867acad5da07cfb59a1eaadf8e366fb58bbed4 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Sun, 1 Apr 2018 21:22:34 -0600 Subject: [PATCH] Linker: Fix #1329: correctly merge unsized arrays, and fix link tests. --- Test/baseResults/150.tesc.out | 2 - Test/baseResults/link1.vk.frag.out | 325 ++++++++++++++++++-- Test/link1.vk.frag | 16 +- Test/link2.vk.frag | 17 +- glslang/MachineIndependent/linkValidate.cpp | 22 +- gtests/Link.FromFile.Vk.cpp | 20 +- 6 files changed, 355 insertions(+), 47 deletions(-) diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out index 0abe12dbe..d237ee4de 100644 --- a/Test/baseResults/150.tesc.out +++ b/Test/baseResults/150.tesc.out @@ -942,8 +942,6 @@ ERROR: Linking tessellation control stage: Multiple function bodies in multiple main( ERROR: Linking tessellation control stage: Multiple function bodies in multiple compilation units for the same signature in the same stage: main( -ERROR: Linking tessellation control stage: Types must match: - gl_out: " out 4-element array of block{ out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out unsized 2-element array of float ClipDistance gl_ClipDistance}" versus " out unsized 1-element array of block{ out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out unsized 1-element array of float ClipDistance gl_ClipDistance}" ERROR: Linking tessellation control stage: Types must match: outa: " global 4-element array of int" versus " global 1-element array of int" ERROR: Linking tessellation control stage: can't handle multiple entry points per stage diff --git a/Test/baseResults/link1.vk.frag.out b/Test/baseResults/link1.vk.frag.out index 576868753..e113a3610 100644 --- a/Test/baseResults/link1.vk.frag.out +++ b/Test/baseResults/link1.vk.frag.out @@ -2,30 +2,105 @@ link1.vk.frag Shader version: 450 gl_FragCoord origin is upper left 0:? Sequence -0:7 Function Definition: main( ( global void) -0:7 Function Parameters: -0:9 Sequence -0:9 move second child to first child ( temp highp 4-component vector of float) -0:9 'color' ( out highp 4-component vector of float) -0:9 Function Call: getColor( ( global highp 4-component vector of float) +0:16 Function Definition: main( ( global void) +0:16 Function Parameters: +0:18 Sequence +0:18 move second child to first child ( temp highp 4-component vector of float) +0:18 'color' (layout( location=0) out highp 4-component vector of float) +0:18 Function Call: getColor( ( global highp 4-component vector of float) +0:20 move second child to first child ( temp highp int) +0:20 direct index ( temp highp int) +0:20 'a1' ( global unsized 9-element array of highp int) +0:20 Constant: +0:20 8 (const int) +0:20 Constant: +0:20 1 (const int) +0:21 move second child to first child ( temp highp int) +0:21 direct index ( temp highp int) +0:21 'a2' ( global unsized 2-element array of highp int) +0:21 Constant: +0:21 1 (const int) +0:21 Constant: +0:21 1 (const int) +0:22 move second child to first child ( temp highp int) +0:22 indirect index ( temp highp int) +0:22 'b' ( global 5-element array of highp int) +0:22 'i' ( global highp int) +0:22 Constant: +0:22 1 (const int) +0:23 move second child to first child ( temp highp int) +0:23 direct index ( temp highp int) +0:23 'c' ( global unsized 4-element array of highp int) +0:23 Constant: +0:23 3 (const int) +0:23 Constant: +0:23 1 (const int) 0:? Linker Objects -0:? 'color' ( out highp 4-component vector of float) +0:? 'color' (layout( location=0) out highp 4-component vector of float) +0:? 'a1' ( global unsized 9-element array of highp int) +0:? 'a2' ( global unsized 2-element array of highp int) +0:? 'b' ( global 5-element array of highp int) +0:? 'c' ( global unsized 4-element array of highp int) +0:? 'i' ( global highp int) +0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float m}) link2.vk.frag Shader version: 450 gl_FragCoord origin is upper left 0:? Sequence -0:5 Function Definition: getColor( ( global highp 4-component vector of float) -0:5 Function Parameters: -0:7 Sequence -0:7 Branch: Return with expression -0:7 texture ( global highp 4-component vector of float) -0:7 's2D' (layout( binding=1) uniform highp sampler2D) -0:7 Constant: -0:7 0.500000 -0:7 0.500000 +0:14 Function Definition: getColor( ( global highp 4-component vector of float) +0:14 Function Parameters: +0:16 Sequence +0:16 move second child to first child ( temp highp int) +0:16 direct index ( temp highp int) +0:16 'a1' ( global unsized 3-element array of highp int) +0:16 Constant: +0:16 2 (const int) +0:16 Constant: +0:16 1 (const int) +0:17 move second child to first child ( temp highp int) +0:17 direct index ( temp highp int) +0:17 'a2' ( global unsized 10-element array of highp int) +0:17 Constant: +0:17 9 (const int) +0:17 Constant: +0:17 1 (const int) +0:18 move second child to first child ( temp highp int) +0:18 direct index ( temp highp int) +0:18 'b' ( global unsized 3-element array of highp int) +0:18 Constant: +0:18 2 (const int) +0:18 Constant: +0:18 1 (const int) +0:19 move second child to first child ( temp highp int) +0:19 direct index ( temp highp int) +0:19 'c' ( global 7-element array of highp int) +0:19 Constant: +0:19 3 (const int) +0:19 Constant: +0:19 1 (const int) +0:20 move second child to first child ( temp highp int) +0:20 indirect index ( temp highp int) +0:20 'c' ( global 7-element array of highp int) +0:20 'i' ( global highp int) +0:20 Constant: +0:20 1 (const int) +0:22 Branch: Return with expression +0:22 texture ( global highp 4-component vector of float) +0:22 's2D' (layout( binding=1) uniform highp sampler2D) +0:22 Constant: +0:22 0.500000 +0:22 0.500000 0:? Linker Objects 0:? 's2D' (layout( binding=1) uniform highp sampler2D) +0:? 'a1' ( global unsized 3-element array of highp int) +0:? 'a2' ( global unsized 10-element array of highp int) +0:? 'b' ( global unsized 3-element array of highp int) +0:? 'c' ( global 7-element array of highp int) +0:? 'i' ( global highp int) +0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) Linked fragment stage: @@ -34,23 +109,207 @@ Linked fragment stage: Shader version: 450 gl_FragCoord origin is upper left 0:? Sequence -0:7 Function Definition: main( ( global void) -0:7 Function Parameters: -0:9 Sequence -0:9 move second child to first child ( temp highp 4-component vector of float) -0:9 'color' ( out highp 4-component vector of float) -0:9 Function Call: getColor( ( global highp 4-component vector of float) -0:5 Function Definition: getColor( ( global highp 4-component vector of float) -0:5 Function Parameters: -0:7 Sequence -0:7 Branch: Return with expression -0:7 texture ( global highp 4-component vector of float) -0:7 's2D' (layout( binding=1) uniform highp sampler2D) -0:7 Constant: -0:7 0.500000 -0:7 0.500000 +0:16 Function Definition: main( ( global void) +0:16 Function Parameters: +0:18 Sequence +0:18 move second child to first child ( temp highp 4-component vector of float) +0:18 'color' (layout( location=0) out highp 4-component vector of float) +0:18 Function Call: getColor( ( global highp 4-component vector of float) +0:20 move second child to first child ( temp highp int) +0:20 direct index ( temp highp int) +0:20 'a1' ( global 9-element array of highp int) +0:20 Constant: +0:20 8 (const int) +0:20 Constant: +0:20 1 (const int) +0:21 move second child to first child ( temp highp int) +0:21 direct index ( temp highp int) +0:21 'a2' ( global 10-element array of highp int) +0:21 Constant: +0:21 1 (const int) +0:21 Constant: +0:21 1 (const int) +0:22 move second child to first child ( temp highp int) +0:22 indirect index ( temp highp int) +0:22 'b' ( global 5-element array of highp int) +0:22 'i' ( global highp int) +0:22 Constant: +0:22 1 (const int) +0:23 move second child to first child ( temp highp int) +0:23 direct index ( temp highp int) +0:23 'c' ( global 7-element array of highp int) +0:23 Constant: +0:23 3 (const int) +0:23 Constant: +0:23 1 (const int) +0:14 Function Definition: getColor( ( global highp 4-component vector of float) +0:14 Function Parameters: +0:16 Sequence +0:16 move second child to first child ( temp highp int) +0:16 direct index ( temp highp int) +0:16 'a1' ( global 3-element array of highp int) +0:16 Constant: +0:16 2 (const int) +0:16 Constant: +0:16 1 (const int) +0:17 move second child to first child ( temp highp int) +0:17 direct index ( temp highp int) +0:17 'a2' ( global 10-element array of highp int) +0:17 Constant: +0:17 9 (const int) +0:17 Constant: +0:17 1 (const int) +0:18 move second child to first child ( temp highp int) +0:18 direct index ( temp highp int) +0:18 'b' ( global 3-element array of highp int) +0:18 Constant: +0:18 2 (const int) +0:18 Constant: +0:18 1 (const int) +0:19 move second child to first child ( temp highp int) +0:19 direct index ( temp highp int) +0:19 'c' ( global 7-element array of highp int) +0:19 Constant: +0:19 3 (const int) +0:19 Constant: +0:19 1 (const int) +0:20 move second child to first child ( temp highp int) +0:20 indirect index ( temp highp int) +0:20 'c' ( global 7-element array of highp int) +0:20 'i' ( global highp int) +0:20 Constant: +0:20 1 (const int) +0:22 Branch: Return with expression +0:22 texture ( global highp 4-component vector of float) +0:22 's2D' (layout( binding=1) uniform highp sampler2D) +0:22 Constant: +0:22 0.500000 +0:22 0.500000 0:? Linker Objects -0:? 'color' ( out highp 4-component vector of float) +0:? 'color' (layout( location=0) out highp 4-component vector of float) +0:? 'a1' ( global 9-element array of highp int) +0:? 'a2' ( global 10-element array of highp int) +0:? 'b' ( global 5-element array of highp int) +0:? 'c' ( global 7-element array of highp int) +0:? 'i' ( global highp int) +0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) 0:? 's2D' (layout( binding=1) uniform highp sampler2D) -SPIR-V is not generated for failed compile or link +// Module Version 10000 +// Generated by (magic number): 80006 +// Id's are bound by 71 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 12 + ExecutionMode 4 OriginUpperLeft + Source GLSL 450 + Name 4 "main" + Name 9 "getColor(" + Name 12 "color" + Name 19 "a1" + Name 27 "a2" + Name 32 "b" + Name 33 "i" + Name 39 "c" + Name 54 "s2D" + Name 63 "bnameRuntime" + MemberName 63(bnameRuntime) 0 "r" + Name 65 "" + Name 68 "bnameImplicit" + MemberName 68(bnameImplicit) 0 "m" + Name 70 "" + Decorate 12(color) Location 0 + Decorate 54(s2D) DescriptorSet 0 + Decorate 54(s2D) Binding 1 + Decorate 62 ArrayStride 4 + MemberDecorate 63(bnameRuntime) 0 Offset 0 + Decorate 63(bnameRuntime) BufferBlock + Decorate 65 DescriptorSet 0 + Decorate 67 ArrayStride 4 + MemberDecorate 68(bnameImplicit) 0 Offset 0 + Decorate 68(bnameImplicit) BufferBlock + Decorate 70 DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypePointer Output 7(fvec4) + 12(color): 11(ptr) Variable Output + 14: TypeInt 32 1 + 15: TypeInt 32 0 + 16: 15(int) Constant 9 + 17: TypeArray 14(int) 16 + 18: TypePointer Private 17 + 19(a1): 18(ptr) Variable Private + 20: 14(int) Constant 8 + 21: 14(int) Constant 1 + 22: TypePointer Private 14(int) + 24: 15(int) Constant 10 + 25: TypeArray 14(int) 24 + 26: TypePointer Private 25 + 27(a2): 26(ptr) Variable Private + 29: 15(int) Constant 5 + 30: TypeArray 14(int) 29 + 31: TypePointer Private 30 + 32(b): 31(ptr) Variable Private + 33(i): 22(ptr) Variable Private + 36: 15(int) Constant 7 + 37: TypeArray 14(int) 36 + 38: TypePointer Private 37 + 39(c): 38(ptr) Variable Private + 40: 14(int) Constant 3 + 42: 14(int) Constant 2 + 43: TypePointer Output 6(float) + 45: 14(int) Constant 9 + 51: TypeImage 6(float) 2D sampled format:Unknown + 52: TypeSampledImage 51 + 53: TypePointer UniformConstant 52 + 54(s2D): 53(ptr) Variable UniformConstant + 56: TypeVector 6(float) 2 + 57: 6(float) Constant 1056964608 + 58: 56(fvec2) ConstantComposite 57 57 + 62: TypeRuntimeArray 6(float) +63(bnameRuntime): TypeStruct 62 + 64: TypePointer Uniform 63(bnameRuntime) + 65: 64(ptr) Variable Uniform + 66: 15(int) Constant 4 + 67: TypeArray 6(float) 66 +68(bnameImplicit): TypeStruct 67 + 69: TypePointer Uniform 68(bnameImplicit) + 70: 69(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + 13: 7(fvec4) FunctionCall 9(getColor() + Store 12(color) 13 + 23: 22(ptr) AccessChain 19(a1) 20 + Store 23 21 + 28: 22(ptr) AccessChain 27(a2) 21 + Store 28 21 + 34: 14(int) Load 33(i) + 35: 22(ptr) AccessChain 32(b) 34 + Store 35 21 + 41: 22(ptr) AccessChain 39(c) 40 + Store 41 21 + Return + FunctionEnd + 9(getColor(): 7(fvec4) Function None 8 + 10: Label + 44: 43(ptr) AccessChain 12(color) 42 + Store 44 21 + 46: 22(ptr) AccessChain 19(a1) 45 + Store 46 21 + 47: 22(ptr) AccessChain 27(a2) 42 + Store 47 21 + 48: 22(ptr) AccessChain 32(b) 40 + Store 48 21 + 49: 37 Load 39(c) + 50: 22(ptr) AccessChain 32(b) 49 + Store 50 21 + 55: 52 Load 54(s2D) + 59: 7(fvec4) ImageSampleImplicitLod 55 58 + ReturnValue 59 + FunctionEnd diff --git a/Test/link1.vk.frag b/Test/link1.vk.frag index 443a32052..167e78ee7 100644 --- a/Test/link1.vk.frag +++ b/Test/link1.vk.frag @@ -2,9 +2,23 @@ vec4 getColor(); -out vec4 color; +layout(location=0) out vec4 color; + +int a1[]; // max size from link1 +int a2[]; // max size from link2 +int b[5]; +int c[]; +int i; + +buffer bnameRuntime { float r[]; }; +buffer bnameImplicit { float m[]; }; void main() { color = getColor(); + + a1[8] = 1; + a2[1] = 1; + b[i] = 1; + c[3] = 1; } diff --git a/Test/link2.vk.frag b/Test/link2.vk.frag index febbe7c46..b80402ca5 100644 --- a/Test/link2.vk.frag +++ b/Test/link2.vk.frag @@ -2,7 +2,22 @@ layout(binding=1) uniform sampler2D s2D; +int a1[]; // max size from link1 +int a2[]; // max size from link2 +int b[]; +int c[7]; +int i; + +buffer bnameRuntime { float r[]; }; +buffer bnameImplicit { float m[4]; }; + vec4 getColor() { - return texture(s2D, vec2(0.5)); + a1[2] = 1; + a2[9] = 1; + b[2] = 1; + c[3] = 1; + c[i] = 1; + + return texture(s2D, vec2(0.5)); } diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 5efd7fb47..c80fdb360 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -268,12 +268,13 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin // Recursively merge the implicit array sizes through the objects' respective type trees. void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType) { - if (type.isUnsizedArray() && unitType.isArray()) { - int newImplicitArraySize = unitType.isSizedArray() ? unitType.getOuterArraySize() : - unitType.getImplicitArraySize(); - type.updateImplicitArraySize(type.getImplicitArraySize()); - if (unitType.isArrayVariablyIndexed()) - type.setArrayVariablyIndexed(); + if (type.isUnsizedArray()) { + if (unitType.isUnsizedArray()) { + type.updateImplicitArraySize(unitType.getImplicitArraySize()); + if (unitType.isArrayVariablyIndexed()) + type.setArrayVariablyIndexed(); + } else if (unitType.isSizedArray()) + type.changeOuterArraySize(unitType.getOuterArraySize()); } // Type mismatches are caught and reported after this, just be careful for now. @@ -296,8 +297,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy // Types have to match if (symbol.getType() != unitSymbol.getType()) { - error(infoSink, "Types must match:"); - writeTypeComparison = true; + // but, we make an exception if one is an implicit array and the other is sized + if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() && + symbol.getType().sameElementType(unitSymbol.getType()) && + (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) { + error(infoSink, "Types must match:"); + writeTypeComparison = true; + } } // Qualifiers have to (almost) match diff --git a/gtests/Link.FromFile.Vk.cpp b/gtests/Link.FromFile.Vk.cpp index 6e1969a2e..0a616d827 100644 --- a/gtests/Link.FromFile.Vk.cpp +++ b/gtests/Link.FromFile.Vk.cpp @@ -52,6 +52,7 @@ TEST_P(LinkTestVulkan, FromFile) GlslangResult result; // Compile each input shader file. + bool success = true; std::vector<std::unique_ptr<glslang::TShader>> shaders; for (size_t i = 0; i < fileCount; ++i) { std::string contents; @@ -61,7 +62,7 @@ TEST_P(LinkTestVulkan, FromFile) new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i])))); auto* shader = shaders.back().get(); shader->setAutoMapLocations(true); - compile(shader, contents, "", controls); + success &= compile(shader, contents, "", controls); result.shaderResults.push_back( {fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()}); } @@ -69,10 +70,25 @@ TEST_P(LinkTestVulkan, FromFile) // Link all of them. glslang::TProgram program; for (const auto& shader : shaders) program.addShader(shader.get()); - program.link(controls); + success &= program.link(controls); result.linkingOutput = program.getInfoLog(); result.linkingError = program.getInfoDebugLog(); + if (success && (controls & EShMsgSpvRules)) { + spv::SpvBuildLogger logger; + std::vector<uint32_t> spirv_binary; + glslang::SpvOptions options; + options.disableOptimizer = true; + glslang::GlslangToSpv(*program.getIntermediate(shaders.front()->getStage()), + spirv_binary, &logger, &options); + + std::ostringstream disassembly_stream; + spv::Parameterize(); + spv::Disassemble(disassembly_stream, spirv_binary); + result.spirvWarningsErrors = logger.getAllMessages(); + result.spirv = disassembly_stream.str(); + } + std::ostringstream stream; outputResultToStream(&stream, result, controls); -- GitLab