HLSL: Flatten whole-struct assigns and returns when targeting flattened I/O structs.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user