Commit ec712ebe by steve-lunarg Committed by John Kessenich

HLSL: fix copies between arrays of structs of builtins, and arrayed builtins.

Structs are split to remove builtin members to create valid SPIR-V. In this process, an outer structure array dimension may be propegated onto the now-removed builtin variables. For example, a mystruct[3].position -> position[3]. The copy between the split and unsplit forms would handle this in some cases, but not if the array dimension was at different levels of aggregate. It now does this, but may not handle arbitrary composite types. Unclear if that has any semantic meaning for builtins though.
parent abd8dca8
...@@ -214,7 +214,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -214,7 +214,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.struct.split.assign.frag", "main"}, {"hlsl.struct.split.assign.frag", "main"},
{"hlsl.struct.split.call.vert", "main"}, {"hlsl.struct.split.call.vert", "main"},
{"hlsl.struct.split.nested.geom", "main"}, {"hlsl.struct.split.nested.geom", "main"},
//{"hlsl.struct.split.trivial.geom", "main"}, {"hlsl.struct.split.trivial.geom", "main"},
{"hlsl.struct.split.trivial.vert", "main"}, {"hlsl.struct.split.trivial.vert", "main"},
{"hlsl.structarray.flatten.frag", "main"}, {"hlsl.structarray.flatten.frag", "main"},
{"hlsl.structarray.flatten.geom", "main"}, {"hlsl.structarray.flatten.geom", "main"},
......
...@@ -1918,6 +1918,11 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -1918,6 +1918,11 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
int memberIdx = 0; int memberIdx = 0;
// When dealing with split arrayed structures of builtins, the arrayness is moved to the extracted builtin
// variables, which is awkward when copying between split and unsplit structures. This variable tracks
// array indirections so they can be percolated from outer structs to inner variables.
std::vector <int> arrayElement;
// We track the outer-most aggregate, so that we can use its storage class later. // We track the outer-most aggregate, so that we can use its storage class later.
const TIntermTyped* outerLeft = left; const TIntermTyped* outerLeft = left;
const TIntermTyped* outerRight = right; const TIntermTyped* outerRight = right;
...@@ -1934,7 +1939,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -1934,7 +1939,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
if (split && derefType.isBuiltInInterstageIO(language)) { if (split && derefType.isBuiltInInterstageIO(language)) {
// copy from interstage IO builtin if needed // copy from interstage IO builtin if needed
subTree = intermediate.addSymbol(*interstageBuiltInIo[tInterstageIoData(derefType, outer->getType())]); subTree = intermediate.addSymbol(*interstageBuiltInIo.find(tInterstageIoData(derefType, outer->getType()))->second);
// Arrayness of builtIn symbols isn't handled by the normal recursion: it's been extracted and moved to the builtin.
if (subTree->getType().isArray() && !arrayElement.empty()) {
const TType splitDerefType(subTree->getType(), arrayElement.back());
subTree = intermediate.addIndex(EOpIndexDirect, subTree, intermediate.addConstantUnion(arrayElement.back(), loc), loc);
subTree->setType(splitDerefType);
}
} else if (flattened && isFinalFlattening(derefType)) { } else if (flattened && isFinalFlattening(derefType)) {
subTree = intermediate.addSymbol(*flatVariables[memberIdx++]); subTree = intermediate.addSymbol(*flatVariables[memberIdx++]);
} else { } else {
...@@ -1972,10 +1984,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op ...@@ -1972,10 +1984,14 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left, element, splitLeft, element) : subLeft; TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left, element, splitLeft, element) : subLeft;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right, element, splitRight, element) : subRight; TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right, element, splitRight, element) : subRight;
arrayElement.push_back(element);
if (isFinalFlattening(dereferencedType)) if (isFinalFlattening(dereferencedType))
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc); assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
else else
traverse(subLeft, subRight, subSplitLeft, subSplitRight); traverse(subLeft, subRight, subSplitLeft, subSplitRight);
arrayElement.pop_back();
} }
} else if (left->getType().isStruct()) { } else if (left->getType().isStruct()) {
// struct case // struct case
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment