Merge pull request #1174 from LoopDawg/y-flip

HLSL: add optional position.Y inversion
This commit is contained in:
John Kessenich
2017-12-12 09:16:01 -07:00
committed by GitHub
13 changed files with 549 additions and 1 deletions

View File

@@ -2301,6 +2301,63 @@ void HlslParseContext::handleFunctionArgument(TFunction* function,
arguments = newArg;
}
// Position may require special handling: we can optionally invert Y.
// See: https://github.com/KhronosGroup/glslang/issues/1173
// https://github.com/KhronosGroup/glslang/issues/494
TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator op,
TIntermTyped* left, TIntermTyped* right)
{
// If we are not asked for Y inversion, use a plain old assign.
if (!intermediate.getInvertY())
return intermediate.addAssign(op, left, right, loc);
// If we get here, we should invert Y.
TIntermAggregate* assignList = nullptr;
// If this is a complex rvalue, we don't want to dereference it many times. Create a temporary.
TVariable* rhsTempVar = nullptr;
rhsTempVar = makeInternalVariable("@position", right->getType());
rhsTempVar->getWritableType().getQualifier().makeTemporary();
{
TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc);
assignList = intermediate.growAggregate(assignList,
intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc);
}
// pos.y = -pos.y
{
const int Y = 1;
TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc);
TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc);
TIntermTyped* index = intermediate.addConstantUnion(Y, loc);
TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc);
TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc);
const TType derefType(right->getType(), 0);
lhsElement->setType(derefType);
rhsElement->setType(derefType);
TIntermTyped* yNeg = intermediate.addUnaryMath(EOpNegative, rhsElement, loc);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, yNeg, loc));
}
// Assign the rhs temp (now with Y inversion) to the final output
{
TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc));
}
assert(assignList != nullptr);
assignList->setOperator(EOpSequence);
return assignList;
}
// Clip and cull distance require special handling due to a semantic mismatch. In HLSL,
// these can be float scalar, float vector, or arrays of float scalar or float vector.
// In SPIR-V, they are arrays of scalar floats in all cases. We must copy individual components
@@ -2566,6 +2623,12 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
wasSplit(binaryNode->getLeft());
};
// Return true if this stage assigns clip position with potentially inverted Y
const auto assignsClipPos = [this](const TIntermTyped* node) -> bool {
return node->getType().getQualifier().builtIn == EbvPosition &&
(language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation);
};
const bool isSplitLeft = wasSplit(left) || indexesSplit(left);
const bool isSplitRight = wasSplit(right) || indexesSplit(right);
@@ -2581,6 +2644,9 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
const int semanticId = (isOutput ? left : right)->getType().getQualifier().layoutLocation;
return assignClipCullDistance(loc, op, semanticId, left, right);
} else if (assignsClipPos(left)) {
// Position can require special handling: see comment above assignPosition
return assignPosition(loc, op, left, right);
}
return intermediate.addAssign(op, left, right, loc);
@@ -2792,7 +2858,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, clipCullAssign, loc);
} else if (assignsClipPos(subSplitLeft)) {
// Position can require special handling: see comment above assignPosition
TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, positionAssign, loc);
} else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight &&
!typeL.containsBuiltIn() && !typeR.containsBuiltIn()) {
// If this is the final flattening (no nested types below to flatten)