Commit bbbd9a2a by John Kessenich

Fix #1843: Handle built-in function output parameters to a swizzled arg

In GLSL/HLSL/AST, v.zyx is an l-value, but not in SPIR-V, which cannot represent it. So, a temporary is used instead.
parent 56364b6b
...@@ -2277,7 +2277,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -2277,7 +2277,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
spv::Id result = spv::NoResult; spv::Id result = spv::NoResult;
spv::Id invertedType = spv::NoType; // to use to override the natural type of the node spv::Id invertedType = spv::NoType; // to use to override the natural type of the node
spv::Builder::AccessChain complexLvalue; // for holding swizzling l-values too complex for SPIR-V, for at out parameter
spv::Id temporaryLvalue = spv::NoResult; // temporary to pass, as proxy for complexLValue
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
// try texturing // try texturing
...@@ -2727,6 +2730,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -2727,6 +2730,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
// Does it need a swizzle inversion? If so, evaluation is inverted; // Does it need a swizzle inversion? If so, evaluation is inverted;
// operate first on the swizzle base, then apply the swizzle. // operate first on the swizzle base, then apply the swizzle.
// That is, we transform
//
// interpolate(v.zy) -> interpolate(v).zy
//
if (glslangOperands[0]->getAsOperator() && if (glslangOperands[0]->getAsOperator() &&
glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
...@@ -2819,8 +2826,19 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -2819,8 +2826,19 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} }
#endif #endif
// for l-values, pass the address, for r-values, pass the value
if (lvalue) { if (lvalue) {
operands.push_back(builder.accessChainGetLValue()); if (invertedType == spv::NoType && !builder.isSpvLvalue()) {
// SPIR-V cannot represent an l-value containing a swizzle that doesn't
// reduce to a simple access chain. So, we need a temporary vector to
// receive the result, and must later swizzle that into the original
// l-value.
complexLvalue = builder.getAccessChain();
temporaryLvalue = builder.createVariable(spv::StorageClassFunction, builder.accessChainGetInferredType(), "swizzleTemp");
operands.push_back(temporaryLvalue);
} else {
operands.push_back(builder.accessChainGetLValue());
}
lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
} else { } else {
...@@ -2883,8 +2901,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -2883,8 +2901,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
break; break;
} }
if (invertedType) if (invertedType != spv::NoResult)
result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
else if (temporaryLvalue != spv::NoResult) {
builder.setAccessChain(complexLvalue);
builder.accessChainStore(builder.createLoad(temporaryLvalue));
}
} }
if (noReturnValue) if (noReturnValue)
......
...@@ -676,6 +676,11 @@ public: ...@@ -676,6 +676,11 @@ public:
// use accessChain and swizzle to load an r-value // use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Return whether or not the access chain can be represented in SPIR-V
// as an l-value.
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
// get the direct pointer for an l-value // get the direct pointer for an l-value
Id accessChainGetLValue(); Id accessChainGetLValue();
......
...@@ -55,9 +55,10 @@ void main() ...@@ -55,9 +55,10 @@ void main()
v += ceil(v); v += ceil(v);
v += fract(v); v += fract(v);
v += mod(v, v); v += mod(v, v);
v += mod(v, v.x); v += mod(v, v.x);
v += modf(v, v); v += modf(v, v);
v += modf(v, v.yzxw);
v += min(v, uv4); v += min(v, uv4);
v += max(v, uv4); v += max(v, uv4);
......
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