Merge pull request #1174 from LoopDawg/y-flip
HLSL: add optional position.Y inversion
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user