Non-functional: HLSL: Simplify I/O logic for splitting.

This commit is contained in:
John Kessenich 2017-08-02 17:08:43 -06:00
parent 4cf5266042
commit 6042eb475b
2 changed files with 36 additions and 55 deletions

View File

@ -1370,15 +1370,12 @@ public:
virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
virtual bool isBuiltInInterstageIO(EShLanguage language) const virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
{
return isPerVertexAndBuiltIn(language) || isLooseAndBuiltIn(language);
}
// Return true if this is an interstage IO builtin // Return true if this is a per-vertex built-in
virtual bool isPerVertexAndBuiltIn(EShLanguage language) const virtual bool isPerVertexBuiltIn(EShLanguage language) const
{ {
if (language == EShLangFragment) if (getQualifier().builtIn == EbvNone || language == EShLangFragment)
return false; return false;
// Any non-fragment stage // 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. // return true if this type contains any subtype which satisfies the given predicate.
template <typename P> template <typename P>
bool contains(P predicate) const bool contains(P predicate) const
@ -1451,10 +1439,10 @@ public:
return contains([](const TType* t) { return t->isOpaque(); } ); return contains([](const TType* t) { return t->isOpaque(); } );
} }
// Recursively checks if the type contains an interstage IO builtin // Recursively checks if the type contains a built-in variable
virtual bool containsBuiltInInterstageIO(EShLanguage language) const 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 virtual bool containsNonOpaque() const

View File

@ -1126,16 +1126,9 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru
// We can ignore arrayness: it's uninvolved. // We can ignore arrayness: it's uninvolved.
if (type.isStruct()) { if (type.isStruct()) {
TTypeList* userStructure = type.getWritableStruct(); TTypeList* userStructure = type.getWritableStruct();
for (auto ioType = userStructure->begin(); ioType != userStructure->end(); ) {
// Get iterator to (now at end) set of built-in interstage IO members if (ioType->type->getQualifier().builtIn != EbvNone) {
const auto firstIo = std::stable_partition(userStructure->begin(), userStructure->end(), // split out built-in interstage IO
[this](const TTypeLoc& t) {
return !t.type->isBuiltInInterstageIO(language);
});
// 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; const TType& memberType = *ioType->type;
TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : "_") + memberType.getFieldName(), TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : "_") + memberType.getFieldName(),
memberType); memberType);
@ -1149,16 +1142,16 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru
// Merge qualifier from the user structure // Merge qualifier from the user structure
mergeQualifiers(ioVar->getWritableType().getQualifier(), outerStructType->getQualifier()); mergeQualifiers(ioVar->getWritableType().getQualifier(), outerStructType->getQualifier());
}
// Erase the IO vars from the user structure. // Erase the IO vars from the user structure.
userStructure->erase(firstIo, userStructure->end()); ioType = userStructure->erase(ioType);
} else {
// Recurse further into the members. split(*ioType->type,
for (unsigned int i = 0; i < userStructure->size(); ++i) name + (name.empty() ? "" : "_") + ioType->type->getFieldName(),
split(*(*userStructure)[i].type,
name + (name.empty() ? "" : "_") + (*userStructure)[i].type->getFieldName(),
outerStructType); outerStructType);
++ioType;
}
}
} }
return type; return type;
@ -1556,7 +1549,7 @@ void HlslParseContext::addInterstageIoToLinkage()
TVariable* var = interstageBuiltInIo[io[idx]]; TVariable* var = interstageBuiltInIo[io[idx]];
// Add the loose interstage IO to the linkage // Add the loose interstage IO to the linkage
if (var->getType().isLooseAndBuiltIn(language)) if (! var->getType().isPerVertexBuiltIn(language))
trackLinkage(*var); trackLinkage(*var);
} }
} }
@ -1906,8 +1899,8 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if ((language == EShLangVertex && qualifier == EvqVaryingIn) || if ((language == EShLangVertex && qualifier == EvqVaryingIn) ||
(language == EShLangFragment && qualifier == EvqVaryingOut)) (language == EShLangFragment && qualifier == EvqVaryingOut))
flatten(variable); flatten(variable);
// Structs contain interstage IO must be split // Structs containing built-ins must be split
else if (variable.getType().containsBuiltInInterstageIO(language)) else if (variable.getType().containsBuiltIn())
split(variable); split(variable);
} }
@ -2530,7 +2523,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
TIntermTyped* subTree; TIntermTyped* subTree;
const TType derefType(node->getType(), member); const TType derefType(node->getType(), member);
if (split && derefType.isBuiltInInterstageIO(language)) { if (split && derefType.isBuiltIn()) {
// copy from interstage IO built-in if needed // copy from interstage IO built-in if needed
const TIntermTyped* outer = isLeft ? outerLeft : outerRight; const TIntermTyped* outer = isLeft ? outerLeft : outerRight;
subTree = intermediate.addSymbol(*interstageBuiltInIo.find( subTree = intermediate.addSymbol(*interstageBuiltInIo.find(
@ -2644,8 +2637,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); assignList = intermediate.growAggregate(assignList, clipCullAssign, loc);
} else if (!isFlattenLeft && !isFlattenRight && } else if (!isFlattenLeft && !isFlattenRight &&
!typeL.containsBuiltInInterstageIO(language) && !typeL.containsBuiltIn() &&
!typeR.containsBuiltInInterstageIO(language)) { !typeR.containsBuiltIn()) {
// If this is the final flattening (no nested types below to flatten) // If this is the final flattening (no nested types below to flatten)
// we'll copy the member, else recurse into the type hierarchy. // we'll copy the member, else recurse into the type hierarchy.
// However, if splitting the struct, that means we can copy a whole // 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); traverse(subLeft, subRight, subSplitLeft, subSplitRight);
} }
memberL += (typeL.isBuiltInInterstageIO(language) ? 0 : 1); memberL += (typeL.isBuiltIn() ? 0 : 1);
memberR += (typeR.isBuiltInInterstageIO(language) ? 0 : 1); memberR += (typeR.isBuiltIn() ? 0 : 1);
} }
} else { } else {
// Member copy // Member copy
@ -9197,7 +9190,7 @@ void HlslParseContext::addPatchConstantInvocation()
TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType); TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType);
pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut; pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut;
if (pcfOutput->getType().containsBuiltInInterstageIO(language)) if (pcfOutput->getType().containsBuiltIn())
split(*pcfOutput); split(*pcfOutput);
assignToInterface(*pcfOutput); assignToInterface(*pcfOutput);