Non-functional HLSL: Factor out built-ins from splitting and related simplifications.

This commit is contained in:
John Kessenich 2017-08-07 23:40:05 -06:00
parent eaed06823a
commit ecd08bc36c
4 changed files with 40 additions and 49 deletions

View File

@ -423,14 +423,14 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
return -1; return -1;
// no locations added if already present, or a built-in variable // no locations added if already present, or a built-in variable
if (type.getQualifier().hasLocation() || type.getQualifier().builtIn != EbvNone) if (type.getQualifier().hasLocation() || type.isBuiltIn())
return -1; return -1;
// no locations on blocks of built-in variables // no locations on blocks of built-in variables
if (type.isStruct()) { if (type.isStruct()) {
if (type.getStruct()->size() < 1) if (type.getStruct()->size() < 1)
return -1; return -1;
if ((*type.getStruct())[0].type->getQualifier().builtIn != EbvNone) if ((*type.getStruct())[0].type->isBuiltIn())
return -1; return -1;
} }

View File

@ -616,7 +616,7 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
qualifier.readonly = type.getQualifier().readonly; qualifier.readonly = type.getQualifier().readonly;
} }
if (type.getQualifier().builtIn != EbvNone) if (type.isBuiltIn())
qualifier.builtIn = type.getQualifier().builtIn; qualifier.builtIn = type.getQualifier().builtIn;
type.getQualifier() = qualifier; type.getQualifier() = qualifier;

View File

@ -1121,58 +1121,51 @@ bool HlslParseContext::isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, co
return false; return false;
} }
// Independently establish a built-in that is a member of a structure.
// 'arraySizes' are what's desired for the independent built-in, whatever
// the higher-level source/expression of them was.
void HlslParseContext::splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes* arraySizes,
const TQualifier& outerQualifier)
{
TVariable* ioVar = makeInternalVariable(baseName + (baseName.empty() ? "" : "_") + memberType.getFieldName(), memberType);
if (arraySizes)
ioVar->getWritableType().newArraySizes(*arraySizes);
fixBuiltInIoType(ioVar->getWritableType());
splitBuiltIns[tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)] = ioVar;
if (!isClipOrCullDistance(ioVar->getType()))
trackLinkage(*ioVar);
// Merge qualifier from the user structure
mergeQualifiers(ioVar->getWritableType().getQualifier(), outerQualifier);
}
// Split a type into // Split a type into
// 1. a struct of non-I/O members // 1. a struct of non-I/O members
// 2. a collection of flattened I/O variables // 2. a collection of independent I/O variables
void HlslParseContext::split(const TVariable& variable) void HlslParseContext::split(const TVariable& variable)
{ {
// Create a new variable: // Create a new variable:
TType& splitType = split(*variable.getType().clone(), variable.getName()); const TType& clonedType = *variable.getType().clone();
const TType& splitType = split(clonedType, variable.getName(), clonedType.getQualifier());
splitNonIoVars[variable.getUniqueId()] = makeInternalVariable(variable.getName(), splitType); splitNonIoVars[variable.getUniqueId()] = makeInternalVariable(variable.getName(), splitType);
} }
// Recursive implementation of split(). // Recursive implementation of split().
// Returns reference to the modified type. // Returns reference to the modified type.
TType& HlslParseContext::split(TType& type, TString name, const TType* outerStructType) const TType& HlslParseContext::split(const TType& type, const TString& name, const TQualifier& outerQualifier)
{ {
const TArraySizes* arraySizes = nullptr;
// At the outer-most scope, remember the struct type so we can examine its storage class
// at deeper levels.
if (outerStructType == nullptr)
outerStructType = &type;
if (type.isArray())
arraySizes = &type.getArraySizes();
// 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(); ) { for (auto ioType = userStructure->begin(); ioType != userStructure->end(); ) {
if (ioType->type->getQualifier().builtIn != EbvNone) { if (ioType->type->isBuiltIn()) {
// split out built-in interstage IO // move out the built-in
const TType& memberType = *ioType->type; splitBuiltIn(name, *ioType->type, type.getArraySizes(), outerQualifier);
TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : "_") + memberType.getFieldName(),
memberType);
if (arraySizes)
ioVar->getWritableType().newArraySizes(*arraySizes);
fixBuiltInIoType(ioVar->getWritableType());
splitBuiltIns[tInterstageIoData(memberType, *outerStructType)] = ioVar;
if (!isClipOrCullDistance(ioVar->getType()))
trackLinkage(*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); ioType = userStructure->erase(ioType);
} else { } else {
split(*ioType->type, split(*ioType->type, name + (name.empty() ? "" : "_") + ioType->type->getFieldName(), outerQualifier);
name + (name.empty() ? "" : "_") + ioType->type->getFieldName(),
outerStructType);
++ioType; ++ioType;
} }
} }
@ -1258,10 +1251,9 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType&
if (flattenData.nextBinding != TQualifier::layoutBindingEnd) if (flattenData.nextBinding != TQualifier::layoutBindingEnd)
memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++; memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++;
if (memberVariable->getType().getQualifier().builtIn == EbvNone) { if (!memberVariable->getType().isBuiltIn()) {
// inherited locations must be auto bumped, not replicated // inherited locations must be auto bumped, not replicated
if (flattenData.nextLocation != TQualifier::layoutLocationEnd && if (flattenData.nextLocation != TQualifier::layoutLocationEnd) {
memberVariable->getType().getQualifier().builtIn == EbvNone) {
memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation; memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation;
flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType()); flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType());
nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation); nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation);
@ -2530,8 +2522,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
if (split && derefType.isBuiltIn()) { 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(*splitBuiltIns.find( subTree = intermediate.addSymbol(
HlslParseContext::tInterstageIoData(derefType, outer->getType()))->second); *splitBuiltIns.find(HlslParseContext::tInterstageIoData(
derefType.getQualifier().builtIn,
outer->getType().getQualifier().storage))->second);
// Arrayness of builtIn symbols isn't handled by the normal recursion: // Arrayness of builtIn symbols isn't handled by the normal recursion:
// it's been extracted and moved to the built-in. // it's been extracted and moved to the built-in.

View File

@ -252,8 +252,9 @@ protected:
bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); } bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); }
// Structure splitting (splits interstage built-in types into its own struct) // Structure splitting (splits interstage built-in types into its own struct)
TType& split(TType& type, TString name, const TType* outerStructType = nullptr);
void split(const TVariable&); void split(const TVariable&);
void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&);
const TType& split(const TType& type, const TString& name, const TQualifier&);
bool wasSplit(const TIntermTyped* node) const; bool wasSplit(const TIntermTyped* node) const;
bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); } bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); }
TVariable* getSplitNonIoVar(int id) const; TVariable* getSplitNonIoVar(int id) const;
@ -393,10 +394,6 @@ protected:
tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) : tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) :
builtIn(bi), storage(q) { } builtIn(bi), storage(q) { }
tInterstageIoData(const TType& memberType, const TType& storageType) :
builtIn(memberType.getQualifier().builtIn),
storage(storageType.getQualifier().storage) { }
TBuiltInVariable builtIn; TBuiltInVariable builtIn;
TStorageQualifier storage; TStorageQualifier storage;