diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 98cc5546..0fcac0b5 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -945,7 +945,11 @@ public: // 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), constSubtree(nullptr) + : TIntermTyped(t), id(i), +#ifdef ENABLE_HLSL + flattenSubset(-1), +#endif + constSubtree(nullptr) { name = n; } virtual int getId() const { return id; } virtual const TString& getName() const { return name; } @@ -956,9 +960,16 @@ public: const TConstUnionArray& getConstArray() const { return constArray; } void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifdef ENABLE_HLSL + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif protected: int id; // the unique id of the symbol this node represents +#ifdef ENABLE_HLSL + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif TString name; // the name of the symbol this node represents TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value TIntermTyped* constSubtree; diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 7cc1845e..a711fd33 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -2870,23 +2870,6 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) return false; } - // This is to guarantee we do this no matter how we get out of the stack frame. - // This way there's no bug if an early return forgets to do it. - struct tFinalize { - tFinalize(HlslParseContext& p) : parseContext(p) { } - ~tFinalize() { parseContext.finalizeFlattening(); } - HlslParseContext& parseContext; - private: - const tFinalize& operator=(const tFinalize&) { return *this; } - tFinalize(const tFinalize& f) : parseContext(f.parseContext) { } - } finalize(parseContext); - - // Initialize the flattening accumulation data, so we can track data across multiple bracket or - // dot operators. This can also be nested, e.g, for [], so we have to track each nesting - // level: hence the init and finalize. Even though in practice these must be - // constants, they are parsed no matter what. - parseContext.initFlattening(); - // Something was found, chain as many postfix operations as exist. do { TSourceLoc loc = token.loc; diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index bd84bd59..e987a984 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1348,11 +1348,11 @@ TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) const TType dereferencedType(base->getType(), member); // dereferenced type const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); - TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, dereferencedType); + TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, dereferencedType, symbolNode.getFlattenSubset()); return flattened ? flattened : base; } -TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TType& dereferencedType) +TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TType& dereferencedType, int subset) { const auto flattenData = flattenMap.find(uniqueId); @@ -1360,18 +1360,24 @@ TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TT return nullptr; // Calculate new cumulative offset from the packed tree - flattenOffset.back() = flattenData->second.offsets[flattenOffset.back() + member]; + int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member]; + TIntermSymbol* subsetSymbol; if (isFinalFlattening(dereferencedType)) { // Finished flattening: create symbol for variable - member = flattenData->second.offsets[flattenOffset.back()]; + member = flattenData->second.offsets[newSubset]; const TVariable* memberVariable = flattenData->second.members[member]; - return intermediate.addSymbol(*memberVariable); + subsetSymbol = intermediate.addSymbol(*memberVariable); + subsetSymbol->setFlattenSubset(-1); } else { + // If this is not the final flattening, accumulate the position and return // an object of the partially dereferenced type. - return new TIntermSymbol(uniqueId, "flattenShadow", dereferencedType); + subsetSymbol = new TIntermSymbol(uniqueId, "flattenShadow", dereferencedType); + subsetSymbol->setFlattenSubset(newSubset); } + + return subsetSymbol; } // Find and return the split IO TVariable for id, or nullptr if none. @@ -1753,11 +1759,9 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l flatten(loc, *variable); const TTypeList* structure = variable->getType().getStruct(); for (int mem = 0; mem < (int)structure->size(); ++mem) { - initFlattening(); paramNodes = intermediate.growAggregate(paramNodes, flattenAccess(variable->getUniqueId(), mem, *(*structure)[mem].type), loc); - finalizeFlattening(); } } else { // Add the parameter to the AST @@ -4908,11 +4912,8 @@ void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& f if (wasFlattened(arg) && shouldFlatten(*function[param].type)) { // Need to pass the structure members instead of the structure. TVector memberArgs; - for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) { - initFlattening(); + for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) memberArgs.push_back(flattenAccess(arg, memb)); - finalizeFlattening(); - } setArgList(param + functionParamNumberOffset, memberArgs); } } diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 6994365e..15c7b070 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -204,10 +204,6 @@ public: // Potentially rename shader entry point function void renameShaderFunction(const TString*& name) const; - // Reset data for incrementally built referencing of flattened composite structures - void initFlattening() { flattenLevel.push_back(0); flattenOffset.push_back(0); } - void finalizeFlattening() { flattenLevel.pop_back(); flattenOffset.pop_back(); } - // Share struct buffer deep types void shareStructBufferType(TType&); @@ -242,7 +238,7 @@ protected: // Array and struct flattening TIntermTyped* flattenAccess(TIntermTyped* base, int member); - TIntermTyped* flattenAccess(int uniqueId, int member, const TType&); + TIntermTyped* flattenAccess(int uniqueId, int member, const TType&, int subset = -1); bool shouldFlatten(const TType&) const; bool wasFlattened(const TIntermTyped* node) const; bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); } @@ -368,7 +364,6 @@ protected: TMap flattenMap; TVector flattenLevel; // nested postfix operator level for flattening - TVector flattenOffset; // cumulative offset for flattening // IO-type map. Maps a pure symbol-table form of a structure-member list into // each of the (up to) three kinds of IO, as each as different allowed decorations,