From d715adc0f2328b517666abecb89501e324813dc2 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Tue, 15 Mar 2016 12:08:31 +0800 Subject: [PATCH 01/20] SPV: Implement boolean selection for mix(). Use OpSelect to implement boolean selection of mix(). FMix is applicable to linear blending of mix(). --- SPIRV/GlslangToSpv.cpp | 7 ++++--- Test/baseResults/spv.400.frag.out | 8 ++++---- Test/baseResults/spv.Operations.frag.out | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 8c1c84f9..9b03b9a7 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3435,11 +3435,12 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: builder.promoteScalar(precision, operands.front(), operands[2]); break; case glslang::EOpMix: - if (isFloat) + if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { + assert(isFloat); libCall = spv::GLSLstd450FMix; - else { + } else { opCode = spv::OpSelect; - spv::MissingFunctionality("translating integer mix to OpSelect"); + std::swap(operands.front(), operands.back()); } builder.promoteScalar(precision, operands.front(), operands.back()); break; diff --git a/Test/baseResults/spv.400.frag.out b/Test/baseResults/spv.400.frag.out index a851500c..0cf2c36e 100644 --- a/Test/baseResults/spv.400.frag.out +++ b/Test/baseResults/spv.400.frag.out @@ -719,28 +719,28 @@ Linked fragment stage: 424: 37(float) Load 39(doublev) 425: 37(float) Load 39(doublev) 429: 426(bool) Load 428(boolv) - 430: 37(float) ExtInst 1(GLSL.std.450) 46(FMix) 424 425 429 + 430: 37(float) Select 429 425 424 431: 37(float) Load 39(doublev) 432: 37(float) FAdd 431 430 Store 39(doublev) 432 433: 41(fvec2) Load 43(dvec2v) 434: 41(fvec2) Load 43(dvec2v) 438: 435(bvec2) Load 437(bvec2v) - 439: 41(fvec2) ExtInst 1(GLSL.std.450) 46(FMix) 433 434 438 + 439: 41(fvec2) Select 438 434 433 440: 41(fvec2) Load 43(dvec2v) 441: 41(fvec2) FAdd 440 439 Store 43(dvec2v) 441 442: 46(fvec3) Load 48(dvec3v) 443: 46(fvec3) Load 48(dvec3v) 447: 444(bvec3) Load 446(bvec3v) - 448: 46(fvec3) ExtInst 1(GLSL.std.450) 46(FMix) 442 443 447 + 448: 46(fvec3) Select 447 443 442 449: 46(fvec3) Load 48(dvec3v) 450: 46(fvec3) FAdd 449 448 Store 48(dvec3v) 450 451: 51(fvec4) Load 53(dvec4v) 452: 51(fvec4) Load 53(dvec4v) 456: 453(bvec4) Load 455(bvec4v) - 457: 51(fvec4) ExtInst 1(GLSL.std.450) 46(FMix) 451 452 456 + 457: 51(fvec4) Select 456 452 451 458: 51(fvec4) Load 53(dvec4v) 459: 51(fvec4) FAdd 458 457 Store 53(dvec4v) 459 diff --git a/Test/baseResults/spv.Operations.frag.out b/Test/baseResults/spv.Operations.frag.out index b3a6d283..a5863729 100755 --- a/Test/baseResults/spv.Operations.frag.out +++ b/Test/baseResults/spv.Operations.frag.out @@ -281,7 +281,7 @@ Linked fragment stage: 176: 7(fvec4) Load 9(v) 177: 7(fvec4) Load 9(v) 182: 179(bvec4) Load 181(ub41) - 183: 7(fvec4) ExtInst 1(GLSL.std.450) 46(FMix) 176 177 182 + 183: 7(fvec4) Select 182 177 176 184: 7(fvec4) Load 9(v) 185: 7(fvec4) FAdd 184 183 Store 9(v) 185 From ed5fd5d8468b23ed6d0d12f09b14246e32feb68f Mon Sep 17 00:00:00 2001 From: David Neto Date: Sun, 28 Feb 2016 23:32:44 -0500 Subject: [PATCH 02/20] Support compilation via MinGW Change-Id: Ie52f0b1b2b20948c6f4b3cb5474537d36a5a3385 --- glslang/MachineIndependent/PoolAlloc.cpp | 2 +- glslang/MachineIndependent/intermOut.cpp | 2 +- glslang/OSDependent/Windows/CMakeLists.txt | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/glslang/MachineIndependent/PoolAlloc.cpp b/glslang/MachineIndependent/PoolAlloc.cpp index a41cadf1..d56979b4 100644 --- a/glslang/MachineIndependent/PoolAlloc.cpp +++ b/glslang/MachineIndependent/PoolAlloc.cpp @@ -32,8 +32,8 @@ //POSSIBILITY OF SUCH DAMAGE. // -#include "../Include/PoolAlloc.h" #include "../Include/Common.h" +#include "../Include/PoolAlloc.h" #include "../Include/InitializeGlobals.h" #include "../OSDependent/osinclude.h" diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index b52551ff..96b5c257 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -48,7 +48,7 @@ namespace { bool is_positive_infinity(double x) { #ifdef _MSC_VER return _fpclass(x) == _FPCLASS_PINF; -#elif defined __ANDROID__ || defined __linux__ +#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__ return std::isinf(x) && (x >= 0); #else return isinf(x) && (x >= 0); diff --git a/glslang/OSDependent/Windows/CMakeLists.txt b/glslang/OSDependent/Windows/CMakeLists.txt index ff0b99e9..9bc73a37 100644 --- a/glslang/OSDependent/Windows/CMakeLists.txt +++ b/glslang/OSDependent/Windows/CMakeLists.txt @@ -4,6 +4,12 @@ set(SOURCES ossource.cpp ../osinclude.h) add_library(OSDependent STATIC ${SOURCES}) +# MinGW GCC complains about function pointer casts to void*. +# Turn that off with -fpermissive. +if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") + target_compile_options(OSDependent PRIVATE -fpermissive) +endif() + if(WIN32) source_group("Source" FILES ${SOURCES}) endif(WIN32) From 644c21025dbf3c0ebb52137b62b62e5d671cd82f Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Fri, 18 Mar 2016 16:26:23 +0800 Subject: [PATCH 03/20] Parser: Type promotion for operator modulus(%) is missing. --- Test/baseResults/spv.400.frag.out | 20 ++++++++++++++++---- Test/spv.400.frag | 3 +++ glslang/MachineIndependent/Intermediate.cpp | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Test/baseResults/spv.400.frag.out b/Test/baseResults/spv.400.frag.out index 0cf2c36e..651d67de 100644 --- a/Test/baseResults/spv.400.frag.out +++ b/Test/baseResults/spv.400.frag.out @@ -7,7 +7,7 @@ Linked fragment stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 1104 +// Id's are bound by 1112 Capability Shader Capability Float64 @@ -15,7 +15,7 @@ Linked fragment stage: Capability SampledRect 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 4 "main" 13 1025 1031 1036 1048 1074 1095 1097 + EntryPoint Fragment 4 "main" 13 1025 1031 1036 1048 1074 1095 1097 1103 1105 ExecutionMode 4 OriginUpperLeft Source GLSL 400 SourceExtension "GL_ARB_separate_shader_objects" @@ -52,6 +52,8 @@ Linked fragment stage: Name 1078 "isamp2DA" Name 1095 "gl_FragCoord" Name 1097 "vl2" + Name 1103 "uo" + Name 1105 "u" Decorate 17(u2drs) DescriptorSet 0 Decorate 1023(arrayedSampler) DescriptorSet 0 Decorate 1025(i) Flat @@ -60,6 +62,7 @@ Linked fragment stage: Decorate 1078(isamp2DA) DescriptorSet 0 Decorate 1095(gl_FragCoord) BuiltIn FragCoord Decorate 1097(vl2) Location 6 + Decorate 1105(u) Flat 2: TypeVoid 3: TypeFunction 2 10: TypeFloat 32 @@ -177,6 +180,10 @@ Linked fragment stage: 1094: TypePointer Input 11(fvec4) 1095(gl_FragCoord): 1094(ptr) Variable Input 1097(vl2): 1094(ptr) Variable Input + 1102: TypePointer Output 30(int) + 1103(uo): 1102(ptr) Variable Output + 1104: TypePointer Input 30(int) + 1105(u): 1104(ptr) Variable Input 4(main): 2 Function None 3 5: Label 1017(v): 1016(ptr) Variable Function @@ -227,8 +234,13 @@ Linked fragment stage: 1100: 11(fvec4) Load 13(outp) 1101: 11(fvec4) FAdd 1100 1099 Store 13(outp) 1101 - 1102: 2 FunctionCall 6(foo23() - 1103: 2 FunctionCall 8(doubles() + 1106: 30(int) Load 1105(u) + 1107: 23(int) Load 1025(i) + 1108: 30(int) Bitcast 1107 + 1109: 30(int) UMod 1106 1108 + Store 1103(uo) 1109 + 1110: 2 FunctionCall 6(foo23() + 1111: 2 FunctionCall 8(doubles() Return FunctionEnd 6(foo23(): 2 Function None 3 diff --git a/Test/spv.400.frag b/Test/spv.400.frag index 2014b5b0..05b4370b 100644 --- a/Test/spv.400.frag +++ b/Test/spv.400.frag @@ -2,6 +2,8 @@ in vec2 c2D; flat in int i; +flat in uint u; +out uint uo; out vec4 outp; out ivec4 ioutp; out uvec4 uoutp; @@ -254,6 +256,7 @@ void main() ioutp += textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i)); outp += gl_FragCoord + vl2; + uo = u % i; foo23(); doubles(); } diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index bafcb917..e4d21e69 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -474,6 +474,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EOpSub: case EOpMul: case EOpDiv: + case EOpMod: case EOpVectorTimesScalar: case EOpVectorTimesMatrix: From 952543e757fb9770ed54eff72423e86b4becd52a Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sat, 19 Mar 2016 18:10:22 -0600 Subject: [PATCH 04/20] Front-end infrastructure: simplify and localize creating symbol nodes, reducing replication. --- glslang/MachineIndependent/Intermediate.cpp | 27 ++++++++++++------- glslang/MachineIndependent/ParseHelper.cpp | 2 +- .../MachineIndependent/localintermediate.h | 7 ++--- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index e4d21e69..66c3680c 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -61,27 +61,35 @@ namespace glslang { // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& loc) +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, const TSourceLoc& loc) { TIntermSymbol* node = new TIntermSymbol(id, name, type); node->setLoc(loc); - - return node; -} - -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, const TSourceLoc& loc) -{ - TIntermSymbol* node = addSymbol(id, name, type, loc); node->setConstArray(constArray); return node; } +TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) +{ + glslang::TSourceLoc loc; // just a null location + loc.init(); + + return addSymbol(variable, loc); +} + TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) { return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), loc); } +TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) +{ + TConstUnionArray unionArray; // just a null constant + + return addSymbol(0, "", type, unionArray, loc); +} + // // Connect two nodes with a new parent that does a binary operation on the nodes. // @@ -1018,8 +1026,7 @@ void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymb const TAnonMember* anon = symbol.getAsAnonMember(); variable = &anon->getAnonContainer(); } - TIntermSymbol* node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType()); - node->setConstArray(variable->getConstArray()); + TIntermSymbol* node = addSymbol(*variable); linkage = growAggregate(linkage, node); } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 8cee3e4b..28af0d40 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1017,7 +1017,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, loc); } } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(0, "", *param.type, loc), loc); + paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); loopNestingLevel = 0; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 99267475..f25c0f11 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -162,10 +162,10 @@ public: int getNumErrors() const { return numErrors; } void addPushConstantCount() { ++numPushConstants; } bool isRecursive() const { return recursive; } - - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, const TSourceLoc&); - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); + + TIntermSymbol* addSymbol(const TVariable&); TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const; TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); @@ -326,6 +326,7 @@ public: static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, const TSourceLoc&); void error(TInfoSink& infoSink, const char*); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); From 7cc0e2896ed3c2d00bc8b19f69ec88a166320343 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sun, 20 Mar 2016 00:46:02 -0600 Subject: [PATCH 05/20] Front-end infrastructure: Encapsulate semantic-level questions/actions about const/temp. Much about const or temp is mechanical, about actual declaration, while much is semantic, about something higher level. This commit checks every use everywhere, and for the high-level ones, substitutes an encapsulated version instead. --- SPIRV/GlslangToSpv.cpp | 4 +- Test/baseResults/310.comp.out | 4 +- glslang/Include/Types.h | 13 ++++++ glslang/MachineIndependent/Intermediate.cpp | 2 +- glslang/MachineIndependent/ParseHelper.cpp | 47 ++++++++++++--------- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 9b03b9a7..b837a25d 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1629,7 +1629,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* // First, steer off constants, which are not SPIR-V variables, but // can still have a mapping to a SPIR-V Id. // This includes specialization constants. - if (node->getQualifier().storage == glslang::EvqConst) { + if (node->getQualifier().isConstant()) { return createSpvSpecConstant(*node); } @@ -3732,7 +3732,7 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De // - when running into a non-spec-constant, switch to createSpvConstant() spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node) { - assert(node.getQualifier().storage == glslang::EvqConst); + assert(node.getQualifier().isConstant()); if (! node.getQualifier().specConstant) { // hand off to the non-spec-constant path diff --git a/Test/baseResults/310.comp.out b/Test/baseResults/310.comp.out index ff438e3a..d6b03322 100644 --- a/Test/baseResults/310.comp.out +++ b/Test/baseResults/310.comp.out @@ -337,7 +337,7 @@ ERROR: node is still EOpNull! 0:201 1 (const int) 0:201 Constant: 0:201 2 (const int) -0:202 Test condition and select (layout(column_major shared ) temp highp float) +0:202 Test condition and select (temp highp float) 0:202 Condition 0:202 'b' (temp bool) 0:202 true case @@ -764,7 +764,7 @@ ERROR: node is still EOpNull! 0:201 1 (const int) 0:201 Constant: 0:201 2 (const int) -0:202 Test condition and select (layout(column_major shared ) temp highp float) +0:202 Test condition and select (temp highp float) 0:202 Condition 0:202 'b' (temp bool) 0:202 true case diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index c88bca67..1d126569 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -411,6 +411,19 @@ public: clearLayout(); } + // Drop just the storage qualification, which perhaps should + // never be done, as it is fundamentally inconsistent, but need to + // explore what downstream consumers need. + // E.g., in a deference, it is an inconsistency between: + // A) partially dereferenced resource is still in the storage class it started in + // B) partially dereferenced resource is a new temporary object + // If A, then nothing should change, if B, then everything should change, but this is half way. + void makePartialTemporary() + { + storage = EvqTemporary; + specConstant = false; + } + TStorageQualifier storage : 6; TBuiltInVariable builtIn : 8; TPrecisionQualifier precision : 3; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 66c3680c..5f474911 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -822,7 +822,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Make a selection node. // TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->getQualifier().storage = EvqTemporary; + node->getQualifier().makeTemporary(); node->setLoc(loc); node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 28af0d40..9057b345 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -484,7 +484,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn TIntermTyped* result = nullptr; int indexValue = 0; - if (index->getQualifier().storage == EvqConst) { + if (index->getQualifier().isConstant()) { indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); checkIndex(loc, base->getType(), indexValue); } @@ -495,7 +495,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); else error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) + } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) return intermediate.foldDereference(base, indexValue, loc); else { // at least one of base and index is variable... @@ -503,7 +503,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) handleIoResizeArrayAccess(loc, base); - if (index->getQualifier().storage == EvqConst) { + if (index->getQualifier().isConstant()) { if (base->getType().isImplicitlySizedArray()) updateImplicitArraySize(loc, base, indexValue); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); @@ -541,10 +541,10 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn } else { // Insert valid dereferenced result TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) + if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) newType.getQualifier().storage = EvqConst; else - newType.getQualifier().storage = EvqTemporary; + newType.getQualifier().makePartialTemporary(); result->setType(newType); if (anyIndexLimits) @@ -587,7 +587,7 @@ void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* b (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && ! base->getType().getQualifier().isPipeInput() && ! base->getType().getQualifier().isPipeOutput() && - base->getType().getQualifier().storage != EvqConst) || + ! base->getType().getQualifier().isConstant()) || (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || base->getType().getQualifier().isPipeOutput()))) { // it's too early to know what the inductive variables are, save it for post processing @@ -849,7 +849,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm } } if (fieldFound) { - if (base->getType().getQualifier().storage == EvqConst) + if (base->getType().getQualifier().isFrontEndConstant()) result = intermediate.foldDereference(base, member, loc); else { blockMemberExtensionCheck(loc, base, field); @@ -2039,7 +2039,7 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt // void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) { - if (node->getQualifier().storage != EvqConst) + if (! node->getQualifier().isConstant()) error(node->getLoc(), "constant expression required", token, ""); } @@ -2204,6 +2204,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T int size = 0; bool constType = true; + bool specConstType = true; bool full = false; bool overFull = false; bool matrixInMatrix = false; @@ -2232,12 +2233,17 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) full = true; - if (function[arg].type->getQualifier().storage != EvqConst) + if (! function[arg].type->getQualifier().isConstant()) constType = false; + if (! function[arg].type->getQualifier().isSpecConstant()) + specConstType = false; } - if (constType) + if (constType) { type.getQualifier().storage = EvqConst; + if (specConstType) + type.getQualifier().specConstant = true; + } if (type.isArray()) { if (function.getParamCount() == 0) { @@ -3147,7 +3153,7 @@ void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier // if (type.getQualifier().storage == EvqConst || type.getQualifier().storage == EvqConstReadOnly) { - type.getQualifier().storage = EvqTemporary; + type.getQualifier().makeTemporary(); error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); } } @@ -4848,7 +4854,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp if (! initializer) { // error recovery; don't leave const without constant values if (qualifier == EvqConst) - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } @@ -4868,21 +4874,22 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp } } - // Uniform and global consts require a constant initializer - if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) { + // Uniforms require a compile-time constant initializer + if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } - if (qualifier == EvqConst && symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) { + // Global consts require a constant initializer (specialization constant is okay) + if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } // Const variables require a constant initializer, depending on version if (qualifier == EvqConst) { - if (initializer->getType().getQualifier().storage != EvqConst) { + if (! initializer->getType().getQualifier().isConstant()) { const char* initFeature = "non-constant initializer"; requireProfile(loc, ~EEsProfile, initFeature); profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); @@ -4894,7 +4901,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // // "In declarations of global variables with no storage qualifier or with a const // qualifier any initializer must be a constant expression." - if (symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) { + if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { const char* initFeature = "non-constant global initializer"; if (relaxedErrors()) warn(loc, "not allowed in this version", initFeature, ""); @@ -4910,7 +4917,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp if (! initializer || ! initializer->getAsConstantUnion() || variable->getType() != initializer->getType()) { error(loc, "non-matching or non-convertible constant type for const initializer", variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } From a5845766e0d89aa0b7aa597fe74a93296f4aeb0d Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sun, 20 Mar 2016 16:46:00 -0600 Subject: [PATCH 06/20] Front-end: Add specialization-constant subtrees for const variables/symbols. --- SPIRV/GlslangToSpv.cpp | 1 + glslang/Include/intermediate.h | 20 ++++++++++------- glslang/MachineIndependent/Intermediate.cpp | 8 ++++--- glslang/MachineIndependent/ParseHelper.cpp | 17 ++++++++++++-- glslang/MachineIndependent/SymbolTable.cpp | 9 +++++--- glslang/MachineIndependent/SymbolTable.h | 22 ++++++++++++++----- glslang/MachineIndependent/intermOut.cpp | 5 +++++ .../MachineIndependent/localintermediate.h | 2 +- 8 files changed, 61 insertions(+), 23 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index b837a25d..6f5697e3 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3763,6 +3763,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); } else { spv::MissingFunctionality("specialization-constant expression trees"); + exit(1); return spv::NoResult; } } diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index ce5fb775..ab177011 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -612,25 +612,29 @@ public: // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from // per process threadPoolAllocator, then it causes increased memory usage per compile // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& n, const TType& t) : - TIntermTyped(t), id(i) { name = n;} + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), constSubtree(nullptr) + { name = n; } virtual int getId() const { return id; } virtual const TString& getName() const { return name; } virtual void traverse(TIntermTraverser*); virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual const TIntermSymbol* getAsSymbolNode() const { return this; } - void setConstArray(const TConstUnionArray& c) { unionArray = c; } - const TConstUnionArray& getConstArray() const { return unionArray; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } protected: int id; // the unique id of the symbol this node represents TString name; // the name of the symbol this node represents - TConstUnionArray unionArray; // if the symbol is a front-end compile-time constant, this is its value + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; }; class TIntermConstantUnion : public TIntermTyped { public: - TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { } - const TConstUnionArray& getConstArray() const { return unionArray; } + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } virtual TIntermConstantUnion* getAsConstantUnion() { return this; } virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } virtual void traverse(TIntermTraverser*); @@ -640,7 +644,7 @@ public: void setExpression() { literal = false; } bool isLiteral() const { return literal; } protected: - const TConstUnionArray unionArray; + const TConstUnionArray constArray; bool literal; // true if node represents a literal in the source code }; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 5f474911..bb4e14bc 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -61,11 +61,13 @@ namespace glslang { // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, const TSourceLoc& loc) +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, + TIntermTyped* constSubtree, const TSourceLoc& loc) { TIntermSymbol* node = new TIntermSymbol(id, name, type); node->setLoc(loc); node->setConstArray(constArray); + node->setConstSubtree(constSubtree); return node; } @@ -80,14 +82,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) { - return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), loc); + return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc); } TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) { TConstUnionArray unionArray; // just a null constant - return addSymbol(0, "", type, unionArray, loc); + return addSymbol(0, "", type, unionArray, nullptr, loc); } // diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 9057b345..cd745a9d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -4914,14 +4914,27 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // Compile-time tagging of the variable with its constant value... initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (! initializer || ! initializer->getAsConstantUnion() || variable->getType() != initializer->getType()) { + if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { error(loc, "non-matching or non-convertible constant type for const initializer", variable->getType().getStorageQualifierString(), ""); variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); + // We either have a folded constant in getAsConstantUnion, or we have to use + // the initializer's subtree in the AST to represent the computation of a + // specialization constant. + assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); + if (initializer->getAsConstantUnion()) + variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); + else { + // It's a specialization constant. + variable->getWritableType().getQualifier().makeSpecConstant(); + + // Keep the subtree that computes the specialization constant with the variable. + // Later, a symbol node will adopt the subtree from the variable. + variable->setConstSubtree(initializer); + } } else { // normal assigning of a value to a variable... specializationCheck(loc, initializer->getType(), "initializer"); diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 9794a5d2..75f50402 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -252,11 +252,14 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) if (copyOf.numExtensions != 0) setExtensions(copyOf.numExtensions, copyOf.extensions); - if (! copyOf.unionArray.empty()) { + if (! copyOf.constArray.empty()) { assert(! copyOf.type.isStruct()); - TConstUnionArray newArray(copyOf.unionArray, 0, copyOf.unionArray.size()); - unionArray = newArray; + TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); + constArray = newArray; } + + // don't support specialization-constant subtrees in cloned tables + constSubtree = nullptr; } TVariable* TVariable::clone() const diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index ad73b3b5..9877ab7f 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -135,7 +135,7 @@ protected: // // Variable class, meaning a symbol that's not a function. // -// There could be a separate class heirarchy for Constant variables; +// There could be a separate class hierarchy for Constant variables; // Only one of int, bool, or float, (or none) is correct for // any particular use, but it's easy to do this way, and doesn't // seem worth having separate classes, and "getConst" can't simply return @@ -144,7 +144,10 @@ protected: // class TVariable : public TSymbol { public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), userType(uT) { type.shallowCopy(t); } + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr) { type.shallowCopy(t); } virtual TVariable* clone() const; virtual ~TVariable() { } @@ -153,9 +156,11 @@ public: virtual const TType& getType() const { return type; } virtual TType& getWritableType() { assert(writable); return type; } virtual bool isUserType() const { return userType; } - virtual const TConstUnionArray& getConstArray() const { return unionArray; } - virtual TConstUnionArray& getWritableConstArray() { assert(writable); return unionArray; } - virtual void setConstArray(const TConstUnionArray& constArray) { unionArray = constArray; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } virtual void dump(TInfoSink &infoSink) const; @@ -167,7 +172,12 @@ protected: bool userType; // we are assuming that Pool Allocator will free the memory allocated to unionArray // when this object is destroyed - TConstUnionArray unionArray; + + // TODO: these two should be a union + // A variable could be a compile-time constant, or a specialization + // constant, or neither, but never both. + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation }; // diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 96b5c257..eb6c30cd 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -605,6 +605,11 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node) if (! node->getConstArray().empty()) OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1); + else if (node->getConstSubtree()) { + incrementDepth(node); + node->getConstSubtree()->traverse(this); + decrementDepth(); + } } bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node) diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index f25c0f11..5e5a2e77 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -326,7 +326,7 @@ public: static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); protected: - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, const TSourceLoc&); + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); void error(TInfoSink& infoSink, const char*); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); From 6d2b07dc3952739b7d540cc326a21eff8c3ef935 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sun, 20 Mar 2016 18:45:23 -0600 Subject: [PATCH 07/20] Front-end: propagate specialization-constness through conversions and swizzles. --- glslang/Include/Types.h | 1 + glslang/MachineIndependent/Intermediate.cpp | 10 ++++++++-- glslang/MachineIndependent/ParseHelper.cpp | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 1d126569..05681c9a 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -740,6 +740,7 @@ public: } void makeSpecConstant() { + storage = EvqConst; specConstant = true; } static const char* getLayoutPackingString(TLayoutPacking packing) diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index bb4e14bc..777de2d6 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -262,6 +262,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo // // For constructors, we are now done, it was all in the conversion. + // TODO: but, did this bypass constant folding? // switch (op) { case EOpConstructInt: @@ -291,7 +292,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo if (child->getAsConstantUnion()) return child->getAsConstantUnion()->fold(op, node->getType()); - // If it's a specialiation constant, the result is too. + // If it's a specialization constant, the result is too. if (child->getType().getQualifier().isSpecConstant()) node->getWritableType().getQualifier().makeSpecConstant(); @@ -616,6 +617,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt newNode->setLoc(node->getLoc()); newNode->setOperand(node); + // TODO: it seems that some unary folding operations should occur here, but are not + + // Propagate specialization-constant-ness. + if (node->getType().getQualifier().isSpecConstant()) + newNode->getWritableType().getQualifier().makeSpecConstant(); + return newNode; } @@ -883,7 +890,6 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseT TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& loc) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); node->setLoc(loc); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index cd745a9d..d6f41151 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -820,6 +820,9 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm return result; else { TType type(base->getBasicType(), EvqTemporary, fields.num); + // Swizzle operations propagate specialization-constantness + if (base->getQualifier().isSpecConstant()) + type.getQualifier().makeSpecConstant(); return addConstructor(loc, base, type, mapTypeToConstructorOp(type)); } } @@ -837,6 +840,9 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int) vectorString.size())); } + // Swizzle operations propagate specialization-constantness + if (base->getType().getQualifier().isSpecConstant()) + result->getWritableType().getQualifier().makeSpecConstant(); } } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { const TTypeList* fields = base->getType().getStruct(); From a132af5b78914e4dadcd66a9e8837de10b3a3c9f Mon Sep 17 00:00:00 2001 From: Andrew Woloszyn Date: Mon, 7 Mar 2016 13:23:09 -0500 Subject: [PATCH 08/20] Updated the includer interface to allow relative includes. This plumbs both the current file path and the include depth back up to the includer. This allows the includer to properly support relative paths. This also replaces the string copy that was done during include with a zero-copy method of accomplishing the same thing. This prevents extra copies of entire files. --- StandAlone/StandAlone.cpp | 3 +- glslang/MachineIndependent/Scan.h | 53 +++++++++-- glslang/MachineIndependent/ShaderLang.cpp | 19 ++-- .../MachineIndependent/preprocessor/Pp.cpp | 26 +++--- .../preprocessor/PpContext.cpp | 6 +- .../preprocessor/PpContext.h | 87 +++++++++++++++---- glslang/Public/ShaderLang.h | 80 +++++++++++++++-- 7 files changed, 220 insertions(+), 54 deletions(-) diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index cc59d389..6ebdb7f5 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -699,8 +699,9 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionOutputPreprocessed) { std::string str; + glslang::TShader::ForbidInclude includer; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, - messages, &str, glslang::TShader::ForbidInclude())) { + messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); } else { CompileFailed = true; diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index 936b99f1..f3102fbf 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -51,10 +51,10 @@ const int EndOfInput = -1; // class TInputScanner { public: - TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0) : + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0, bool single = false) : numSources(n), sources(reinterpret_cast(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters - lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f) + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single) { loc = new TSourceLoc[numSources]; for (int i = 0; i < numSources; ++i) { @@ -67,6 +67,10 @@ public: loc[currentSource].string = -stringBias; loc[currentSource].line = 1; loc[currentSource].column = 0; + logicalSourceLoc.string = 0; + logicalSourceLoc.line = 1; + logicalSourceLoc.column = 0; + logicalSourceLoc.name = loc[0].name; } virtual ~TInputScanner() @@ -82,8 +86,11 @@ public: int ret = peek(); ++loc[currentSource].column; + ++logicalSourceLoc.column; if (ret == '\n') { ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; loc[currentSource].column = 0; } advance(); @@ -118,6 +125,7 @@ public: if (currentChar > 0) { --currentChar; --loc[currentSource].column; + --logicalSourceLoc.column; if (loc[currentSource].column < 0) { // We've moved back past a new line. Find the // previous newline (or start of the file) to compute @@ -129,6 +137,7 @@ public: } --chIndex; } + logicalSourceLoc.column = (int)(currentChar - chIndex); loc[currentSource].column = (int)(currentChar - chIndex); } } else { @@ -141,23 +150,49 @@ public: } else currentChar = lengths[currentSource] - 1; } - if (peek() == '\n') + if (peek() == '\n') { --loc[currentSource].line; + --logicalSourceLoc.line; + } } // for #line override - void setLine(int newLine) { loc[getLastValidSourceIndex()].line = newLine; } - void setFile(const char* filename) { loc[getLastValidSourceIndex()].name = filename; } + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + logicalSourceLoc.name = filename; + loc[getLastValidSourceIndex()].name = filename; + } + void setString(int newString) { + logicalSourceLoc.string = newString; loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; loc[getLastValidSourceIndex()].name = nullptr; } // for #include content indentation - void setColumn(int col) { loc[getLastValidSourceIndex()].column = col; } + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } - const TSourceLoc& getSourceLoc() const { return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; } + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } // Returns the index (starting from 0) of the most recent valid source string we are reading from. int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } @@ -204,6 +239,10 @@ protected: int stringBias; // the first string that is the user's string number 0 int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. }; } // end namespace glslang diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 1f835539..2a6e1e19 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -131,7 +131,8 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil TIntermediate intermediate(language, version, profile); TParseContext parseContext(symbolTable, intermediate, true, version, profile, spv, vulkan, language, infoSink); - TPpContext ppContext(parseContext, TShader::ForbidInclude()); + TShader::ForbidInclude includer; + TPpContext ppContext(parseContext, "", includer); TScanContext scanContext(parseContext); parseContext.setScanContext(&scanContext); parseContext.setPpContext(&ppContext); @@ -482,7 +483,7 @@ bool ProcessDeferred( TIntermediate& intermediate, // returned tree, etc. ProcessingContext& processingContext, bool requireNonempty, - const TShader::Includer& includer + TShader::Includer& includer ) { if (! InitThread()) @@ -550,7 +551,6 @@ bool ProcessDeferred( version = defaultVersion; profile = defaultProfile; } - int spv = (messages & EShMsgSpvRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, version, profile, spv); bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); @@ -590,7 +590,7 @@ bool ProcessDeferred( TParseContext parseContext(symbolTable, intermediate, false, version, profile, spv, vulkan, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages); glslang::TScanContext scanContext(parseContext); - TPpContext ppContext(parseContext, includer); + TPpContext ppContext(parseContext, names[numPre]? names[numPre]: "", includer); parseContext.setScanContext(&scanContext); parseContext.setPpContext(&ppContext); parseContext.setLimits(*resources); @@ -863,7 +863,7 @@ bool PreprocessDeferred( bool forceDefaultVersionAndProfile, bool forwardCompatible, // give errors for use of deprecated features EShMessages messages, // warnings/errors/AST; things to print out - const TShader::Includer& includer, + TShader::Includer& includer, TIntermediate& intermediate, // returned tree, etc. std::string* outputString) { @@ -902,7 +902,7 @@ bool CompileDeferred( bool forwardCompatible, // give errors for use of deprecated features EShMessages messages, // warnings/errors/AST; things to print out TIntermediate& intermediate,// returned tree, etc. - const TShader::Includer& includer) + TShader::Includer& includer) { DoFullParse parser; return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, @@ -1051,9 +1051,10 @@ int ShCompile( compiler->infoSink.debug.erase(); TIntermediate intermediate(compiler->getLanguage()); + TShader::ForbidInclude includer; bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, "", optLevel, resources, defaultVersion, ENoProfile, false, - forwardCompatible, messages, intermediate, TShader::ForbidInclude()); + forwardCompatible, messages, intermediate, includer); // // Call the machine dependent compiler @@ -1361,7 +1362,7 @@ void TShader::setStringsWithLengthsAndNames( // Returns true for success. // bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages, const Includer& includer) + bool forwardCompatible, EShMessages messages, Includer& includer) { if (! InitThread()) return false; @@ -1389,7 +1390,7 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, std::string* output_string, - const TShader::Includer& includer) + Includer& includer) { if (! InitThread()) return false; diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index 9a33a776..ed554359 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -611,24 +611,28 @@ int TPpContext::CPPinclude(TPpToken* ppToken) if (token != '\n' && token != EndOfInput) { parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", ""); } else { - auto include = includer.include(filename.c_str()); - std::string sourceName = include.first; - std::string replacement = include.second; - if (!sourceName.empty()) { - if (!replacement.empty()) { + TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1); + if (res && !res->file_name.empty()) { + if (res->file_data && res->file_length) { const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); - std::ostringstream content; - content << "#line " << forNextLine << " " << "\"" << sourceName << "\"\n"; - content << replacement << (replacement.back() == '\n' ? "" : "\n"); - content << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; - pushInput(new TokenizableString(directiveLoc, content.str(), this)); + std::ostringstream prologue; + std::ostringstream epilogue; + prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n"; + epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; + pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); } // At EOF, there's no "current" location anymore. if (token != EndOfInput) parseContext.setCurrentColumn(0); // Don't accidentally return EndOfInput, which will end all preprocessing. return '\n'; } else { - parseContext.ppError(directiveLoc, replacement.c_str(), "#include", ""); + std::string message = + res ? std::string(res->file_data, res->file_length) + : std::string("Could not process include directive"); + parseContext.ppError(directiveLoc, message.c_str(), "#include", ""); + if (res) { + includer.releaseInclude(res); + } } } } diff --git a/glslang/MachineIndependent/preprocessor/PpContext.cpp b/glslang/MachineIndependent/preprocessor/PpContext.cpp index b8d2c737..37c2a5f2 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ b/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -83,8 +83,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace glslang { -TPpContext::TPpContext(TParseContext& pc, const TShader::Includer& inclr) : - preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false) +TPpContext::TPpContext(TParseContext& pc, const std::string& rootFileName, TShader::Includer& inclr) : + preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false), + rootFileName(rootFileName), + currentSourceFile(rootFileName) { InitAtomTable(); InitScanner(); diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index f1d54691..113215bd 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -78,6 +78,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PPCONTEXT_H #define PPCONTEXT_H +#include #include #include "../ParseHelper.h" @@ -121,7 +122,7 @@ class TInputScanner; // Don't expect too much in terms of OO design. class TPpContext { public: - TPpContext(TParseContext&, const TShader::Includer&); + TPpContext(TParseContext&, const std::string& rootFileName, TShader::Includer&); virtual ~TPpContext(); void setPreamble(const char* preamble, size_t length); @@ -290,7 +291,7 @@ protected: // // Used to obtain #include content. - const TShader::Includer& includer; + TShader::Includer& includer; int InitCPP(); int CPPdefine(TPpToken * ppToken); @@ -430,16 +431,30 @@ protected: TInputScanner* input; }; - // Holds a string that can be tokenized via the tInput interface. - class TokenizableString : public tInput { + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { public: - // Copies str, which must be non-empty. - TokenizableString(const TSourceLoc& startLoc, const std::string& str, TPpContext* pp) + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) : tInput(pp), - str_(str), - strings(str_.data()), - length(str_.size()), - scanner(1, &strings, &length), + prologue_(prologue), + includedFile_(includedFile), + epilogue_(epilogue), + strings({prologue_.data(), includedFile_->file_data, epilogue_.data()}), + lengths({prologue_.size(), includedFile_->file_length, epilogue_.size()}), + names({ + includedFile_->file_name.c_str(), + includedFile_->file_name.c_str(), + includedFile_->file_name.c_str() + }), + scanner(3, strings, lengths, names, 0, 0, true), prevScanner(nullptr), stringInput(pp, scanner) { scanner.setLine(startLoc.line); @@ -456,16 +471,34 @@ protected: { prevScanner = pp->parseContext.getScanner(); pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); } - void notifyDeleted() override { pp->parseContext.setScanner(prevScanner); } private: - // Stores the titular string. - const std::string str_; - // Will point to str_[0] and be passed to scanner constructor. - const char* const strings; + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->file_data and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; // Length of str_, passed to scanner constructor. - size_t length; + size_t lengths[3]; + // String names + const char* names[3]; // Scans over str_. TInputScanner scanner; // The previous effective scanner before the scanner in this instance @@ -480,6 +513,24 @@ protected: void missingEndifCheck(); int lFloatConst(int len, int ch, TPpToken* ppToken); + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->file_name; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->file_name; + } + } + bool inComment; // @@ -487,8 +538,12 @@ protected: // typedef TUnorderedMap TAtomMap; typedef TVector TStringMap; + TAtomMap atomMap; TStringMap stringMap; + std::stack includeStack; + std::string currentSourceFile; + std::string rootFileName; int nextAtom; void InitAtomTable(); void AddAtomFixed(const char* s, int atom); diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 702b66f4..0771d194 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -292,25 +292,89 @@ public: void setPreamble(const char* s) { preamble = s; } // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. class Includer { public: - // On success, returns the full path and content of the file with the given - // filename that replaces "#include filename". On failure, returns an empty - // string and an error message. - virtual std::pair include(const char* filename) const = 0; + typedef enum { + EIncludeRelative, // For #include "something" + EIncludeStandard // Reserved. For #include + } IncludeType; + + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a filesystem-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + std::string file_name; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the file_data + // field points to a string containing error details. + const char* file_data; + const size_t file_length; + // Include resolver's context. + void* user_data; + }; + + // Resolves an inclusion request by name, type, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. On failure, returns an IncludeResult + // with an empty string for the file_name and error details in the + // file_data field. The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + virtual IncludeResult* include(const char* requested_source, + IncludeType type, + const char* requesting_source, + size_t inclusion_depth) = 0; + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult* result) = 0; }; // Returns an error message for any #include directive. class ForbidInclude : public Includer { public: - std::pair include(const char* /*filename*/) const override + IncludeResult* include(const char*, IncludeType, const char*, size_t) override { - return std::make_pair("", "unexpected include directive"); + static const char unexpected_include[] = + "unexpected include directive"; + return new IncludeResult( + {"", unexpected_include, sizeof(unexpected_include) - 1, nullptr}); + } + virtual void releaseInclude(IncludeResult* result) override + { + delete result; } }; + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidInclude includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages, const Includer& = ForbidInclude()); + bool forwardCompatible, EShMessages, Includer&); // Equivalent to parse() without a default profile and without forcing defaults. // Provided for backwards compatibility. @@ -318,7 +382,7 @@ public: bool preprocess(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, std::string* outputString, - const TShader::Includer& includer); + Includer& includer); const char* getInfoLog(); const char* getInfoDebugLog(); From ddb65a46f7d851c2c94e3544eeff3877ae4c8fde Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Mon, 21 Mar 2016 12:55:00 -0600 Subject: [PATCH 09/20] Front-end: Propagate spec-constness up through aggregate constructors. --- glslang/MachineIndependent/ParseHelper.cpp | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index d6f41151..13296318 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2210,7 +2210,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T int size = 0; bool constType = true; - bool specConstType = true; + bool specConstType = false; // value is only valid if constType is true bool full = false; bool overFull = false; bool matrixInMatrix = false; @@ -2241,14 +2241,15 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T if (! function[arg].type->getQualifier().isConstant()) constType = false; - if (! function[arg].type->getQualifier().isSpecConstant()) - specConstType = false; + if (function[arg].type->getQualifier().isSpecConstant()) + specConstType = true; } if (constType) { - type.getQualifier().storage = EvqConst; if (specConstType) - type.getQualifier().specConstant = true; + type.getQualifier().makeSpecConstant(); + else + type.getQualifier().storage = EvqConst; } if (type.isArray()) { @@ -5101,12 +5102,16 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* // if the structure constructor contains more than one parameter, then construct // each parameter - int paramCount = 0; // keeps a track of the constructor parameter number being checked + int paramCount = 0; // keeps track of the constructor parameter number being checked // for each parameter to the constructor call, check to see if the right type is passed or convert them // to the right type if possible (and allowed). // for structure constructors, just check if the right type is passed, no conversion is allowed. + // We don't know "top down" whether type is a specialization constant, + // but a const becomes a specialization constant if any of its children are. + bool specConst = false; + for (TIntermSequence::iterator p = sequenceVector.begin(); p != sequenceVector.end(); p++, paramCount++) { if (type.isArray()) @@ -5116,13 +5121,17 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* else newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - if (newNode) + if (newNode) { *p = newNode; - else + if (newNode->getType().getQualifier().isSpecConstant()) + specConst = true; + } else return nullptr; } TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); + if (constructor->getType().getQualifier().isConstant() && specConst) + constructor->getWritableType().getQualifier().makeSpecConstant(); return constructor; } From 272afd2d0ae76b372f3896f47418623aa645c006 Mon Sep 17 00:00:00 2001 From: Andrew Woloszyn Date: Mon, 21 Mar 2016 15:56:31 -0400 Subject: [PATCH 10/20] Fixed compilation issue introduced by my last commit --- glslang/MachineIndependent/Scan.h | 8 ++++++ .../preprocessor/PpContext.h | 27 +++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index f3102fbf..219049be 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -170,6 +170,14 @@ public: loc[getLastValidSourceIndex()].name = filename; } + void setFile(const char* filename, size_t i) + { + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = filename; + } + loc[i].name = filename; + } + void setString(int newString) { logicalSourceLoc.string = newString; diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index 113215bd..b68c6916 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -447,19 +447,24 @@ protected: prologue_(prologue), includedFile_(includedFile), epilogue_(epilogue), - strings({prologue_.data(), includedFile_->file_data, epilogue_.data()}), - lengths({prologue_.size(), includedFile_->file_length, epilogue_.size()}), - names({ - includedFile_->file_name.c_str(), - includedFile_->file_name.c_str(), - includedFile_->file_name.c_str() - }), scanner(3, strings, lengths, names, 0, 0, true), prevScanner(nullptr), - stringInput(pp, scanner) { - scanner.setLine(startLoc.line); - scanner.setString(startLoc.string); - scanner.setFile(startLoc.name); + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->file_data; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->file_length; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.name, 0); + scanner.setFile(startLoc.name, 1); + scanner.setFile(startLoc.name, 2); } // tInput methods: From 4e8bf59778f850b7ac9e6dc84820649f50981470 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Tue, 22 Mar 2016 15:42:07 +0800 Subject: [PATCH 11/20] Parser: Fix a build issue (VS2012). --- glslang/Public/ShaderLang.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 0771d194..c9182618 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -357,8 +357,9 @@ public: { static const char unexpected_include[] = "unexpected include directive"; - return new IncludeResult( - {"", unexpected_include, sizeof(unexpected_include) - 1, nullptr}); + static const IncludeResult unexpectedIncludeResult = + {"", unexpected_include, sizeof(unexpected_include) - 1, nullptr}; + return new IncludeResult(unexpectedIncludeResult); } virtual void releaseInclude(IncludeResult* result) override { From 0840838d1739f2d5ebfe2037f4c6f09478710689 Mon Sep 17 00:00:00 2001 From: qining Date: Mon, 21 Mar 2016 09:51:37 -0400 Subject: [PATCH 12/20] Support specialization composite constants Fix issue #163, support creation and reference of composite type specialization constants. e.g.: ``` layout(constant_id = 200) const float myfloat = 1.25; layout(constant_id = 201) const int myint = 14; struct structtype { float f; int i; }; const structtype outer_struct_var = {myfloat, myint}; void main(){} ``` generated code (use glslangValidator): ``` // Module Version 10000 // Generated by (magic number): 80001 // Id's are bound by 12 Capability Shader 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" Source GLSL 450 Name 4 "main" Name 10 "structtype" MemberName 10(structtype) 0 "f" MemberName 10(structtype) 1 "i" Decorate 7 SpecId 200 Decorate 9 SpecId 201 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 7: 6(float) SpecConstant 1067450368 8: TypeInt 32 1 9: 8(int) SpecConstant 14 10(structtype): TypeStruct 6(float) 8(int) 11:10(structtype) SpecConstantComposite 7 9 4(main): 2 Function None 3 5: Label Return FunctionEnd ``` Rname two function names to match their functionalities. 1) Rename `GlslangToSpvTraverser::createSpvSpecConstant()` to `createSpvConstant()`; 2) Rename `GlslangToSpvTraverser::createSpvConstant()` to `createSpvConstantFromConstUnionArray()` Add function `GlslangToSpvTraverser::createSpvConstantFromSubTree()` to handle constant creation from sub trees (e.g.: specialization constants). Related PR: #208 --- SPIRV/GlslangToSpv.cpp | 87 +++++++-- .../spv.specConstantComposite.vert.out | 172 ++++++++++++++++++ Test/spv.specConstantComposite.vert | 93 ++++++++++ Test/test-spirv-list | 1 + glslang/Include/Types.h | 1 + glslang/MachineIndependent/ParseHelper.cpp | 27 ++- 6 files changed, 362 insertions(+), 19 deletions(-) create mode 100644 Test/baseResults/spv.specConstantComposite.vert.out create mode 100644 Test/spv.specConstantComposite.vert diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 6f5697e3..dd5afd4b 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -128,8 +128,9 @@ protected: void addDecoration(spv::Id id, spv::Decoration dec, unsigned value); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); - spv::Id createSpvSpecConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstant(const glslang::TIntermTyped&); + spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstantFromConstSubTree(const glslang::TIntermTyped* subTree); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); @@ -1520,7 +1521,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) { int nextConst = 0; - spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false); + spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); builder.clearAccessChain(); builder.setAccessChainRValue(constant); @@ -1630,7 +1631,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* // can still have a mapping to a SPIR-V Id. // This includes specialization constants. if (node->getQualifier().isConstant()) { - return createSpvSpecConstant(*node); + return createSpvConstant(*node); } // Now, handle actual variables @@ -3730,7 +3731,7 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De // recursively walks. So, this function walks the "top" of the tree: // - emit specialization constant-building instructions for specConstant // - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node) +spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) { assert(node.getQualifier().isConstant()); @@ -3738,7 +3739,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType // hand off to the non-spec-constant path assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); int nextConst = 0; - return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, false); } @@ -3747,7 +3748,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) { // this is a direct literal assigned to a layout(constant_id=) declaration int nextConst = 0; - return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, true); } else { // gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants, @@ -3761,8 +3762,10 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); } return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); + } else if (auto* sn = node.getAsSymbolNode()){ + return createSpvConstantFromConstSubTree(sn->getConstSubtree()); } else { - spv::MissingFunctionality("specialization-constant expression trees"); + spv::MissingFunctionality("Neither a front-end constant nor a spec constant."); exit(1); return spv::NoResult; } @@ -3775,7 +3778,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType // If there are not enough elements present in 'consts', 0 will be substituted; // an empty 'consts' can be used to create a fully zeroed SPIR-V constant. // -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) { // vector of constants for SPIR-V std::vector spvConsts; @@ -3786,15 +3789,15 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT if (glslangType.isArray()) { glslang::TType elementType(glslangType, 0); for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); } else if (glslangType.isMatrix()) { glslang::TType vectorType(glslangType, 0); for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); } else if (glslangType.getStruct()) { glslang::TVector::const_iterator iter; for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); } else if (glslangType.isVector()) { for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { bool zero = nextConst >= consts.size(); @@ -3851,6 +3854,66 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT return builder.makeCompositeConstant(typeId, spvConsts); } +// Create constant ID from const initializer sub tree. +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( + const glslang::TIntermTyped* subTree) { + const glslang::TType& glslangType = subTree->getType(); + spv::Id typeId = convertGlslangToSpvType(glslangType); + bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); + if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { + // Aggregate node, we should generate OpConstantComposite or + // OpSpecConstantComposite instruction. + std::vector const_constituents; + for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); + NI++) { + const_constituents.push_back( + createSpvConstantFromConstSubTree((*NI)->getAsTyped())); + } + // Note that constructors are aggregate nodes, so expressions like: + // float x = float(y) will become an aggregate node. If 'x' is declared + // as a constant, the aggregate node representing 'float(y)' will be + // processed here. + if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) || + builder.isAggregateType(typeId)) { + return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const); + } else { + assert(builder.isScalarType(typeId) && const_constituents.size() == 1); + return const_constituents.front(); + } + + } else if (const glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { + // Binary operation node, we should generate OpSpecConstantOp + // This case should only happen when Specialization Constants are involved. + spv::MissingFunctionality("OpSpecConstantOp not implemented"); + return spv::NoResult; + + } else if (const glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { + // Unary operation node, similar to binary operation node, should only + // happen when specialization constants are involved. + spv::MissingFunctionality("OpSpecConstantOp not implemented"); + return spv::NoResult; + + } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) { + // ConstantUnion node, should redirect to + // createSpvConstantFromConstUnionArray + int nextConst = 0; + return createSpvConstantFromConstUnionArray( + glslangType, cn->getConstArray(), nextConst, is_spec_const); + + } else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) { + // Symbol node. Call getSymbolId(). This should cover both cases 1) the + // symbol has already been assigned an ID, 2) need a new ID for this + // symbol. + return getSymbolId(sn); + + } else { + spv::MissingFunctionality( + "createSpvConstantFromConstSubTree() not covered TIntermTyped* const " + "initializer subtree."); + return spv::NoResult; + } +} + // Return true if the node is a constant or symbol whose reading has no // non-trivial observable cost or effect. bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) diff --git a/Test/baseResults/spv.specConstantComposite.vert.out b/Test/baseResults/spv.specConstantComposite.vert.out new file mode 100644 index 00000000..5e2dfa4a --- /dev/null +++ b/Test/baseResults/spv.specConstantComposite.vert.out @@ -0,0 +1,172 @@ +spv.specConstantComposite.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked vertex stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 106 + + Capability Shader + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 27 105 + Source GLSL 450 + Name 4 "main" + Name 6 "refer_primary_spec_const(" + Name 8 "refer_composite_spec_const(" + Name 10 "refer_copmosite_dot_dereference(" + Name 12 "refer_composite_bracket_dereference(" + Name 16 "refer_spec_const_array_length(" + Name 18 "declare_spec_const_in_func(" + Name 27 "color" + Name 41 "flat_struct" + MemberName 41(flat_struct) 0 "i" + MemberName 41(flat_struct) 1 "f" + MemberName 41(flat_struct) 2 "d" + MemberName 41(flat_struct) 3 "b" + Name 42 "nesting_struct" + MemberName 42(nesting_struct) 0 "nested" + MemberName 42(nesting_struct) 1 "v" + MemberName 42(nesting_struct) 2 "i" + Name 72 "indexable" + Name 76 "indexable" + Name 83 "len" + Name 105 "global_vec4_array_with_spec_length" + Decorate 21 SpecId 203 + Decorate 28 SpecId 200 + Decorate 32 SpecId 201 + Decorate 43 SpecId 202 + 2: TypeVoid + 3: TypeFunction 2 + 14: TypeInt 32 1 + 15: TypeFunction 14(int) + 20: TypeBool + 21: 20(bool) SpecConstantTrue + 24: TypeFloat 32 + 25: TypeVector 24(float) 4 + 26: TypePointer Output 25(fvec4) + 27(color): 26(ptr) Variable Output + 28: 14(int) SpecConstant 3 + 32: 24(float) SpecConstant 1078523331 + 33: 25(fvec4) SpecConstantComposite 32 32 32 32 + 36: 24(float) Constant 1133908460 + 37: 25(fvec4) SpecConstantComposite 32 32 36 36 + 40: TypeFloat 64 + 41(flat_struct): TypeStruct 14(int) 24(float) 40(float) 20(bool) +42(nesting_struct): TypeStruct 41(flat_struct) 25(fvec4) 14(int) + 43: 40(float) SpecConstant 1413754136 1074340347 + 44:41(flat_struct) SpecConstantComposite 28 32 43 21 + 45:42(nesting_struct) SpecConstantComposite 44 33 28 + 46: 14(int) Constant 2 + 51: TypeInt 32 0 + 52: 51(int) Constant 0 + 57: 51(int) Constant 5 + 58: TypeArray 24(float) 57 + 59: 24(float) Constant 1065353216 + 60: 24(float) Constant 1073741824 + 61: 24(float) Constant 1077936128 + 62: 58 SpecConstantComposite 32 32 59 60 61 + 63: 14(int) Constant 1 + 68: TypeArray 14(int) 57 + 69: 14(int) Constant 30 + 70: 68 SpecConstantComposite 28 28 63 46 69 + 71: TypePointer Function 68 + 73: TypePointer Function 14(int) + 87: 24(float) Constant 1106321080 + 88:41(flat_struct) SpecConstantComposite 69 87 43 21 + 89: 14(int) Constant 10 + 90:42(nesting_struct) SpecConstantComposite 88 37 89 + 96: 20(bool) ConstantFalse + 97:41(flat_struct) SpecConstantComposite 28 32 43 96 + 98: 24(float) Constant 1036831949 + 99: 25(fvec4) ConstantComposite 98 98 98 98 + 100:42(nesting_struct) SpecConstantComposite 97 99 28 + 101: 14(int) Constant 3000 + 102:42(nesting_struct) SpecConstantComposite 88 37 101 + 103: TypeArray 25(fvec4) 28 + 104: TypePointer Input 103 +105(global_vec4_array_with_spec_length): 104(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd +6(refer_primary_spec_const(): 2 Function None 3 + 7: Label + SelectionMerge 23 None + BranchConditional 21 22 23 + 22: Label + 29: 24(float) ConvertSToF 28 + 30: 25(fvec4) Load 27(color) + 31: 25(fvec4) VectorTimesScalar 30 29 + Store 27(color) 31 + Branch 23 + 23: Label + Return + FunctionEnd +8(refer_composite_spec_const(): 2 Function None 3 + 9: Label + 34: 25(fvec4) Load 27(color) + 35: 25(fvec4) FAdd 34 33 + Store 27(color) 35 + 38: 25(fvec4) Load 27(color) + 39: 25(fvec4) FSub 38 37 + Store 27(color) 39 + Return + FunctionEnd +10(refer_copmosite_dot_dereference(): 2 Function None 3 + 11: Label + 47: 14(int) CompositeExtract 45 2 + 48: 24(float) ConvertSToF 47 + 49: 25(fvec4) Load 27(color) + 50: 25(fvec4) VectorTimesScalar 49 48 + Store 27(color) 50 + 53: 24(float) CompositeExtract 33 0 + 54: 25(fvec4) Load 27(color) + 55: 25(fvec4) CompositeConstruct 53 53 53 53 + 56: 25(fvec4) FAdd 54 55 + Store 27(color) 56 + Return + FunctionEnd +12(refer_composite_bracket_dereference(): 2 Function None 3 + 13: Label + 72(indexable): 71(ptr) Variable Function + 76(indexable): 71(ptr) Variable Function + 64: 24(float) CompositeExtract 62 1 + 65: 25(fvec4) Load 27(color) + 66: 25(fvec4) CompositeConstruct 64 64 64 64 + 67: 25(fvec4) FSub 65 66 + Store 27(color) 67 + Store 72(indexable) 70 + 74: 73(ptr) AccessChain 72(indexable) 28 + 75: 14(int) Load 74 + Store 76(indexable) 70 + 77: 73(ptr) AccessChain 76(indexable) 75 + 78: 14(int) Load 77 + 79: 24(float) ConvertSToF 78 + 80: 25(fvec4) Load 27(color) + 81: 25(fvec4) CompositeConstruct 79 79 79 79 + 82: 25(fvec4) FDiv 80 81 + Store 27(color) 82 + Return + FunctionEnd +16(refer_spec_const_array_length(): 14(int) Function None 15 + 17: Label + 83(len): 73(ptr) Variable Function + Store 83(len) 28 + 84: 14(int) Load 83(len) + ReturnValue 84 + FunctionEnd +18(declare_spec_const_in_func(): 2 Function None 3 + 19: Label + 91: 14(int) CompositeExtract 90 2 + 92: 24(float) ConvertSToF 91 + 93: 25(fvec4) Load 27(color) + 94: 25(fvec4) CompositeConstruct 92 92 92 92 + 95: 25(fvec4) FDiv 93 94 + Store 27(color) 95 + Return + FunctionEnd diff --git a/Test/spv.specConstantComposite.vert b/Test/spv.specConstantComposite.vert new file mode 100644 index 00000000..4450ddd6 --- /dev/null +++ b/Test/spv.specConstantComposite.vert @@ -0,0 +1,93 @@ +#version 450 + +// constant_id specified scalar spec constants +layout(constant_id = 200) const int spec_int = 3; +layout(constant_id = 201) const float spec_float = 3.14; +layout(constant_id = 202) const + double spec_double = 3.1415926535897932384626433832795; +layout(constant_id = 203) const bool spec_bool = true; + +const float cast_spec_float = float(spec_float); + +// Flat struct +struct flat_struct { + int i; + float f; + double d; + bool b; +}; + +// Nesting struct +struct nesting_struct { + flat_struct nested; + vec4 v; + int i; +}; + +// Expect OpSpecConstantComposite +// Flat struct initializer +const flat_struct spec_flat_struct_all_spec = {spec_int, spec_float, + spec_double, spec_bool}; +const flat_struct spec_flat_struct_partial_spec = {30, 30.14, spec_double, + spec_bool}; + +// Nesting struct initializer +const nesting_struct nesting_struct_ctor = { + {spec_int, spec_float, spec_double, false}, + vec4(0.1, 0.1, 0.1, 0.1), + spec_int}; + +// Vector constructor +const vec4 spec_vec4_all_spec = + vec4(spec_float, spec_float, spec_float, spec_float); +const vec4 spec_vec4_partial_spec = + vec4(spec_float, spec_float, 300.14, 300.14); + +// Struct nesting constructor +const nesting_struct spec_nesting_struct_all_spec = { + spec_flat_struct_all_spec, spec_vec4_all_spec, spec_int}; +const nesting_struct spec_nesting_struct_partial_spec = { + spec_flat_struct_partial_spec, spec_vec4_partial_spec, 3000}; + +const float spec_float_array[5] = {spec_float, spec_float, 1.0, 2.0, 3.0}; +const int spec_int_array[5] = {spec_int, spec_int, 1, 2, 30}; + +// global_vec4_array_with_spec_length is not a spec constant, but its array +// size is. When calling global_vec4_array_with_spec_length.length(), A +// TIntermSymbol Node shoule be returned, instead of a TIntermConstantUnion +// node which represents a known constant value. +in vec4 global_vec4_array_with_spec_length[spec_int]; + +out vec4 color; + +void refer_primary_spec_const() { + if (spec_bool) color *= spec_int; +} + +void refer_composite_spec_const() { + color += spec_vec4_all_spec; + color -= spec_vec4_partial_spec; +} + +void refer_copmosite_dot_dereference() { + color *= spec_nesting_struct_all_spec.i; + color += spec_vec4_all_spec.x; +} + +void refer_composite_bracket_dereference() { + color -= spec_float_array[1]; + color /= spec_int_array[spec_int_array[spec_int]]; +} + +int refer_spec_const_array_length() { + int len = global_vec4_array_with_spec_length.length(); + return len; +} + +void declare_spec_const_in_func() { + const nesting_struct spec_const_declared_in_func = { + spec_flat_struct_partial_spec, spec_vec4_partial_spec, 10}; + color /= spec_const_declared_in_func.i; +} + +void main() {} diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 0e223674..4534132f 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -102,6 +102,7 @@ spv.pushConstant.vert spv.subpass.frag spv.specConstant.vert spv.specConstant.comp +spv.specConstantComposite.vert # GLSL-level semantics vulkan.frag vulkan.vert diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 05681c9a..bff7e9a9 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -1223,6 +1223,7 @@ public: virtual int getMatrixCols() const { return matrixCols; } virtual int getMatrixRows() const { return matrixRows; } virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 13296318..5de89e1b 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -484,7 +484,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn TIntermTyped* result = nullptr; int indexValue = 0; - if (index->getQualifier().isConstant()) { + if (index->getQualifier().isFrontEndConstant()) { indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); checkIndex(loc, base->getType(), indexValue); } @@ -503,7 +503,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) handleIoResizeArrayAccess(loc, base); - if (index->getQualifier().isConstant()) { + if (index->getQualifier().isFrontEndConstant()) { if (base->getType().isImplicitlySizedArray()) updateImplicitArraySize(loc, base, indexValue); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); @@ -541,10 +541,15 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn } else { // Insert valid dereferenced result TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) + if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { newType.getQualifier().storage = EvqConst; - else + // If base or index is a specialization constant, the result should also be a specialization constant. + if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { + newType.getQualifier().makeSpecConstant(); + } + } else { newType.getQualifier().makePartialTemporary(); + } result->setType(newType); if (anyIndexLimits) @@ -1226,6 +1231,11 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction else error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); } + } else if (type.getOuterArrayNode()) { + // If the array's outer size is specified by an intermediate node, it means the array's length + // was specified by a specialization constant. In such a case, we should return the node of the + // specialization constants to represent the length. + return type.getOuterArrayNode(); } else length = type.getOuterArraySize(); } else if (type.isMatrix()) @@ -5110,7 +5120,8 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* // We don't know "top down" whether type is a specialization constant, // but a const becomes a specialization constant if any of its children are. - bool specConst = false; + bool hasSpecConst = false; + bool isConstConstrutor = true; for (TIntermSequence::iterator p = sequenceVector.begin(); p != sequenceVector.end(); p++, paramCount++) { @@ -5123,14 +5134,16 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* if (newNode) { *p = newNode; + if (! newNode->getType().getQualifier().isConstant()) + isConstConstrutor = false; if (newNode->getType().getQualifier().isSpecConstant()) - specConst = true; + hasSpecConst = true; } else return nullptr; } TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); - if (constructor->getType().getQualifier().isConstant() && specConst) + if (isConstConstrutor && hasSpecConst) constructor->getWritableType().getQualifier().makeSpecConstant(); return constructor; From cb0e471ad4e24a9ec655edf77c08f9e38dda5f39 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Sun, 27 Mar 2016 08:42:23 +0800 Subject: [PATCH 13/20] Parser: Update array size of gl_ClipDistance/gl_CullDistance in gl_in[]. --- Test/baseResults/150.geom.out | 16 +- Test/baseResults/150.tesc.out | 106 ++++---- Test/baseResults/400.tesc.out | 34 +-- Test/baseResults/400.tese.out | 16 +- Test/baseResults/420.tesc.out | 14 +- Test/baseResults/450.geom.out | 8 +- Test/baseResults/450.tesc.out | 16 +- Test/baseResults/450.tese.out | 8 +- Test/baseResults/spv.400.tesc.out | 273 +++++++++++---------- Test/baseResults/spv.400.tese.out | 132 +++++----- glslang/MachineIndependent/ParseHelper.cpp | 24 +- 11 files changed, 330 insertions(+), 317 deletions(-) diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out index aa00868d..48b7925f 100644 --- a/Test/baseResults/150.geom.out +++ b/Test/baseResults/150.geom.out @@ -215,9 +215,9 @@ ERROR: node is still EOpNull! 0:33 Constant: 0:33 3 (const int) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -230,8 +230,8 @@ ERROR: node is still EOpNull! 0:34 Constant: 0:34 0 (const uint) 0:34 gl_Position: direct index for structure (in 4-component vector of float Position) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 0 (const int) 0:34 Constant: @@ -242,8 +242,8 @@ ERROR: node is still EOpNull! 0:35 Constant: 0:35 1 (const uint) 0:35 gl_PointSize: direct index for structure (in float PointSize) -0:35 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:35 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:35 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:35 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:35 Constant: 0:35 3 (const int) 0:35 Constant: @@ -293,7 +293,7 @@ ERROR: node is still EOpNull! 0:? 'toF' (layout(stream=0 ) out block{layout(stream=0 ) out 3-component vector of float color}) 0:? 'anon@0' (layout(stream=0 ) out block{layout(stream=0 ) out 3-component vector of float color}) 0:? 'anon@1' (layout(stream=0 ) out block{layout(stream=0 ) gl_Position 4-component vector of float Position gl_Position, layout(stream=0 ) gl_PointSize float PointSize gl_PointSize, layout(stream=0 ) out 4-element array of float ClipDistance gl_ClipDistance}) -0:? 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ov0' (layout(stream=0 ) out 4-component vector of float) 0:? 'ov4' (layout(stream=4 ) out 4-component vector of float) 0:? 'o1v0' (layout(stream=0 ) out 4-component vector of float) diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out index a5289c93..8b7ab7dc 100644 --- a/Test/baseResults/150.tesc.out +++ b/Test/baseResults/150.tesc.out @@ -932,8 +932,8 @@ vertices = 4 0:20 move second child to first child (temp 4-component vector of float) 0:20 'p' (temp 4-component vector of float) 0:20 gl_Position: direct index for structure (in 4-component vector of float Position) -0:20 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:20 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:20 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:20 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:20 Constant: 0:20 1 (const int) 0:20 Constant: @@ -942,8 +942,8 @@ vertices = 4 0:21 move second child to first child (temp float) 0:21 'ps' (temp float) 0:21 gl_PointSize: direct index for structure (in float PointSize) -0:21 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:21 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:21 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:21 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:21 Constant: 0:21 1 (const int) 0:21 Constant: @@ -952,9 +952,9 @@ vertices = 4 0:22 move second child to first child (temp float) 0:22 'cd' (temp float) 0:22 direct index (temp float ClipDistance) -0:22 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:22 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:22 Constant: 0:22 1 (const int) 0:22 Constant: @@ -975,25 +975,25 @@ vertices = 4 0:26 'gl_InvocationID' (in int InvocationID) 0:28 move second child to first child (temp 4-component vector of float) 0:28 gl_Position: direct index for structure (out 4-component vector of float Position) -0:28 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:28 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:28 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:28 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:28 'gl_InvocationID' (in int InvocationID) 0:28 Constant: 0:28 0 (const int) 0:28 'p' (temp 4-component vector of float) 0:29 move second child to first child (temp float) 0:29 gl_PointSize: direct index for structure (out float PointSize) -0:29 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:29 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:29 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:29 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:29 'gl_InvocationID' (in int InvocationID) 0:29 Constant: 0:29 1 (const int) 0:29 'ps' (temp float) 0:30 move second child to first child (temp float) 0:30 direct index (temp float ClipDistance) -0:30 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:30 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:30 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:30 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:30 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:30 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:30 'gl_InvocationID' (in int InvocationID) 0:30 Constant: 0:30 2 (const int) @@ -1027,8 +1027,8 @@ vertices = 4 0:23 move second child to first child (temp 4-component vector of float) 0:23 'p' (temp 4-component vector of float) 0:23 gl_Position: direct index for structure (in 4-component vector of float Position) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -1037,8 +1037,8 @@ vertices = 4 0:24 move second child to first child (temp float) 0:24 'ps' (temp float) 0:24 gl_PointSize: direct index for structure (in float PointSize) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -1047,9 +1047,9 @@ vertices = 4 0:25 move second child to first child (temp float) 0:25 'cd' (temp float) 0:25 direct index (temp float ClipDistance) -0:25 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:25 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:25 Constant: 0:25 1 (const int) 0:25 Constant: @@ -1070,25 +1070,25 @@ vertices = 4 0:29 'gl_InvocationID' (in int InvocationID) 0:31 move second child to first child (temp 4-component vector of float) 0:31 gl_Position: direct index for structure (out 4-component vector of float Position) -0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:31 'gl_InvocationID' (in int InvocationID) 0:31 Constant: 0:31 0 (const int) 0:31 'p' (temp 4-component vector of float) 0:32 move second child to first child (temp float) 0:32 gl_PointSize: direct index for structure (out float PointSize) -0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:32 'gl_InvocationID' (in int InvocationID) 0:32 Constant: 0:32 1 (const int) 0:32 'ps' (temp float) 0:33 move second child to first child (temp float) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:33 'gl_InvocationID' (in int InvocationID) 0:33 Constant: 0:33 2 (const int) @@ -1158,8 +1158,8 @@ vertices = 4 0:67 Function Parameters: 0:69 Sequence 0:69 gl_PointSize: direct index for structure (out float PointSize) -0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:69 Constant: 0:69 4 (const int) 0:69 Constant: @@ -1192,8 +1192,8 @@ vertices = 4 0:17 move second child to first child (temp 4-component vector of float) 0:17 'p' (temp 4-component vector of float) 0:17 gl_Position: direct index for structure (in 4-component vector of float Position) -0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:17 Constant: 0:17 1 (const int) 0:17 Constant: @@ -1202,8 +1202,8 @@ vertices = 4 0:18 move second child to first child (temp float) 0:18 'ps' (temp float) 0:18 gl_PointSize: direct index for structure (in float PointSize) -0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:18 Constant: 0:18 1 (const int) 0:18 Constant: @@ -1212,9 +1212,9 @@ vertices = 4 0:19 move second child to first child (temp float) 0:19 'cd' (temp float) 0:19 direct index (temp float ClipDistance) -0:19 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:19 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:19 Constant: 0:19 1 (const int) 0:19 Constant: @@ -1280,7 +1280,7 @@ vertices = 4 0:37 0 (const int) 0:36 true case is null 0:? Linker Objects -0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:? 'outa' (global 4-element array of int) 0:? 'patchOut' (patch out 4-component vector of float) 0:? 'patchIn' (patch in 4-component vector of float) @@ -1324,8 +1324,8 @@ ERROR: node is still EOpNull! 0:22 move second child to first child (temp 4-component vector of float) 0:22 'p' (temp 4-component vector of float) 0:22 gl_Position: direct index for structure (in 4-component vector of float Position) -0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:22 Constant: 0:22 1 (const int) 0:22 Constant: @@ -1334,8 +1334,8 @@ ERROR: node is still EOpNull! 0:23 move second child to first child (temp float) 0:23 'ps' (temp float) 0:23 gl_PointSize: direct index for structure (in float PointSize) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -1344,9 +1344,9 @@ ERROR: node is still EOpNull! 0:24 move second child to first child (temp float) 0:24 'cd' (temp float) 0:24 direct index (temp float ClipDistance) -0:24 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -1414,8 +1414,8 @@ ERROR: node is still EOpNull! 0:32 move second child to first child (temp 4-component vector of float) 0:32 'p' (temp 4-component vector of float) 0:32 gl_Position: direct index for structure (in 4-component vector of float Position) -0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:32 Constant: 0:32 1 (const int) 0:32 Constant: @@ -1424,8 +1424,8 @@ ERROR: node is still EOpNull! 0:33 move second child to first child (temp float) 0:33 'ps' (temp float) 0:33 gl_PointSize: direct index for structure (in float PointSize) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -1434,9 +1434,9 @@ ERROR: node is still EOpNull! 0:34 move second child to first child (temp float) 0:34 'cd' (temp float) 0:34 direct index (temp float ClipDistance) -0:34 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 1 (const int) 0:34 Constant: @@ -1572,7 +1572,7 @@ ERROR: node is still EOpNull! 0:? 'badp2' (flat patch in 4-component vector of float) 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) -0:? 'gl_in' (in 32-element array of block{in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ina' (in 2-component vector of float) 0:? 'inb' (in 32-element array of 2-component vector of float) 0:? 'inc' (in 32-element array of 2-component vector of float) diff --git a/Test/baseResults/400.tesc.out b/Test/baseResults/400.tesc.out index 6a0b895a..99867ca5 100644 --- a/Test/baseResults/400.tesc.out +++ b/Test/baseResults/400.tesc.out @@ -233,8 +233,8 @@ ERROR: node is still EOpNull! 0:23 move second child to first child (temp 4-component vector of float) 0:23 'p' (temp 4-component vector of float) 0:23 gl_Position: direct index for structure (in 4-component vector of float Position) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -243,8 +243,8 @@ ERROR: node is still EOpNull! 0:24 move second child to first child (temp float) 0:24 'ps' (temp float) 0:24 gl_PointSize: direct index for structure (in float PointSize) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -253,9 +253,9 @@ ERROR: node is still EOpNull! 0:25 move second child to first child (temp float) 0:25 'cd' (temp float) 0:25 direct index (temp float ClipDistance) -0:25 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:25 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:25 Constant: 0:25 1 (const int) 0:25 Constant: @@ -276,25 +276,25 @@ ERROR: node is still EOpNull! 0:29 'gl_InvocationID' (in int InvocationID) 0:31 move second child to first child (temp 4-component vector of float) 0:31 gl_Position: direct index for structure (out 4-component vector of float Position) -0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:31 'gl_InvocationID' (in int InvocationID) 0:31 Constant: 0:31 0 (const int) 0:31 'p' (temp 4-component vector of float) 0:32 move second child to first child (temp float) 0:32 gl_PointSize: direct index for structure (out float PointSize) -0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:32 'gl_InvocationID' (in int InvocationID) 0:32 Constant: 0:32 1 (const int) 0:32 'ps' (temp float) 0:33 move second child to first child (temp float) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:33 'gl_InvocationID' (in int InvocationID) 0:33 Constant: 0:33 2 (const int) @@ -364,8 +364,8 @@ ERROR: node is still EOpNull! 0:67 Function Parameters: 0:69 Sequence 0:69 gl_PointSize: direct index for structure (out float PointSize) -0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:69 Constant: 0:69 4 (const int) 0:69 Constant: @@ -390,7 +390,7 @@ ERROR: node is still EOpNull! 0:97 'd' (temp double) 0:97 'd' (temp double) 0:? Linker Objects -0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:? 'outa' (global 4-element array of int) 0:? 'patchIn' (patch in 4-component vector of float) 0:? 'patchOut' (patch out 4-component vector of float) diff --git a/Test/baseResults/400.tese.out b/Test/baseResults/400.tese.out index 55670f87..76883aa7 100644 --- a/Test/baseResults/400.tese.out +++ b/Test/baseResults/400.tese.out @@ -179,8 +179,8 @@ ERROR: node is still EOpNull! 0:32 move second child to first child (temp 4-component vector of float) 0:32 'p' (temp 4-component vector of float) 0:32 gl_Position: direct index for structure (in 4-component vector of float Position) -0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:32 Constant: 0:32 1 (const int) 0:32 Constant: @@ -189,8 +189,8 @@ ERROR: node is still EOpNull! 0:33 move second child to first child (temp float) 0:33 'ps' (temp float) 0:33 gl_PointSize: direct index for structure (in float PointSize) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -199,9 +199,9 @@ ERROR: node is still EOpNull! 0:34 move second child to first child (temp float) 0:34 'cd' (temp float) 0:34 direct index (temp float ClipDistance) -0:34 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 1 (const int) 0:34 Constant: @@ -263,7 +263,7 @@ ERROR: node is still EOpNull! 0:? 'badp2' (flat patch in 4-component vector of float) 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) -0:? 'gl_in' (in 32-element array of block{in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ina' (in 2-component vector of float) 0:? 'inb' (in 32-element array of 2-component vector of float) 0:? 'inc' (in 32-element array of 2-component vector of float) diff --git a/Test/baseResults/420.tesc.out b/Test/baseResults/420.tesc.out index db65fd99..594e1302 100644 --- a/Test/baseResults/420.tesc.out +++ b/Test/baseResults/420.tesc.out @@ -132,8 +132,8 @@ ERROR: node is still EOpNull! 0:17 move second child to first child (temp 4-component vector of float) 0:17 'p' (temp 4-component vector of float) 0:17 gl_Position: direct index for structure (in 4-component vector of float Position) -0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:17 Constant: 0:17 1 (const int) 0:17 Constant: @@ -142,8 +142,8 @@ ERROR: node is still EOpNull! 0:18 move second child to first child (temp float) 0:18 'ps' (temp float) 0:18 gl_PointSize: direct index for structure (in float PointSize) -0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:18 Constant: 0:18 1 (const int) 0:18 Constant: @@ -152,9 +152,9 @@ ERROR: node is still EOpNull! 0:19 move second child to first child (temp float) 0:19 'cd' (temp float) 0:19 direct index (temp float ClipDistance) -0:19 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:19 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:19 Constant: 0:19 1 (const int) 0:19 Constant: diff --git a/Test/baseResults/450.geom.out b/Test/baseResults/450.geom.out index fd98d088..1579e18d 100644 --- a/Test/baseResults/450.geom.out +++ b/Test/baseResults/450.geom.out @@ -57,9 +57,9 @@ output primitive = none 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 2-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 2-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -67,6 +67,6 @@ output primitive = none 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 2-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 2-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:? 'anon@0' (layout(stream=0 ) out block{layout(stream=0 ) out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/450.tesc.out b/Test/baseResults/450.tesc.out index 8a8e9fbf..66cd5c26 100644 --- a/Test/baseResults/450.tesc.out +++ b/Test/baseResults/450.tesc.out @@ -44,18 +44,18 @@ vertices = -1 0:13 Sequence 0:13 move second child to first child (temp float) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (out 1-element array of float CullDistance) -0:13 indirect index (temp block{out 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_out' (out 4-element array of block{out 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (out 3-element array of float CullDistance) +0:13 indirect index (temp block{out 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_out' (out 4-element array of block{out 3-element array of float CullDistance gl_CullDistance}) 0:13 'gl_InvocationID' (in int InvocationID) 0:13 Constant: 0:13 0 (const int) 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -63,6 +63,6 @@ vertices = -1 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) -0:? 'gl_out' (out 4-element array of block{out 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) +0:? 'gl_out' (out 4-element array of block{out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/450.tese.out b/Test/baseResults/450.tese.out index c6e97b8d..a1116b40 100644 --- a/Test/baseResults/450.tese.out +++ b/Test/baseResults/450.tese.out @@ -53,9 +53,9 @@ triangle order = ccw 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -63,6 +63,6 @@ triangle order = ccw 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:? 'anon@0' (out block{out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/spv.400.tesc.out b/Test/baseResults/spv.400.tesc.out index eea07ce7..290a19cd 100755 --- a/Test/baseResults/spv.400.tesc.out +++ b/Test/baseResults/spv.400.tesc.out @@ -7,68 +7,68 @@ Linked tessellation control stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 93 +// Id's are bound by 94 Capability Tessellation Capability TessellationPointSize Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint TessellationControl 4 "main" 23 40 43 46 52 66 73 79 83 84 87 88 91 92 + EntryPoint TessellationControl 4 "main" 24 41 44 47 55 69 74 80 84 85 88 89 92 93 ExecutionMode 4 OutputVertices 4 Source GLSL 400 SourceExtension "GL_ARB_separate_shader_objects" Name 4 "main" Name 12 "a" Name 17 "p" - Name 19 "gl_PerVertex" - MemberName 19(gl_PerVertex) 0 "gl_Position" - MemberName 19(gl_PerVertex) 1 "gl_PointSize" - MemberName 19(gl_PerVertex) 2 "gl_ClipDistance" - Name 23 "gl_in" - Name 30 "ps" - Name 34 "cd" - Name 38 "pvi" - Name 40 "gl_PatchVerticesIn" - Name 42 "pid" - Name 43 "gl_PrimitiveID" - Name 45 "iid" - Name 46 "gl_InvocationID" - Name 48 "gl_PerVertex" - MemberName 48(gl_PerVertex) 0 "gl_Position" - MemberName 48(gl_PerVertex) 1 "gl_PointSize" - MemberName 48(gl_PerVertex) 2 "gl_ClipDistance" - Name 52 "gl_out" - Name 66 "gl_TessLevelOuter" - Name 73 "gl_TessLevelInner" - Name 78 "outa" - Name 79 "patchOut" - Name 83 "inb" - Name 84 "ind" - Name 87 "ivla" - Name 88 "ivlb" - Name 91 "ovla" - Name 92 "ovlb" - MemberDecorate 19(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 19(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 19(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 19(gl_PerVertex) Block - Decorate 40(gl_PatchVerticesIn) BuiltIn PatchVertices - Decorate 43(gl_PrimitiveID) BuiltIn PrimitiveId - Decorate 46(gl_InvocationID) BuiltIn InvocationId - MemberDecorate 48(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 48(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 48(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 48(gl_PerVertex) Block - Decorate 66(gl_TessLevelOuter) Patch - Decorate 66(gl_TessLevelOuter) BuiltIn TessLevelOuter - Decorate 73(gl_TessLevelInner) Patch - Decorate 73(gl_TessLevelInner) BuiltIn TessLevelInner - Decorate 79(patchOut) Patch - Decorate 87(ivla) Location 3 - Decorate 88(ivlb) Location 4 - Decorate 91(ovla) Location 3 - Decorate 92(ovlb) Location 4 + Name 20 "gl_PerVertex" + MemberName 20(gl_PerVertex) 0 "gl_Position" + MemberName 20(gl_PerVertex) 1 "gl_PointSize" + MemberName 20(gl_PerVertex) 2 "gl_ClipDistance" + Name 24 "gl_in" + Name 31 "ps" + Name 35 "cd" + Name 39 "pvi" + Name 41 "gl_PatchVerticesIn" + Name 43 "pid" + Name 44 "gl_PrimitiveID" + Name 46 "iid" + Name 47 "gl_InvocationID" + Name 51 "gl_PerVertex" + MemberName 51(gl_PerVertex) 0 "gl_Position" + MemberName 51(gl_PerVertex) 1 "gl_PointSize" + MemberName 51(gl_PerVertex) 2 "gl_ClipDistance" + Name 55 "gl_out" + Name 69 "gl_TessLevelOuter" + Name 74 "gl_TessLevelInner" + Name 79 "outa" + Name 80 "patchOut" + Name 84 "inb" + Name 85 "ind" + Name 88 "ivla" + Name 89 "ivlb" + Name 92 "ovla" + Name 93 "ovlb" + MemberDecorate 20(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 20(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 20(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 20(gl_PerVertex) Block + Decorate 41(gl_PatchVerticesIn) BuiltIn PatchVertices + Decorate 44(gl_PrimitiveID) BuiltIn PrimitiveId + Decorate 47(gl_InvocationID) BuiltIn InvocationId + MemberDecorate 51(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 51(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 51(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 51(gl_PerVertex) Block + Decorate 69(gl_TessLevelOuter) Patch + Decorate 69(gl_TessLevelOuter) BuiltIn TessLevelOuter + Decorate 74(gl_TessLevelInner) Patch + Decorate 74(gl_TessLevelInner) BuiltIn TessLevelInner + Decorate 80(patchOut) Patch + Decorate 88(ivla) Location 3 + Decorate 89(ivlb) Location 4 + Decorate 92(ovla) Location 3 + Decorate 93(ovlb) Location 4 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -81,98 +81,99 @@ Linked tessellation control stage: 14: TypeFloat 32 15: TypeVector 14(float) 4 16: TypePointer Function 15(fvec4) - 18: TypeArray 14(float) 7 -19(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 18 - 20: 6(int) Constant 32 - 21: TypeArray 19(gl_PerVertex) 20 - 22: TypePointer Input 21 - 23(gl_in): 22(ptr) Variable Input - 24: 10(int) Constant 1 - 25: 10(int) Constant 0 - 26: TypePointer Input 15(fvec4) - 29: TypePointer Function 14(float) - 31: TypePointer Input 14(float) - 35: 10(int) Constant 2 - 39: TypePointer Input 10(int) -40(gl_PatchVerticesIn): 39(ptr) Variable Input -43(gl_PrimitiveID): 39(ptr) Variable Input -46(gl_InvocationID): 39(ptr) Variable Input -48(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 18 - 49: 6(int) Constant 4 - 50: TypeArray 48(gl_PerVertex) 49 - 51: TypePointer Output 50 - 52(gl_out): 51(ptr) Variable Output - 55: TypePointer Output 15(fvec4) - 59: TypePointer Output 14(float) - 64: TypeArray 14(float) 49 - 65: TypePointer Output 64 -66(gl_TessLevelOuter): 65(ptr) Variable Output - 67: 10(int) Constant 3 - 68: 14(float) Constant 1078774989 - 70: 6(int) Constant 2 - 71: TypeArray 14(float) 70 - 72: TypePointer Output 71 -73(gl_TessLevelInner): 72(ptr) Variable Output - 74: 14(float) Constant 1067869798 - 76: TypeArray 10(int) 49 - 77: TypePointer Private 76 - 78(outa): 77(ptr) Variable Private - 79(patchOut): 55(ptr) Variable Output - 80: TypeVector 14(float) 2 - 81: TypeArray 80(fvec2) 20 - 82: TypePointer Input 81 - 83(inb): 82(ptr) Variable Input - 84(ind): 82(ptr) Variable Input - 85: TypeArray 15(fvec4) 20 - 86: TypePointer Input 85 - 87(ivla): 86(ptr) Variable Input - 88(ivlb): 86(ptr) Variable Input - 89: TypeArray 15(fvec4) 49 - 90: TypePointer Output 89 - 91(ovla): 90(ptr) Variable Output - 92(ovlb): 90(ptr) Variable Output + 18: 6(int) Constant 3 + 19: TypeArray 14(float) 18 +20(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 19 + 21: 6(int) Constant 32 + 22: TypeArray 20(gl_PerVertex) 21 + 23: TypePointer Input 22 + 24(gl_in): 23(ptr) Variable Input + 25: 10(int) Constant 1 + 26: 10(int) Constant 0 + 27: TypePointer Input 15(fvec4) + 30: TypePointer Function 14(float) + 32: TypePointer Input 14(float) + 36: 10(int) Constant 2 + 40: TypePointer Input 10(int) +41(gl_PatchVerticesIn): 40(ptr) Variable Input +44(gl_PrimitiveID): 40(ptr) Variable Input +47(gl_InvocationID): 40(ptr) Variable Input + 49: 6(int) Constant 2 + 50: TypeArray 14(float) 49 +51(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 50 + 52: 6(int) Constant 4 + 53: TypeArray 51(gl_PerVertex) 52 + 54: TypePointer Output 53 + 55(gl_out): 54(ptr) Variable Output + 58: TypePointer Output 15(fvec4) + 62: TypePointer Output 14(float) + 67: TypeArray 14(float) 52 + 68: TypePointer Output 67 +69(gl_TessLevelOuter): 68(ptr) Variable Output + 70: 10(int) Constant 3 + 71: 14(float) Constant 1078774989 + 73: TypePointer Output 50 +74(gl_TessLevelInner): 73(ptr) Variable Output + 75: 14(float) Constant 1067869798 + 77: TypeArray 10(int) 52 + 78: TypePointer Private 77 + 79(outa): 78(ptr) Variable Private + 80(patchOut): 58(ptr) Variable Output + 81: TypeVector 14(float) 2 + 82: TypeArray 81(fvec2) 21 + 83: TypePointer Input 82 + 84(inb): 83(ptr) Variable Input + 85(ind): 83(ptr) Variable Input + 86: TypeArray 15(fvec4) 21 + 87: TypePointer Input 86 + 88(ivla): 87(ptr) Variable Input + 89(ivlb): 87(ptr) Variable Input + 90: TypeArray 15(fvec4) 52 + 91: TypePointer Output 90 + 92(ovla): 91(ptr) Variable Output + 93(ovlb): 91(ptr) Variable Output 4(main): 2 Function None 3 5: Label 12(a): 11(ptr) Variable Function 17(p): 16(ptr) Variable Function - 30(ps): 29(ptr) Variable Function - 34(cd): 29(ptr) Variable Function - 38(pvi): 11(ptr) Variable Function - 42(pid): 11(ptr) Variable Function - 45(iid): 11(ptr) Variable Function + 31(ps): 30(ptr) Variable Function + 35(cd): 30(ptr) Variable Function + 39(pvi): 11(ptr) Variable Function + 43(pid): 11(ptr) Variable Function + 46(iid): 11(ptr) Variable Function MemoryBarrier 7 8 ControlBarrier 7 7 9 Store 12(a) 13 - 27: 26(ptr) AccessChain 23(gl_in) 24 25 - 28: 15(fvec4) Load 27 - Store 17(p) 28 - 32: 31(ptr) AccessChain 23(gl_in) 24 24 - 33: 14(float) Load 32 - Store 30(ps) 33 - 36: 31(ptr) AccessChain 23(gl_in) 24 35 35 - 37: 14(float) Load 36 - Store 34(cd) 37 - 41: 10(int) Load 40(gl_PatchVerticesIn) - Store 38(pvi) 41 - 44: 10(int) Load 43(gl_PrimitiveID) - Store 42(pid) 44 - 47: 10(int) Load 46(gl_InvocationID) - Store 45(iid) 47 - 53: 10(int) Load 46(gl_InvocationID) - 54: 15(fvec4) Load 17(p) - 56: 55(ptr) AccessChain 52(gl_out) 53 25 - Store 56 54 - 57: 10(int) Load 46(gl_InvocationID) - 58: 14(float) Load 30(ps) - 60: 59(ptr) AccessChain 52(gl_out) 57 24 - Store 60 58 - 61: 10(int) Load 46(gl_InvocationID) - 62: 14(float) Load 34(cd) - 63: 59(ptr) AccessChain 52(gl_out) 61 35 24 - Store 63 62 - 69: 59(ptr) AccessChain 66(gl_TessLevelOuter) 67 - Store 69 68 - 75: 59(ptr) AccessChain 73(gl_TessLevelInner) 24 - Store 75 74 + 28: 27(ptr) AccessChain 24(gl_in) 25 26 + 29: 15(fvec4) Load 28 + Store 17(p) 29 + 33: 32(ptr) AccessChain 24(gl_in) 25 25 + 34: 14(float) Load 33 + Store 31(ps) 34 + 37: 32(ptr) AccessChain 24(gl_in) 25 36 36 + 38: 14(float) Load 37 + Store 35(cd) 38 + 42: 10(int) Load 41(gl_PatchVerticesIn) + Store 39(pvi) 42 + 45: 10(int) Load 44(gl_PrimitiveID) + Store 43(pid) 45 + 48: 10(int) Load 47(gl_InvocationID) + Store 46(iid) 48 + 56: 10(int) Load 47(gl_InvocationID) + 57: 15(fvec4) Load 17(p) + 59: 58(ptr) AccessChain 55(gl_out) 56 26 + Store 59 57 + 60: 10(int) Load 47(gl_InvocationID) + 61: 14(float) Load 31(ps) + 63: 62(ptr) AccessChain 55(gl_out) 60 25 + Store 63 61 + 64: 10(int) Load 47(gl_InvocationID) + 65: 14(float) Load 35(cd) + 66: 62(ptr) AccessChain 55(gl_out) 64 36 25 + Store 66 65 + 72: 62(ptr) AccessChain 69(gl_TessLevelOuter) 70 + Store 72 71 + 76: 62(ptr) AccessChain 74(gl_TessLevelInner) 25 + Store 76 75 Return FunctionEnd diff --git a/Test/baseResults/spv.400.tese.out b/Test/baseResults/spv.400.tese.out index 03e181ce..51534b12 100755 --- a/Test/baseResults/spv.400.tese.out +++ b/Test/baseResults/spv.400.tese.out @@ -7,14 +7,14 @@ Linked tessellation evaluation stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 98 +// Id's are bound by 96 Capability Tessellation Capability TessellationPointSize Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint TessellationEvaluation 4 "main" 21 38 41 47 53 61 68 77 81 82 86 90 93 94 97 + EntryPoint TessellationEvaluation 4 "main" 21 38 41 47 53 61 66 75 79 80 84 88 91 92 95 ExecutionMode 4 Triangles ExecutionMode 4 SpacingFractionalOdd ExecutionMode 4 VertexOrderCcw @@ -41,23 +41,23 @@ Linked tessellation evaluation stage: Name 53 "gl_TessLevelOuter" Name 57 "tli" Name 61 "gl_TessLevelInner" - Name 66 "gl_PerVertex" - MemberName 66(gl_PerVertex) 0 "gl_Position" - MemberName 66(gl_PerVertex) 1 "gl_PointSize" - MemberName 66(gl_PerVertex) 2 "gl_ClipDistance" - Name 68 "" - Name 77 "patchIn" - Name 81 "inb" - Name 82 "ind" - Name 83 "testblb" - MemberName 83(testblb) 0 "f" - Name 86 "blb" - Name 87 "testbld" - MemberName 87(testbld) 0 "f" - Name 90 "bld" - Name 93 "ivla" - Name 94 "ivlb" - Name 97 "ovla" + Name 64 "gl_PerVertex" + MemberName 64(gl_PerVertex) 0 "gl_Position" + MemberName 64(gl_PerVertex) 1 "gl_PointSize" + MemberName 64(gl_PerVertex) 2 "gl_ClipDistance" + Name 66 "" + Name 75 "patchIn" + Name 79 "inb" + Name 80 "ind" + Name 81 "testblb" + MemberName 81(testblb) 0 "f" + Name 84 "blb" + Name 85 "testbld" + MemberName 85(testbld) 0 "f" + Name 88 "bld" + Name 91 "ivla" + Name 92 "ivlb" + Name 95 "ovla" MemberDecorate 17(gl_PerVertex) 0 BuiltIn Position MemberDecorate 17(gl_PerVertex) 1 BuiltIn PointSize MemberDecorate 17(gl_PerVertex) 2 BuiltIn ClipDistance @@ -69,16 +69,16 @@ Linked tessellation evaluation stage: Decorate 53(gl_TessLevelOuter) BuiltIn TessLevelOuter Decorate 61(gl_TessLevelInner) Patch Decorate 61(gl_TessLevelInner) BuiltIn TessLevelInner - MemberDecorate 66(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 66(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 66(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 66(gl_PerVertex) Block - Decorate 77(patchIn) Patch - Decorate 83(testblb) Block - Decorate 87(testbld) Block - Decorate 93(ivla) Location 23 - Decorate 94(ivlb) Location 24 - Decorate 97(ovla) Location 23 + MemberDecorate 64(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 64(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 64(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 64(gl_PerVertex) Block + Decorate 75(patchIn) Patch + Decorate 81(testblb) Block + Decorate 85(testbld) Block + Decorate 91(ivla) Location 23 + Decorate 92(ivlb) Location 24 + Decorate 95(ovla) Location 23 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 1 @@ -88,7 +88,7 @@ Linked tessellation evaluation stage: 11: TypeVector 10(float) 4 12: TypePointer Function 11(fvec4) 14: TypeInt 32 0 - 15: 14(int) Constant 1 + 15: 14(int) Constant 3 16: TypeArray 10(float) 15 17(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 16 18: 14(int) Constant 32 @@ -117,34 +117,32 @@ Linked tessellation evaluation stage: 59: TypeArray 10(float) 58 60: TypePointer Input 59 61(gl_TessLevelInner): 60(ptr) Variable Input - 64: 14(int) Constant 3 - 65: TypeArray 10(float) 64 -66(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 65 - 67: TypePointer Output 66(gl_PerVertex) - 68: 67(ptr) Variable Output - 70: TypePointer Output 11(fvec4) - 73: TypePointer Output 10(float) - 77(patchIn): 24(ptr) Variable Input - 78: TypeVector 10(float) 2 - 79: TypeArray 78(fvec2) 18 - 80: TypePointer Input 79 - 81(inb): 80(ptr) Variable Input - 82(ind): 80(ptr) Variable Input - 83(testblb): TypeStruct 6(int) - 84: TypeArray 83(testblb) 18 - 85: TypePointer Input 84 - 86(blb): 85(ptr) Variable Input - 87(testbld): TypeStruct 6(int) - 88: TypeArray 87(testbld) 18 - 89: TypePointer Input 88 - 90(bld): 89(ptr) Variable Input - 91: TypeArray 11(fvec4) 18 - 92: TypePointer Input 91 - 93(ivla): 92(ptr) Variable Input - 94(ivlb): 92(ptr) Variable Input - 95: TypeArray 11(fvec4) 58 - 96: TypePointer Output 95 - 97(ovla): 96(ptr) Variable Output +64(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 16 + 65: TypePointer Output 64(gl_PerVertex) + 66: 65(ptr) Variable Output + 68: TypePointer Output 11(fvec4) + 71: TypePointer Output 10(float) + 75(patchIn): 24(ptr) Variable Input + 76: TypeVector 10(float) 2 + 77: TypeArray 76(fvec2) 18 + 78: TypePointer Input 77 + 79(inb): 78(ptr) Variable Input + 80(ind): 78(ptr) Variable Input + 81(testblb): TypeStruct 6(int) + 82: TypeArray 81(testblb) 18 + 83: TypePointer Input 82 + 84(blb): 83(ptr) Variable Input + 85(testbld): TypeStruct 6(int) + 86: TypeArray 85(testbld) 18 + 87: TypePointer Input 86 + 88(bld): 87(ptr) Variable Input + 89: TypeArray 11(fvec4) 18 + 90: TypePointer Input 89 + 91(ivla): 90(ptr) Variable Input + 92(ivlb): 90(ptr) Variable Input + 93: TypeArray 11(fvec4) 58 + 94: TypePointer Output 93 + 95(ovla): 94(ptr) Variable Output 4(main): 2 Function None 3 5: Label 8(a): 7(ptr) Variable Function @@ -178,14 +176,14 @@ Linked tessellation evaluation stage: 62: 29(ptr) AccessChain 61(gl_TessLevelInner) 22 63: 10(float) Load 62 Store 57(tli) 63 - 69: 11(fvec4) Load 13(p) - 71: 70(ptr) AccessChain 68 23 - Store 71 69 - 72: 10(float) Load 28(ps) - 74: 73(ptr) AccessChain 68 22 - Store 74 72 - 75: 10(float) Load 32(cd) - 76: 73(ptr) AccessChain 68 33 33 - Store 76 75 + 67: 11(fvec4) Load 13(p) + 69: 68(ptr) AccessChain 66 23 + Store 69 67 + 70: 10(float) Load 28(ps) + 72: 71(ptr) AccessChain 66 22 + Store 72 70 + 73: 10(float) Load 32(cd) + 74: 71(ptr) AccessChain 66 33 33 + Store 74 73 Return FunctionEnd diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 5de89e1b..bb8bdb62 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -3122,16 +3122,27 @@ void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode * // This has to be the result of a block dereference, unless it's bad shader code // If it's a uniform block, then an error will be issued elsewhere, but // return early now to avoid crashing later in this function. - if (! deref->getLeft()->getAsSymbolNode() || deref->getLeft()->getBasicType() != EbtBlock || + if (deref->getLeft()->getBasicType() != EbtBlock || deref->getLeft()->getType().getQualifier().storage == EvqUniform || deref->getRight()->getAsConstantUnion() == nullptr) return; - blockIndex = deref->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); + const TIntermTyped* left = deref->getLeft(); + const TIntermTyped* right = deref->getRight(); - lookupName = &deref->getLeft()->getAsSymbolNode()->getName(); + if (left->getAsBinaryNode()) { + left = left->getAsBinaryNode()->getLeft(); // Block array access + assert(left->isArray()); + } + + if (! left->getAsSymbolNode()) + return; + + blockIndex = right->getAsConstantUnion()->getConstArray()[0].getIConst(); + + lookupName = &left->getAsSymbolNode()->getName(); if (IsAnonymous(*lookupName)) - lookupName = &(*deref->getLeft()->getType().getStruct())[blockIndex].type->getFieldName(); + lookupName = &(*left->getType().getStruct())[blockIndex].type->getFieldName(); } // Lookup the symbol, should only fail if shader code is incorrect @@ -3144,7 +3155,10 @@ void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode * return; } - symbol->getWritableType().setImplicitArraySize(index + 1); + if (symbol->getType().isStruct() && blockIndex != -1) + (*symbol->getWritableType().getStruct())[blockIndex].type->setImplicitArraySize(index + 1); + else + symbol->getWritableType().setImplicitArraySize(index + 1); } // Returns true if the first argument to the #line directive is the line number for the next line. From 135452061aca1346936aa7a28ebb138341052229 Mon Sep 17 00:00:00 2001 From: qining Date: Mon, 21 Mar 2016 09:51:37 -0400 Subject: [PATCH 14/20] Spec Constant Operations Approach: Add a flag in `Builder` to indicate 'spec constant mode' and 'normal mode'. When the builder is in 'normal mode', nothing changed. When the builder is in 'spec constant mode', binary, unary and other instruction creation rountines will be redirected to `createSpecConstantOp()` to create instrution at module level with `OpSpecConstantOp `. 'spec constant mode' should be enabled if and only if we are creating spec constants. So a flager setter/recover guard is added when handling binary/unary nodes in `createSpvConstantsFromConstSubTree()`. Note when handling spec constants which are represented as ConstantUnion Node, we should not use `OpSpecConstantOp` to initialize the composite constant, so builder is set to 'normal mode'. Tests: Tests are added in Test/spv.specConstantOperations.vert, including: 1) Arithmetic, shift opeations for both scalar and composite type spec constants. 2) Size conversion from/to float and double for both scalar and vector. 3) Bitwise and/or/xor for both scalar and vector. 4) Unary negate/not for both scalar and vector. 5) Vector swizzles. 6) Comparisons for scalars. 7) == and != for composite type spec constants Issues: 1) To implement == and != for composite type spec constants, the Spec needs to allow OpAll, OpAny, OpFOrdEqual, OpFUnordEqual, OpOrdNotEqual, OpFUnordNotEqual. Currently none of them are allowed in the Spec. --- SPIRV/GlslangToSpv.cpp | 48 ++++- SPIRV/SpvBuilder.cpp | 143 ++++++++++++- SPIRV/SpvBuilder.h | 9 + .../spv.specConstantOperations.vert.out | 191 ++++++++++++++++++ Test/spv.specConstantOperations.vert | 127 ++++++++++++ Test/test-spirv-list | 1 + 6 files changed, 506 insertions(+), 13 deletions(-) create mode 100644 Test/baseResults/spv.specConstantOperations.vert.out create mode 100644 Test/spv.specConstantOperations.vert diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index dd5afd4b..ee48b3c1 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -130,7 +130,7 @@ protected: void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); spv::Id createSpvConstant(const glslang::TIntermTyped&); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); - spv::Id createSpvConstantFromConstSubTree(const glslang::TIntermTyped* subTree); + spv::Id createSpvConstantFromConstSubTree(glslang::TIntermTyped* subTree); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); @@ -3854,15 +3854,37 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla return builder.makeCompositeConstant(typeId, spvConsts); } +namespace { +class SpecConstOpCodeGenerationSettingGuard{ + public: + SpecConstOpCodeGenerationSettingGuard(spv::Builder* builder, + bool shouldGeneratingForSpecConst) + : builder_(builder) { + previous_flag_ = builder->isInSpecConstCodeGenMode(); + shouldGeneratingForSpecConst ? builder->setToSpecConstCodeGenMode() + : builder->setToNormalCodeGenMode(); + } + ~SpecConstOpCodeGenerationSettingGuard() { + previous_flag_ ? builder_->setToSpecConstCodeGenMode() + : builder_->setToNormalCodeGenMode(); + } + + private: + spv::Builder* builder_; + bool previous_flag_; +}; +} + // Create constant ID from const initializer sub tree. spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( - const glslang::TIntermTyped* subTree) { + glslang::TIntermTyped* subTree) { const glslang::TType& glslangType = subTree->getType(); spv::Id typeId = convertGlslangToSpvType(glslangType); bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { // Aggregate node, we should generate OpConstantComposite or // OpSpecConstantComposite instruction. + std::vector const_constituents; for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); NI++) { @@ -3881,17 +3903,27 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( return const_constituents.front(); } - } else if (const glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { + } else if (glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { // Binary operation node, we should generate OpSpecConstantOp // This case should only happen when Specialization Constants are involved. - spv::MissingFunctionality("OpSpecConstantOp not implemented"); - return spv::NoResult; - } else if (const glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { + // Spec constants defined with binary operations and other constants requires + // OpSpecConstantOp instruction. + SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true); + + bn->traverse(this); + return accessChainLoad(bn->getType()); + + } else if (glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { // Unary operation node, similar to binary operation node, should only // happen when specialization constants are involved. - spv::MissingFunctionality("OpSpecConstantOp not implemented"); - return spv::NoResult; + + // Spec constants defined with unary operations and other constants requires + // OpSpecConstantOp instruction. + SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true); + + un->traverse(this); + return accessChainLoad(un->getType()); } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) { // ConstantUnion node, should redirect to diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 336d3de3..3c0e2f63 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -64,7 +64,8 @@ Builder::Builder(unsigned int magicNumber) : builderNumber(magicNumber), buildPoint(0), uniqueId(0), - mainFunction(0) + mainFunction(0), + generatingOpCodeForSpecConst(false) { clearAccessChain(); } @@ -1063,6 +1064,11 @@ Id Builder::createArrayLength(Id base, unsigned int member) Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(OpCompositeExtract, typeId, {composite}, {index}); + } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); extract->addImmediateOperand(index); @@ -1073,6 +1079,11 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector& indexes) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(OpCompositeExtract, typeId, {composite}, indexes); + } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); for (int i = 0; i < (int)indexes.size(); ++i) @@ -1170,6 +1181,11 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant // An opcode that has one operands, a result id, and a type Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(opCode, typeId, {operand}, {}); + } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(operand); buildPoint->addInstruction(std::unique_ptr(op)); @@ -1179,6 +1195,11 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(opCode, typeId, {left, right}, {}); + } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(left); op->addIdOperand(right); @@ -1208,6 +1229,102 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) return op->getResultId(); } +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) { + switch(opCode) { + // OpCodes that do not need any capababilities. + case OpSConvert: + case OpFConvert: + case OpSNegate: + case OpNot: + case OpIAdd: + case OpISub: + case OpIMul: + case OpUDiv: + case OpSDiv: + case OpUMod: + case OpSRem: + case OpSMod: + case OpShiftRightLogical: + case OpShiftRightArithmetic: + case OpShiftLeftLogical: + case OpBitwiseOr: + case OpBitwiseXor: + case OpBitwiseAnd: + case OpVectorShuffle: + case OpCompositeExtract: + case OpCompositeInsert: + case OpLogicalOr: + case OpLogicalAnd: + case OpLogicalNot: + case OpLogicalEqual: + case OpLogicalNotEqual: + case OpSelect: + case OpIEqual: + case OpULessThan: + case OpSLessThan: + case OpUGreaterThan: + case OpSGreaterThan: + case OpULessThanEqual: + case OpSLessThanEqual: + case OpUGreaterThanEqual: + case OpSGreaterThanEqual: + // Added temporarily to enable compsite type spec constants comparison. + // Remove this comment after Spec being updated. + case OpAll: + case OpAny: + case OpFOrdEqual: + case OpFUnordEqual: + case OpFOrdNotEqual: + case OpFUnordNotEqual: + break; + + // OpCodes that need Shader capability. + case OpQuantizeToF16: + addCapability(CapabilityShader); + break; + + // OpCodes that need Kernel capability. + case OpConvertFToS: + case OpConvertSToF: + case OpConvertFToU: + case OpConvertUToF: + case OpUConvert: + case OpConvertPtrToU: + case OpConvertUToPtr: + case OpGenericCastToPtr: + case OpPtrCastToGeneric: + case OpBitcast: + case OpFNegate: + case OpFAdd: + case OpFSub: + case OpFMul: + case OpFDiv: + case OpFRem: + case OpFMod: + case OpAccessChain: + case OpInBoundsAccessChain: + case OpPtrAccessChain: + case OpInBoundsPtrAccessChain: + addCapability(CapabilityKernel); + break; + + default: + // Invalid OpCode for Spec Constant operations. + return NoResult; + } + + Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); + op->addImmediateOperand((unsigned) opCode); + for (auto it = operands.cbegin(); it != operands.cend(); ++it) + op->addIdOperand(*it); + for (auto it = literals.cbegin(); it != literals.cend(); ++it) + op->addImmediateOperand(*it); + module.mapInstruction(op); + constantsTypesGlobals.push_back(std::unique_ptr(op)); + + return op->getResultId(); +} + Id Builder::createFunctionCall(spv::Function* function, std::vector& args) { Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); @@ -1225,6 +1342,9 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, std: if (channels.size() == 1) return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); + if (generatingOpCodeForSpecConst) { + return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, {source, source}, channels), precision); + } Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); assert(isVector(source)); swizzle->addIdOperand(source); @@ -1290,10 +1410,23 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) if (numComponents == 1) return scalar; - Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); + Instruction* smear = nullptr; + if (generatingOpCodeForSpecConst) { + auto members = std::vector(numComponents, scalar); + // 'scalar' can not be spec constant here. All spec constant involved + // promotion is done in createSpvConstantFromConstUnionArray(). This + // 'if' branch is only accessed when 'scalar' is used in the def-chain + // of other vector type spec constants. In such cases, all the + // instructions needed to promote 'scalar' to a vector type constants + // should be added at module level. + auto result_id = makeCompositeConstant(vectorType, members, false); + smear = module.getInstruction(result_id); + } else { + smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); + for (int c = 0; c < numComponents; ++c) + smear->addIdOperand(scalar); + buildPoint->addInstruction(std::unique_ptr(smear)); + } return setPrecision(smear->getResultId(), precision); } diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index e16ba38c..46bdee84 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -262,6 +262,7 @@ public: Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createOp(Op, Id typeId, const std::vector& operands); Id createFunctionCall(spv::Function*, std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); // Take an rvalue (source) and a set of channels to extract from it to // make a new rvalue, which is returned. @@ -521,6 +522,13 @@ public: void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control); + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + protected: Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const; @@ -544,6 +552,7 @@ public: Block* buildPoint; Id uniqueId; Function* mainFunction; + bool generatingOpCodeForSpecConst; AccessChain accessChain; // special blocks of instructions for output diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out new file mode 100644 index 00000000..c3eaedd5 --- /dev/null +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -0,0 +1,191 @@ +spv.specConstantOperations.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked vertex stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 163 + + Capability Shader + Capability Kernel + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" + Source GLSL 450 + Name 4 "main" + Name 108 "int_float_double_vec2" + MemberName 108(int_float_double_vec2) 0 "i" + MemberName 108(int_float_double_vec2) 1 "f" + MemberName 108(int_float_double_vec2) 2 "d" + MemberName 108(int_float_double_vec2) 3 "v" + Decorate 7 SpecId 200 + Decorate 9 SpecId 201 + Decorate 11 SpecId 202 + Decorate 12 SpecId 203 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: 6(float) SpecConstant 1078530010 + 8: TypeInt 32 1 + 9: 8(int) SpecConstant 10 + 10: TypeInt 32 0 + 11: 10(int) SpecConstant 100 + 12: 8(int) SpecConstant 4294967286 + 13: TypeFloat 64 + 14: 13(float) SpecConstantOp 115 7 + 15: 6(float) SpecConstantOp 115 14 + 16: 8(int) SpecConstantOp 126 9 + 17: 8(int) SpecConstantOp 200 9 + 18: 8(int) Constant 2 + 19: 8(int) SpecConstantOp 128 9 18 + 20: 8(int) SpecConstantOp 128 9 18 + 21: 8(int) Constant 3 + 22: 8(int) SpecConstantOp 130 20 21 + 23: 8(int) Constant 4 + 24: 8(int) SpecConstantOp 130 19 23 + 25: 8(int) SpecConstantOp 132 12 18 + 26: 10(int) Constant 2 + 27: 10(int) SpecConstantOp 132 11 26 + 28: 8(int) Constant 5 + 29: 8(int) SpecConstantOp 135 25 28 + 30: 10(int) Constant 5 + 31: 10(int) SpecConstantOp 134 27 30 + 32: 8(int) SpecConstantOp 139 12 23 + 33: 10(int) Constant 4 + 34: 10(int) SpecConstantOp 137 11 33 + 35: 8(int) SpecConstantOp 132 12 21 + 36: 8(int) SpecConstantOp 135 35 28 + 37: 8(int) Constant 10 + 38: 8(int) SpecConstantOp 195 12 37 + 39: 8(int) Constant 20 + 40: 10(int) SpecConstantOp 194 11 39 + 41: 8(int) Constant 1 + 42: 8(int) SpecConstantOp 196 12 41 + 43: 10(int) SpecConstantOp 196 11 18 + 44: 8(int) Constant 256 + 45: 8(int) SpecConstantOp 197 12 44 + 46: 10(int) Constant 512 + 47: 10(int) SpecConstantOp 198 11 46 + 48: 8(int) SpecConstantOp 124 11 + 49: 8(int) SpecConstantOp 199 12 48 + 50: TypeBool + 51: 50(bool) SpecConstantOp 177 9 12 + 52: 10(int) SpecConstantOp 124 12 + 53: 50(bool) SpecConstantOp 176 11 52 + 54: 10(int) SpecConstantOp 124 12 + 55: 50(bool) SpecConstantOp 176 54 11 + 56: TypeVector 8(int) 4 + 57: 8(int) Constant 30 + 58: 56(ivec4) SpecConstantComposite 39 57 9 9 + 59: TypeVector 10(int) 4 + 60: 10(int) Constant 4294967295 + 61: 10(int) Constant 4294967294 + 62: 59(ivec4) SpecConstantComposite 11 11 60 61 + 63: TypeVector 6(float) 4 + 64: 6(float) Constant 1067450368 + 65: 63(fvec4) SpecConstantComposite 7 64 7 64 + 66: TypeVector 13(float) 4 + 67: 66(fvec4) SpecConstantOp 115 65 + 68: 63(fvec4) SpecConstantOp 115 67 + 69: 56(ivec4) SpecConstantOp 200 58 + 70: 63(fvec4) SpecConstantOp 111 69 + 71: 56(ivec4) SpecConstantOp 126 58 + 72: 56(ivec4) ConstantComposite 18 18 18 18 + 73: 56(ivec4) SpecConstantOp 128 58 72 + 74: 56(ivec4) SpecConstantOp 128 58 72 + 75: 56(ivec4) ConstantComposite 21 21 21 21 + 76: 56(ivec4) SpecConstantOp 130 74 75 + 77: 56(ivec4) ConstantComposite 23 23 23 23 + 78: 56(ivec4) SpecConstantOp 130 76 77 + 79: 56(ivec4) SpecConstantOp 132 58 72 + 80: 56(ivec4) ConstantComposite 28 28 28 28 + 81: 56(ivec4) SpecConstantOp 135 79 80 + 82: 56(ivec4) SpecConstantOp 139 58 77 + 83: 56(ivec4) ConstantComposite 37 37 37 37 + 84: 56(ivec4) SpecConstantOp 195 58 83 + 85: 56(ivec4) SpecConstantOp 196 58 72 + 86: 8(int) Constant 1024 + 87: 56(ivec4) ConstantComposite 86 86 86 86 + 88: 56(ivec4) SpecConstantOp 197 58 87 + 89: 10(int) Constant 2048 + 90: 59(ivec4) ConstantComposite 89 89 89 89 + 91: 59(ivec4) SpecConstantOp 198 62 90 + 92: 56(ivec4) SpecConstantOp 124 62 + 93: 56(ivec4) SpecConstantOp 199 58 92 + 94: 10(int) Constant 0 + 95: 8(int) SpecConstantOp 81 58 0 + 96: TypeVector 8(int) 2 + 97: 96(ivec2) SpecConstantOp 79 58 58 1(GLSL.std.450) 0 + 98: TypeVector 8(int) 3 + 99: 98(ivec3) SpecConstantOp 79 58 58 2 1(GLSL.std.450) 0 + 100: 56(ivec4) SpecConstantOp 79 58 58 1(GLSL.std.450) 2 0 3 + 101: 59(ivec4) SpecConstantOp 124 58 + 102: TypeVector 50(bool) 4 + 103: 102(bvec4) SpecConstantOp 170 101 62 + 104: 50(bool) SpecConstantOp 155 103 + 105: 59(ivec4) SpecConstantOp 124 58 + 106: 50(bool) SpecConstantOp 154 0 + 107: TypeVector 6(float) 2 +108(int_float_double_vec2): TypeStruct 8(int) 6(float) 13(float) 107(fvec2) + 109: 6(float) Constant 1065353216 + 110: 107(fvec2) SpecConstantComposite 15 109 + 111:108(int_float_double_vec2) SpecConstantComposite 9 7 14 110 + 112: 107(fvec2) SpecConstantComposite 15 109 + 113:108(int_float_double_vec2) SpecConstantComposite 9 7 14 112 + 114: 8(int) SpecConstantOp 81 111 0 + 115: 8(int) SpecConstantOp 81 113 0 + 116: 50(bool) SpecConstantOp 170 114 115 + 117: 6(float) SpecConstantOp 81 111 1(GLSL.std.450) + 118: 6(float) SpecConstantOp 81 113 1(GLSL.std.450) + 119: 50(bool) SpecConstantOp 180 117 118 + 120: 50(bool) SpecConstantOp 167 116 119 + 121: 13(float) SpecConstantOp 81 111 2 + 122: 13(float) SpecConstantOp 81 113 2 + 123: 50(bool) SpecConstantOp 180 121 122 + 124: 50(bool) SpecConstantOp 167 120 123 + 125: 107(fvec2) SpecConstantOp 81 111 3 + 126: 107(fvec2) SpecConstantOp 81 113 3 + 127: TypeVector 50(bool) 2 + 128: 127(bvec2) SpecConstantOp 180 125 126 + 129: 50(bool) SpecConstantOp 155 128 + 130: 50(bool) SpecConstantOp 167 124 129 + 131: 8(int) SpecConstantOp 81 111 0 + 132: 8(int) SpecConstantOp 81 113 0 + 133: 6(float) SpecConstantOp 81 111 1(GLSL.std.450) + 134: 6(float) SpecConstantOp 81 113 1(GLSL.std.450) + 135: 50(bool) SpecConstantOp 182 133 134 + 136: 50(bool) SpecConstantOp 166 0 135 + 137: 13(float) SpecConstantOp 81 111 2 + 138: 13(float) SpecConstantOp 81 113 2 + 139: 50(bool) SpecConstantOp 182 137 138 + 140: 50(bool) SpecConstantOp 166 136 139 + 141: 107(fvec2) SpecConstantOp 81 111 3 + 142: 107(fvec2) SpecConstantOp 81 113 3 + 143: 127(bvec2) SpecConstantOp 182 141 142 + 144: 50(bool) SpecConstantOp 154 143 + 145: 50(bool) SpecConstantOp 166 140 144 + 146: TypeArray 6(float) 26 + 147: 146 SpecConstantComposite 7 7 + 148: 146 SpecConstantComposite 7 7 + 149: 6(float) SpecConstantOp 81 147 0 + 150: 6(float) SpecConstantOp 81 148 0 + 151: 50(bool) SpecConstantOp 180 149 150 + 152: 6(float) SpecConstantOp 81 147 1(GLSL.std.450) + 153: 6(float) SpecConstantOp 81 148 1(GLSL.std.450) + 154: 50(bool) SpecConstantOp 180 152 153 + 155: 50(bool) SpecConstantOp 167 151 154 + 156: 6(float) SpecConstantOp 81 147 0 + 157: 6(float) SpecConstantOp 81 148 0 + 158: 50(bool) SpecConstantOp 182 156 157 + 159: 6(float) SpecConstantOp 81 147 1(GLSL.std.450) + 160: 6(float) SpecConstantOp 81 148 1(GLSL.std.450) + 161: 50(bool) SpecConstantOp 182 159 160 + 162: 50(bool) SpecConstantOp 166 158 161 + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/spv.specConstantOperations.vert b/Test/spv.specConstantOperations.vert new file mode 100644 index 00000000..93588bf8 --- /dev/null +++ b/Test/spv.specConstantOperations.vert @@ -0,0 +1,127 @@ +#version 450 + +layout(constant_id = 200) const float sp_float = 3.1415926; +layout(constant_id = 201) const int sp_int = 10; +layout(constant_id = 202) const uint sp_uint = 100; +layout(constant_id = 203) const int sp_sint = -10; + + +// +// Scalars +// + +// Size convert +const double float_to_double = double(sp_float); +const float double_to_float = float(float_to_double); + +// Negate and Not +const int negate_int = -sp_int; +const int not_int = ~sp_int; + +// Add and Subtract +const int sp_int_add_two = sp_int + 2; +const int sp_int_add_two_sub_three = sp_int + 2 - 3; +const int sp_int_add_two_sub_four = sp_int_add_two - 4; + +// Mul, Div and Rem +const int sp_sint_mul_two = sp_sint * 2; +const uint sp_uint_mul_two = sp_uint * 2; +const int sp_sint_mul_two_div_five = sp_sint_mul_two / 5; +const uint sp_uint_mul_two_div_five = sp_uint_mul_two / 5; +const int sp_sint_rem_four = sp_sint % 4; +const uint sp_uint_rem_four = sp_uint % 4; +const int sp_sint_mul_three_div_five = sp_sint * 3 / 5; + +// Shift +const int sp_sint_shift_right_arithmetic = sp_sint >> 10; +const uint sp_uint_shift_right_arithmetic = sp_uint >> 20; +const int sp_sint_shift_left = sp_sint << 1; +const uint sp_uint_shift_left = sp_uint << 2; + +// Bitwise And, Or, Xor +const int sp_sint_or_256 = sp_sint | 0x100; +const uint sp_uint_xor_512 = sp_uint ^ 0x200; +const int sp_sint_and_sp_uint = sp_sint & int(sp_uint); + +// Scalar comparison +const bool sp_int_lt_sp_sint = sp_int < sp_sint; +const bool sp_uint_lt_sp_sint = sp_uint < sp_sint; +const bool sp_sint_lt_sp_uint = sp_sint < sp_uint; + +// +// Vectors +// +const ivec4 iv = ivec4(20, 30, sp_int, sp_int); +const uvec4 uv = uvec4(sp_uint, sp_uint, -1, -2); +const vec4 fv = vec4(sp_float, 1.25, sp_float, 1.25); + +// Size convert +const dvec4 fv_to_dv = dvec4(fv); +const vec4 dv_to_fv = vec4(fv_to_dv); + +// Negate and Not +const vec4 not_iv = ~iv; +const ivec4 negate_iv = -iv; + +// Add and Subtract +const ivec4 iv_add_two = iv + 2; +const ivec4 iv_add_two_sub_three = iv + 2 - 3; +const ivec4 iv_add_two_sub_four = iv_add_two_sub_three - 4; + +// Mul, Div and Rem +const ivec4 iv_mul_two = iv * 2; +const ivec4 iv_mul_two_div_five = iv_mul_two / 5; +const ivec4 iv_rem_four = iv % 4; + +// Shift +const ivec4 iv_shift_right_arithmetic = iv >> 10; +const ivec4 iv_shift_left = iv << 2; + +// Bitwise And, Or, Xor +const ivec4 iv_or_1024 = iv | 0x400; +const uvec4 uv_xor_2048 = uv ^ 0x800; +const ivec4 iv_and_uv = iv & ivec4(uv); + +// Swizzles +const int iv_x = iv.x; +const ivec2 iv_yx = iv.yx; +const ivec3 iv_zyx = iv.zyx; +const ivec4 iv_yzxw = iv.yzxw; + +// Vector comparison, only == and != are supported and allowd. +const bool iv_equal_uv = iv == uv; +const bool iv_not_equal_uv = iv != uv; + +// +// Composite types other than vectors +// + +// Struct +struct int_float_double_vec2 { + int i; + float f; + double d; + vec2 v; +}; + +const int_float_double_vec2 sp_struct_a = { + sp_int, sp_float, float_to_double, + vec2(double_to_float, 1.0) +}; + +const int_float_double_vec2 sp_struct_b = { + sp_int, sp_float, float_to_double, + vec2(double_to_float, 1.0) +}; + +const bool struct_a_equal_struct_b = sp_struct_a == sp_struct_b; +const bool struct_a_not_equal_struct_b = sp_struct_a != sp_struct_b; + +// Array +const float array_a[2] = {sp_float, sp_float}; +const float array_b[2] = {sp_float, sp_float}; +const bool array_a_equal_array_b = array_a == array_b; +const bool array_a_not_equal_array_b = array_a != array_b; + +void main() {} + diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 4534132f..b7dfd537 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -103,6 +103,7 @@ spv.subpass.frag spv.specConstant.vert spv.specConstant.comp spv.specConstantComposite.vert +spv.specConstantOperations.vert # GLSL-level semantics vulkan.frag vulkan.vert From 414eb604825888d0b7a981027b675e77a6bd298b Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Fri, 4 Mar 2016 16:22:34 -0500 Subject: [PATCH 15/20] Link in Google Test framework. The existing test harness is a homemade shell script. All the tests and the expected results are written in plain text files. The harness just reads in a test, invoke the glslangValidator binary on it, and compare the result with the golden file. All tests are kinda integration tests. This patch add Google Test as an external project, which provides a new harness for reading shader source files, compile to SPIR-V, and then compare with the expected output. --- .gitignore | 1 + CMakeLists.txt | 7 + External/CMakeLists.txt | 16 ++ README.md | 12 +- StandAlone/CMakeLists.txt | 11 +- StandAlone/DefaultResourceLimits.cpp | 239 +++++++++++++++++++++ StandAlone/DefaultResourceLimits.h | 54 +++++ StandAlone/StandAlone.cpp | 108 +--------- Test/baseResults/spv.330.geom.out | 0 Test/baseResults/spv.test.frag.out | 0 Test/baseResults/spv.test.vert.out | 0 gtests/AST.FromFile.cpp | 191 +++++++++++++++++ gtests/BuiltInResource.FromFile.cpp | 57 +++++ gtests/CMakeLists.txt | 32 +++ gtests/Initializer.h | 119 +++++++++++ gtests/Pp.FromFile.cpp | 74 +++++++ gtests/README.md | 26 +++ gtests/Settings.cpp | 41 ++++ gtests/Settings.h | 54 +++++ gtests/Spv.FromFile.cpp | 188 ++++++++++++++++ gtests/TestFixture.cpp | 124 +++++++++++ gtests/TestFixture.h | 307 +++++++++++++++++++++++++++ gtests/main.cpp | 63 ++++++ 23 files changed, 1618 insertions(+), 106 deletions(-) create mode 100644 External/CMakeLists.txt create mode 100644 StandAlone/DefaultResourceLimits.cpp create mode 100644 StandAlone/DefaultResourceLimits.h mode change 100755 => 100644 Test/baseResults/spv.330.geom.out mode change 100755 => 100644 Test/baseResults/spv.test.frag.out mode change 100755 => 100644 Test/baseResults/spv.test.vert.out create mode 100644 gtests/AST.FromFile.cpp create mode 100644 gtests/BuiltInResource.FromFile.cpp create mode 100644 gtests/CMakeLists.txt create mode 100644 gtests/Initializer.h create mode 100644 gtests/Pp.FromFile.cpp create mode 100644 gtests/README.md create mode 100644 gtests/Settings.cpp create mode 100644 gtests/Settings.h create mode 100644 gtests/Spv.FromFile.cpp create mode 100644 gtests/TestFixture.cpp create mode 100644 gtests/TestFixture.h create mode 100644 gtests/main.cpp diff --git a/.gitignore b/.gitignore index d93c2022..66cbff97 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build/ Test/localResults/ Test/multiThread.out Test/singleThread.out +External/googletest diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d723d87..ac756f55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 2.8) +enable_testing() + set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix") project(glslang) @@ -20,7 +22,12 @@ elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") add_definitions(-std=c++11) endif() +# We depend on these for later projects, so they should come first. +add_subdirectory(External) + add_subdirectory(glslang) add_subdirectory(OGLCompilersDLL) add_subdirectory(StandAlone) add_subdirectory(SPIRV) + +add_subdirectory(gtests) diff --git a/External/CMakeLists.txt b/External/CMakeLists.txt new file mode 100644 index 00000000..d43cf9d0 --- /dev/null +++ b/External/CMakeLists.txt @@ -0,0 +1,16 @@ +# Suppress all warnings from external projects. +set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) + +if (TARGET gmock) + message(STATUS "Google Mock already configured - use it") +elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) + # We need to make sure Google Test does not mess up with the + # global CRT settings on Windows. + if(WIN32) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + endif(WIN32) + add_subdirectory(googletest) +else() + message(STATUS + "Google Mock was not found - tests based on that will not build") +endif() diff --git a/README.md b/README.md index 7a60e280..77508774 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,12 @@ bison --defines=MachineIndependent/glslang_tab.cpp.h -o MachineIndependent/glslang_tab.cpp ``` +Glslang is adding the ability to test with +[Google Test](https://github.com/google/googletest) framework. If you want to +build and run those tests, please make sure you have a copy of Google Tests +checked out in the `External/` directory: +`git clone https://github.com/google/googletest.git`. + Programmatic Interfaces ----------------------- @@ -118,7 +124,11 @@ Testing ------- Test results should always be included with a pull request that modifies -functionality. There is a simple process for doing this, described here: +functionality. And since glslang is adding the ability to test with +[Google Test](https://github.com/google/googletest) framework, +please write your new tests using Google Test. + +The old (deprecated) testing process is: `Test` is an active test directory that contains test input and a subdirectory `baseResults` that contains the expected results of the diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt index 38cb2bdb..51f332a6 100644 --- a/StandAlone/CMakeLists.txt +++ b/StandAlone/CMakeLists.txt @@ -1,5 +1,13 @@ cmake_minimum_required(VERSION 2.8) +add_library(glslang-default-resource-limits + ${CMAKE_CURRENT_SOURCE_DIR}/DefaultResourceLimits.cpp +) +target_include_directories(glslang-default-resource-limits + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC ${PROJECT_SOURCE_DIR} +) + set(SOURCES StandAlone.cpp) set(REMAPPER_SOURCES spirv-remap.cpp) @@ -10,7 +18,8 @@ set(LIBRARIES glslang OGLCompiler OSDependent - SPIRV) + SPIRV + glslang-default-resource-limits) if(WIN32) set(LIBRARIES ${LIBRARIES} psapi) diff --git a/StandAlone/DefaultResourceLimits.cpp b/StandAlone/DefaultResourceLimits.cpp new file mode 100644 index 00000000..66032de1 --- /dev/null +++ b/StandAlone/DefaultResourceLimits.cpp @@ -0,0 +1,239 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "DefaultResourceLimits.h" + +namespace glslang { + +const TBuiltInResource DefaultTBuiltInResource = { + /* .MaxLights = */ 32, + /* .MaxClipPlanes = */ 6, + /* .MaxTextureUnits = */ 32, + /* .MaxTextureCoords = */ 32, + /* .MaxVertexAttribs = */ 64, + /* .MaxVertexUniformComponents = */ 4096, + /* .MaxVaryingFloats = */ 64, + /* .MaxVertexTextureImageUnits = */ 32, + /* .MaxCombinedTextureImageUnits = */ 80, + /* .MaxTextureImageUnits = */ 32, + /* .MaxFragmentUniformComponents = */ 4096, + /* .MaxDrawBuffers = */ 32, + /* .MaxVertexUniformVectors = */ 128, + /* .MaxVaryingVectors = */ 8, + /* .MaxFragmentUniformVectors = */ 16, + /* .MaxVertexOutputVectors = */ 16, + /* .MaxFragmentInputVectors = */ 15, + /* .MinProgramTexelOffset = */ -8, + /* .MaxProgramTexelOffset = */ 7, + /* .MaxClipDistances = */ 8, + /* .MaxComputeWorkGroupCountX = */ 65535, + /* .MaxComputeWorkGroupCountY = */ 65535, + /* .MaxComputeWorkGroupCountZ = */ 65535, + /* .MaxComputeWorkGroupSizeX = */ 1024, + /* .MaxComputeWorkGroupSizeY = */ 1024, + /* .MaxComputeWorkGroupSizeZ = */ 64, + /* .MaxComputeUniformComponents = */ 1024, + /* .MaxComputeTextureImageUnits = */ 16, + /* .MaxComputeImageUniforms = */ 8, + /* .MaxComputeAtomicCounters = */ 8, + /* .MaxComputeAtomicCounterBuffers = */ 1, + /* .MaxVaryingComponents = */ 60, + /* .MaxVertexOutputComponents = */ 64, + /* .MaxGeometryInputComponents = */ 64, + /* .MaxGeometryOutputComponents = */ 128, + /* .MaxFragmentInputComponents = */ 128, + /* .MaxImageUnits = */ 8, + /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, + /* .MaxCombinedShaderOutputResources = */ 8, + /* .MaxImageSamples = */ 0, + /* .MaxVertexImageUniforms = */ 0, + /* .MaxTessControlImageUniforms = */ 0, + /* .MaxTessEvaluationImageUniforms = */ 0, + /* .MaxGeometryImageUniforms = */ 0, + /* .MaxFragmentImageUniforms = */ 8, + /* .MaxCombinedImageUniforms = */ 8, + /* .MaxGeometryTextureImageUnits = */ 16, + /* .MaxGeometryOutputVertices = */ 256, + /* .MaxGeometryTotalOutputComponents = */ 1024, + /* .MaxGeometryUniformComponents = */ 1024, + /* .MaxGeometryVaryingComponents = */ 64, + /* .MaxTessControlInputComponents = */ 128, + /* .MaxTessControlOutputComponents = */ 128, + /* .MaxTessControlTextureImageUnits = */ 16, + /* .MaxTessControlUniformComponents = */ 1024, + /* .MaxTessControlTotalOutputComponents = */ 4096, + /* .MaxTessEvaluationInputComponents = */ 128, + /* .MaxTessEvaluationOutputComponents = */ 128, + /* .MaxTessEvaluationTextureImageUnits = */ 16, + /* .MaxTessEvaluationUniformComponents = */ 1024, + /* .MaxTessPatchComponents = */ 120, + /* .MaxPatchVertices = */ 32, + /* .MaxTessGenLevel = */ 64, + /* .MaxViewports = */ 16, + /* .MaxVertexAtomicCounters = */ 0, + /* .MaxTessControlAtomicCounters = */ 0, + /* .MaxTessEvaluationAtomicCounters = */ 0, + /* .MaxGeometryAtomicCounters = */ 0, + /* .MaxFragmentAtomicCounters = */ 8, + /* .MaxCombinedAtomicCounters = */ 8, + /* .MaxAtomicCounterBindings = */ 1, + /* .MaxVertexAtomicCounterBuffers = */ 0, + /* .MaxTessControlAtomicCounterBuffers = */ 0, + /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, + /* .MaxGeometryAtomicCounterBuffers = */ 0, + /* .MaxFragmentAtomicCounterBuffers = */ 1, + /* .MaxCombinedAtomicCounterBuffers = */ 1, + /* .MaxAtomicCounterBufferSize = */ 16384, + /* .MaxTransformFeedbackBuffers = */ 4, + /* .MaxTransformFeedbackInterleavedComponents = */ 64, + /* .MaxCullDistances = */ 8, + /* .MaxCombinedClipAndCullDistances = */ 8, + /* .MaxSamples = */ 4, + /* .limits = */ { + /* .nonInductiveForLoops = */ 1, + /* .whileLoops = */ 1, + /* .doWhileLoops = */ 1, + /* .generalUniformIndexing = */ 1, + /* .generalAttributeMatrixVectorIndexing = */ 1, + /* .generalVaryingIndexing = */ 1, + /* .generalSamplerIndexing = */ 1, + /* .generalVariableIndexing = */ 1, + /* .generalConstantMatrixVectorIndexing = */ 1, + }}; + +std::string GetDefaultTBuiltInResourceString() +{ + std::ostringstream ostream; + + ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n" + << "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n" + << "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n" + << "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n" + << "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n" + << "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n" + << "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n" + << "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n" + << "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n" + << "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n" + << "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n" + << "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n" + << "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n" + << "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n" + << "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n" + << "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n" + << "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n" + << "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n" + << "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n" + << "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n" + << "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n" + << "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n" + << "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n" + << "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n" + << "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n" + << "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n" + << "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n" + << "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n" + << "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n" + << "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n" + << "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n" + << "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n" + << "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n" + << "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n" + << "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n" + << "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n" + << "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n" + << "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n" + << "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n" + << "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n" + << "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n" + << "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n" + << "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n" + << "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n" + << "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n" + << "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n" + << "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n" + << "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n" + << "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n" + << "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n" + << "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n" + << "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n" + << "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n" + << "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n" + << "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n" + << "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n" + << "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n" + << "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n" + << "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n" + << "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n" + << "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n" + << "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n" + << "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n" + << "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n" + << "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n" + << "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n" + << "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n" + << "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n" + << "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n" + << "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n" + << "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n" + << "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n" + << "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n" + << "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n" + << "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n" + << "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n" + << "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n" + << "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n" + << "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n" + << "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n" + << "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n" + << "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n" + << "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n" + + << "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n" + << "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n" + << "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n" + << "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n" + << "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n" + << "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n" + << "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n" + << "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n" + << "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n" + ; + + return ostream.str(); +} + +} // end namespace glslang diff --git a/StandAlone/DefaultResourceLimits.h b/StandAlone/DefaultResourceLimits.h new file mode 100644 index 00000000..fa52a2a7 --- /dev/null +++ b/StandAlone/DefaultResourceLimits.h @@ -0,0 +1,54 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef _DEFAULT_RESOURCE_LIMITS_INCLUDED_ +#define _DEFAULT_RESOURCE_LIMITS_INCLUDED_ + +#include + +#include "glslang/Include/ResourceLimits.h" + +namespace glslang { + +// These are the default resources for TBuiltInResources, used for both +// - parsing this string for the case where the user didn't supply one, +// - dumping out a template for user construction of a config file. +extern const TBuiltInResource DefaultTBuiltInResource; + +// Returns the DefaultTBuiltInResource as a human-readable string. +std::string GetDefaultTBuiltInResourceString(); + +} // end namespace glslang + +#endif // _DEFAULT_RESOURCE_LIMITS_INCLUDED_ diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 6ebdb7f5..e8ab7b56 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -37,6 +37,7 @@ // this only applies to the standalone wrapper, not the front end in general #define _CRT_SECURE_NO_WARNINGS +#include "DefaultResourceLimits.h" #include "Worklist.h" #include "./../glslang/Include/ShHandle.h" #include "./../glslang/Include/revision.h" @@ -110,107 +111,6 @@ int NumShaderStrings; TBuiltInResource Resources; std::string ConfigFile; -// -// These are the default resources for TBuiltInResources, used for both -// - parsing this string for the case where the user didn't supply one -// - dumping out a template for user construction of a config file -// -const char* DefaultConfig = - "MaxLights 32\n" - "MaxClipPlanes 6\n" - "MaxTextureUnits 32\n" - "MaxTextureCoords 32\n" - "MaxVertexAttribs 64\n" - "MaxVertexUniformComponents 4096\n" - "MaxVaryingFloats 64\n" - "MaxVertexTextureImageUnits 32\n" - "MaxCombinedTextureImageUnits 80\n" - "MaxTextureImageUnits 32\n" - "MaxFragmentUniformComponents 4096\n" - "MaxDrawBuffers 32\n" - "MaxVertexUniformVectors 128\n" - "MaxVaryingVectors 8\n" - "MaxFragmentUniformVectors 16\n" - "MaxVertexOutputVectors 16\n" - "MaxFragmentInputVectors 15\n" - "MinProgramTexelOffset -8\n" - "MaxProgramTexelOffset 7\n" - "MaxClipDistances 8\n" - "MaxComputeWorkGroupCountX 65535\n" - "MaxComputeWorkGroupCountY 65535\n" - "MaxComputeWorkGroupCountZ 65535\n" - "MaxComputeWorkGroupSizeX 1024\n" - "MaxComputeWorkGroupSizeY 1024\n" - "MaxComputeWorkGroupSizeZ 64\n" - "MaxComputeUniformComponents 1024\n" - "MaxComputeTextureImageUnits 16\n" - "MaxComputeImageUniforms 8\n" - "MaxComputeAtomicCounters 8\n" - "MaxComputeAtomicCounterBuffers 1\n" - "MaxVaryingComponents 60\n" - "MaxVertexOutputComponents 64\n" - "MaxGeometryInputComponents 64\n" - "MaxGeometryOutputComponents 128\n" - "MaxFragmentInputComponents 128\n" - "MaxImageUnits 8\n" - "MaxCombinedImageUnitsAndFragmentOutputs 8\n" - "MaxCombinedShaderOutputResources 8\n" - "MaxImageSamples 0\n" - "MaxVertexImageUniforms 0\n" - "MaxTessControlImageUniforms 0\n" - "MaxTessEvaluationImageUniforms 0\n" - "MaxGeometryImageUniforms 0\n" - "MaxFragmentImageUniforms 8\n" - "MaxCombinedImageUniforms 8\n" - "MaxGeometryTextureImageUnits 16\n" - "MaxGeometryOutputVertices 256\n" - "MaxGeometryTotalOutputComponents 1024\n" - "MaxGeometryUniformComponents 1024\n" - "MaxGeometryVaryingComponents 64\n" - "MaxTessControlInputComponents 128\n" - "MaxTessControlOutputComponents 128\n" - "MaxTessControlTextureImageUnits 16\n" - "MaxTessControlUniformComponents 1024\n" - "MaxTessControlTotalOutputComponents 4096\n" - "MaxTessEvaluationInputComponents 128\n" - "MaxTessEvaluationOutputComponents 128\n" - "MaxTessEvaluationTextureImageUnits 16\n" - "MaxTessEvaluationUniformComponents 1024\n" - "MaxTessPatchComponents 120\n" - "MaxPatchVertices 32\n" - "MaxTessGenLevel 64\n" - "MaxViewports 16\n" - "MaxVertexAtomicCounters 0\n" - "MaxTessControlAtomicCounters 0\n" - "MaxTessEvaluationAtomicCounters 0\n" - "MaxGeometryAtomicCounters 0\n" - "MaxFragmentAtomicCounters 8\n" - "MaxCombinedAtomicCounters 8\n" - "MaxAtomicCounterBindings 1\n" - "MaxVertexAtomicCounterBuffers 0\n" - "MaxTessControlAtomicCounterBuffers 0\n" - "MaxTessEvaluationAtomicCounterBuffers 0\n" - "MaxGeometryAtomicCounterBuffers 0\n" - "MaxFragmentAtomicCounterBuffers 1\n" - "MaxCombinedAtomicCounterBuffers 1\n" - "MaxAtomicCounterBufferSize 16384\n" - "MaxTransformFeedbackBuffers 4\n" - "MaxTransformFeedbackInterleavedComponents 64\n" - "MaxCullDistances 8\n" - "MaxCombinedClipAndCullDistances 8\n" - "MaxSamples 4\n" - - "nonInductiveForLoops 1\n" - "whileLoops 1\n" - "doWhileLoops 1\n" - "generalUniformIndexing 1\n" - "generalAttributeMatrixVectorIndexing 1\n" - "generalVaryingIndexing 1\n" - "generalSamplerIndexing 1\n" - "generalVariableIndexing 1\n" - "generalConstantMatrixVectorIndexing 1\n" - ; - // // Parse either a .conf file provided by the user or the default string above. // @@ -229,8 +129,8 @@ void ProcessConfigFile() } if (config == 0) { - config = new char[strlen(DefaultConfig) + 1]; - strcpy(config, DefaultConfig); + Resources = glslang::DefaultTBuiltInResource; + return; } const char* delims = " \t\n\r"; @@ -832,7 +732,7 @@ int C_DECL main(int argc, char* argv[]) ProcessArguments(argc, argv); if (Options & EOptionDumpConfig) { - printf("%s", DefaultConfig); + printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str()); if (Worklist.empty()) return ESuccess; } diff --git a/Test/baseResults/spv.330.geom.out b/Test/baseResults/spv.330.geom.out old mode 100755 new mode 100644 diff --git a/Test/baseResults/spv.test.frag.out b/Test/baseResults/spv.test.frag.out old mode 100755 new mode 100644 diff --git a/Test/baseResults/spv.test.vert.out b/Test/baseResults/spv.test.vert.out old mode 100755 new mode 100644 diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp new file mode 100644 index 00000000..5e0b31e9 --- /dev/null +++ b/gtests/AST.FromFile.cpp @@ -0,0 +1,191 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using CompileToAstTest = GlslangTest<::testing::TestWithParam>; + +TEST_P(CompileToAstTest, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::OpenGL, Target::AST); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, CompileToAstTest, + ::testing::ValuesIn(std::vector({ + "sample.frag", + "sample.vert", + "decls.frag", + "specExamples.frag", + "specExamples.vert", + "versionsClean.frag", + "versionsClean.vert", + "versionsErrors.frag", + "versionsErrors.vert", + "100.frag", + "120.vert", + "120.frag", + "130.vert", + "130.frag", + "140.vert", + "140.frag", + "150.vert", + "150.geom", + "150.frag", + "precision.frag", + "precision.vert", + "nonSquare.vert", + "matrixError.vert", + "cppSimple.vert", + "cppIndent.vert", + "cppNest.vert", + "cppComplexExpr.vert", + "badChars.frag", + "pointCoord.frag", + "array.frag", + "array100.frag", + "comment.frag", + "300.vert", + "300.frag", + "300BuiltIns.frag", + "300layout.vert", + "300layout.frag", + "300operations.frag", + "300block.frag", + "310.comp", + "310.vert", + "310.geom", + "310.frag", + "310.tesc", + "310.tese", + "310implicitSizeArrayError.vert", + "310AofA.vert", + "330.frag", + "330comp.frag", + "constErrors.frag", + "constFold.frag", + "errors.frag", + "forwardRef.frag", + "uint.frag", + "switch.frag", + "tokenLength.vert", + "100Limits.vert", + "100scope.vert", + "110scope.vert", + "300scope.vert", + "400.frag", + "420.frag", + "420.vert", + "420.geom", + "420_size_gl_in.geom", + "430scope.vert", + "lineContinuation100.vert", + "lineContinuation.vert", + "numeral.frag", + "400.geom", + "400.tesc", + "400.tese", + "410.tesc", + "420.tesc", + "420.tese", + "410.geom", + "430.vert", + "430.comp", + "430AofA.frag", + "440.vert", + "440.frag", + "450.vert", + "450.geom", + "450.tesc", + "450.tese", + "450.frag", + "450.comp", + "dce.frag", + "atomic_uint.frag", + "aggOps.frag", + "always-discard.frag", + "always-discard2.frag", + "conditionalDiscard.frag", + "conversion.frag", + "dataOut.frag", + "dataOutIndirect.frag", + "deepRvalue.frag", + "depthOut.frag", + "discard-dce.frag", + "doWhileLoop.frag", + "earlyReturnDiscard.frag", + "flowControl.frag", + "forLoop.frag", + "functionCall.frag", + "functionSemantics.frag", + "length.frag", + "localAggregates.frag", + "loops.frag", + "loopsArtificial.frag", + "matrix.frag", + "matrix2.frag", + "newTexture.frag", + "Operations.frag", + "prepost.frag", + "simpleFunctionCall.frag", + "structAssignment.frag", + "structDeref.frag", + "structure.frag", + "swizzle.frag", + "syntaxError.frag", + "test.frag", + "texture.frag", + "types.frag", + "uniformArray.frag", + "variableArrayIndex.frag", + "varyingArray.frag", + "varyingArrayIndirect.frag", + "voidFunction.frag", + "whileLoop.frag", + "nonVulkan.frag", + "spv.atomic.comp", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/BuiltInResource.FromFile.cpp b/gtests/BuiltInResource.FromFile.cpp new file mode 100644 index 00000000..c2d2b8b6 --- /dev/null +++ b/gtests/BuiltInResource.FromFile.cpp @@ -0,0 +1,57 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "StandAlone/DefaultResourceLimits.h" +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using DefaultResourceTest = GlslangTest<::testing::Test>; + +TEST_F(DefaultResourceTest, FromFile) +{ + const std::string path = GLSLANG_TEST_DIRECTORY "/baseResults/test.conf"; + std::string expectedConfig; + tryLoadFile(path, "expected resource limit", &expectedConfig); + const std::string realConfig = glslang::GetDefaultTBuiltInResourceString(); + ASSERT_EQ(expectedConfig, realConfig); +} + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/CMakeLists.txt b/gtests/CMakeLists.txt new file mode 100644 index 00000000..57378cea --- /dev/null +++ b/gtests/CMakeLists.txt @@ -0,0 +1,32 @@ +if (TARGET gmock) + message(STATUS "Google Mock found - building tests") + + set(TEST_SOURCES + # Framework related source files + ${CMAKE_CURRENT_SOURCE_DIR}/Initializer.h + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Settings.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Settings.h + ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.h + + # Test related source files + ${CMAKE_CURRENT_SOURCE_DIR}/AST.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BuiltInResource.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp + ) + + add_executable(glslangtests ${TEST_SOURCES}) + target_compile_definitions(glslangtests + PRIVATE GLSLANG_TEST_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/../Test") + target_include_directories(glslangtests PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${gmock_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/include) + target_link_libraries(glslangtests PRIVATE + glslang OSDependent OGLCompiler glslang + SPIRV glslang-default-resource-limits gmock) + add_test(NAME glslang-gtests COMMAND glslangtests) +endif() diff --git a/gtests/Initializer.h b/gtests/Initializer.h new file mode 100644 index 00000000..e8fa30d1 --- /dev/null +++ b/gtests/Initializer.h @@ -0,0 +1,119 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_INITIALIZER_H +#define GLSLANG_GTESTS_INITIALIZER_H + +#include + +#include "glslang/Public/ShaderLang.h" + +namespace glslangtest { + +// Initializes glslang on creation, and destroys it on completion. +// And provides .Acquire() as a way to reinitialize glslang if semantics change. +// This object is expected to be a singleton, so that internal glslang state +// can be correctly handled. +// +// TODO(antiagainst): It's a known bug that some of the internal states need to +// be reset if semantics change: +// https://github.com/KhronosGroup/glslang/issues/166 +// Therefore, the following mechanism is needed. Remove this once the above bug +// gets fixed. +class GlslangInitializer { +public: + GlslangInitializer() : lastMessages(EShMsgDefault) + { + glslang::InitializeProcess(); + } + + ~GlslangInitializer() { glslang::FinalizeProcess(); } + + // A token indicates that the glslang is reinitialized (if necessary) to the + // required semantics. And that won't change until the token is destroyed. + class InitializationToken { + public: + InitializationToken() : initializer(nullptr) {} + ~InitializationToken() + { + if (initializer) { + initializer->release(); + } + } + + InitializationToken(InitializationToken&& other) + : initializer(other.initializer) + { + other.initializer = nullptr; + } + + InitializationToken(const InitializationToken&) = delete; + + private: + InitializationToken(GlslangInitializer* initializer) + : initializer(initializer) {} + + friend class GlslangInitializer; + GlslangInitializer* initializer; + }; + + // Obtains exclusive access to the glslang state. The state remains + // exclusive until the Initialization Token has been destroyed. + // Re-initializes glsl state iff the previous messages and the current + // messages are incompatible. + InitializationToken acquire(EShMessages new_messages) + { + stateLock.lock(); + + if ((lastMessages ^ new_messages) & + (EShMsgVulkanRules | EShMsgSpvRules)) { + glslang::FinalizeProcess(); + glslang::InitializeProcess(); + } + lastMessages = new_messages; + return InitializationToken(this); + } + +private: + void release() { stateLock.unlock(); } + + friend class InitializationToken; + + EShMessages lastMessages; + std::mutex stateLock; +}; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_INITIALIZER_H diff --git a/gtests/Pp.FromFile.cpp b/gtests/Pp.FromFile.cpp new file mode 100644 index 00000000..cfd987ba --- /dev/null +++ b/gtests/Pp.FromFile.cpp @@ -0,0 +1,74 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using PreprocessingTest = GlslangTest<::testing::TestWithParam>; + +TEST_P(PreprocessingTest, FromFile) +{ + loadFilePreprocessAndCheck(GLSLANG_TEST_DIRECTORY, GetParam()); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, PreprocessingTest, + ::testing::ValuesIn(std::vector({ + "preprocessor.cpp_style_line_directive.vert", + "preprocessor.cpp_style___FILE__.vert", + "preprocessor.edge_cases.vert", + "preprocessor.errors.vert", + "preprocessor.extensions.vert", + "preprocessor.function_macro.vert", + "preprocessor.include.enabled.vert", + "preprocessor.include.disabled.vert", + "preprocessor.line.vert", + "preprocessor.line.frag", + "preprocessor.pragma.vert", + "preprocessor.simple.vert", + "preprocessor.success_if_parse_would_fail.vert", + "preprocessor.defined.vert", + "preprocessor.many.endif.vert", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/README.md b/gtests/README.md new file mode 100644 index 00000000..c8261cc4 --- /dev/null +++ b/gtests/README.md @@ -0,0 +1,26 @@ +Glslang Tests based on the Google Test Framework +================================================ + +This directory contains [Google Test][gtest] based test fixture and test +cases for glslang. + +Apart from typical unit tests, necessary utility methods are added into +the [`GlslangTests`](TestFixture.h) fixture to provide the ability to do +file-based integration tests. Various `*.FromFile.cpp` files lists names +of files containing input shader code in the `Test/` directory. Utility +methods will load the input shader source, compile them, and compare with +the corresponding expected output in the `Test/baseResults/` directory. + +How to run the tests +-------------------- + +Please make sure you have a copy of [Google Test][gtest] checked out under +the `External` directory before building. After building, just run the +`ctest` command or the `gtests/glslangtests` binary in your build directory. + +The `gtests/glslangtests` binary also provides an `--update-mode` command +line option, which, if supplied, will overwrite the golden files under +the `Test/baseResults/` directory with real output from that invocation. +This serves as an easy way to update golden files. + +[gtest]: https://github.com/google/googletest diff --git a/gtests/Settings.cpp b/gtests/Settings.cpp new file mode 100644 index 00000000..4ba7989b --- /dev/null +++ b/gtests/Settings.cpp @@ -0,0 +1,41 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "Settings.h" + +namespace glslangtest { + +GTestSettings GlobalTestSettings = {nullptr, false}; + +} // namespace glslangtest diff --git a/gtests/Settings.h b/gtests/Settings.h new file mode 100644 index 00000000..30056a7b --- /dev/null +++ b/gtests/Settings.h @@ -0,0 +1,54 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_SETTINGS_H +#define GLSLANG_GTESTS_SETTINGS_H + +namespace glslangtest { + +class GlslangInitializer; + +struct GTestSettings { + // A handle to GlslangInitializer instance. + GlslangInitializer* initializer; + // An indicator of whether GTest should write real output to the file for + // the expected output. + bool updateMode; +}; + +extern GTestSettings GlobalTestSettings; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_SETTINGS_H diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp new file mode 100644 index 00000000..9cd0787a --- /dev/null +++ b/gtests/Spv.FromFile.cpp @@ -0,0 +1,188 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using CompileToSpirvTest = GlslangTest<::testing::TestWithParam>; +using VulkanSemantics = GlslangTest<::testing::TestWithParam>; + +// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully +// generate SPIR-V. +TEST_P(CompileToSpirvTest, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::Vulkan, Target::Spirv); +} + +// GLSL-level Vulkan semantics test. Expected to error out before generating +// SPIR-V. +TEST_P(VulkanSemantics, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::Vulkan, Target::Spirv); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, CompileToSpirvTest, + ::testing::ValuesIn(std::vector({ + // Test looping constructs. + // No tests yet for making sure break and continue from a nested loop + // goes to the innermost target. + "spv.do-simple.vert", + "spv.do-while-continue-break.vert", + "spv.for-complex-condition.vert", + "spv.for-continue-break.vert", + "spv.for-simple.vert", + "spv.for-notest.vert", + "spv.for-nobody.vert", + "spv.while-continue-break.vert", + "spv.while-simple.vert", + // vulkan-specific tests + "spv.set.vert", + "spv.double.comp", + "spv.100ops.frag", + "spv.130.frag", + "spv.140.frag", + "spv.150.geom", + "spv.150.vert", + "spv.300BuiltIns.vert", + "spv.300layout.frag", + "spv.300layout.vert", + "spv.300layoutp.vert", + "spv.310.comp", + "spv.330.geom", + "spv.400.frag", + "spv.400.tesc", + "spv.400.tese", + "spv.420.geom", + "spv.430.vert", + "spv.accessChain.frag", + "spv.aggOps.frag", + "spv.always-discard.frag", + "spv.always-discard2.frag", + "spv.bitCast.frag", + "spv.bool.vert", + "spv.boolInBlock.frag", + "spv.branch-return.vert", + "spv.conditionalDiscard.frag", + "spv.conversion.frag", + "spv.dataOut.frag", + "spv.dataOutIndirect.frag", + "spv.dataOutIndirect.vert", + "spv.deepRvalue.frag", + "spv.depthOut.frag", + "spv.discard-dce.frag", + "spv.doWhileLoop.frag", + "spv.earlyReturnDiscard.frag", + "spv.flowControl.frag", + "spv.forLoop.frag", + "spv.forwardFun.frag", + "spv.functionCall.frag", + "spv.functionSemantics.frag", + "spv.interpOps.frag", + "spv.layoutNested.vert", + "spv.length.frag", + "spv.localAggregates.frag", + "spv.loops.frag", + "spv.loopsArtificial.frag", + "spv.matFun.vert", + "spv.matrix.frag", + "spv.matrix2.frag", + "spv.memoryQualifier.frag", + "spv.merge-unreachable.frag", + "spv.newTexture.frag", + "spv.noDeadDecorations.vert", + "spv.nonSquare.vert", + "spv.Operations.frag", + "spv.intOps.vert", + "spv.precision.frag", + "spv.prepost.frag", + "spv.qualifiers.vert", + "spv.shiftOps.frag", + "spv.simpleFunctionCall.frag", + "spv.simpleMat.vert", + "spv.sparseTexture.frag", + "spv.sparseTextureClamp.frag", + "spv.structAssignment.frag", + "spv.structDeref.frag", + "spv.structure.frag", + "spv.switch.frag", + "spv.swizzle.frag", + "spv.test.frag", + "spv.test.vert", + "spv.texture.frag", + "spv.texture.vert", + "spv.image.frag", + "spv.types.frag", + "spv.uint.frag", + "spv.uniformArray.frag", + "spv.variableArrayIndex.frag", + "spv.varyingArray.frag", + "spv.varyingArrayIndirect.frag", + "spv.voidFunction.frag", + "spv.whileLoop.frag", + "spv.AofA.frag", + "spv.queryL.frag", + "spv.separate.frag", + "spv.shortCircuit.frag", + "spv.pushConstant.vert", + "spv.subpass.frag", + "spv.specConstant.vert", + "spv.specConstant.comp", + "spv.specConstantComposite.vert", + })), + FileNameAsCustomTestName +); + +INSTANTIATE_TEST_CASE_P( + Glsl, VulkanSemantics, + ::testing::ValuesIn(std::vector({ + "vulkan.frag", + "vulkan.vert", + "vulkan.comp", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/TestFixture.cpp b/gtests/TestFixture.cpp new file mode 100644 index 00000000..744fa558 --- /dev/null +++ b/gtests/TestFixture.cpp @@ -0,0 +1,124 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "TestFixture.h" + +namespace glslangtest { + +std::string FileNameAsCustomTestName( + const ::testing::TestParamInfo& info) +{ + std::string name = info.param; + // A valid test case suffix cannot have '.' and '-' inside. + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '-', '_'); + return name; +} + +EShLanguage GetGlslLanguageForStage(const std::string& stage) +{ + if (stage == "vert") { + return EShLangVertex; + } else if (stage == "tesc") { + return EShLangTessControl; + } else if (stage == "tese") { + return EShLangTessEvaluation; + } else if (stage == "geom") { + return EShLangGeometry; + } else if (stage == "frag") { + return EShLangFragment; + } else if (stage == "comp") { + return EShLangCompute; + } else { + assert(0 && "Unknown shader stage"); + return EShLangCount; + } +} + +EShMessages GetSpirvMessageOptionsForSemanticsAndTarget(Semantics semantics, + Target target) +{ + EShMessages result = EShMsgDefault; + + switch (target) { + case Target::AST: + result = EShMsgAST; + break; + case Target::Spirv: + result = EShMsgSpvRules; + break; + }; + + switch (semantics) { + case Semantics::OpenGL: + break; + case Semantics::Vulkan: + result = static_cast(result | EShMsgVulkanRules); + break; + } + + return result; +} + +std::pair ReadFile(const std::string& path) +{ + std::ifstream fstream(path, std::ios::in); + if (fstream) { + std::string contents; + fstream.seekg(0, std::ios::end); + contents.reserve(fstream.tellg()); + fstream.seekg(0, std::ios::beg); + contents.assign((std::istreambuf_iterator(fstream)), + std::istreambuf_iterator()); + return std::make_pair(true, contents); + } + return std::make_pair(false, ""); +} + +bool WriteFile(const std::string& path, const std::string& contents) +{ + std::ofstream fstream(path, std::ios::out); + if (!fstream) return false; + fstream << contents; + fstream.flush(); + return true; +} + +std::string GetSuffix(const std::string& name) +{ + const size_t pos = name.rfind('.'); + return (pos == std::string::npos) ? "" : name.substr(name.rfind('.') + 1); +} + +} // namespace glslangtest diff --git a/gtests/TestFixture.h b/gtests/TestFixture.h new file mode 100644 index 00000000..87a365b5 --- /dev/null +++ b/gtests/TestFixture.h @@ -0,0 +1,307 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_TEST_FIXTURE_H +#define GLSLANG_GTESTS_TEST_FIXTURE_H + +#include +#include +#include +#include +#include + +#include + +#include "SPIRV/GlslangToSpv.h" +#include "SPIRV/disassemble.h" +#include "SPIRV/doc.h" +#include "StandAlone/DefaultResourceLimits.h" +#include "glslang/Public/ShaderLang.h" + +#include "Initializer.h" +#include "Settings.h" + +// We need CMake to provide us the absolute path to the directory containing +// test files, so we are certain to find those files no matter where the test +// harness binary is generated. This provides out-of-source build capability. +#ifndef GLSLANG_TEST_DIRECTORY +#error \ + "GLSLANG_TEST_DIRECTORY needs to be defined for gtest to locate test files." +#endif + +namespace glslangtest { + +// This function is used to provide custom test name suffixes based on the +// shader source file names. Otherwise, the test name suffixes will just be +// numbers, which are not quite obvious. +std::string FileNameAsCustomTestName( + const ::testing::TestParamInfo& info); + +// Enum for shader compilation semantics. +enum class Semantics { + OpenGL, + Vulkan, +}; + +// Enum for compilation target. +enum class Target { + AST, + Spirv, +}; + +EShLanguage GetGlslLanguageForStage(const std::string& stage); + +EShMessages GetSpirvMessageOptionsForSemanticsAndTarget(Semantics semantics, + Target target); + +// Reads the content of the file at the given |path|. On success, returns true +// and the contents; otherwise, returns false and an empty string. +std::pair ReadFile(const std::string& path); + +// Writes the given |contents| into the file at the given |path|. Returns true +// on successful output. +bool WriteFile(const std::string& path, const std::string& contents); + +// Returns the suffix of the given |name|. +std::string GetSuffix(const std::string& name); + +// Base class for glslang integration tests. It contains many handy utility-like +// methods such as reading shader source files, compiling into AST/SPIR-V, and +// comparing with expected outputs. +// +// To write value-Parameterized tests: +// using ValueParamTest = GlslangTest<::testing::TestWithParam>; +// To use as normal fixture: +// using FixtureTest = GlslangTest<::testing::Test>; +template +class GlslangTest : public GT { +public: + GlslangTest() + : defaultVersion(100), + defaultProfile(ENoProfile), + forceVersionProfile(false), + isForwardCompatible(false) {} + + // Tries to load the contents from the file at the given |path|. On success, + // writes the contents into |contents|. On failure, errors out. + void tryLoadFile(const std::string& path, const std::string& tag, + std::string* contents) + { + bool fileReadOk; + std::tie(fileReadOk, *contents) = ReadFile(path); + ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path; + } + + // Checks the equality of |expected| and |real|. If they are not equal, + // write + // |real| to the given file named as |fname| if update mode is on. + void checkEqAndUpdateIfRequested(const std::string& expected, + const std::string& real, + const std::string& fname) + { + // In order to output the message we want under proper circumstances, we + // need the following operator<< stuff. + EXPECT_EQ(expected, real) + << (GlobalTestSettings.updateMode + ? ("Mismatch found and update mode turned on - " + "flushing expected result output.") + : ""); + + // Update the expected output file if requested. + // It looks weird to duplicate the comparison between expected_output + // and + // stream.str(). However, if creating a variable for the comparison + // result, + // we cannot have pretty print of the string diff in the above. + if (GlobalTestSettings.updateMode && expected != real) { + EXPECT_TRUE(WriteFile(fname, real)) << "Flushing failed"; + } + } + + // A struct for holding all the information returned by glslang compilation + // and linking. + struct GlslangResult { + const std::string compilationOutput; + const std::string compilationError; + const std::string linkingOutput; + const std::string linkingError; + const std::string spirv; // Optional SPIR-V disassembly text. + }; + + // Compiles and linkes the given GLSL |source| code of the given shader + // |stage| into the given |target| under the given |semantics|. Returns + // a GlslangResult instance containing all the information generated + // during the process. If |target| is Target::Spirv, also disassembles + // the result and returns disassembly text. + GlslangResult compileGlsl(const std::string& source, + const std::string& stage, Semantics semantics, + Target target) + { + const char* shaderStrings = source.data(); + const int shaderLengths = static_cast(source.size()); + const EShLanguage language = GetGlslLanguageForStage(stage); + + glslang::TShader shader(language); + shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); + const EShMessages messages = + GetSpirvMessageOptionsForSemanticsAndTarget(semantics, target); + // Reinitialize glslang if the semantics change. + GlslangInitializer::InitializationToken token = + GlobalTestSettings.initializer->acquire(messages); + bool success = + shader.parse(&glslang::DefaultTBuiltInResource, defaultVersion, + isForwardCompatible, messages); + + glslang::TProgram program; + program.addShader(&shader); + success &= program.link(messages); + + if (success && target == Target::Spirv) { + std::vector spirv_binary; + glslang::GlslangToSpv(*program.getIntermediate(language), + spirv_binary); + + std::ostringstream disassembly_stream; + spv::Parameterize(); + spv::Disassemble(disassembly_stream, spirv_binary); + return {shader.getInfoLog(), shader.getInfoDebugLog(), + program.getInfoLog(), program.getInfoDebugLog(), + disassembly_stream.str()}; + } else { + return {shader.getInfoLog(), shader.getInfoDebugLog(), + program.getInfoLog(), program.getInfoDebugLog(), ""}; + } + } + + void loadFileCompileAndCheck(const std::string& testDir, + const std::string& testName, + Semantics semantics, Target target) + { + const std::string inputFname = testDir + "/" + testName; + const std::string expectedOutputFname = + testDir + "/baseResults/" + testName + ".out"; + std::string input, expectedOutput; + + tryLoadFile(inputFname, "input", &input); + tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); + + GlslangResult result = + compileGlsl(input, GetSuffix(testName), semantics, target); + + // Generate the hybrid output in the way of glslangValidator. + std::ostringstream stream; + + const auto outputIfNotEmpty = [&stream](const std::string& str) { + if (!str.empty()) stream << str << "\n"; + }; + + stream << testName << "\n"; + outputIfNotEmpty(result.compilationOutput); + outputIfNotEmpty(result.compilationError); + outputIfNotEmpty(result.linkingOutput); + outputIfNotEmpty(result.linkingError); + if (target == Target::Spirv) { + stream + << (result.spirv.empty() + ? "SPIR-V is not generated for failed compile or link\n" + : result.spirv); + } + + checkEqAndUpdateIfRequested(expectedOutput, stream.str(), + expectedOutputFname); + } + + // Preprocesses the given GLSL |source| code. On success, returns true, the + // preprocessed shader, and warning messages. Otherwise, returns false, an + // empty string, and error messages. + std::tuple preprocessGlsl( + const std::string& source) + { + const char* shaderStrings = source.data(); + const int shaderLengths = static_cast(source.size()); + + glslang::TShader shader(EShLangVertex); + shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); + std::string ppShader; + glslang::TShader::ForbidInclude includer; + const bool success = shader.preprocess( + &glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile, + forceVersionProfile, isForwardCompatible, EShMsgOnlyPreprocessor, + &ppShader, includer); + + std::string log = shader.getInfoLog(); + log += shader.getInfoDebugLog(); + if (success) { + return std::make_tuple(true, ppShader, log); + } else { + return std::make_tuple(false, "", log); + } + } + + void loadFilePreprocessAndCheck(const std::string& testDir, + const std::string& testName) + { + const std::string inputFname = testDir + "/" + testName; + const std::string expectedOutputFname = + testDir + "/baseResults/" + testName + ".out"; + const std::string expectedErrorFname = + testDir + "/baseResults/" + testName + ".err"; + std::string input, expectedOutput, expectedError; + + tryLoadFile(inputFname, "input", &input); + tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); + tryLoadFile(expectedErrorFname, "expected error", &expectedError); + + bool ppOk; + std::string output, error; + std::tie(ppOk, output, error) = preprocessGlsl(input); + if (!output.empty()) output += '\n'; + if (!error.empty()) error += '\n'; + + checkEqAndUpdateIfRequested(expectedOutput, output, + expectedOutputFname); + checkEqAndUpdateIfRequested(expectedError, error, + expectedErrorFname); + } + +private: + const int defaultVersion; + const EProfile defaultProfile; + const bool forceVersionProfile; + const bool isForwardCompatible; +}; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_TEST_FIXTURE_H diff --git a/gtests/main.cpp b/gtests/main.cpp new file mode 100644 index 00000000..b9806aa2 --- /dev/null +++ b/gtests/main.cpp @@ -0,0 +1,63 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "Initializer.h" +#include "Settings.h" + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + std::unique_ptr initializer( + new glslangtest::GlslangInitializer); + + glslangtest::GlobalTestSettings.initializer = initializer.get(); + + for (int i = 1; i < argc; ++i) { + if (!strncmp("--update-mode", argv[i], 13)) { + glslangtest::GlobalTestSettings.updateMode = true; + break; + } + } + + const int result = RUN_ALL_TESTS(); + + glslangtest::GlobalTestSettings.initializer = nullptr; + + return result; +} From 5c61d8e0f95981359db3353383677773040509ca Mon Sep 17 00:00:00 2001 From: qining Date: Thu, 31 Mar 2016 13:57:28 -0400 Subject: [PATCH 16/20] fix format; remove unnecessary parameters; rename some spec op mode guard class; remove support of float point comparison and composite type comparison; update the tests. --- SPIRV/GlslangToSpv.cpp | 21 ++- SPIRV/SpvBuilder.cpp | 86 +-------- .../spv.specConstantOperations.vert.out | 169 +++++------------- Test/spv.specConstantOperations.vert | 45 +---- 4 files changed, 63 insertions(+), 258 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index ee48b3c1..9622a775 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3855,21 +3855,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla } namespace { -class SpecConstOpCodeGenerationSettingGuard{ - public: - SpecConstOpCodeGenerationSettingGuard(spv::Builder* builder, - bool shouldGeneratingForSpecConst) +class SpecConstantOpModeGuard { +public: + SpecConstantOpModeGuard(spv::Builder* builder) : builder_(builder) { previous_flag_ = builder->isInSpecConstCodeGenMode(); - shouldGeneratingForSpecConst ? builder->setToSpecConstCodeGenMode() - : builder->setToNormalCodeGenMode(); + builder->setToSpecConstCodeGenMode(); } - ~SpecConstOpCodeGenerationSettingGuard() { + ~SpecConstantOpModeGuard() { previous_flag_ ? builder_->setToSpecConstCodeGenMode() : builder_->setToNormalCodeGenMode(); } - private: +private: spv::Builder* builder_; bool previous_flag_; }; @@ -3877,7 +3875,8 @@ class SpecConstOpCodeGenerationSettingGuard{ // Create constant ID from const initializer sub tree. spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( - glslang::TIntermTyped* subTree) { + glslang::TIntermTyped* subTree) +{ const glslang::TType& glslangType = subTree->getType(); spv::Id typeId = convertGlslangToSpvType(glslangType); bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); @@ -3909,7 +3908,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( // Spec constants defined with binary operations and other constants requires // OpSpecConstantOp instruction. - SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true); + SpecConstantOpModeGuard set_to_spec_const_mode(&builder); bn->traverse(this); return accessChainLoad(bn->getType()); @@ -3920,7 +3919,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( // Spec constants defined with unary operations and other constants requires // OpSpecConstantOp instruction. - SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true); + SpecConstantOpModeGuard set_to_spec_const_mode(&builder); un->traverse(this); return accessChainLoad(un->getType()); diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 3c0e2f63..4235f273 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -1229,90 +1229,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) return op->getResultId(); } -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) { - switch(opCode) { - // OpCodes that do not need any capababilities. - case OpSConvert: - case OpFConvert: - case OpSNegate: - case OpNot: - case OpIAdd: - case OpISub: - case OpIMul: - case OpUDiv: - case OpSDiv: - case OpUMod: - case OpSRem: - case OpSMod: - case OpShiftRightLogical: - case OpShiftRightArithmetic: - case OpShiftLeftLogical: - case OpBitwiseOr: - case OpBitwiseXor: - case OpBitwiseAnd: - case OpVectorShuffle: - case OpCompositeExtract: - case OpCompositeInsert: - case OpLogicalOr: - case OpLogicalAnd: - case OpLogicalNot: - case OpLogicalEqual: - case OpLogicalNotEqual: - case OpSelect: - case OpIEqual: - case OpULessThan: - case OpSLessThan: - case OpUGreaterThan: - case OpSGreaterThan: - case OpULessThanEqual: - case OpSLessThanEqual: - case OpUGreaterThanEqual: - case OpSGreaterThanEqual: - // Added temporarily to enable compsite type spec constants comparison. - // Remove this comment after Spec being updated. - case OpAll: - case OpAny: - case OpFOrdEqual: - case OpFUnordEqual: - case OpFOrdNotEqual: - case OpFUnordNotEqual: - break; - - // OpCodes that need Shader capability. - case OpQuantizeToF16: - addCapability(CapabilityShader); - break; - - // OpCodes that need Kernel capability. - case OpConvertFToS: - case OpConvertSToF: - case OpConvertFToU: - case OpConvertUToF: - case OpUConvert: - case OpConvertPtrToU: - case OpConvertUToPtr: - case OpGenericCastToPtr: - case OpPtrCastToGeneric: - case OpBitcast: - case OpFNegate: - case OpFAdd: - case OpFSub: - case OpFMul: - case OpFDiv: - case OpFRem: - case OpFMod: - case OpAccessChain: - case OpInBoundsAccessChain: - case OpPtrAccessChain: - case OpInBoundsPtrAccessChain: - addCapability(CapabilityKernel); - break; - - default: - // Invalid OpCode for Spec Constant operations. - return NoResult; - } - +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) +{ Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); op->addImmediateOperand((unsigned) opCode); for (auto it = operands.cbegin(); it != operands.cend(); ++it) diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out index c3eaedd5..476efc90 100644 --- a/Test/baseResults/spv.specConstantOperations.vert.out +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -7,21 +7,15 @@ Linked vertex stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 163 +// Id's are bound by 94 Capability Shader - Capability Kernel Capability Float64 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" Source GLSL 450 Name 4 "main" - Name 108 "int_float_double_vec2" - MemberName 108(int_float_double_vec2) 0 "i" - MemberName 108(int_float_double_vec2) 1 "f" - MemberName 108(int_float_double_vec2) 2 "d" - MemberName 108(int_float_double_vec2) 3 "v" Decorate 7 SpecId 200 Decorate 9 SpecId 201 Decorate 11 SpecId 202 @@ -70,121 +64,52 @@ Linked vertex stage: 45: 8(int) SpecConstantOp 197 12 44 46: 10(int) Constant 512 47: 10(int) SpecConstantOp 198 11 46 - 48: 8(int) SpecConstantOp 124 11 - 49: 8(int) SpecConstantOp 199 12 48 - 50: TypeBool - 51: 50(bool) SpecConstantOp 177 9 12 - 52: 10(int) SpecConstantOp 124 12 - 53: 50(bool) SpecConstantOp 176 11 52 - 54: 10(int) SpecConstantOp 124 12 - 55: 50(bool) SpecConstantOp 176 54 11 - 56: TypeVector 8(int) 4 - 57: 8(int) Constant 30 - 58: 56(ivec4) SpecConstantComposite 39 57 9 9 - 59: TypeVector 10(int) 4 - 60: 10(int) Constant 4294967295 - 61: 10(int) Constant 4294967294 - 62: 59(ivec4) SpecConstantComposite 11 11 60 61 - 63: TypeVector 6(float) 4 - 64: 6(float) Constant 1067450368 - 65: 63(fvec4) SpecConstantComposite 7 64 7 64 - 66: TypeVector 13(float) 4 - 67: 66(fvec4) SpecConstantOp 115 65 - 68: 63(fvec4) SpecConstantOp 115 67 - 69: 56(ivec4) SpecConstantOp 200 58 - 70: 63(fvec4) SpecConstantOp 111 69 - 71: 56(ivec4) SpecConstantOp 126 58 - 72: 56(ivec4) ConstantComposite 18 18 18 18 - 73: 56(ivec4) SpecConstantOp 128 58 72 - 74: 56(ivec4) SpecConstantOp 128 58 72 - 75: 56(ivec4) ConstantComposite 21 21 21 21 - 76: 56(ivec4) SpecConstantOp 130 74 75 - 77: 56(ivec4) ConstantComposite 23 23 23 23 - 78: 56(ivec4) SpecConstantOp 130 76 77 - 79: 56(ivec4) SpecConstantOp 132 58 72 - 80: 56(ivec4) ConstantComposite 28 28 28 28 - 81: 56(ivec4) SpecConstantOp 135 79 80 - 82: 56(ivec4) SpecConstantOp 139 58 77 - 83: 56(ivec4) ConstantComposite 37 37 37 37 - 84: 56(ivec4) SpecConstantOp 195 58 83 - 85: 56(ivec4) SpecConstantOp 196 58 72 - 86: 8(int) Constant 1024 - 87: 56(ivec4) ConstantComposite 86 86 86 86 - 88: 56(ivec4) SpecConstantOp 197 58 87 - 89: 10(int) Constant 2048 - 90: 59(ivec4) ConstantComposite 89 89 89 89 - 91: 59(ivec4) SpecConstantOp 198 62 90 - 92: 56(ivec4) SpecConstantOp 124 62 - 93: 56(ivec4) SpecConstantOp 199 58 92 - 94: 10(int) Constant 0 - 95: 8(int) SpecConstantOp 81 58 0 - 96: TypeVector 8(int) 2 - 97: 96(ivec2) SpecConstantOp 79 58 58 1(GLSL.std.450) 0 - 98: TypeVector 8(int) 3 - 99: 98(ivec3) SpecConstantOp 79 58 58 2 1(GLSL.std.450) 0 - 100: 56(ivec4) SpecConstantOp 79 58 58 1(GLSL.std.450) 2 0 3 - 101: 59(ivec4) SpecConstantOp 124 58 - 102: TypeVector 50(bool) 4 - 103: 102(bvec4) SpecConstantOp 170 101 62 - 104: 50(bool) SpecConstantOp 155 103 - 105: 59(ivec4) SpecConstantOp 124 58 - 106: 50(bool) SpecConstantOp 154 0 - 107: TypeVector 6(float) 2 -108(int_float_double_vec2): TypeStruct 8(int) 6(float) 13(float) 107(fvec2) - 109: 6(float) Constant 1065353216 - 110: 107(fvec2) SpecConstantComposite 15 109 - 111:108(int_float_double_vec2) SpecConstantComposite 9 7 14 110 - 112: 107(fvec2) SpecConstantComposite 15 109 - 113:108(int_float_double_vec2) SpecConstantComposite 9 7 14 112 - 114: 8(int) SpecConstantOp 81 111 0 - 115: 8(int) SpecConstantOp 81 113 0 - 116: 50(bool) SpecConstantOp 170 114 115 - 117: 6(float) SpecConstantOp 81 111 1(GLSL.std.450) - 118: 6(float) SpecConstantOp 81 113 1(GLSL.std.450) - 119: 50(bool) SpecConstantOp 180 117 118 - 120: 50(bool) SpecConstantOp 167 116 119 - 121: 13(float) SpecConstantOp 81 111 2 - 122: 13(float) SpecConstantOp 81 113 2 - 123: 50(bool) SpecConstantOp 180 121 122 - 124: 50(bool) SpecConstantOp 167 120 123 - 125: 107(fvec2) SpecConstantOp 81 111 3 - 126: 107(fvec2) SpecConstantOp 81 113 3 - 127: TypeVector 50(bool) 2 - 128: 127(bvec2) SpecConstantOp 180 125 126 - 129: 50(bool) SpecConstantOp 155 128 - 130: 50(bool) SpecConstantOp 167 124 129 - 131: 8(int) SpecConstantOp 81 111 0 - 132: 8(int) SpecConstantOp 81 113 0 - 133: 6(float) SpecConstantOp 81 111 1(GLSL.std.450) - 134: 6(float) SpecConstantOp 81 113 1(GLSL.std.450) - 135: 50(bool) SpecConstantOp 182 133 134 - 136: 50(bool) SpecConstantOp 166 0 135 - 137: 13(float) SpecConstantOp 81 111 2 - 138: 13(float) SpecConstantOp 81 113 2 - 139: 50(bool) SpecConstantOp 182 137 138 - 140: 50(bool) SpecConstantOp 166 136 139 - 141: 107(fvec2) SpecConstantOp 81 111 3 - 142: 107(fvec2) SpecConstantOp 81 113 3 - 143: 127(bvec2) SpecConstantOp 182 141 142 - 144: 50(bool) SpecConstantOp 154 143 - 145: 50(bool) SpecConstantOp 166 140 144 - 146: TypeArray 6(float) 26 - 147: 146 SpecConstantComposite 7 7 - 148: 146 SpecConstantComposite 7 7 - 149: 6(float) SpecConstantOp 81 147 0 - 150: 6(float) SpecConstantOp 81 148 0 - 151: 50(bool) SpecConstantOp 180 149 150 - 152: 6(float) SpecConstantOp 81 147 1(GLSL.std.450) - 153: 6(float) SpecConstantOp 81 148 1(GLSL.std.450) - 154: 50(bool) SpecConstantOp 180 152 153 - 155: 50(bool) SpecConstantOp 167 151 154 - 156: 6(float) SpecConstantOp 81 147 0 - 157: 6(float) SpecConstantOp 81 148 0 - 158: 50(bool) SpecConstantOp 182 156 157 - 159: 6(float) SpecConstantOp 81 147 1(GLSL.std.450) - 160: 6(float) SpecConstantOp 81 148 1(GLSL.std.450) - 161: 50(bool) SpecConstantOp 182 159 160 - 162: 50(bool) SpecConstantOp 166 158 161 + 48: TypeBool + 49: 48(bool) SpecConstantOp 177 9 12 + 50: 48(bool) SpecConstantOp 170 11 11 + 51: 48(bool) SpecConstantOp 173 9 12 + 52: TypeVector 8(int) 4 + 53: 8(int) Constant 30 + 54: 52(ivec4) SpecConstantComposite 39 53 9 9 + 55: TypeVector 10(int) 4 + 56: 10(int) Constant 4294967295 + 57: 10(int) Constant 4294967294 + 58: 55(ivec4) SpecConstantComposite 11 11 56 57 + 59: TypeVector 6(float) 4 + 60: 6(float) Constant 1067450368 + 61: 59(fvec4) SpecConstantComposite 7 60 7 60 + 62: TypeVector 13(float) 4 + 63: 62(fvec4) SpecConstantOp 115 61 + 64: 59(fvec4) SpecConstantOp 115 63 + 65: 52(ivec4) SpecConstantOp 200 54 + 66: 52(ivec4) SpecConstantOp 126 54 + 67: 52(ivec4) ConstantComposite 18 18 18 18 + 68: 52(ivec4) SpecConstantOp 128 54 67 + 69: 52(ivec4) SpecConstantOp 128 54 67 + 70: 52(ivec4) ConstantComposite 21 21 21 21 + 71: 52(ivec4) SpecConstantOp 130 69 70 + 72: 52(ivec4) ConstantComposite 23 23 23 23 + 73: 52(ivec4) SpecConstantOp 130 71 72 + 74: 52(ivec4) SpecConstantOp 132 54 67 + 75: 52(ivec4) ConstantComposite 28 28 28 28 + 76: 52(ivec4) SpecConstantOp 135 74 75 + 77: 52(ivec4) SpecConstantOp 139 54 72 + 78: 52(ivec4) ConstantComposite 37 37 37 37 + 79: 52(ivec4) SpecConstantOp 195 54 78 + 80: 52(ivec4) SpecConstantOp 196 54 67 + 81: 8(int) Constant 1024 + 82: 52(ivec4) ConstantComposite 81 81 81 81 + 83: 52(ivec4) SpecConstantOp 197 54 82 + 84: 10(int) Constant 2048 + 85: 55(ivec4) ConstantComposite 84 84 84 84 + 86: 55(ivec4) SpecConstantOp 198 58 85 + 87: 10(int) Constant 0 + 88: 8(int) SpecConstantOp 81 54 0 + 89: TypeVector 8(int) 2 + 90: 89(ivec2) SpecConstantOp 79 54 54 1(GLSL.std.450) 0 + 91: TypeVector 8(int) 3 + 92: 91(ivec3) SpecConstantOp 79 54 54 2 1(GLSL.std.450) 0 + 93: 52(ivec4) SpecConstantOp 79 54 54 1(GLSL.std.450) 2 0 3 4(main): 2 Function None 3 5: Label Return diff --git a/Test/spv.specConstantOperations.vert b/Test/spv.specConstantOperations.vert index 93588bf8..9de96aee 100644 --- a/Test/spv.specConstantOperations.vert +++ b/Test/spv.specConstantOperations.vert @@ -41,12 +41,11 @@ const uint sp_uint_shift_left = sp_uint << 2; // Bitwise And, Or, Xor const int sp_sint_or_256 = sp_sint | 0x100; const uint sp_uint_xor_512 = sp_uint ^ 0x200; -const int sp_sint_and_sp_uint = sp_sint & int(sp_uint); -// Scalar comparison +/* // Scalar comparison */ const bool sp_int_lt_sp_sint = sp_int < sp_sint; -const bool sp_uint_lt_sp_sint = sp_uint < sp_sint; -const bool sp_sint_lt_sp_uint = sp_sint < sp_uint; +const bool sp_uint_equal_sp_uint = sp_uint == sp_uint; +const bool sp_int_gt_sp_sint = sp_int > sp_sint; // // Vectors @@ -60,7 +59,7 @@ const dvec4 fv_to_dv = dvec4(fv); const vec4 dv_to_fv = vec4(fv_to_dv); // Negate and Not -const vec4 not_iv = ~iv; +const ivec4 not_iv = ~iv; const ivec4 negate_iv = -iv; // Add and Subtract @@ -80,7 +79,6 @@ const ivec4 iv_shift_left = iv << 2; // Bitwise And, Or, Xor const ivec4 iv_or_1024 = iv | 0x400; const uvec4 uv_xor_2048 = uv ^ 0x800; -const ivec4 iv_and_uv = iv & ivec4(uv); // Swizzles const int iv_x = iv.x; @@ -88,40 +86,5 @@ const ivec2 iv_yx = iv.yx; const ivec3 iv_zyx = iv.zyx; const ivec4 iv_yzxw = iv.yzxw; -// Vector comparison, only == and != are supported and allowd. -const bool iv_equal_uv = iv == uv; -const bool iv_not_equal_uv = iv != uv; - -// -// Composite types other than vectors -// - -// Struct -struct int_float_double_vec2 { - int i; - float f; - double d; - vec2 v; -}; - -const int_float_double_vec2 sp_struct_a = { - sp_int, sp_float, float_to_double, - vec2(double_to_float, 1.0) -}; - -const int_float_double_vec2 sp_struct_b = { - sp_int, sp_float, float_to_double, - vec2(double_to_float, 1.0) -}; - -const bool struct_a_equal_struct_b = sp_struct_a == sp_struct_b; -const bool struct_a_not_equal_struct_b = sp_struct_a != sp_struct_b; - -// Array -const float array_a[2] = {sp_float, sp_float}; -const float array_b[2] = {sp_float, sp_float}; -const bool array_a_equal_array_b = array_a == array_b; -const bool array_a_not_equal_array_b = array_a != array_b; - void main() {} From 0dfbe3f90d35e298b0160a16656eb69fa8023ca2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 2 Apr 2016 13:38:28 +0200 Subject: [PATCH 17/20] Change {parameter} lists into explicit std::vector temporaries --- SPIRV/SpvBuilder.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 4235f273..9437c9e4 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -1067,7 +1067,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) // Generate code for spec constants if in spec constant operation // generation mode. if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, {composite}, {index}); + return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); @@ -1082,7 +1082,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector(1, composite), indexes); } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); @@ -1184,7 +1184,7 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) // Generate code for spec constants if in spec constant operation // generation mode. if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, {operand}, {}); + return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(operand); @@ -1198,7 +1198,9 @@ Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) // Generate code for spec constants if in spec constant operation // generation mode. if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, {left, right}, {}); + std::vector operands(2); + operands[0] = left; operands[1] = right; + return createSpecConstantOp(opCode, typeId, operands, std::vector()); } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(left); @@ -1261,7 +1263,9 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, std: return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); if (generatingOpCodeForSpecConst) { - return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, {source, source}, channels), precision); + std::vector operands(2); + operands[0] = operands[1] = source; + return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); } Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); assert(isVector(source)); From bd9f8351f4fafd16fbe26f07e5150f18460f05ca Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 2 Apr 2016 13:38:42 +0200 Subject: [PATCH 18/20] Specify explicit return type on lambda function --- SPIRV/SpvBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 9437c9e4..dda6bb09 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -2213,7 +2213,7 @@ void Builder::eliminateDeadDecorations() { } } decorations.erase(std::remove_if(decorations.begin(), decorations.end(), - [&unreachable_definitions](std::unique_ptr& I) { + [&unreachable_definitions](std::unique_ptr& I) -> bool { Instruction* inst = I.get(); Id decoration_id = inst->getIdOperand(0); return unreachable_definitions.count(decoration_id) != 0; From f0bcb0aaf4287ce5170886e71b75c7c18ce4f398 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sat, 2 Apr 2016 13:09:14 -0600 Subject: [PATCH 19/20] Comment: fix comment from gtest check in. --- StandAlone/StandAlone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index e8ab7b56..94eceaff 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -112,7 +112,7 @@ TBuiltInResource Resources; std::string ConfigFile; // -// Parse either a .conf file provided by the user or the default string above. +// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource // void ProcessConfigFile() { From 6a6d6dda956332b3a8f16b1feebdcf4c19fac8b3 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 3 Apr 2016 01:17:13 +0100 Subject: [PATCH 20/20] fix spelling mistakes --- CMakeLists.txt | 2 +- README.md | 4 ++-- SPIRV/SPVRemapper.cpp | 2 +- SPIRV/SpvBuilder.cpp | 2 +- glslang/Include/InfoSink.h | 2 +- glslang/Include/PoolAlloc.h | 6 +++--- glslang/OSDependent/Unix/ossource.cpp | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac756f55..12655f78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ elseif(UNIX) add_definitions(-fPIC) add_definitions(-DGLSLANG_OSINCLUDE_UNIX) else(WIN32) - message("unkown platform") + message("unknown platform") endif(WIN32) if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/README.md b/README.md index 77508774..56bdeec9 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ class TProgram See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more details. -### C Functional Interface (orginal) +### C Functional Interface (orignal) This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to as the `Sh*()` interface, as all the entry points start `Sh`. @@ -118,7 +118,7 @@ ShCompile(shader, compiler) -> compiler(AST) -> ``` In practice, `ShCompile()` takes shader strings, default version, and -warning/error and other options for controling compilation. +warning/error and other options for controlling compilation. Testing ------- diff --git a/SPIRV/SPVRemapper.cpp b/SPIRV/SPVRemapper.cpp index 965867ef..35dda17b 100755 --- a/SPIRV/SPVRemapper.cpp +++ b/SPIRV/SPVRemapper.cpp @@ -573,7 +573,7 @@ namespace spv { op_fn_nop); // Window size for context-sensitive canonicalization values - // Emperical best size from a single data set. TODO: Would be a good tunable. + // Empirical best size from a single data set. TODO: Would be a good tunable. // We essentially perform a little convolution around each instruction, // to capture the flavor of nearby code, to hopefully match to similar // code in other modules. diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 4235f273..e347fe38 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -2319,7 +2319,7 @@ void Builder::simplifyAccessChainSwizzle() // To the extent any swizzling can become part of the chain // of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transfering a non-static component index, +// If 'dynamic' is true, include transferring a non-static component index, // otherwise, only transfer static indexes. // // Also, Boolean vectors are likely to be special. While diff --git a/glslang/Include/InfoSink.h b/glslang/Include/InfoSink.h index a321ebcc..5862e5d8 100644 --- a/glslang/Include/InfoSink.h +++ b/glslang/Include/InfoSink.h @@ -92,7 +92,7 @@ public: case EPrefixInternalError: append("INTERNAL ERROR: "); break; case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; case EPrefixNote: append("NOTE: "); break; - default: append("UNKOWN ERROR: "); break; + default: append("UNKNOWN ERROR: "); break; } } void location(const TSourceLoc& loc) { diff --git a/glslang/Include/PoolAlloc.h b/glslang/Include/PoolAlloc.h index de41053f..c3bebc63 100644 --- a/glslang/Include/PoolAlloc.h +++ b/glslang/Include/PoolAlloc.h @@ -95,7 +95,7 @@ public: void checkAllocList() const; - // Return total size needed to accomodate user buffer of 'size', + // Return total size needed to accommodate user buffer of 'size', // plus our tracking data. inline static size_t allocationSize(size_t size) { return size + 2 * guardBlockSize + headerSize(); @@ -241,8 +241,8 @@ protected: int numCalls; // just an interesting statistic size_t totalBytes; // just an interesting statistic private: - TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor }; diff --git a/glslang/OSDependent/Unix/ossource.cpp b/glslang/OSDependent/Unix/ossource.cpp index 5ce882ab..3bd725ea 100644 --- a/glslang/OSDependent/Unix/ossource.cpp +++ b/glslang/OSDependent/Unix/ossource.cpp @@ -61,7 +61,7 @@ static void DetachThreadLinux(void *) // -// Registers cleanup handler, sets cancel type and state, and excecutes the thread specific +// Registers cleanup handler, sets cancel type and state, and executes the thread specific // cleanup handler. This function will be called in the Standalone.cpp for regression // testing. When OpenGL applications are run with the driver code, Linux OS does the // thread cleanup.