HLSL: Flatten whole-struct assigns and returns when targeting flattened I/O structs.

This commit is contained in:
John Kessenich
2016-09-16 03:05:12 -06:00
parent f8e494c18c
commit d21baed6bc
67 changed files with 4024 additions and 2886 deletions

View File

@@ -1672,7 +1672,7 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
return false;
}
node = intermediate.addAssign(assignOp, node, rightNode, loc);
node = parseContext.handleAssign(loc, assignOp, node, rightNode);
if (node == nullptr) {
parseContext.error(loc, "could not create assignment", "", "");
return false;

View File

@@ -1011,7 +1011,7 @@ TIntermNode* HlslParseContext::handleReturnValue(const TSourceLoc& loc, TIntermT
assert(entryPointOutput != nullptr); // should have been error tested at the beginning
TIntermSymbol* left = new TIntermSymbol(entryPointOutput->getUniqueId(), entryPointOutput->getName(),
entryPointOutput->getType());
TIntermNode* returnSequence = intermediate.addAssign(EOpAssign, left, converted, loc);
TIntermNode* returnSequence = handleAssign(loc, EOpAssign, left, converted);
returnSequence = intermediate.makeAggregate(returnSequence);
returnSequence = intermediate.growAggregate(returnSequence, intermediate.addBranch(EOpReturn, loc));
returnSequence->getAsAggregate()->setOperator(EOpSequence);
@@ -1032,6 +1032,32 @@ void HlslParseContext::handleFunctionArgument(TFunction* function, TIntermTyped*
arguments = newArg;
}
// Some simple source assignments need to be flattened to a sequence
// of AST assignments. Catch these and flatten, otherwise, pass through
// to intermediate.addAssign().
TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right)
{
if (! shouldFlatten(left->getType()) ||
! left->getAsSymbolNode() ||
flattenMap.find(left->getAsSymbolNode()->getId()) == flattenMap.end())
return intermediate.addAssign(op, left, right, loc);
// If we get here, we are assigning a whole struct to a flattened l-value, so have to
// do member-by-member assignment:
const auto& members = *left->getType().getStruct();
const auto& memberVariables = flattenMap[left->getAsSymbolNode()->getId()];
TIntermAggregate* assignList = nullptr;
for (int member = 0; member < (int)memberVariables.size(); ++member) {
TIntermTyped* subRight = intermediate.addIndex(EOpIndexDirectStruct, right, intermediate.addConstantUnion(member, loc), loc);
subRight->setType(*members[member].type);
TIntermTyped* subLeft = intermediate.addSymbol(*memberVariables[member]);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc));
}
assignList->setOperator(EOpSequence);
return assignList;
}
//
// HLSL atomic operations have slightly different arguments than
// GLSL/AST/SPIRV. The semantics are converted below in decomposeIntrinsic.

View File

@@ -94,6 +94,7 @@ public:
void remapNonEntrypointIO(TFunction& function);
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
@@ -238,7 +239,7 @@ protected:
//
TVector<TSymbol*> ioArraySymbolResizeList;
TUnorderedMap<int, TVector<TVariable*>> flattenMap;
TMap<int, TVector<TVariable*>> flattenMap;
unsigned int nextInLocation;
unsigned int nextOutLocation;
};