diff --git a/3rdparty/glslang/.travis.yml b/3rdparty/glslang/.travis.yml index 4a88dce5a..40e3fc7e7 100644 --- a/3rdparty/glslang/.travis.yml +++ b/3rdparty/glslang/.travis.yml @@ -7,7 +7,7 @@ os: - osx # Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment. -sudo: required +sudo: false dist: trusty env: @@ -24,6 +24,9 @@ matrix: # Skip GCC builds on Mac OS X. - os: osx compiler: gcc + include: + # Additional build using Android NDK. + - env: BUILD_NDK=ON cache: apt: true @@ -41,20 +44,38 @@ addons: install: # Install ninja on Mac OS X. - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install ninja; fi - # Make sure that clang-3.6 is selected. + # Make sure that clang-3.6 is selected on Linux. - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then export CC=clang-3.6 CXX=clang++-3.6; fi + # Download Android NDK and Android CMake toolchain file. + - if [[ "$BUILD_NDK" == "ON" ]]; then + git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk; + export ANDROID_NDK=$HOME/android-ndk; + git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake; + export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake; + fi before_script: - git clone https://github.com/google/googletest.git External/googletest script: - mkdir build && cd build - # We need to install the compiled binaries so the paths in the runtests script can resolve correctly. - - cmake -GNinja -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=`pwd`/install .. - - ninja install - # Run Google-Test-based tests. - - ctest --output-on-failure - # Run runtests-based tests. - - cd ../Test && ./runtests + # For Android, do release building using NDK without testing. + # For Linux and macOS, do debug/release building with testing. + - if [[ "$BUILD_NDK" == "ON" ]]; then + cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH} + -DANDROID_NATIVE_API_LEVEL=android-12 + -DCMAKE_BUILD_TYPE=Release + -DANDROID_ABI="armeabi-v7a with NEON" + -DBUILD_TESTING=OFF + -GNinja ..; + ninja; + else + cmake -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=`pwd`/install + -GNinja ..; + ninja install; + ctest --output-on-failure && + cd ../Test && ./runtests; + fi diff --git a/3rdparty/glslang/SPIRV/SPVRemapper.cpp b/3rdparty/glslang/SPIRV/SPVRemapper.cpp index 9b1270501..e8031d022 100755 --- a/3rdparty/glslang/SPIRV/SPVRemapper.cpp +++ b/3rdparty/glslang/SPIRV/SPVRemapper.cpp @@ -464,8 +464,8 @@ namespace spv { { const auto instructionStart = word; const unsigned wordCount = asWordCount(instructionStart); - const spv::Op opCode = asOpCode(instructionStart); const int nextInst = word++ + wordCount; + spv::Op opCode = asOpCode(instructionStart); if (nextInst > int(spv.size())) error("spir instruction terminated too early"); @@ -506,6 +506,18 @@ namespace spv { // Store IDs from instruction in our map for (int op = 0; numOperands > 0; ++op, --numOperands) { + // SpecConstantOp is special: it includes the operands of another opcode which is + // given as a literal in the 3rd word. We will switch over to pretending that the + // opcode being processed is the literal opcode value of the SpecConstantOp. See the + // SPIRV spec for details. This way we will handle IDs and literals as appropriate for + // the embedded op. + if (opCode == spv::OpSpecConstantOp) { + if (op == 0) { + opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. + --numOperands; + } + } + switch (spv::InstructionDesc[opCode].operands.getClass(op)) { case spv::OperandId: case spv::OperandScope: diff --git a/3rdparty/glslang/StandAlone/StandAlone.cpp b/3rdparty/glslang/StandAlone/StandAlone.cpp index d713e760d..8a6b12dc4 100644 --- a/3rdparty/glslang/StandAlone/StandAlone.cpp +++ b/3rdparty/glslang/StandAlone/StandAlone.cpp @@ -90,6 +90,7 @@ enum TOptions { EOptionKeepUncalled = (1 << 22), EOptionHlslOffsets = (1 << 23), EOptionHlslIoMapping = (1 << 24), + EOptionAutoMapLocations = (1 << 25), }; // @@ -386,6 +387,9 @@ void ProcessArguments(std::vector>& workItem lowerword == "hlsl-iomapper" || lowerword == "hlsl-iomapping") { Options |= EOptionHlslIoMapping; + } else if (lowerword == "auto-map-locations" || // synonyms + lowerword == "aml") { + Options |= EOptionAutoMapLocations; } else { usage(); } @@ -648,6 +652,9 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionAutoMapBindings) shader->setAutoMapBindings(true); + if (Options & EOptionAutoMapLocations) + shader->setAutoMapLocations(true); + shaders.push_back(shader); const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; @@ -1063,6 +1070,11 @@ void usage() " explicit bindings.\n" " --amb synonym for --auto-map-bindings\n" "\n" + " --auto-map-locations automatically locate input/output lacking 'location'\n" + " (fragile, not cross stage: recommend explicit\n" + " 'location' use in shader)\n" + " --aml synonym for --auto-map-locations\n" + "\n" " --flatten-uniform-arrays flatten uniform texture & sampler arrays to scalars\n" " --fua synonym for --flatten-uniform-arrays\n" "\n" diff --git a/3rdparty/glslang/Test/baseResults/hlsl.fraggeom.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.fraggeom.frag.out new file mode 100644 index 000000000..7cb85cd5a --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.fraggeom.frag.out @@ -0,0 +1,112 @@ +hlsl.fraggeom.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:9 Function Definition: GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41; ( temp void) +0:9 Function Parameters: +0:9 'IN' ( in structure{ temp 4-component vector of float pos}) +0:9 'OutputStream' ( out structure{ temp 4-component vector of float pos}) +0:? Sequence +0:10 Constant: +0:10 0.000000 +0:11 Constant: +0:11 0.000000 +0:15 Function Definition: @main( ( temp 4-component vector of float) +0:15 Function Parameters: +0:? Sequence +0:16 Branch: Return with expression +0:16 Constant: +0:16 0.000000 +0:16 0.000000 +0:16 0.000000 +0:16 0.000000 +0:15 Function Definition: main( ( temp void) +0:15 Function Parameters: +0:? Sequence +0:15 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:15 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:9 Function Definition: GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41; ( temp void) +0:9 Function Parameters: +0:9 'IN' ( in structure{ temp 4-component vector of float pos}) +0:9 'OutputStream' ( out structure{ temp 4-component vector of float pos}) +0:? Sequence +0:10 Constant: +0:10 0.000000 +0:11 Constant: +0:11 0.000000 +0:15 Function Definition: @main( ( temp 4-component vector of float) +0:15 Function Parameters: +0:? Sequence +0:16 Branch: Return with expression +0:16 Constant: +0:16 0.000000 +0:16 0.000000 +0:16 0.000000 +0:16 0.000000 +0:15 Function Definition: main( ( temp void) +0:15 Function Parameters: +0:? Sequence +0:15 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:15 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 25 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 23 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 8 "myVertex" + MemberName 8(myVertex) 0 "pos" + Name 13 "GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41;" + Name 11 "IN" + Name 12 "OutputStream" + Name 16 "@main(" + Name 23 "@entryPointOutput" + Decorate 23(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8(myVertex): TypeStruct 7(fvec4) + 9: TypePointer Function 8(myVertex) + 10: TypeFunction 2 9(ptr) 9(ptr) + 15: TypeFunction 7(fvec4) + 18: 6(float) Constant 0 + 19: 7(fvec4) ConstantComposite 18 18 18 18 + 22: TypePointer Output 7(fvec4) +23(@entryPointOutput): 22(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 24: 7(fvec4) FunctionCall 16(@main() + Store 23(@entryPointOutput) 24 + Return + FunctionEnd +13(GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41;): 2 Function None 10 + 11(IN): 9(ptr) FunctionParameter +12(OutputStream): 9(ptr) FunctionParameter + 14: Label + Return + FunctionEnd + 16(@main(): 7(fvec4) Function None 15 + 17: Label + ReturnValue 19 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.memberFunCall.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.memberFunCall.frag.out new file mode 100755 index 000000000..97743606c --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.memberFunCall.frag.out @@ -0,0 +1,264 @@ +hlsl.memberFunCall.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:1 Function Definition: method3(f1; ( temp float) +0:1 Function Parameters: +0:1 'a' ( in float) +0:? Sequence +0:1 Branch: Return with expression +0:1 Constant: +0:1 1.000000 +0:4 Function Definition: myContext::method1( ( temp float) +0:4 Function Parameters: +0:4 '@this' ( temp structure{ temp float f}) +0:? Sequence +0:4 Branch: Return with expression +0:4 Function Call: myContext::method2( ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:5 Function Definition: myContext::method2( ( temp float) +0:5 Function Parameters: +0:5 '@this' ( temp structure{ temp float f}) +0:? Sequence +0:5 Branch: Return with expression +0:5 Function Call: myContext::method3(f1; ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:5 Constant: +0:5 1.000000 +0:6 Function Definition: myContext::method3(f1; ( temp float) +0:6 Function Parameters: +0:6 '@this' ( temp structure{ temp float f}) +0:6 'a' ( in float) +0:? Sequence +0:6 Branch: Return with expression +0:6 Function Call: myContext::method4(f1;f1; ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:6 'a' ( in float) +0:6 'a' ( in float) +0:7 Function Definition: myContext::method4(f1;f1; ( temp float) +0:7 Function Parameters: +0:7 '@this' ( temp structure{ temp float f}) +0:7 'a' ( in float) +0:7 'b' ( in float) +0:? Sequence +0:7 Branch: Return with expression +0:7 add ( temp float) +0:7 add ( temp float) +0:7 'a' ( in float) +0:7 'b' ( in float) +0:7 f: direct index for structure ( temp float) +0:7 '@this' ( temp structure{ temp float f}) +0:7 Constant: +0:7 0 (const uint) +0:12 Function Definition: @main( ( temp 4-component vector of float) +0:12 Function Parameters: +0:? Sequence +0:14 move second child to first child ( temp float) +0:14 f: direct index for structure ( temp float) +0:14 'context' ( temp structure{ temp float f}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 3.000000 +0:15 Branch: Return with expression +0:15 Construct vec4 ( temp 4-component vector of float) +0:15 Function Call: myContext::method1( ( temp float) +0:15 'context' ( temp structure{ temp float f}) +0:12 Function Definition: main( ( temp void) +0:12 Function Parameters: +0:? Sequence +0:12 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:12 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:1 Function Definition: method3(f1; ( temp float) +0:1 Function Parameters: +0:1 'a' ( in float) +0:? Sequence +0:1 Branch: Return with expression +0:1 Constant: +0:1 1.000000 +0:4 Function Definition: myContext::method1( ( temp float) +0:4 Function Parameters: +0:4 '@this' ( temp structure{ temp float f}) +0:? Sequence +0:4 Branch: Return with expression +0:4 Function Call: myContext::method2( ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:5 Function Definition: myContext::method2( ( temp float) +0:5 Function Parameters: +0:5 '@this' ( temp structure{ temp float f}) +0:? Sequence +0:5 Branch: Return with expression +0:5 Function Call: myContext::method3(f1; ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:5 Constant: +0:5 1.000000 +0:6 Function Definition: myContext::method3(f1; ( temp float) +0:6 Function Parameters: +0:6 '@this' ( temp structure{ temp float f}) +0:6 'a' ( in float) +0:? Sequence +0:6 Branch: Return with expression +0:6 Function Call: myContext::method4(f1;f1; ( temp float) +0:? '@this' ( temp structure{ temp float f}) +0:6 'a' ( in float) +0:6 'a' ( in float) +0:7 Function Definition: myContext::method4(f1;f1; ( temp float) +0:7 Function Parameters: +0:7 '@this' ( temp structure{ temp float f}) +0:7 'a' ( in float) +0:7 'b' ( in float) +0:? Sequence +0:7 Branch: Return with expression +0:7 add ( temp float) +0:7 add ( temp float) +0:7 'a' ( in float) +0:7 'b' ( in float) +0:7 f: direct index for structure ( temp float) +0:7 '@this' ( temp structure{ temp float f}) +0:7 Constant: +0:7 0 (const uint) +0:12 Function Definition: @main( ( temp 4-component vector of float) +0:12 Function Parameters: +0:? Sequence +0:14 move second child to first child ( temp float) +0:14 f: direct index for structure ( temp float) +0:14 'context' ( temp structure{ temp float f}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 3.000000 +0:15 Branch: Return with expression +0:15 Construct vec4 ( temp 4-component vector of float) +0:15 Function Call: myContext::method1( ( temp float) +0:15 'context' ( temp structure{ temp float f}) +0:12 Function Definition: main( ( temp void) +0:12 Function Parameters: +0:? Sequence +0:12 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:12 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 73 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 71 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 10 "method3(f1;" + Name 9 "a" + Name 12 "myContext" + MemberName 12(myContext) 0 "f" + Name 16 "myContext::method1(" + Name 15 "@this" + Name 19 "myContext::method2(" + Name 18 "@this" + Name 24 "myContext::method3(f1;" + Name 22 "@this" + Name 23 "a" + Name 30 "myContext::method4(f1;f1;" + Name 27 "@this" + Name 28 "a" + Name 29 "b" + Name 34 "@main(" + Name 42 "param" + Name 46 "param" + Name 48 "param" + Name 63 "context" + Name 71 "@entryPointOutput" + Decorate 71(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypePointer Function 6(float) + 8: TypeFunction 6(float) 7(ptr) + 12(myContext): TypeStruct 6(float) + 13: TypePointer Function 12(myContext) + 14: TypeFunction 6(float) 13(ptr) + 21: TypeFunction 6(float) 13(ptr) 7(ptr) + 26: TypeFunction 6(float) 13(ptr) 7(ptr) 7(ptr) + 32: TypeVector 6(float) 4 + 33: TypeFunction 32(fvec4) + 36: 6(float) Constant 1065353216 + 56: TypeInt 32 1 + 57: 56(int) Constant 0 + 64: 6(float) Constant 1077936128 + 70: TypePointer Output 32(fvec4) +71(@entryPointOutput): 70(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 72: 32(fvec4) FunctionCall 34(@main() + Store 71(@entryPointOutput) 72 + Return + FunctionEnd + 10(method3(f1;): 6(float) Function None 8 + 9(a): 7(ptr) FunctionParameter + 11: Label + ReturnValue 36 + FunctionEnd +16(myContext::method1(): 6(float) Function None 14 + 15(@this): 13(ptr) FunctionParameter + 17: Label + 39: 6(float) FunctionCall 19(myContext::method2() 15(@this) + ReturnValue 39 + FunctionEnd +19(myContext::method2(): 6(float) Function None 14 + 18(@this): 13(ptr) FunctionParameter + 20: Label + 42(param): 7(ptr) Variable Function + Store 42(param) 36 + 43: 6(float) FunctionCall 24(myContext::method3(f1;) 18(@this) 42(param) + ReturnValue 43 + FunctionEnd +24(myContext::method3(f1;): 6(float) Function None 21 + 22(@this): 13(ptr) FunctionParameter + 23(a): 7(ptr) FunctionParameter + 25: Label + 46(param): 7(ptr) Variable Function + 48(param): 7(ptr) Variable Function + 47: 6(float) Load 23(a) + Store 46(param) 47 + 49: 6(float) Load 23(a) + Store 48(param) 49 + 50: 6(float) FunctionCall 30(myContext::method4(f1;f1;) 22(@this) 46(param) 48(param) + ReturnValue 50 + FunctionEnd +30(myContext::method4(f1;f1;): 6(float) Function None 26 + 27(@this): 13(ptr) FunctionParameter + 28(a): 7(ptr) FunctionParameter + 29(b): 7(ptr) FunctionParameter + 31: Label + 53: 6(float) Load 28(a) + 54: 6(float) Load 29(b) + 55: 6(float) FAdd 53 54 + 58: 7(ptr) AccessChain 27(@this) 57 + 59: 6(float) Load 58 + 60: 6(float) FAdd 55 59 + ReturnValue 60 + FunctionEnd + 34(@main(): 32(fvec4) Function None 33 + 35: Label + 63(context): 13(ptr) Variable Function + 65: 7(ptr) AccessChain 63(context) 57 + Store 65 64 + 66: 6(float) FunctionCall 16(myContext::method1() 63(context) + 67: 32(fvec4) CompositeConstruct 66 66 66 66 + ReturnValue 67 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.mip.negative.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.mip.negative.frag.out new file mode 100644 index 000000000..36f41377d --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.mip.negative.frag.out @@ -0,0 +1,68 @@ +hlsl.mip.negative.frag +ERROR: 0:5: '' : unterminated mips operator: +ERROR: 1 compilation errors. No code generated. + + +Shader version: 500 +gl_FragCoord origin is upper left +ERROR: node is still EOpNull! +0:4 Function Definition: @main( ( temp 4-component vector of float) +0:4 Function Parameters: +0:? Sequence +0:? textureFetch ( temp 4-component vector of float) +0:5 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:5 Constant: +0:5 2 (const int) +0:7 Branch: Return with expression +0:7 Constant: +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:4 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +ERROR: node is still EOpNull! +0:4 Function Definition: @main( ( temp 4-component vector of float) +0:4 Function Parameters: +0:? Sequence +0:? textureFetch ( temp 4-component vector of float) +0:5 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:5 Constant: +0:5 2 (const int) +0:7 Branch: Return with expression +0:7 Constant: +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:4 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +SPIR-V is not generated for failed compile or link diff --git a/3rdparty/glslang/Test/baseResults/hlsl.mip.negative2.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.mip.negative2.frag.out new file mode 100644 index 000000000..75cf95fc5 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.mip.negative2.frag.out @@ -0,0 +1,74 @@ +hlsl.mip.negative2.frag +ERROR: 0:5: 'r' : unexpected operator on texture type: uniform texture2D +ERROR: 1 compilation errors. No code generated. + + +Shader version: 500 +gl_FragCoord origin is upper left +ERROR: node is still EOpNull! +0:4 Function Definition: @main( ( temp 4-component vector of float) +0:4 Function Parameters: +0:? Sequence +0:5 direct index ( temp float) +0:5 textureFetch ( temp 4-component vector of float) +0:5 'g_tTex2df4' ( uniform texture2D) +0:5 Constant: +0:5 2 (const int) +0:5 Constant: +0:5 0 (const int) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:7 Branch: Return with expression +0:7 Constant: +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:4 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +ERROR: node is still EOpNull! +0:4 Function Definition: @main( ( temp 4-component vector of float) +0:4 Function Parameters: +0:? Sequence +0:5 direct index ( temp float) +0:5 textureFetch ( temp 4-component vector of float) +0:5 'g_tTex2df4' ( uniform texture2D) +0:5 Constant: +0:5 2 (const int) +0:5 Constant: +0:5 0 (const int) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:7 Branch: Return with expression +0:7 Constant: +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:7 0.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:4 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +SPIR-V is not generated for failed compile or link diff --git a/3rdparty/glslang/Test/baseResults/hlsl.mip.operator.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.mip.operator.frag.out new file mode 100644 index 000000000..3c68fd97e --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.mip.operator.frag.out @@ -0,0 +1,209 @@ +hlsl.mip.operator.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:5 Function Definition: @main( ( temp 4-component vector of float) +0:5 Function Parameters: +0:? Sequence +0:13 Branch: Return with expression +0:9 add ( temp 4-component vector of float) +0:6 add ( temp 4-component vector of float) +0:? textureFetch ( temp 4-component vector of float) +0:6 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:6 Constant: +0:6 2 (const int) +0:? textureFetch ( temp 4-component vector of float) +0:9 'g_tTex2df4a' ( uniform texture2DArray) +0:? Constant: +0:? 6 (const uint) +0:? 7 (const uint) +0:? 8 (const uint) +0:9 Constant: +0:9 5 (const uint) +0:13 textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:13 Convert float to uint ( temp 2-component vector of uint) +0:13 vector swizzle ( temp 2-component vector of float) +0:? textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 14 (const uint) +0:? 15 (const uint) +0:13 Constant: +0:13 13 (const int) +0:13 Sequence +0:13 Constant: +0:13 0 (const int) +0:13 Constant: +0:13 1 (const int) +0:13 Convert float to uint ( temp uint) +0:13 direct index ( temp float) +0:? textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 10 (const uint) +0:? 11 (const uint) +0:13 Constant: +0:13 9 (const int) +0:13 Constant: +0:13 0 (const int) +0:5 Function Definition: main( ( temp void) +0:5 Function Parameters: +0:? Sequence +0:5 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:5 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4a' ( uniform texture2DArray) +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:5 Function Definition: @main( ( temp 4-component vector of float) +0:5 Function Parameters: +0:? Sequence +0:13 Branch: Return with expression +0:9 add ( temp 4-component vector of float) +0:6 add ( temp 4-component vector of float) +0:? textureFetch ( temp 4-component vector of float) +0:6 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 3 (const uint) +0:? 4 (const uint) +0:6 Constant: +0:6 2 (const int) +0:? textureFetch ( temp 4-component vector of float) +0:9 'g_tTex2df4a' ( uniform texture2DArray) +0:? Constant: +0:? 6 (const uint) +0:? 7 (const uint) +0:? 8 (const uint) +0:9 Constant: +0:9 5 (const uint) +0:13 textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:13 Convert float to uint ( temp 2-component vector of uint) +0:13 vector swizzle ( temp 2-component vector of float) +0:? textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 14 (const uint) +0:? 15 (const uint) +0:13 Constant: +0:13 13 (const int) +0:13 Sequence +0:13 Constant: +0:13 0 (const int) +0:13 Constant: +0:13 1 (const int) +0:13 Convert float to uint ( temp uint) +0:13 direct index ( temp float) +0:? textureFetch ( temp 4-component vector of float) +0:13 'g_tTex2df4' ( uniform texture2D) +0:? Constant: +0:? 10 (const uint) +0:? 11 (const uint) +0:13 Constant: +0:13 9 (const int) +0:13 Constant: +0:13 0 (const int) +0:5 Function Definition: main( ( temp void) +0:5 Function Parameters: +0:? Sequence +0:5 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:5 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'g_tTex2df4a' ( uniform texture2DArray) +0:? 'g_tTex2df4' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 61 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 59 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 13 "g_tTex2df4" + Name 25 "g_tTex2df4a" + Name 59 "@entryPointOutput" + Decorate 13(g_tTex2df4) DescriptorSet 0 + Decorate 25(g_tTex2df4a) DescriptorSet 0 + Decorate 59(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypeImage 6(float) 2D sampled format:Unknown + 12: TypePointer UniformConstant 11 + 13(g_tTex2df4): 12(ptr) Variable UniformConstant + 15: TypeInt 32 0 + 16: TypeVector 15(int) 2 + 17: 15(int) Constant 3 + 18: 15(int) Constant 4 + 19: 16(ivec2) ConstantComposite 17 18 + 20: TypeInt 32 1 + 21: 20(int) Constant 2 + 23: TypeImage 6(float) 2D array sampled format:Unknown + 24: TypePointer UniformConstant 23 + 25(g_tTex2df4a): 24(ptr) Variable UniformConstant + 27: TypeVector 15(int) 3 + 28: 15(int) Constant 6 + 29: 15(int) Constant 7 + 30: 15(int) Constant 8 + 31: 27(ivec3) ConstantComposite 28 29 30 + 32: 15(int) Constant 5 + 37: 15(int) Constant 14 + 38: 15(int) Constant 15 + 39: 16(ivec2) ConstantComposite 37 38 + 40: 20(int) Constant 13 + 42: TypeVector 6(float) 2 + 46: 15(int) Constant 10 + 47: 15(int) Constant 11 + 48: 16(ivec2) ConstantComposite 46 47 + 49: 20(int) Constant 9 + 51: 15(int) Constant 0 + 58: TypePointer Output 7(fvec4) +59(@entryPointOutput): 58(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 60: 7(fvec4) FunctionCall 9(@main() + Store 59(@entryPointOutput) 60 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 14: 11 Load 13(g_tTex2df4) + 22: 7(fvec4) ImageFetch 14 19 Lod 21 + 26: 23 Load 25(g_tTex2df4a) + 33: 7(fvec4) ImageFetch 26 31 Lod 32 + 34: 7(fvec4) FAdd 22 33 + 35: 11 Load 13(g_tTex2df4) + 36: 11 Load 13(g_tTex2df4) + 41: 7(fvec4) ImageFetch 36 39 Lod 40 + 43: 42(fvec2) VectorShuffle 41 41 0 1 + 44: 16(ivec2) ConvertFToU 43 + 45: 11 Load 13(g_tTex2df4) + 50: 7(fvec4) ImageFetch 45 48 Lod 49 + 52: 6(float) CompositeExtract 50 0 + 53: 15(int) ConvertFToU 52 + 54: 7(fvec4) ImageFetch 35 44 Lod 53 + 55: 7(fvec4) FAdd 34 54 + ReturnValue 55 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.append.fn.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.append.fn.frag.out new file mode 100644 index 000000000..487247824 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.append.fn.frag.out @@ -0,0 +1,275 @@ +hlsl.structbuffer.append.fn.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:8 Function Definition: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float) +0:8 Function Parameters: +0:8 'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:8 'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:8 'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:8 'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:? Sequence +0:9 move second child to first child ( temp 4-component vector of float) +0:9 indirect index ( buffer 4-component vector of float) +0:9 @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float) +0:9 'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:9 Constant: +0:9 0 (const uint) +0:9 AtomicAdd ( temp uint) +0:9 @count: direct index for structure ( temp int) +0:9 'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:9 Constant: +0:9 0 (const int) +0:9 Constant: +0:9 1 (const int) +0:? Constant: +0:? 1.000000 +0:? 2.000000 +0:? 3.000000 +0:? 4.000000 +0:10 Branch: Return with expression +0:10 indirect index ( buffer 4-component vector of float) +0:10 @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float) +0:10 'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:10 Constant: +0:10 0 (const uint) +0:10 add ( temp uint) +0:10 AtomicAdd ( temp uint) +0:10 @count: direct index for structure ( temp int) +0:10 'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:10 Constant: +0:10 0 (const int) +0:10 Constant: +0:10 -1 (const int) +0:10 Constant: +0:10 -1 (const int) +0:19 Function Definition: @main(u1; ( temp 4-component vector of float) +0:19 Function Parameters: +0:19 'pos' ( in uint) +0:? Sequence +0:22 Branch: Return with expression +0:22 Function Call: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float) +0:22 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:22 'sbuf_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:22 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:22 'sbuf_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:19 Function Definition: main( ( temp void) +0:19 Function Parameters: +0:? Sequence +0:19 move second child to first child ( temp uint) +0:? 'pos' ( temp uint) +0:? 'pos' (layout( location=0) in uint) +0:19 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:19 Function Call: @main(u1; ( temp 4-component vector of float) +0:? 'pos' ( temp uint) +0:? Linker Objects +0:? 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) +0:? 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) +0:? 'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:? 'pos' (layout( location=0) in uint) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:8 Function Definition: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float) +0:8 Function Parameters: +0:8 'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:8 'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:8 'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:8 'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:? Sequence +0:9 move second child to first child ( temp 4-component vector of float) +0:9 indirect index ( buffer 4-component vector of float) +0:9 @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float) +0:9 'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:9 Constant: +0:9 0 (const uint) +0:9 AtomicAdd ( temp uint) +0:9 @count: direct index for structure ( temp int) +0:9 'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:9 Constant: +0:9 0 (const int) +0:9 Constant: +0:9 1 (const int) +0:? Constant: +0:? 1.000000 +0:? 2.000000 +0:? 3.000000 +0:? 4.000000 +0:10 Branch: Return with expression +0:10 indirect index ( buffer 4-component vector of float) +0:10 @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float) +0:10 'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:10 Constant: +0:10 0 (const uint) +0:10 add ( temp uint) +0:10 AtomicAdd ( temp uint) +0:10 @count: direct index for structure ( temp int) +0:10 'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:10 Constant: +0:10 0 (const int) +0:10 Constant: +0:10 -1 (const int) +0:10 Constant: +0:10 -1 (const int) +0:19 Function Definition: @main(u1; ( temp 4-component vector of float) +0:19 Function Parameters: +0:19 'pos' ( in uint) +0:? Sequence +0:22 Branch: Return with expression +0:22 Function Call: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float) +0:22 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:22 'sbuf_a@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:22 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:22 'sbuf_c@count' ( buffer block{layout( row_major std430) buffer int @count}) +0:19 Function Definition: main( ( temp void) +0:19 Function Parameters: +0:? Sequence +0:19 move second child to first child ( temp uint) +0:? 'pos' ( temp uint) +0:? 'pos' (layout( location=0) in uint) +0:19 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:19 Function Call: @main(u1; ( temp 4-component vector of float) +0:? 'pos' ( temp uint) +0:? Linker Objects +0:? 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) +0:? 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) +0:? 'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data}) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:? 'pos' (layout( location=0) in uint) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 70 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 58 61 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 9 "" + MemberName 9 0 "@data" + Name 12 "" + MemberName 12 0 "@count" + Name 19 "Fn2(block--vf4[0]1;block--vf4[0]1;" + Name 15 "arg_a" + Name 16 "arg_a@count" + Name 17 "arg_c" + Name 18 "arg_c@count" + Name 25 "@main(u1;" + Name 24 "pos" + Name 49 "sbuf_a" + Name 50 "sbuf_a@count" + Name 51 "sbuf_c" + Name 52 "sbuf_c@count" + Name 56 "pos" + Name 58 "pos" + Name 61 "@entryPointOutput" + Name 62 "param" + Name 65 "sbuf_a@count" + MemberName 65(sbuf_a@count) 0 "@count" + Name 67 "sbuf_a@count" + Name 68 "sbuf_c@count" + Name 69 "sbuf_unused" + Decorate 8 ArrayStride 16 + MemberDecorate 9 0 Offset 0 + Decorate 9 BufferBlock + Decorate 12 BufferBlock + Decorate 49(sbuf_a) DescriptorSet 0 + Decorate 50(sbuf_a@count) DescriptorSet 0 + Decorate 51(sbuf_c) DescriptorSet 0 + Decorate 52(sbuf_c@count) DescriptorSet 0 + Decorate 58(pos) Location 0 + Decorate 61(@entryPointOutput) Location 0 + MemberDecorate 65(sbuf_a@count) 0 Offset 0 + Decorate 65(sbuf_a@count) BufferBlock + Decorate 67(sbuf_a@count) DescriptorSet 0 + Decorate 68(sbuf_c@count) DescriptorSet 0 + Decorate 69(sbuf_unused) DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeRuntimeArray 7(fvec4) + 9: TypeStruct 8 + 10: TypePointer Uniform 9(struct) + 11: TypeInt 32 1 + 12: TypeStruct 11(int) + 13: TypePointer Uniform 12(struct) + 14: TypeFunction 7(fvec4) 10(ptr) 13(ptr) 10(ptr) 13(ptr) + 21: TypeInt 32 0 + 22: TypePointer Function 21(int) + 23: TypeFunction 7(fvec4) 22(ptr) + 27: 11(int) Constant 0 + 28: TypePointer Uniform 11(int) + 30: 11(int) Constant 1 + 31: 21(int) Constant 1 + 32: 21(int) Constant 0 + 34: 6(float) Constant 1065353216 + 35: 6(float) Constant 1073741824 + 36: 6(float) Constant 1077936128 + 37: 6(float) Constant 1082130432 + 38: 7(fvec4) ConstantComposite 34 35 36 37 + 39: TypePointer Uniform 7(fvec4) + 42: 11(int) Constant 4294967295 + 49(sbuf_a): 10(ptr) Variable Uniform +50(sbuf_a@count): 13(ptr) Variable Uniform + 51(sbuf_c): 10(ptr) Variable Uniform +52(sbuf_c@count): 13(ptr) Variable Uniform + 57: TypePointer Input 21(int) + 58(pos): 57(ptr) Variable Input + 60: TypePointer Output 7(fvec4) +61(@entryPointOutput): 60(ptr) Variable Output +65(sbuf_a@count): TypeStruct 11(int) + 66: TypePointer Uniform 65(sbuf_a@count) +67(sbuf_a@count): 66(ptr) Variable Uniform +68(sbuf_c@count): 66(ptr) Variable Uniform + 69(sbuf_unused): 10(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + 56(pos): 22(ptr) Variable Function + 62(param): 22(ptr) Variable Function + 59: 21(int) Load 58(pos) + Store 56(pos) 59 + 63: 21(int) Load 56(pos) + Store 62(param) 63 + 64: 7(fvec4) FunctionCall 25(@main(u1;) 62(param) + Store 61(@entryPointOutput) 64 + Return + FunctionEnd +19(Fn2(block--vf4[0]1;block--vf4[0]1;): 7(fvec4) Function None 14 + 15(arg_a): 10(ptr) FunctionParameter + 16(arg_a@count): 13(ptr) FunctionParameter + 17(arg_c): 10(ptr) FunctionParameter + 18(arg_c@count): 13(ptr) FunctionParameter + 20: Label + 29: 28(ptr) AccessChain 16(arg_a@count) 27 + 33: 21(int) AtomicIAdd 29 31 32 30 + 40: 39(ptr) AccessChain 15(arg_a) 27 33 + Store 40 38 + 41: 28(ptr) AccessChain 18(arg_c@count) 27 + 43: 21(int) AtomicIAdd 41 31 32 42 + 44: 21(int) IAdd 43 42 + 45: 39(ptr) AccessChain 17(arg_c) 27 44 + 46: 7(fvec4) Load 45 + ReturnValue 46 + FunctionEnd + 25(@main(u1;): 7(fvec4) Function None 23 + 24(pos): 22(ptr) FunctionParameter + 26: Label + 53: 7(fvec4) FunctionCall 19(Fn2(block--vf4[0]1;block--vf4[0]1;) 49(sbuf_a) 50(sbuf_a@count) 51(sbuf_c) 52(sbuf_c@count) + ReturnValue 53 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out index 762ea807e..0fcdab32e 100644 --- a/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out +++ b/3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out @@ -17,6 +17,7 @@ gl_FragCoord origin is upper left 0:10 Function Definition: set(block--vu4[0]1;u1;vu4; ( temp void) 0:10 Function Parameters: 0:10 'sb' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:10 'sb@count' ( buffer block{layout( row_major std430) buffer int @count}) 0:10 'bufferOffset' ( in uint) 0:10 'data' ( in 4-component vector of uint) 0:? Sequence @@ -34,6 +35,7 @@ gl_FragCoord origin is upper left 0:? Sequence 0:21 Function Call: set(block--vu4[0]1;u1;vu4; ( temp void) 0:21 'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:21 'sbuf2@count' ( buffer block{layout( row_major std430) buffer int @count}) 0:21 Constant: 0:21 2 (const uint) 0:21 Function Call: get(block--vu4[0]1;u1; ( temp 4-component vector of uint) @@ -59,6 +61,7 @@ gl_FragCoord origin is upper left 0:? Linker Objects 0:? 'sbuf' (layout( binding=10 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) 0:? 'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:? 'sbuf2@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) 0:? 'sbuf3' (layout( binding=12 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 3-component vector of uint @data}) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'pos' (layout( location=0) in uint) @@ -85,6 +88,7 @@ gl_FragCoord origin is upper left 0:10 Function Definition: set(block--vu4[0]1;u1;vu4; ( temp void) 0:10 Function Parameters: 0:10 'sb' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:10 'sb@count' ( buffer block{layout( row_major std430) buffer int @count}) 0:10 'bufferOffset' ( in uint) 0:10 'data' ( in 4-component vector of uint) 0:? Sequence @@ -102,6 +106,7 @@ gl_FragCoord origin is upper left 0:? Sequence 0:21 Function Call: set(block--vu4[0]1;u1;vu4; ( temp void) 0:21 'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:21 'sbuf2@count' ( buffer block{layout( row_major std430) buffer int @count}) 0:21 Constant: 0:21 2 (const uint) 0:21 Function Call: get(block--vu4[0]1;u1; ( temp 4-component vector of uint) @@ -127,18 +132,19 @@ gl_FragCoord origin is upper left 0:? Linker Objects 0:? 'sbuf' (layout( binding=10 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) 0:? 'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data}) +0:? 'sbuf2@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count}) 0:? 'sbuf3' (layout( binding=12 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 3-component vector of uint @data}) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'pos' (layout( location=0) in uint) // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 71 +// Id's are bound by 78 Capability Shader 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 4 "main" 59 62 + EntryPoint Fragment 4 "main" 63 66 ExecutionMode 4 OriginUpperLeft Source HLSL 500 Name 4 "main" @@ -149,24 +155,31 @@ gl_FragCoord origin is upper left Name 14 "bufferOffset" Name 18 "" MemberName 18 0 "@data" - Name 25 "set(block--vu4[0]1;u1;vu4;" - Name 22 "sb" - Name 23 "bufferOffset" - Name 24 "data" - Name 31 "@main(u1;" - Name 30 "pos" - Name 44 "sbuf2" - Name 46 "sbuf" - Name 48 "param" - Name 50 "param" - Name 51 "param" - Name 57 "pos" - Name 59 "pos" - Name 62 "@entryPointOutput" - Name 63 "param" - Name 68 "sbuf3" - MemberName 68(sbuf3) 0 "@data" - Name 70 "sbuf3" + Name 21 "" + MemberName 21 0 "@count" + Name 29 "set(block--vu4[0]1;u1;vu4;" + Name 25 "sb" + Name 26 "sb@count" + Name 27 "bufferOffset" + Name 28 "data" + Name 35 "@main(u1;" + Name 34 "pos" + Name 47 "sbuf2" + Name 48 "sbuf2@count" + Name 50 "sbuf" + Name 52 "param" + Name 54 "param" + Name 55 "param" + Name 61 "pos" + Name 63 "pos" + Name 66 "@entryPointOutput" + Name 67 "param" + Name 70 "sbuf2@count" + MemberName 70(sbuf2@count) 0 "@count" + Name 72 "sbuf2@count" + Name 75 "sbuf3" + MemberName 75(sbuf3) 0 "@data" + Name 77 "sbuf3" Decorate 8 ArrayStride 16 MemberDecorate 9 0 NonWritable MemberDecorate 9 0 Offset 0 @@ -174,17 +187,22 @@ gl_FragCoord origin is upper left Decorate 17 ArrayStride 16 MemberDecorate 18 0 Offset 0 Decorate 18 BufferBlock - Decorate 44(sbuf2) DescriptorSet 0 - Decorate 46(sbuf) DescriptorSet 0 - Decorate 46(sbuf) Binding 10 - Decorate 59(pos) Location 0 - Decorate 62(@entryPointOutput) Location 0 - Decorate 67 ArrayStride 16 - MemberDecorate 68(sbuf3) 0 NonWritable - MemberDecorate 68(sbuf3) 0 Offset 0 - Decorate 68(sbuf3) BufferBlock - Decorate 70(sbuf3) DescriptorSet 0 - Decorate 70(sbuf3) Binding 12 + Decorate 21 BufferBlock + Decorate 47(sbuf2) DescriptorSet 0 + Decorate 48(sbuf2@count) DescriptorSet 0 + Decorate 50(sbuf) DescriptorSet 0 + Decorate 50(sbuf) Binding 10 + Decorate 63(pos) Location 0 + Decorate 66(@entryPointOutput) Location 0 + MemberDecorate 70(sbuf2@count) 0 Offset 0 + Decorate 70(sbuf2@count) BufferBlock + Decorate 72(sbuf2@count) DescriptorSet 0 + Decorate 74 ArrayStride 16 + MemberDecorate 75(sbuf3) 0 NonWritable + MemberDecorate 75(sbuf3) 0 Offset 0 + Decorate 75(sbuf3) BufferBlock + Decorate 77(sbuf3) DescriptorSet 0 + Decorate 77(sbuf3) Binding 12 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -197,71 +215,78 @@ gl_FragCoord origin is upper left 17: TypeRuntimeArray 7(ivec4) 18: TypeStruct 17 19: TypePointer Uniform 18(struct) - 20: TypePointer Function 7(ivec4) - 21: TypeFunction 2 19(ptr) 11(ptr) 20(ptr) - 27: TypeFloat 32 - 28: TypeVector 27(float) 4 - 29: TypeFunction 28(fvec4) 11(ptr) - 33: TypeInt 32 1 - 34: 33(int) Constant 0 - 36: TypePointer Uniform 7(ivec4) - 44(sbuf2): 19(ptr) Variable Uniform - 45: 6(int) Constant 2 - 46(sbuf): 10(ptr) Variable Uniform - 47: 6(int) Constant 3 - 53: 27(float) Constant 0 - 54: 28(fvec4) ConstantComposite 53 53 53 53 - 58: TypePointer Input 6(int) - 59(pos): 58(ptr) Variable Input - 61: TypePointer Output 28(fvec4) -62(@entryPointOutput): 61(ptr) Variable Output - 66: TypeVector 6(int) 3 - 67: TypeRuntimeArray 66(ivec3) - 68(sbuf3): TypeStruct 67 - 69: TypePointer Uniform 68(sbuf3) - 70(sbuf3): 69(ptr) Variable Uniform + 20: TypeInt 32 1 + 21: TypeStruct 20(int) + 22: TypePointer Uniform 21(struct) + 23: TypePointer Function 7(ivec4) + 24: TypeFunction 2 19(ptr) 22(ptr) 11(ptr) 23(ptr) + 31: TypeFloat 32 + 32: TypeVector 31(float) 4 + 33: TypeFunction 32(fvec4) 11(ptr) + 37: 20(int) Constant 0 + 39: TypePointer Uniform 7(ivec4) + 47(sbuf2): 19(ptr) Variable Uniform + 48(sbuf2@count): 22(ptr) Variable Uniform + 49: 6(int) Constant 2 + 50(sbuf): 10(ptr) Variable Uniform + 51: 6(int) Constant 3 + 57: 31(float) Constant 0 + 58: 32(fvec4) ConstantComposite 57 57 57 57 + 62: TypePointer Input 6(int) + 63(pos): 62(ptr) Variable Input + 65: TypePointer Output 32(fvec4) +66(@entryPointOutput): 65(ptr) Variable Output + 70(sbuf2@count): TypeStruct 20(int) + 71: TypePointer Uniform 70(sbuf2@count) + 72(sbuf2@count): 71(ptr) Variable Uniform + 73: TypeVector 6(int) 3 + 74: TypeRuntimeArray 73(ivec3) + 75(sbuf3): TypeStruct 74 + 76: TypePointer Uniform 75(sbuf3) + 77(sbuf3): 76(ptr) Variable Uniform 4(main): 2 Function None 3 5: Label - 57(pos): 11(ptr) Variable Function - 63(param): 11(ptr) Variable Function - 60: 6(int) Load 59(pos) - Store 57(pos) 60 - 64: 6(int) Load 57(pos) - Store 63(param) 64 - 65: 28(fvec4) FunctionCall 31(@main(u1;) 63(param) - Store 62(@entryPointOutput) 65 + 61(pos): 11(ptr) Variable Function + 67(param): 11(ptr) Variable Function + 64: 6(int) Load 63(pos) + Store 61(pos) 64 + 68: 6(int) Load 61(pos) + Store 67(param) 68 + 69: 32(fvec4) FunctionCall 35(@main(u1;) 67(param) + Store 66(@entryPointOutput) 69 Return FunctionEnd 15(get(block--vu4[0]1;u1;): 7(ivec4) Function None 12 13(sb): 10(ptr) FunctionParameter 14(bufferOffset): 11(ptr) FunctionParameter 16: Label - 35: 6(int) Load 14(bufferOffset) - 37: 36(ptr) AccessChain 13(sb) 34 35 - 38: 7(ivec4) Load 37 - ReturnValue 38 + 38: 6(int) Load 14(bufferOffset) + 40: 39(ptr) AccessChain 13(sb) 37 38 + 41: 7(ivec4) Load 40 + ReturnValue 41 FunctionEnd -25(set(block--vu4[0]1;u1;vu4;): 2 Function None 21 - 22(sb): 19(ptr) FunctionParameter -23(bufferOffset): 11(ptr) FunctionParameter - 24(data): 20(ptr) FunctionParameter - 26: Label - 41: 6(int) Load 23(bufferOffset) - 42: 7(ivec4) Load 24(data) - 43: 36(ptr) AccessChain 22(sb) 34 41 - Store 43 42 +29(set(block--vu4[0]1;u1;vu4;): 2 Function None 24 + 25(sb): 19(ptr) FunctionParameter + 26(sb@count): 22(ptr) FunctionParameter +27(bufferOffset): 11(ptr) FunctionParameter + 28(data): 23(ptr) FunctionParameter + 30: Label + 44: 6(int) Load 27(bufferOffset) + 45: 7(ivec4) Load 28(data) + 46: 39(ptr) AccessChain 25(sb) 37 44 + Store 46 45 Return FunctionEnd - 31(@main(u1;): 28(fvec4) Function None 29 - 30(pos): 11(ptr) FunctionParameter - 32: Label - 48(param): 11(ptr) Variable Function - 50(param): 11(ptr) Variable Function - 51(param): 20(ptr) Variable Function - Store 48(param) 47 - 49: 7(ivec4) FunctionCall 15(get(block--vu4[0]1;u1;) 46(sbuf) 48(param) - Store 50(param) 45 - Store 51(param) 49 - 52: 2 FunctionCall 25(set(block--vu4[0]1;u1;vu4;) 44(sbuf2) 50(param) 51(param) - ReturnValue 54 + 35(@main(u1;): 32(fvec4) Function None 33 + 34(pos): 11(ptr) FunctionParameter + 36: Label + 52(param): 11(ptr) Variable Function + 54(param): 11(ptr) Variable Function + 55(param): 23(ptr) Variable Function + Store 52(param) 51 + 53: 7(ivec4) FunctionCall 15(get(block--vu4[0]1;u1;) 50(sbuf) 52(param) + Store 54(param) 49 + Store 55(param) 53 + 56: 2 FunctionCall 29(set(block--vu4[0]1;u1;vu4;) 47(sbuf2) 48(sbuf2@count) 54(param) 55(param) + ReturnValue 58 FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/remap.specconst.comp.out b/3rdparty/glslang/Test/baseResults/remap.specconst.comp.out new file mode 100644 index 000000000..141c1a479 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/remap.specconst.comp.out @@ -0,0 +1,33 @@ +remap.specconst.comp +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 16104 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 5663 "main" + ExecutionMode 5663 LocalSize 1 1 1 + Decorate 2 SpecId 0 + Decorate 3 SpecId 1 + Decorate 4 SpecId 2 + Decorate 5 BuiltIn WorkgroupSize + 8: TypeVoid + 1282: TypeFunction 8 + 11: TypeInt 32 0 + 2: 11(int) SpecConstant 1 + 3: 11(int) SpecConstant 1 + 4: 11(int) SpecConstant 1 + 20: TypeVector 11(int) 3 + 5: 20(ivec3) SpecConstantComposite 2 3 4 + 6: 11(int) SpecConstantOp 81 5 0 + 7: 11(int) SpecConstantOp 81 5 1(GLSL.std.450) + 9: 11(int) SpecConstantOp 81 5 2 + 10: 11(int) SpecConstantOp 132 7 9 + 12: 11(int) SpecConstantOp 128 6 10 + 5663: 8 Function None 1282 + 16103: Label + Return + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out b/3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out index 11818f647..8216e05f0 100644 --- a/3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out +++ b/3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out @@ -78,6 +78,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre Decorate 126(g_tTex_unused2) DescriptorSet 0 Decorate 126(g_tTex_unused2) Binding 12 Decorate 128(g_sSamp_unused2) DescriptorSet 0 + Decorate 137(FragColor) Location 0 Decorate 141(g_tTex_unused3) DescriptorSet 0 2: TypeVoid 3: TypeFunction 2 diff --git a/3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out b/3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out index 327ac04ae..8595a89cb 100644 --- a/3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out +++ b/3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out @@ -72,6 +72,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre Decorate 126(g_tTex_unused2) DescriptorSet 0 Decorate 126(g_tTex_unused2) Binding 12 Decorate 128(g_sSamp_unused2) DescriptorSet 0 + Decorate 137(FragColor) Location 0 Decorate 141(g_tTex_unused3) DescriptorSet 0 2: TypeVoid 3: TypeFunction 2 diff --git a/3rdparty/glslang/Test/baseResults/spv.noLocation.vert.out b/3rdparty/glslang/Test/baseResults/spv.noLocation.vert.out new file mode 100644 index 000000000..43e2534c7 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/spv.noLocation.vert.out @@ -0,0 +1,8 @@ +spv.noLocation.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. +ERROR: spv.noLocation.vert:4: 'location' : SPIR-V requires location for user input/output +ERROR: spv.noLocation.vert:8: 'location' : SPIR-V requires location for user input/output +ERROR: 2 compilation errors. No code generated. + + +SPIR-V is not generated for failed compile or link diff --git a/3rdparty/glslang/Test/hlsl.fraggeom.frag b/3rdparty/glslang/Test/hlsl.fraggeom.frag new file mode 100644 index 000000000..5592e857a --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.fraggeom.frag @@ -0,0 +1,17 @@ +// test geometry shader in fragment shader. GS attributes should be successfully ignored. + +struct myVertex { + float4 pos : SV_Position; +}; + +[maxvertexcount(1)] +void GS_Draw(point myVertex IN, inout PointStream OutputStream) +{ + OutputStream.Append(IN); + OutputStream.RestartStrip(); +} + +float4 main() : SV_TARGET +{ + return 0; +} diff --git a/3rdparty/glslang/Test/hlsl.memberFunCall.frag b/3rdparty/glslang/Test/hlsl.memberFunCall.frag new file mode 100644 index 000000000..27d3f6e01 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.memberFunCall.frag @@ -0,0 +1,16 @@ +float method3(float a) { return 1.0; } + +struct myContext { + float method1() { return method2(); } + float method2() { return method3(1.0); } + float method3(float a) { return method4(a, a); } + float method4(float a, float b) { return a + b + f; } + float f; +}; + +float4 main() : SV_TARGET0 +{ + myContext context; + context.f = 3.0; + return (float4)context.method1(); +} diff --git a/3rdparty/glslang/Test/hlsl.mip.negative.frag b/3rdparty/glslang/Test/hlsl.mip.negative.frag new file mode 100644 index 000000000..900d38506 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.mip.negative.frag @@ -0,0 +1,9 @@ +Texture2D g_tTex2df4; + +float4 main() : SV_Target0 +{ + g_tTex2df4.mips.mips[2][uint2(3, 4)]; // error to chain like this + + return 0; +} + diff --git a/3rdparty/glslang/Test/hlsl.mip.negative2.frag b/3rdparty/glslang/Test/hlsl.mip.negative2.frag new file mode 100644 index 000000000..c07179eb2 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.mip.negative2.frag @@ -0,0 +1,9 @@ +Texture2D g_tTex2df4; + +float4 main() : SV_Target0 +{ + g_tTex2df4.r[2][uint2(3, 4)]; // '.r' not valid on texture object + + return 0; +} + diff --git a/3rdparty/glslang/Test/hlsl.mip.operator.frag b/3rdparty/glslang/Test/hlsl.mip.operator.frag new file mode 100644 index 000000000..af4f15013 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.mip.operator.frag @@ -0,0 +1,14 @@ +Texture2DArray g_tTex2df4a; +Texture2D g_tTex2df4; + +float4 main() : SV_Target0 +{ + return g_tTex2df4.mips[2][uint2(3, 4)] + + + // test float->uint cast on the mip arg + g_tTex2df4a.mips[5.2][uint3(6, 7, 8)] + + + // Test nesting involving .mips operators: + // ....outer operator mip level...... .....outer operator coordinate.... + g_tTex2df4.mips[ g_tTex2df4.mips[9][uint2(10,11)][0] ][ g_tTex2df4.mips[13][uint2(14,15)].xy ]; +} diff --git a/3rdparty/glslang/Test/hlsl.structbuffer.append.fn.frag b/3rdparty/glslang/Test/hlsl.structbuffer.append.fn.frag new file mode 100644 index 000000000..668bc1e8e --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.structbuffer.append.fn.frag @@ -0,0 +1,23 @@ + +// float4 Fn1(ConsumeStructuredBuffer arg_c) +// { +// return arg_c.Consume(); +// } + +float4 Fn2(AppendStructuredBuffer arg_a, ConsumeStructuredBuffer arg_c) +{ + arg_a.Append(float4(1,2,3,4)); + return arg_c.Consume(); +} + +AppendStructuredBuffer sbuf_a; +ConsumeStructuredBuffer sbuf_c; + +AppendStructuredBuffer sbuf_unused; + +float4 main(uint pos : FOO) : SV_Target0 +{ + // Fn1(sbuf_c); + + return Fn2(sbuf_a, sbuf_c); +} diff --git a/3rdparty/glslang/Test/remap.specconst.comp b/3rdparty/glslang/Test/remap.specconst.comp new file mode 100644 index 000000000..52ac07aa0 --- /dev/null +++ b/3rdparty/glslang/Test/remap.specconst.comp @@ -0,0 +1,7 @@ +#version 450 + +layout (local_size_x_id = 0, local_size_y_id = 1, local_size_z_id = 2) in; + +shared int foo[gl_WorkGroupSize.x + gl_WorkGroupSize.y * gl_WorkGroupSize.z]; + +void main () {} diff --git a/3rdparty/glslang/Test/runtests b/3rdparty/glslang/Test/runtests index 4edb8f097..a3c89e045 100755 --- a/3rdparty/glslang/Test/runtests +++ b/3rdparty/glslang/Test/runtests @@ -86,12 +86,19 @@ $EXE -i --hlsl-offsets -D -e main -H hlsl.hlslOffset.vert > $TARGETDIR/hlsl.hls diff -b $BASEDIR/hlsl.hlslOffset.vert.out $TARGETDIR/hlsl.hlslOffset.vert.out || HASERROR=1 # -# Tesing --resource-set-binding +# Testing --resource-set-binding # echo Configuring HLSL descriptor set and binding number manually $EXE -V -D -e main -H hlsl.multiDescriptorSet.frag --rsb frag t0 0 0 t1 1 0 s0 0 1 s1 1 1 b0 2 0 b1 2 1 b2 2 2 > $TARGETDIR/hlsl.multiDescriptorSet.frag.out diff -b $BASEDIR/hlsl.multiDescriptorSet.frag.out $TARGETDIR/hlsl.multiDescriptorSet.frag.out +# +# Testing location error +# +echo Testing SPV no location +$EXE -V -C spv.noLocation.vert > $TARGETDIR/spv.noLocation.vert.out +diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out + # # Final checking # diff --git a/3rdparty/glslang/Test/spv.noLocation.vert b/3rdparty/glslang/Test/spv.noLocation.vert new file mode 100644 index 000000000..e3c02eedc --- /dev/null +++ b/3rdparty/glslang/Test/spv.noLocation.vert @@ -0,0 +1,14 @@ +#version 450 + +layout(location = 1) in vec4 in1; +in vec4 in2; +layout(location = 3) in vec4 in3; + +layout(location = 1) out vec4 out1; +out vec4 out2; +layout(location = 3) out vec4 out3; + + +void main() +{ +} diff --git a/3rdparty/glslang/glslang/Include/Types.h b/3rdparty/glslang/glslang/Include/Types.h index 6f58a52c3..6bcbe4088 100644 --- a/3rdparty/glslang/glslang/Include/Types.h +++ b/3rdparty/glslang/glslang/Include/Types.h @@ -400,6 +400,7 @@ public: invariant = false; noContraction = false; makeTemporary(); + declaredBuiltIn = EbvNone; } // drop qualifiers that don't belong in a temporary variable @@ -457,6 +458,7 @@ public: const char* semanticName; TStorageQualifier storage : 6; TBuiltInVariable builtIn : 8; + TBuiltInVariable declaredBuiltIn : 8; TPrecisionQualifier precision : 3; bool invariant : 1; // require canonical treatment for cross-shader invariance bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index b7240eabc..b3dbeda2f 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -4332,6 +4332,18 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb default: break; } + } else if (spvVersion.spv > 0) { + switch (qualifier.storage) { + case EvqVaryingIn: + case EvqVaryingOut: + if (! parsingBuiltins && qualifier.builtIn == EbvNone) { + if (!intermediate.getAutoMapLocations()) + error(loc, "SPIR-V requires location for user input/output", "location", ""); + } + break; + default: + break; + } } // Check packing and matrix @@ -5022,6 +5034,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden // look for errors in layout qualifier use layoutObjectCheck(loc, *symbol); + + // fix up fixOffset(loc, *symbol); return initNode; @@ -5728,6 +5742,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con // Check for general layout qualifier errors layoutObjectCheck(loc, variable); + // fix up if (isIoResizeArray(blockType)) { ioArraySymbolResizeList.push_back(&variable); checkIoArraysConsistency(loc, true); diff --git a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp index 5563da807..1f7c005f3 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp @@ -1571,6 +1571,8 @@ void TShader::setShiftUavBinding(unsigned int base) { intermediate->setShift void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); } // Enables binding automapping using TIoMapper void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } +// Fragile: currently within one stage: simple auto-assignment of location +void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } // See comment above TDefaultHlslIoMapper in iomapper.cpp: void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } diff --git a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h index 8dc154cdc..f928b7aed 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h +++ b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h @@ -198,7 +198,6 @@ struct TParameter { TString *name; TType* type; TIntermTyped* defaultValue; - TBuiltInVariable declaredBuiltIn; void copyParam(const TParameter& param) { if (param.name) @@ -207,8 +206,8 @@ struct TParameter { name = 0; type = param.type->clone(); defaultValue = param.defaultValue; - declaredBuiltIn = param.declaredBuiltIn; } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } }; // @@ -241,7 +240,6 @@ public: virtual void addParameter(TParameter& p) { assert(writable); - p.declaredBuiltIn = p.type->getQualifier().builtIn; parameters.push_back(p); p.type->appendMangledName(mangledName); @@ -264,6 +262,12 @@ public: mangledName.insert(0, prefix); } + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + virtual const TString& getMangledName() const override { return mangledName; } virtual const TType& getType() const override { return returnType; } virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } @@ -688,19 +692,27 @@ public: // Normal find of a symbol, that can optionally say whether the symbol was found // at a built-in level or the current top-scope level. - TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0) + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) { int level = currentLevel(); TSymbol* symbol; + int thisDepth = 0; do { + if (table[level]->isThisLevel()) + ++thisDepth; symbol = table[level]->find(name); --level; - } while (symbol == 0 && level >= 0); + } while (symbol == nullptr && level >= 0); level++; if (builtIn) *builtIn = isBuiltInLevel(level); if (currentScope) *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } return symbol; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp index 0e7dea10c..26772ddc4 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp @@ -214,6 +214,8 @@ struct TNotifyUniformAdaptor { resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); } +private: + TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&); }; struct TNotifyInOutAdaptor @@ -229,6 +231,8 @@ struct TNotifyInOutAdaptor { resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); } +private: + TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&); }; struct TResolverUniformAdaptor @@ -350,7 +354,8 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver int baseSsboBinding; int baseUavBinding; std::vector baseResourceSetBinding; - bool doAutoMapping; + bool doAutoBindingMapping; + bool doAutoLocationMapping; typedef std::vector TSlotSet; typedef std::unordered_map TSlotSetMap; TSlotSetMap slots; @@ -401,9 +406,19 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver { return true; } - int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override + int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override { - return -1; + if (!doAutoLocationMapping || type.getQualifier().hasLocation()) + return -1; + + // Placeholder. + // TODO: It would be nice to flesh this out using + // intermediate->computeTypeLocationSize(type), or functions that call it like + // intermediate->addUsedLocation() + // These in turn would want the intermediate, which is not available here, but + // is available in many places, and a lot of copying from it could be saved if + // it were just available. + return 0; } int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override { @@ -493,7 +508,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase if (isUboType(type)) return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding); - } else if (is_live && doAutoMapping) { + } else if (is_live && doAutoBindingMapping) { // find free slot, the caller did make sure it passes all vars with binding // first and now all are passed that do not have a binding and needs one @@ -607,7 +622,7 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase if (isUboType(type)) return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding); - } else if (is_live && doAutoMapping) { + } else if (is_live && doAutoBindingMapping) { // find free slot, the caller did make sure it passes all vars with binding // first and now all are passed that do not have a binding and needs one @@ -659,6 +674,7 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi intermediate.getShiftUavBinding() == 0 && intermediate.getResourceSetBinding().empty() && intermediate.getAutoMapBindings() == false && + intermediate.getAutoMapLocations() == false && resolver == nullptr) return true; @@ -689,7 +705,8 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding(); resolverBase->baseUavBinding = intermediate.getShiftUavBinding(); resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding(); - resolverBase->doAutoMapping = intermediate.getAutoMapBindings(); + resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings(); + resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations(); resolver = resolverBase; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp b/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp index 4bb295104..02dde9efc 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp @@ -860,7 +860,7 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp return -1; // no collision } -// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions +// Accumulate bindings and offsets, and check for collisions // as the accumulation is done. // // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h index c28d02a2c..444d341d5 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h @@ -177,6 +177,7 @@ public: shiftSsboBinding(0), shiftUavBinding(0), autoMapBindings(false), + autoMapLocations(false), flattenUniformArrays(false), useUnknownFormat(false), hlslOffsets(false), @@ -218,9 +219,11 @@ public: unsigned int getShiftUavBinding() const { return shiftUavBinding; } void setResourceSetBinding(const std::vector& shift) { resourceSetBinding = shift; } const std::vector& getResourceSetBinding() const { return resourceSetBinding; } - void setAutoMapBindings(bool map) { autoMapBindings = map; } + void setAutoMapBindings(bool map) { autoMapBindings = map; } bool getAutoMapBindings() const { return autoMapBindings; } - void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; } + void setAutoMapLocations(bool map) { autoMapLocations = map; } + bool getAutoMapLocations() const { return autoMapLocations; } + void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; } bool getFlattenUniformArrays() const { return flattenUniformArrays; } void setNoStorageFormat(bool b) { useUnknownFormat = b; } bool getNoStorageFormat() const { return useUnknownFormat; } @@ -516,6 +519,7 @@ protected: unsigned int shiftUavBinding; std::vector resourceSetBinding; bool autoMapBindings; + bool autoMapLocations; bool flattenUniformArrays; bool useUnknownFormat; bool hlslOffsets; diff --git a/3rdparty/glslang/glslang/Public/ShaderLang.h b/3rdparty/glslang/glslang/Public/ShaderLang.h index 42e4a4628..3be66d43e 100644 --- a/3rdparty/glslang/glslang/Public/ShaderLang.h +++ b/3rdparty/glslang/glslang/Public/ShaderLang.h @@ -309,6 +309,7 @@ public: void setShiftSsboBinding(unsigned int base); void setResourceSetBinding(const std::vector& base); void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); void setHlslIoMapping(bool hlslIoMap); void setFlattenUniformArrays(bool flatten); void setNoStorageFormat(bool useUnknownFormat); diff --git a/3rdparty/glslang/gtests/Hlsl.FromFile.cpp b/3rdparty/glslang/gtests/Hlsl.FromFile.cpp index c53e1e55c..456d3f6ae 100644 --- a/3rdparty/glslang/gtests/Hlsl.FromFile.cpp +++ b/3rdparty/glslang/gtests/Hlsl.FromFile.cpp @@ -109,6 +109,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.emptystruct.init.vert", "main"}, {"hlsl.entry-in.frag", "PixelShaderFunction"}, {"hlsl.entry-out.frag", "PixelShaderFunction"}, + {"hlsl.fraggeom.frag", "main"}, {"hlsl.float1.frag", "PixelShaderFunction"}, {"hlsl.float4.frag", "PixelShaderFunction"}, {"hlsl.flatten.return.frag", "main"}, @@ -176,10 +177,14 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.logicalConvert.frag", "main"}, {"hlsl.logical.unary.frag", "main"}, {"hlsl.loopattr.frag", "main"}, + {"hlsl.mip.operator.frag", "main"}, + {"hlsl.mip.negative.frag", "main"}, + {"hlsl.mip.negative2.frag", "main"}, {"hlsl.namespace.frag", "main"}, {"hlsl.nonint-index.frag", "main"}, {"hlsl.matNx1.frag", "main"}, {"hlsl.matrixSwizzle.vert", "ShaderFunction"}, + {"hlsl.memberFunCall.frag", "main"}, {"hlsl.mintypes.frag", "main"}, {"hlsl.multiEntry.vert", "RealEntrypoint"}, {"hlsl.multiReturn.frag", "main"}, @@ -251,6 +256,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.structarray.flatten.geom", "main"}, {"hlsl.structbuffer.frag", "main"}, {"hlsl.structbuffer.append.frag", "main"}, + {"hlsl.structbuffer.append.fn.frag", "main"}, {"hlsl.structbuffer.atomics.frag", "main"}, {"hlsl.structbuffer.byte.frag", "main"}, {"hlsl.structbuffer.coherent.frag", "main"}, diff --git a/3rdparty/glslang/gtests/Link.FromFile.Vk.cpp b/3rdparty/glslang/gtests/Link.FromFile.Vk.cpp index 6ce1fe9f7..6e1969a2e 100644 --- a/3rdparty/glslang/gtests/Link.FromFile.Vk.cpp +++ b/3rdparty/glslang/gtests/Link.FromFile.Vk.cpp @@ -60,6 +60,7 @@ TEST_P(LinkTestVulkan, FromFile) shaders.emplace_back( new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i])))); auto* shader = shaders.back().get(); + shader->setAutoMapLocations(true); compile(shader, contents, "", controls); result.shaderResults.push_back( {fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()}); diff --git a/3rdparty/glslang/gtests/Remap.FromFile.cpp b/3rdparty/glslang/gtests/Remap.FromFile.cpp index 9f25a6f22..50bce8e35 100644 --- a/3rdparty/glslang/gtests/Remap.FromFile.cpp +++ b/3rdparty/glslang/gtests/Remap.FromFile.cpp @@ -89,6 +89,7 @@ INSTANTIATE_TEST_CASE_P( { "remap.basic.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.basic.dcefunc.frag", "main", Source::GLSL, spv::spirvbin_t::DCE_FUNCS }, { "remap.basic.strip.frag", "main", Source::GLSL, spv::spirvbin_t::STRIP }, + { "remap.specconst.comp", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.switch.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, { "remap.switch.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.literal64.none.spv", "main", Source::GLSL, spv::spirvbin_t::NONE }, diff --git a/3rdparty/glslang/gtests/TestFixture.h b/3rdparty/glslang/gtests/TestFixture.h index 38ec54c63..c00645bed 100644 --- a/3rdparty/glslang/gtests/TestFixture.h +++ b/3rdparty/glslang/gtests/TestFixture.h @@ -202,6 +202,7 @@ public: const EShLanguage kind = GetShaderStage(GetSuffix(shaderName)); glslang::TShader shader(kind); + shader.setAutoMapLocations(true); shader.setFlattenUniformArrays(flattenUniformArrays); bool success = compile(&shader, code, entryPointName, controls); @@ -254,6 +255,7 @@ public: shader.setShiftUboBinding(baseUboBinding); shader.setShiftSsboBinding(baseSsboBinding); shader.setAutoMapBindings(autoMapBindings); + shader.setAutoMapLocations(true); shader.setFlattenUniformArrays(flattenUniformArrays); bool success = compile(&shader, code, entryPointName, controls); @@ -295,6 +297,8 @@ public: const EShLanguage kind = GetShaderStage(GetSuffix(shaderName)); glslang::TShader shader(kind); + shader.setAutoMapLocations(true); + bool success = compile(&shader, code, entryPointName, controls); glslang::TProgram program; diff --git a/3rdparty/glslang/hlsl/hlslGrammar.cpp b/3rdparty/glslang/hlsl/hlslGrammar.cpp index cdf8a0777..69155850a 100755 --- a/3rdparty/glslang/hlsl/hlslGrammar.cpp +++ b/3rdparty/glslang/hlsl/hlslGrammar.cpp @@ -1933,7 +1933,7 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) // All member functions get parsed inside the class/struct namespace and with the // class/struct members in a symbol-table level. parseContext.pushNamespace(structName); - parseContext.pushThisScope(type); + parseContext.pushThisScope(type, functionDeclarators); bool deferredSuccess = true; for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) { // parse body diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.cpp b/3rdparty/glslang/hlsl/hlslParseHelper.cpp index 7b4346d70..e875cb7b4 100755 --- a/3rdparty/glslang/hlsl/hlslParseHelper.cpp +++ b/3rdparty/glslang/hlsl/hlslParseHelper.cpp @@ -677,19 +677,30 @@ TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIn if (base->getType().getBasicType() == EbtSampler && !base->isArray()) { const TSampler& sampler = base->getType().getSampler(); if (sampler.isImage() || sampler.isTexture()) { - TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch); + if (! mipsOperatorMipArg.empty() && mipsOperatorMipArg.back().mipLevel == nullptr) { + // The first operator[] to a .mips[] sequence is the mip level. We'll remember it. + mipsOperatorMipArg.back().mipLevel = index; + return base; // next [] index is to the same base. + } else { + TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch); - load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize)); - load->setLoc(loc); - load->getSequence().push_back(base); - load->getSequence().push_back(index); + load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize)); + load->setLoc(loc); + load->getSequence().push_back(base); + load->getSequence().push_back(index); - // Textures need a MIP. First indirection is always to mip 0. If there's another, we'll add it - // later. - if (sampler.isTexture()) - load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true)); + // Textures need a MIP. If we saw one go by, use it. Otherwise, use zero. + if (sampler.isTexture()) { + if (! mipsOperatorMipArg.empty()) { + load->getSequence().push_back(mipsOperatorMipArg.back().mipLevel); + mipsOperatorMipArg.pop_back(); + } else { + load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true)); + } + } - return load; + return load; + } } } @@ -874,7 +885,21 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt } TIntermTyped* result = base; - if (base->isVector() || base->isScalar()) { + + if (base->getType().getBasicType() == EbtSampler) { + // Handle .mips[mipid][pos] operation on textures + const TSampler& sampler = base->getType().getSampler(); + if (sampler.isTexture() && field == "mips") { + // Push a null to signify that we expect a mip level under operator[] next. + mipsOperatorMipArg.push_back(tMipsOperatorData(loc, nullptr)); + // Keep 'result' pointing to 'base', since we expect an operator[] to go by next. + } else { + if (field == "mips") + error(loc, "unexpected texture type for .mips[][] operator:", base->getType().getCompleteString().c_str(), ""); + else + error(loc, "unexpected operator on texture type:", field.c_str(), base->getType().getCompleteString().c_str()); + } + } else if (base->isVector() || base->isScalar()) { TSwizzleSelectors selectors; parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); @@ -1555,6 +1580,28 @@ void HlslParseContext::addInterstageIoToLinkage() } } +// For struct buffers with counters, we must pass the counter buffer as hidden parameter. +// This adds the hidden parameter to the parameter list in 'paramNodes' if needed. +// Otherwise, it's a no-op +void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter& param, TIntermAggregate*& paramNodes) +{ + if (! hasStructBuffCounter(*param.type)) + return; + + const TString counterBlockName(getStructBuffCounterName(*param.name)); + + TType counterType; + counterBufferType(loc, counterType); + TVariable *variable = makeInternalVariable(counterBlockName, counterType); + + if (! symbolTable.insert(*variable)) + error(loc, "redefinition", variable->getName().c_str(), ""); + + paramNodes = intermediate.growAggregate(paramNodes, + intermediate.addSymbol(*variable, loc), + loc); +} + // // Handle seeing the function prototype in front of a function definition in the grammar. // The body is handled after this function returns. @@ -1624,7 +1671,8 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l intermediate.addSymbol(*variable, loc), loc); - // TODO: for struct buffers with counters, pass counter buffer as hidden parameter + // Add hidden parameter for struct buffer counters, if needed. + addStructBufferHiddenCounterParam(loc, param, paramNodes); } else paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } @@ -1960,7 +2008,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct // GS outputs are via emit, so we do not copy them here. if (param.type->getQualifier().isParamOutput()) { - if (param.declaredBuiltIn == EbvGsOutputStream) { + if (param.getDeclaredBuiltIn() == EbvGsOutputStream) { // GS output stream does not assign outputs here: it's the Append() method // which writes to the output, probably multiple times separated by Emit. // We merely remember the output to use, here. @@ -2067,7 +2115,7 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingIn); inputs.push_back(argAsGlobal); - if (function[i].declaredBuiltIn == EbvInputPatch) + if (function[i].getDeclaredBuiltIn() == EbvInputPatch) inputPatch = argAsGlobal; } if (paramType.getQualifier().isParamOutput()) { @@ -2456,13 +2504,9 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc } // Return true if this a buffer type that has an associated counter buffer. -bool HlslParseContext::hasStructBuffCounter(const TString& name) const +bool HlslParseContext::hasStructBuffCounter(const TType& type) const { - const auto bivIt = structBufferBuiltIn.find(name); - if (bivIt == structBufferBuiltIn.end()) - return false; - - switch (bivIt->second) { + switch (type.getQualifier().declaredBuiltIn) { case EbvAppendConsume: // fall through... case EbvRWStructuredBuffer: // ... return true; @@ -2471,6 +2515,29 @@ bool HlslParseContext::hasStructBuffCounter(const TString& name) const } } +void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type) +{ + // Counter type + TType* counterType = new TType(EbtInt, EvqBuffer); + counterType->setFieldName("@count"); + + TTypeList* blockStruct = new TTypeList; + TTypeLoc member = { counterType, loc }; + blockStruct->push_back(member); + + TType blockType(blockStruct, "", counterType->getQualifier()); + blockType.getQualifier().storage = EvqBuffer; + + type.shallowCopy(blockType); + shareStructBufferType(type); +} + +// knowledge of how to construct block name, in one place instead of N places. +TString HlslParseContext::getStructBuffCounterName(const TString& blockName) const +{ + return blockName + "@count"; +} + // declare counter for a structured buffer type void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name) { @@ -2478,25 +2545,17 @@ void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const T if (! isStructBufferType(bufferType)) return; - if (! hasStructBuffCounter(name)) + if (! hasStructBuffCounter(bufferType)) return; - // Counter type - TType* counterType = new TType(EbtInt, EvqBuffer); - counterType->setFieldName("@count"); + TType blockType; + counterBufferType(loc, blockType); - TTypeList* blockStruct = new TTypeList; - TTypeLoc member = { counterType, loc }; - blockStruct->push_back(member); - - TString* blockName = new TString(name); - *blockName += "@count"; + TString* blockName = new TString(getStructBuffCounterName(name)); + // Counter buffer does not have its own counter buffer. TODO: there should be a better way to track this. structBufferCounter[*blockName] = false; - TType blockType(blockStruct, "", counterType->getQualifier()); - blockType.getQualifier().storage = EvqBuffer; - shareStructBufferType(blockType); declareBlock(loc, blockType, blockName); } @@ -2508,13 +2567,12 @@ TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TI if (buffer == nullptr || ! isStructBufferType(buffer->getType())) return nullptr; - TString blockName(buffer->getAsSymbolNode()->getName()); - blockName += "@count"; + const TString counterBlockName(getStructBuffCounterName(buffer->getAsSymbolNode()->getName())); // Mark the counter as being used - structBufferCounter[blockName] = true; + structBufferCounter[counterBlockName] = true; - TIntermTyped* counterVar = handleVariable(loc, &blockName); // find the block structure + TIntermTyped* counterVar = handleVariable(loc, &counterBlockName); // find the block structure TIntermTyped* index = intermediate.addConstantUnion(0, loc); // index to counter inside block struct TIntermTyped* counterMember = intermediate.addIndex(EOpIndexDirectStruct, counterVar, index, loc); @@ -2549,8 +2607,6 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr) return; - const TString bufferName(bufferObj->getAsSymbolNode()->getName()); - // Some methods require a hidden internal counter, obtained via getStructBufferCounter(). // This lambda adds something to it and returns the old value. const auto incDecCounter = [&](int incval) -> TIntermTyped* { @@ -2579,20 +2635,14 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte { TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - const auto bivIt = structBufferBuiltIn.find(bufferName); - - const TBuiltInVariable builtInType = (bivIt != structBufferBuiltIn.end()) ? bivIt->second : EbvNone; - const TType& bufferType = bufferObj->getType(); + const TBuiltInVariable builtInType = bufferType.getQualifier().declaredBuiltIn; + // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address // buffer then, but that's what it calls itself. - // TODO: it would be easier to track the declared (pre-sanitized) builtInType in the TType. - // If/when that happens, this should be simplified to look *only* at the builtin type. const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || - builtInType == EbvRWByteAddressBuffer || - (builtInType == EbvNone && !bufferType.isVector() && - bufferType.getBasicType() == EbtUint)); + builtInType == EbvRWByteAddressBuffer); if (isByteAddressBuffer) @@ -3660,6 +3710,12 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy switch (op) { case EOpMethodAppend: if (argAggregate) { + // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. + if (language != EShLangGeometry) { + node = nullptr; + return; + } + TIntermAggregate* sequence = nullptr; TIntermAggregate* emit = new TIntermAggregate(EOpEmitVertex); @@ -3689,6 +3745,12 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy case EOpMethodRestartStrip: { + // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. + if (language != EShLangGeometry) { + node = nullptr; + return; + } + TIntermAggregate* cut = new TIntermAggregate(EOpEndPrimitive); cut->setLoc(loc); cut->setType(TType(EbtVoid)); @@ -4294,6 +4356,9 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct // const TFunction* fnCandidate = nullptr; bool builtIn = false; + int thisDepth = 0; + + TIntermAggregate* aggregate = arguments ? arguments->getAsAggregate() : nullptr; // TODO: this needs improvement: there's no way at present to look up a signature in // the symbol table for an arbitrary type. This is a temporary hack until that ability exists. @@ -4304,14 +4369,12 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct TIntermTyped* arg0 = nullptr; - if (arguments->getAsAggregate() && arguments->getAsAggregate()->getSequence().size() > 0) - arg0 = arguments->getAsAggregate()->getSequence()[0]->getAsTyped(); + if (aggregate && aggregate->getSequence().size() > 0) + arg0 = aggregate->getSequence()[0]->getAsTyped(); else if (arguments->getAsSymbolNode()) arg0 = arguments->getAsSymbolNode(); if (arg0 != nullptr && isStructBufferType(arg0->getType())) { - // TODO: for struct buffers with counters, pass counter buffer as hidden parameter - static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1; if (function->getName().length() > methodPrefixSize && @@ -4326,7 +4389,7 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct } if (fnCandidate == nullptr) - fnCandidate = findFunction(loc, *function, builtIn, arguments); + fnCandidate = findFunction(loc, *function, builtIn, thisDepth, arguments); if (fnCandidate) { // This is a declared function that might map to @@ -4338,10 +4401,27 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct if (builtIn && fnCandidate->getNumExtensions()) requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); + // turn an implicit member-function resolution into an explicit call + TString callerName; + if (thisDepth == 0) + callerName = fnCandidate->getMangledName(); + else { + // get the explicit (full) name of the function + callerName = currentTypePrefix[currentTypePrefix.size() - thisDepth]; + callerName += fnCandidate->getMangledName(); + // insert the implicit calling argument + pushFrontArguments(intermediate.addSymbol(*getImplicitThis(thisDepth)), arguments); + } + // Convert 'in' arguments if (arguments) addInputArgumentConversions(*fnCandidate, arguments); + // If any argument is a pass-by-reference struct buffer with an associated counter + // buffer, we have to add another hidden parameter for that counter. + if (aggregate && !builtIn) + addStructBuffArguments(loc, aggregate); + op = fnCandidate->getBuiltInOp(); if (builtIn && op != EOpNull) { // A function call mapped to a built-in operation. @@ -4358,14 +4438,14 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct // It could still be a built-in function, but only if PureOperatorBuiltins == false. result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); TIntermAggregate* call = result->getAsAggregate(); - call->setName(fnCandidate->getMangledName()); + call->setName(callerName); // this is how we know whether the given function is a built-in function or a user-defined function // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also // if builtIn == true, it's definitely a built-in function with EOpNull if (! builtIn) { call->setUserDefined(); - intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); + intermediate.addToCallGraph(infoSink, currentCaller, callerName); } } @@ -4388,7 +4468,12 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct for (int i = 0; i < fnCandidate->getParamCount(); ++i) { TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; qualifierList.push_back(qual); + + // add counter buffer argument qualifier + if (hasStructBuffCounter(*(*fnCandidate)[i].type)) + qualifierList.push_back(qual); } + result = addOutputArgumentConversions(*fnCandidate, *result->getAsOperator()); } } @@ -4402,6 +4487,19 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct return result; } +// An initial argument list is difficult: it can be null, or a single node, +// or an aggregate if more than one argument. Add one to the front, maintaining +// this lack of uniformity. +void HlslParseContext::pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments) +{ + if (arguments == nullptr) + arguments = front; + else if (arguments->getAsAggregate() != nullptr) + arguments->getAsAggregate()->getSequence().insert(arguments->getAsAggregate()->getSequence().begin(), front); + else + arguments = intermediate.growAggregate(front, arguments); +} + // // Add any needed implicit conversions for function-call arguments to input parameters. // @@ -4557,6 +4655,55 @@ TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& fu return conversionTree; } +// +// Add any needed "hidden" counter buffer arguments for function calls. +// +// Modifies the 'aggregate' argument if needed. Otherwise, is no-op. +// +void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*& aggregate) +{ + // See if there are any SB types with counters. + const bool hasStructBuffArg = + std::any_of(aggregate->getSequence().begin(), + aggregate->getSequence().end(), + [this](const TIntermNode* node) { + return (node->getAsTyped() != nullptr) && hasStructBuffCounter(node->getAsTyped()->getType()); + }); + + // Nothing to do, if we didn't find one. + if (! hasStructBuffArg) + return; + + TIntermSequence argsWithCounterBuffers; + + for (int param=0; paramgetSequence().size()); ++param) { + argsWithCounterBuffers.push_back(aggregate->getSequence()[param]); + + if (hasStructBuffCounter(aggregate->getSequence()[param]->getAsTyped()->getType())) { + const TIntermSymbol* blockSym = aggregate->getSequence()[param]->getAsSymbolNode(); + if (blockSym != nullptr) { + TType counterType; + counterBufferType(loc, counterType); + + const TString counterBlockName(getStructBuffCounterName(blockSym->getName())); + + TVariable* variable = makeInternalVariable(counterBlockName, counterType); + + // Mark this buffer as requiring a counter block. TODO: there should be a better + // way to track it. + structBufferCounter[counterBlockName] = true; + + TIntermSymbol* sym = intermediate.addSymbol(*variable, loc); + argsWithCounterBuffers.push_back(sym); + } + } + } + + // Swap with the temp list we've built up. + aggregate->getSequence().swap(argsWithCounterBuffers); +} + + // // Do additional checking of built-in function calls that is not caught // by normal semantic checks on argument type, extension tagging, etc. @@ -5715,6 +5862,7 @@ void HlslParseContext::paramFix(TType& type) bufferQualifier.storage = type.getQualifier().storage; bufferQualifier.readonly = type.getQualifier().readonly; bufferQualifier.coherent = type.getQualifier().coherent; + bufferQualifier.declaredBuiltIn = type.getQualifier().declaredBuiltIn; type.getQualifier() = bufferQualifier; break; } @@ -6159,18 +6307,17 @@ void HlslParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQuali // // Return the function symbol if found, otherwise nullptr. // -const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, +const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args) { - // const TFunction* function = nullptr; - if (symbolTable.isFunctionNameVariable(call.getName())) { error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); return nullptr; } // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); + bool dummyScope; + TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn, &dummyScope, &thisDepth); if (symbol) return symbol->getAsFunction(); @@ -6180,7 +6327,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction TVector candidateList; symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - // These builtin ops can accept any type, so we bypass the argument selection + // These built-in ops can accept any type, so we bypass the argument selection if (candidateList.size() == 1 && builtIn && (candidateList[0]->getBuiltInOp() == EOpMethodAppend || candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip || @@ -7197,10 +7344,6 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS switch (type.getQualifier().storage) { case EvqUniform: case EvqBuffer: - // remember pre-sanitized builtin type - if (type.getQualifier().storage == EvqBuffer && instanceName != nullptr) - structBufferBuiltIn[*instanceName] = type.getQualifier().builtIn; - correctUniform(type.getQualifier()); break; case EvqVaryingIn: @@ -7761,11 +7904,23 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex // Make a new symbol-table level that is made out of the members of a structure. // This should be done as an anonymous struct (name is "") so that the symbol table -// finds the members with on explicit reference to a 'this' variable. -void HlslParseContext::pushThisScope(const TType& thisStruct) +// finds the members with no explicit reference to a 'this' variable. +void HlslParseContext::pushThisScope(const TType& thisStruct, const TVector& functionDeclarators) { + // member variables TVariable& thisVariable = *new TVariable(NewPoolTString(""), thisStruct); symbolTable.pushThis(thisVariable); + + // member functions + for (auto it = functionDeclarators.begin(); it != functionDeclarators.end(); ++it) { + // member should have a prefix matching currentTypePrefix.back() + // but, symbol lookup within the class scope will just use the + // unprefixed name. Hence, there are two: one fully prefixed and + // one with no prefix. + TFunction& member = *it->function->clone(); + member.removePrefix(currentTypePrefix.back()); + symbolTable.insert(member); + } } // Track levels of class/struct/namespace nesting with a prefix string using @@ -7780,11 +7935,10 @@ void HlslParseContext::pushNamespace(const TString& typeName) { // make new type prefix TString newPrefix; - if (currentTypePrefix.size() > 0) { + if (currentTypePrefix.size() > 0) newPrefix = currentTypePrefix.back(); - newPrefix.append(scopeMangler); - } newPrefix.append(typeName); + newPrefix.append(scopeMangler); currentTypePrefix.push_back(newPrefix); } @@ -7802,7 +7956,6 @@ void HlslParseContext::getFullNamespaceName(const TString*& name) const return; TString* fullName = NewPoolTString(currentTypePrefix.back().c_str()); - fullName->append(scopeMangler); fullName->append(*name); name = fullName; } @@ -8006,6 +8159,9 @@ void HlslParseContext::correctOutput(TQualifier& qualifier) // Make the IO decorations etc. be appropriate only for uniform type interfaces. void HlslParseContext::correctUniform(TQualifier& qualifier) { + if (qualifier.declaredBuiltIn == EbvNone) + qualifier.declaredBuiltIn = qualifier.builtIn; + qualifier.builtIn = EbvNone; qualifier.clearInterstage(); qualifier.clearInterstageLayout(); @@ -8074,8 +8230,8 @@ void HlslParseContext::addPatchConstantInvocation() if (storage == EvqConstReadOnly) // treated identically to input storage = EvqIn; - if (function[p].declaredBuiltIn != EbvNone) - builtIns.insert(HlslParseContext::tInterstageIoData(function[p].declaredBuiltIn, storage)); + if (function[p].getDeclaredBuiltIn() != EbvNone) + builtIns.insert(HlslParseContext::tInterstageIoData(function[p].getDeclaredBuiltIn(), storage)); else builtIns.insert(HlslParseContext::tInterstageIoData(function[p].type->getQualifier().builtIn, storage)); } @@ -8105,7 +8261,7 @@ void HlslParseContext::addPatchConstantInvocation() const auto isOutputPatch = [this](TFunction& patchConstantFunction, int param) { const TType& type = *patchConstantFunction[param].type; - const TBuiltInVariable biType = patchConstantFunction[param].declaredBuiltIn; + const TBuiltInVariable biType = patchConstantFunction[param].getDeclaredBuiltIn(); return type.isArray() && !type.isRuntimeSizedArray() && biType == EbvOutputPatch; }; @@ -8161,7 +8317,7 @@ void HlslParseContext::addPatchConstantInvocation() // Now we'll add those to the entry and to the linkage. for (int p=0; pgetQualifier().storage; // Track whether there is an output patch param @@ -8227,7 +8383,7 @@ void HlslParseContext::addPatchConstantInvocation() inputArg = intermediate.addSymbol(*perCtrlPtVar, loc); } else { // find which builtin it is - const TBuiltInVariable biType = patchConstantFunction[p].declaredBuiltIn; + const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn(); inputArg = findLinkageSymbol(biType); @@ -8308,7 +8464,7 @@ void HlslParseContext::addPatchConstantInvocation() if (paramType.getQualifier().isParamInput()) { TIntermTyped* arg = nullptr; - if ((*entryPointFunction)[i].declaredBuiltIn == EbvInvocationId) { + if ((*entryPointFunction)[i].getDeclaredBuiltIn() == EbvInvocationId) { // substitute invocation ID with the array element ID arg = intermediate.addConstantUnion(cpt, loc); } else { @@ -8414,6 +8570,12 @@ void HlslParseContext::removeUnusedStructBufferCounters() // post-processing void HlslParseContext::finish() { + // Error check: There was a dangling .mips operator. These are not nested constructs in the grammar, so + // cannot be detected there. This is not strictly needed in a non-validating parser; it's just helpful. + if (! mipsOperatorMipArg.empty()) { + error(mipsOperatorMipArg.back().loc, "unterminated mips operator:", "", ""); + } + removeUnusedStructBufferCounters(); addPatchConstantInvocation(); addInterstageIoToLinkage(); diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.h b/3rdparty/glslang/hlsl/hlslParseHelper.h index d5cbc0633..f7b293abb 100755 --- a/3rdparty/glslang/hlsl/hlslParseHelper.h +++ b/3rdparty/glslang/hlsl/hlslParseHelper.h @@ -42,6 +42,7 @@ namespace glslang { class TAttributeMap; // forward declare +class TFunctionDeclarator; class HlslParseContext : public TParseContextBase { public: @@ -93,6 +94,7 @@ public: void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); + void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments); void addInputArgumentConversions(const TFunction&, TIntermTyped*&); TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); @@ -135,7 +137,7 @@ public: void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); - const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args); + const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args); void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&); void declareStruct(const TSourceLoc&, TString& structName, TType&); TSymbol* lookupUserType(const TString&, TType&); @@ -166,7 +168,7 @@ public: void pushScope() { symbolTable.push(); } void popScope() { symbolTable.pop(0); } - void pushThisScope(const TType&); + void pushThisScope(const TType&, const TVector&); void popThisScope() { symbolTable.pop(0); } void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); } @@ -275,6 +277,7 @@ protected: // Test method names bool isStructBufferMethod(const TString& name) const; + void counterBufferType(const TSourceLoc& loc, TType& type); // Return standard sample position array TIntermConstantUnion* getSamplePosArray(int count); @@ -283,13 +286,16 @@ protected: bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; } TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const; TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer); + TString getStructBuffCounterName(const TString&) const; + void addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*&); + void addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter&, TIntermAggregate*&); // Return true if this type is a reference. This is not currently a type method in case that's // a language specific answer. bool isReference(const TType& type) const { return isStructBufferType(type); } // Return true if this a buffer type that has an associated counter buffer. - bool hasStructBuffCounter(const TString& name) const; + bool hasStructBuffCounter(const TType&) const; // Finalization step: remove unused buffer blocks from linkage (we don't know until the // shader is entirely compiled) @@ -383,7 +389,6 @@ protected: // Structuredbuffer shared types. Typically there are only a few. TVector structBufferTypes; - TMap structBufferBuiltIn; TMap structBufferCounter; // The builtin interstage IO map considers e.g, EvqPosition on input and output separately, so that we @@ -429,6 +434,17 @@ protected: TVector implicitThisStack; // currently active 'this' variables for nested structures TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method) + + // This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as + // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting + // purposes. + struct tMipsOperatorData { + tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { } + TSourceLoc loc; + TIntermTyped* mipLevel; + }; + + TVector mipsOperatorMipArg; }; // This is the prefix we use for builtin methods to avoid namespace collisions with