diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 72c13881..18448c86 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -1370,15 +1370,12 @@ public: virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } - virtual bool isBuiltInInterstageIO(EShLanguage language) const - { - return isPerVertexAndBuiltIn(language) || isLooseAndBuiltIn(language); - } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } - // Return true if this is an interstage IO builtin - virtual bool isPerVertexAndBuiltIn(EShLanguage language) const + // Return true if this is a per-vertex built-in + virtual bool isPerVertexBuiltIn(EShLanguage language) const { - if (language == EShLangFragment) + if (getQualifier().builtIn == EbvNone || language == EShLangFragment) return false; // Any non-fragment stage @@ -1401,15 +1398,6 @@ public: } } - // Return true if this is a loose builtin - virtual bool isLooseAndBuiltIn(EShLanguage language) const - { - if (getQualifier().builtIn == EbvNone) - return false; - - return !isPerVertexAndBuiltIn(language); - } - // return true if this type contains any subtype which satisfies the given predicate. template bool contains(P predicate) const @@ -1451,10 +1439,10 @@ public: return contains([](const TType* t) { return t->isOpaque(); } ); } - // Recursively checks if the type contains an interstage IO builtin - virtual bool containsBuiltInInterstageIO(EShLanguage language) const + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const { - return contains([language](const TType* t) { return t->isBuiltInInterstageIO(language); } ); + return contains([](const TType* t) { return t->isBuiltIn(); } ); } virtual bool containsNonOpaque() const diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 272c494b..968248ed 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1126,39 +1126,32 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru // We can ignore arrayness: it's uninvolved. if (type.isStruct()) { TTypeList* userStructure = type.getWritableStruct(); + for (auto ioType = userStructure->begin(); ioType != userStructure->end(); ) { + if (ioType->type->getQualifier().builtIn != EbvNone) { + // split out built-in interstage IO + const TType& memberType = *ioType->type; + TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : "_") + memberType.getFieldName(), + memberType); - // Get iterator to (now at end) set of built-in interstage IO members - const auto firstIo = std::stable_partition(userStructure->begin(), userStructure->end(), - [this](const TTypeLoc& t) { - return !t.type->isBuiltInInterstageIO(language); - }); + if (arraySizes) + ioVar->getWritableType().newArraySizes(*arraySizes); - // Move those to the built-in IO. However, we also propagate arrayness (just one level is handled - // now) to this variable. - for (auto ioType = firstIo; ioType != userStructure->end(); ++ioType) { - const TType& memberType = *ioType->type; - TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : "_") + memberType.getFieldName(), - memberType); + fixBuiltInIoType(ioVar->getWritableType()); - if (arraySizes) - ioVar->getWritableType().newArraySizes(*arraySizes); + interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar; - fixBuiltInIoType(ioVar->getWritableType()); + // Merge qualifier from the user structure + mergeQualifiers(ioVar->getWritableType().getQualifier(), outerStructType->getQualifier()); - interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar; - - // Merge qualifier from the user structure - mergeQualifiers(ioVar->getWritableType().getQualifier(), outerStructType->getQualifier()); + // Erase the IO vars from the user structure. + ioType = userStructure->erase(ioType); + } else { + split(*ioType->type, + name + (name.empty() ? "" : "_") + ioType->type->getFieldName(), + outerStructType); + ++ioType; + } } - - // Erase the IO vars from the user structure. - userStructure->erase(firstIo, userStructure->end()); - - // Recurse further into the members. - for (unsigned int i = 0; i < userStructure->size(); ++i) - split(*(*userStructure)[i].type, - name + (name.empty() ? "" : "_") + (*userStructure)[i].type->getFieldName(), - outerStructType); } return type; @@ -1556,7 +1549,7 @@ void HlslParseContext::addInterstageIoToLinkage() TVariable* var = interstageBuiltInIo[io[idx]]; // Add the loose interstage IO to the linkage - if (var->getType().isLooseAndBuiltIn(language)) + if (! var->getType().isPerVertexBuiltIn(language)) trackLinkage(*var); } } @@ -1906,8 +1899,8 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct if ((language == EShLangVertex && qualifier == EvqVaryingIn) || (language == EShLangFragment && qualifier == EvqVaryingOut)) flatten(variable); - // Structs contain interstage IO must be split - else if (variable.getType().containsBuiltInInterstageIO(language)) + // Structs containing built-ins must be split + else if (variable.getType().containsBuiltIn()) split(variable); } @@ -2530,7 +2523,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op TIntermTyped* subTree; const TType derefType(node->getType(), member); - if (split && derefType.isBuiltInInterstageIO(language)) { + if (split && derefType.isBuiltIn()) { // copy from interstage IO built-in if needed const TIntermTyped* outer = isLeft ? outerLeft : outerRight; subTree = intermediate.addSymbol(*interstageBuiltInIo.find( @@ -2644,8 +2637,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); } else if (!isFlattenLeft && !isFlattenRight && - !typeL.containsBuiltInInterstageIO(language) && - !typeR.containsBuiltInInterstageIO(language)) { + !typeL.containsBuiltIn() && + !typeR.containsBuiltIn()) { // If this is the final flattening (no nested types below to flatten) // we'll copy the member, else recurse into the type hierarchy. // However, if splitting the struct, that means we can copy a whole @@ -2661,8 +2654,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op traverse(subLeft, subRight, subSplitLeft, subSplitRight); } - memberL += (typeL.isBuiltInInterstageIO(language) ? 0 : 1); - memberR += (typeR.isBuiltInInterstageIO(language) ? 0 : 1); + memberL += (typeL.isBuiltIn() ? 0 : 1); + memberR += (typeR.isBuiltIn() ? 0 : 1); } } else { // Member copy @@ -9197,7 +9190,7 @@ void HlslParseContext::addPatchConstantInvocation() TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType); pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut; - if (pcfOutput->getType().containsBuiltInInterstageIO(language)) + if (pcfOutput->getType().containsBuiltIn()) split(*pcfOutput); assignToInterface(*pcfOutput);