HLSL: Flatten vertex input and fragment output structures.
Vulkan can't handle structures into the vertex stage or out of the fragment stage.
This commit is contained in:
parent
6295c27900
commit
cd0a78a0d9
7 changed files with 255 additions and 67 deletions
|
|
@ -679,12 +679,16 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
|
|||
}
|
||||
}
|
||||
if (fieldFound) {
|
||||
if (base->getType().getQualifier().storage == EvqConst)
|
||||
result = intermediate.foldDereference(base, member, loc);
|
||||
if (base->getAsSymbolNode() && shouldFlatten(base->getType()))
|
||||
result = flattenAccess(base, member);
|
||||
else {
|
||||
TIntermTyped* index = intermediate.addConstantUnion(member, loc);
|
||||
result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
|
||||
result->setType(*(*fields)[member].type);
|
||||
if (base->getType().getQualifier().storage == EvqConst)
|
||||
result = intermediate.foldDereference(base, member, loc);
|
||||
else {
|
||||
TIntermTyped* index = intermediate.addConstantUnion(member, loc);
|
||||
result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
|
||||
result->setType(*(*fields)[member].type);
|
||||
}
|
||||
}
|
||||
} else
|
||||
error(loc, "no such field in structure", field.c_str(), "");
|
||||
|
|
@ -694,6 +698,54 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
|
|||
return result;
|
||||
}
|
||||
|
||||
// Is this a structure that can't be passed down the stack?
|
||||
// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage.
|
||||
bool HlslParseContext::shouldFlatten(const TType& type)
|
||||
{
|
||||
const TStorageQualifier qualifier = type.getQualifier().storage;
|
||||
|
||||
return type.isStruct() &&
|
||||
((language == EShLangVertex && qualifier == EvqVaryingIn) ||
|
||||
(language == EShLangFragment && qualifier == EvqVaryingOut));
|
||||
}
|
||||
|
||||
// Figure out mapping between a structures top members and an
|
||||
// equivalent set of individual variables.
|
||||
//
|
||||
// Assumes shouldFlatten() or equivalent was called first.
|
||||
//
|
||||
// TODO: generalize this to arbitrary nesting?
|
||||
void HlslParseContext::flattenStruct(const TVariable& variable)
|
||||
{
|
||||
TVector<TVariable*> memberVariables;
|
||||
|
||||
auto members = *variable.getType().getStruct();
|
||||
int location = variable.getType().getQualifier().layoutLocation;
|
||||
for (int member = 0; member < (int)members.size(); ++member) {
|
||||
TVariable* memberVariable = makeInternalVariable(members[member].type->getFieldName().c_str(), *members[member].type);
|
||||
memberVariable->getWritableType().getQualifier() = variable.getType().getQualifier();
|
||||
memberVariable->getWritableType().getQualifier().layoutLocation = location;
|
||||
location += intermediate.computeTypeLocationSize(memberVariable->getType());
|
||||
memberVariables.push_back(memberVariable);
|
||||
}
|
||||
|
||||
flattenMap[variable.getUniqueId()] = memberVariables;
|
||||
}
|
||||
|
||||
// Turn an access into structure that was flattened to instead be
|
||||
// an access to the individual variable the member was flattened to.
|
||||
// Assumes shouldFlatten() or equivalent was called first.
|
||||
TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
|
||||
{
|
||||
const TIntermSymbol& symbolNode = *base->getAsSymbolNode();
|
||||
|
||||
if (flattenMap.find(symbolNode.getId()) == flattenMap.end())
|
||||
return base;
|
||||
|
||||
const TVariable* memberVariable = flattenMap[symbolNode.getId()][member];
|
||||
return intermediate.addSymbol(*memberVariable);
|
||||
}
|
||||
|
||||
//
|
||||
// Handle seeing a function declarator in the grammar. This is the precursor
|
||||
// to recognizing a function prototype or function definition.
|
||||
|
|
@ -800,6 +852,9 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
|||
paramNodes = intermediate.growAggregate(paramNodes,
|
||||
intermediate.addSymbol(*variable, loc),
|
||||
loc);
|
||||
|
||||
if (shouldFlatten(*param.type))
|
||||
flattenStruct(*variable);
|
||||
}
|
||||
} else
|
||||
paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
|
||||
|
|
@ -861,20 +916,21 @@ void HlslParseContext::remapEntrypointIO(TFunction& function)
|
|||
|
||||
// parameters are actually shader-scoped inputs and outputs (in or out)
|
||||
for (int i = 0; i < function.getParamCount(); i++) {
|
||||
if (function[i].type->getQualifier().isParamInput()) {
|
||||
function[i].type->getQualifier().storage = EvqVaryingIn;
|
||||
if (function[i].type->getQualifier().builtIn == EbvNone) {
|
||||
function[i].type->getQualifier().layoutLocation = inCount;
|
||||
TType& paramType = *function[i].type;
|
||||
if (paramType.getQualifier().isParamInput()) {
|
||||
paramType.getQualifier().storage = EvqVaryingIn;
|
||||
if (paramType.getQualifier().builtIn == EbvNone) {
|
||||
paramType.getQualifier().layoutLocation = inCount;
|
||||
inCount += intermediate.computeTypeLocationSize(*function[i].type);
|
||||
}
|
||||
} else {
|
||||
function[i].type->getQualifier().storage = EvqVaryingOut;
|
||||
if (function[i].type->getQualifier().builtIn == EbvNone && language != EShLangFragment) {
|
||||
function[i].type->getQualifier().layoutLocation = outCount;
|
||||
paramType.getQualifier().storage = EvqVaryingOut;
|
||||
if (paramType.getQualifier().builtIn == EbvNone) {
|
||||
paramType.getQualifier().layoutLocation = outCount;
|
||||
outCount += intermediate.computeTypeLocationSize(*function[i].type);
|
||||
}
|
||||
}
|
||||
remapBuiltInType(*function[i].type);
|
||||
remapBuiltInType(paramType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue