mirror of
https://github.com/RPCS3/glslang.git
synced 2024-11-28 21:50:46 +00:00
Merge pull request #222 from Qining/support-precise
Full stack: Support *precise* qualifier
This commit is contained in:
commit
3357d870e4
@ -33,8 +33,6 @@
|
|||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
|
||||||
// Author: John Kessenich, LunarG
|
|
||||||
//
|
//
|
||||||
// Visit the nodes in the glslang intermediate tree representation to
|
// Visit the nodes in the glslang intermediate tree representation to
|
||||||
// translate them to SPIR-V.
|
// translate them to SPIR-V.
|
||||||
@ -135,10 +133,10 @@ protected:
|
|||||||
spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
|
spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
|
||||||
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
|
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
|
||||||
|
|
||||||
spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
|
spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
|
||||||
spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right);
|
spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right);
|
||||||
spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
|
spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
|
||||||
spv::Id createUnaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
|
spv::Id createUnaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
|
||||||
spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand);
|
spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand);
|
||||||
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
|
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
|
||||||
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
|
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
|
||||||
@ -385,6 +383,15 @@ spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifie
|
|||||||
return (spv::Decoration)spv::BadValue;
|
return (spv::Decoration)spv::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If glslang type is noContraction, return SPIR-V NoContraction decoration.
|
||||||
|
spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier)
|
||||||
|
{
|
||||||
|
if (qualifier.noContraction)
|
||||||
|
return spv::DecorationNoContraction;
|
||||||
|
else
|
||||||
|
return (spv::Decoration)spv::BadValue;
|
||||||
|
}
|
||||||
|
|
||||||
// Translate glslang built-in variable to SPIR-V built in decoration.
|
// Translate glslang built-in variable to SPIR-V built in decoration.
|
||||||
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn)
|
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn)
|
||||||
{
|
{
|
||||||
@ -874,6 +881,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
|
|
||||||
// do the operation
|
// do the operation
|
||||||
rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
||||||
|
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
|
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
|
||||||
node->getType().getBasicType());
|
node->getType().getBasicType());
|
||||||
|
|
||||||
@ -992,6 +1000,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
|
|
||||||
// get result
|
// get result
|
||||||
spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
||||||
|
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
convertGlslangToSpvType(node->getType()), left, right,
|
convertGlslangToSpvType(node->getType()), left, right,
|
||||||
node->getLeft()->getType().getBasicType());
|
node->getLeft()->getType().getBasicType());
|
||||||
|
|
||||||
@ -1058,6 +1067,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||||||
operand = accessChainLoad(node->getOperand()->getType());
|
operand = accessChainLoad(node->getOperand()->getType());
|
||||||
|
|
||||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||||
|
spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier());
|
||||||
|
|
||||||
// it could be a conversion
|
// it could be a conversion
|
||||||
if (! result)
|
if (! result)
|
||||||
@ -1065,7 +1075,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||||||
|
|
||||||
// if not, then possibly an operation
|
// if not, then possibly an operation
|
||||||
if (! result)
|
if (! result)
|
||||||
result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
|
result = createUnaryOperation(node->getOp(), precision, noContraction, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
@ -1097,6 +1107,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||||||
op = glslang::EOpSub;
|
op = glslang::EOpSub;
|
||||||
|
|
||||||
spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()),
|
spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()),
|
||||||
|
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
convertGlslangToSpvType(node->getType()), operand, one,
|
convertGlslangToSpvType(node->getType()), operand, one,
|
||||||
node->getType().getBasicType());
|
node->getType().getBasicType());
|
||||||
assert(result != spv::NoResult);
|
assert(result != spv::NoResult);
|
||||||
@ -1395,7 +1406,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
right->traverse(this);
|
right->traverse(this);
|
||||||
spv::Id rightId = accessChainLoad(right->getType());
|
spv::Id rightId = accessChainLoad(right->getType());
|
||||||
|
|
||||||
result = createBinaryOperation(binOp, precision,
|
result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
convertGlslangToSpvType(node->getType()), leftId, rightId,
|
convertGlslangToSpvType(node->getType()), leftId, rightId,
|
||||||
left->getType().getBasicType(), reduceComparison);
|
left->getType().getBasicType(), reduceComparison);
|
||||||
|
|
||||||
@ -1469,7 +1480,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
result = createNoArgOperation(node->getOp());
|
result = createNoArgOperation(node->getOp());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), glslangOperands[0]->getAsTyped()->getBasicType());
|
result = createUnaryOperation(
|
||||||
|
node->getOp(), precision,
|
||||||
|
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
|
convertGlslangToSpvType(node->getType()), operands.front(),
|
||||||
|
glslangOperands[0]->getAsTyped()->getBasicType());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
|
result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
|
||||||
@ -2661,6 +2676,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||||||
|
|
||||||
// Translate AST operation to SPV operation, already having SPV-based operands/types.
|
// Translate AST operation to SPV operation, already having SPV-based operands/types.
|
||||||
spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision,
|
spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision,
|
||||||
|
spv::Decoration noContraction,
|
||||||
spv::Id typeId, spv::Id left, spv::Id right,
|
spv::Id typeId, spv::Id left, spv::Id right,
|
||||||
glslang::TBasicType typeProxy, bool reduceComparison)
|
glslang::TBasicType typeProxy, bool reduceComparison)
|
||||||
{
|
{
|
||||||
@ -2797,13 +2813,15 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||||||
if (binOp != spv::OpNop) {
|
if (binOp != spv::OpNop) {
|
||||||
assert(comparison == false);
|
assert(comparison == false);
|
||||||
if (builder.isMatrix(left) || builder.isMatrix(right))
|
if (builder.isMatrix(left) || builder.isMatrix(right))
|
||||||
return createBinaryMatrixOperation(binOp, precision, typeId, left, right);
|
return createBinaryMatrixOperation(binOp, precision, noContraction, typeId, left, right);
|
||||||
|
|
||||||
// No matrix involved; make both operands be the same number of components, if needed
|
// No matrix involved; make both operands be the same number of components, if needed
|
||||||
if (needMatchingVectors)
|
if (needMatchingVectors)
|
||||||
builder.promoteScalar(precision, left, right);
|
builder.promoteScalar(precision, left, right);
|
||||||
|
|
||||||
return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision);
|
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
|
||||||
|
addDecoration(result, noContraction);
|
||||||
|
return builder.setPrecision(result, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! comparison)
|
if (! comparison)
|
||||||
@ -2872,8 +2890,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binOp != spv::OpNop)
|
if (binOp != spv::OpNop) {
|
||||||
return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision);
|
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
|
||||||
|
addDecoration(result, noContraction);
|
||||||
|
return builder.setPrecision(result, precision);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2892,7 +2913,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||||||
// matrix op scalar op in {+, -, /}
|
// matrix op scalar op in {+, -, /}
|
||||||
// scalar op matrix op in {+, -, /}
|
// scalar op matrix op in {+, -, /}
|
||||||
//
|
//
|
||||||
spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right)
|
spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right)
|
||||||
{
|
{
|
||||||
bool firstClass = true;
|
bool firstClass = true;
|
||||||
|
|
||||||
@ -2928,8 +2949,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstClass)
|
if (firstClass) {
|
||||||
return builder.setPrecision(builder.createBinOp(op, typeId, left, right), precision);
|
spv::Id result = builder.createBinOp(op, typeId, left, right);
|
||||||
|
addDecoration(result, noContraction);
|
||||||
|
return builder.setPrecision(result, precision);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle component-wise +, -, *, and / for all combinations of type.
|
// Handle component-wise +, -, *, and / for all combinations of type.
|
||||||
// The result type of all of them is the same type as the (a) matrix operand.
|
// The result type of all of them is the same type as the (a) matrix operand.
|
||||||
@ -2964,8 +2988,9 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
|
|||||||
indexes.push_back(c);
|
indexes.push_back(c);
|
||||||
spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
|
spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
|
||||||
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
|
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
|
||||||
results.push_back(builder.createBinOp(op, vecType, leftVec, rightVec));
|
spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
|
||||||
builder.setPrecision(results.back(), precision);
|
addDecoration(result, noContraction);
|
||||||
|
results.push_back(builder.setPrecision(result, precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the pieces together
|
// put the pieces together
|
||||||
@ -2977,7 +3002,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
|
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
|
||||||
{
|
{
|
||||||
spv::Op unaryOp = spv::OpNop;
|
spv::Op unaryOp = spv::OpNop;
|
||||||
int libCall = -1;
|
int libCall = -1;
|
||||||
@ -2989,7 +3014,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||||||
if (isFloat) {
|
if (isFloat) {
|
||||||
unaryOp = spv::OpFNegate;
|
unaryOp = spv::OpFNegate;
|
||||||
if (builder.isMatrixType(typeId))
|
if (builder.isMatrixType(typeId))
|
||||||
return createUnaryMatrixOperation(unaryOp, precision, typeId, operand, typeProxy);
|
return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy);
|
||||||
} else
|
} else
|
||||||
unaryOp = spv::OpSNegate;
|
unaryOp = spv::OpSNegate;
|
||||||
break;
|
break;
|
||||||
@ -3271,11 +3296,12 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||||||
id = builder.createUnaryOp(unaryOp, typeId, operand);
|
id = builder.createUnaryOp(unaryOp, typeId, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addDecoration(id, noContraction);
|
||||||
return builder.setPrecision(id, precision);
|
return builder.setPrecision(id, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a unary operation on a matrix
|
// Create a unary operation on a matrix
|
||||||
spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */)
|
spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */)
|
||||||
{
|
{
|
||||||
// Handle unary operations vector by vector.
|
// Handle unary operations vector by vector.
|
||||||
// The result type is the same type as the original type.
|
// The result type is the same type as the original type.
|
||||||
@ -3296,8 +3322,9 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Deco
|
|||||||
std::vector<unsigned int> indexes;
|
std::vector<unsigned int> indexes;
|
||||||
indexes.push_back(c);
|
indexes.push_back(c);
|
||||||
spv::Id vec = builder.createCompositeExtract(operand, vecType, indexes);
|
spv::Id vec = builder.createCompositeExtract(operand, vecType, indexes);
|
||||||
results.push_back(builder.createUnaryOp(op, vecType, vec));
|
spv::Id vec_result = builder.createUnaryOp(op, vecType, vec);
|
||||||
builder.setPrecision(results.back(), precision);
|
addDecoration(vec_result, noContraction);
|
||||||
|
results.push_back(builder.setPrecision(vec_result, precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the pieces together
|
// put the pieces together
|
||||||
|
768
Test/baseResults/precise.tesc.out
Normal file
768
Test/baseResults/precise.tesc.out
Normal file
@ -0,0 +1,768 @@
|
|||||||
|
precise.tesc
|
||||||
|
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
|
||||||
|
|
||||||
|
Shader version: 450
|
||||||
|
Requested GL_EXT_gpu_shader5
|
||||||
|
Requested GL_EXT_shader_io_blocks
|
||||||
|
Requested GL_EXT_tessellation_shader
|
||||||
|
vertices = -1
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: minimal( (global float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:6 Sequence
|
||||||
|
0:6 Sequence
|
||||||
|
0:6 move second child to first child (temp float)
|
||||||
|
0:6 'result' (noContraction temp float)
|
||||||
|
0:6 Constant:
|
||||||
|
0:6 5.000000
|
||||||
|
0:7 Sequence
|
||||||
|
0:7 move second child to first child (temp float)
|
||||||
|
0:7 'a' (noContraction temp float)
|
||||||
|
0:7 Constant:
|
||||||
|
0:7 10.000000
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 move second child to first child (temp float)
|
||||||
|
0:8 'b' (noContraction temp float)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 20.000000
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child (temp float)
|
||||||
|
0:9 'c' (noContraction temp float)
|
||||||
|
0:9 Constant:
|
||||||
|
0:9 30.000000
|
||||||
|
0:10 Sequence
|
||||||
|
0:10 move second child to first child (temp float)
|
||||||
|
0:10 'd' (noContraction temp float)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 40.000000
|
||||||
|
0:11 move second child to first child (temp float)
|
||||||
|
0:11 'result' (noContraction temp float)
|
||||||
|
0:11 add (noContraction temp float)
|
||||||
|
0:11 component-wise multiply (noContraction temp float)
|
||||||
|
0:11 'a' (noContraction temp float)
|
||||||
|
0:11 'b' (noContraction temp float)
|
||||||
|
0:11 component-wise multiply (noContraction temp float)
|
||||||
|
0:11 'c' (noContraction temp float)
|
||||||
|
0:11 'd' (noContraction temp float)
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 'result' (noContraction temp float)
|
||||||
|
0:15 Function Definition: continuous_assignment( (global void)
|
||||||
|
0:15 Function Parameters:
|
||||||
|
0:16 Sequence
|
||||||
|
0:16 Sequence
|
||||||
|
0:16 move second child to first child (temp float)
|
||||||
|
0:16 'result' (noContraction temp float)
|
||||||
|
0:16 Constant:
|
||||||
|
0:16 5.000000
|
||||||
|
0:17 Sequence
|
||||||
|
0:17 move second child to first child (temp float)
|
||||||
|
0:17 'a' (noContraction temp float)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 10.000000
|
||||||
|
0:18 Sequence
|
||||||
|
0:18 move second child to first child (temp float)
|
||||||
|
0:18 'b' (noContraction temp float)
|
||||||
|
0:18 Constant:
|
||||||
|
0:18 20.000000
|
||||||
|
0:19 move second child to first child (temp float)
|
||||||
|
0:19 'result' (noContraction temp float)
|
||||||
|
0:19 move second child to first child (temp float)
|
||||||
|
0:19 'a' (noContraction temp float)
|
||||||
|
0:19 add (noContraction temp float)
|
||||||
|
0:19 'b' (noContraction temp float)
|
||||||
|
0:19 Constant:
|
||||||
|
0:19 4.000000
|
||||||
|
0:22 Function Definition: convert( (global void)
|
||||||
|
0:22 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:24 Sequence
|
||||||
|
0:24 move second child to first child (temp float)
|
||||||
|
0:24 'a' (noContraction temp float)
|
||||||
|
0:24 Constant:
|
||||||
|
0:24 10.000000
|
||||||
|
0:25 Sequence
|
||||||
|
0:25 move second child to first child (temp float)
|
||||||
|
0:25 'b' (noContraction temp float)
|
||||||
|
0:25 Constant:
|
||||||
|
0:25 20.000000
|
||||||
|
0:26 move second child to first child (temp float)
|
||||||
|
0:26 'b' (noContraction temp float)
|
||||||
|
0:26 add (noContraction temp float)
|
||||||
|
0:26 'a' (noContraction temp float)
|
||||||
|
0:26 'b' (noContraction temp float)
|
||||||
|
0:27 move second child to first child (temp double)
|
||||||
|
0:27 'result' (noContraction temp double)
|
||||||
|
0:27 Convert float to double (temp double)
|
||||||
|
0:27 'b' (noContraction temp float)
|
||||||
|
0:30 Function Definition: loop_for( (global float)
|
||||||
|
0:30 Function Parameters:
|
||||||
|
0:31 Sequence
|
||||||
|
0:31 Sequence
|
||||||
|
0:31 move second child to first child (temp float)
|
||||||
|
0:31 'r1' (noContraction temp float)
|
||||||
|
0:31 Constant:
|
||||||
|
0:31 5.000000
|
||||||
|
0:32 Sequence
|
||||||
|
0:32 move second child to first child (temp float)
|
||||||
|
0:32 'r2' (noContraction temp float)
|
||||||
|
0:32 Constant:
|
||||||
|
0:32 10.000000
|
||||||
|
0:33 Sequence
|
||||||
|
0:33 move second child to first child (temp int)
|
||||||
|
0:33 'a' (temp int)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 10 (const int)
|
||||||
|
0:34 Sequence
|
||||||
|
0:34 move second child to first child (temp int)
|
||||||
|
0:34 'b' (noContraction temp int)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 20 (const int)
|
||||||
|
0:35 Sequence
|
||||||
|
0:35 move second child to first child (temp int)
|
||||||
|
0:35 'c' (noContraction temp int)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 30 (const int)
|
||||||
|
0:36 Sequence
|
||||||
|
0:36 Sequence
|
||||||
|
0:36 move second child to first child (temp int)
|
||||||
|
0:36 'i' (noContraction temp int)
|
||||||
|
0:36 Constant:
|
||||||
|
0:36 0 (const int)
|
||||||
|
0:36 Loop with condition tested first
|
||||||
|
0:36 Loop Condition
|
||||||
|
0:36 Compare Less Than (temp bool)
|
||||||
|
0:36 'i' (temp int)
|
||||||
|
0:36 'a' (temp int)
|
||||||
|
0:36 Loop Body
|
||||||
|
0:37 Sequence
|
||||||
|
0:37 add second child into first child (noContraction temp float)
|
||||||
|
0:37 'r1' (noContraction temp float)
|
||||||
|
0:37 add (noContraction temp float)
|
||||||
|
0:37 add (noContraction temp float)
|
||||||
|
0:37 Constant:
|
||||||
|
0:37 3.120000
|
||||||
|
0:37 Convert int to float (temp float)
|
||||||
|
0:37 'b' (noContraction temp int)
|
||||||
|
0:37 Convert int to float (temp float)
|
||||||
|
0:37 'i' (noContraction temp int)
|
||||||
|
0:38 add second child into first child (noContraction temp int)
|
||||||
|
0:38 'c' (noContraction temp int)
|
||||||
|
0:38 Constant:
|
||||||
|
0:38 1 (const int)
|
||||||
|
0:36 Loop Terminal Expression
|
||||||
|
0:36 Post-Increment (noContraction temp int)
|
||||||
|
0:36 'i' (noContraction temp int)
|
||||||
|
0:40 add second child into first child (temp int)
|
||||||
|
0:40 'a' (temp int)
|
||||||
|
0:40 Constant:
|
||||||
|
0:40 1 (const int)
|
||||||
|
0:41 move second child to first child (temp float)
|
||||||
|
0:41 'r2' (noContraction temp float)
|
||||||
|
0:41 Convert int to float (temp float)
|
||||||
|
0:41 'c' (noContraction temp int)
|
||||||
|
0:42 Branch: Return with expression
|
||||||
|
0:42 Construct float (temp float)
|
||||||
|
0:42 add (temp float)
|
||||||
|
0:42 'r1' (noContraction temp float)
|
||||||
|
0:42 'r2' (noContraction temp float)
|
||||||
|
0:45 Function Definition: loop_array( (global void)
|
||||||
|
0:45 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:48 Sequence
|
||||||
|
0:48 move second child to first child (temp int)
|
||||||
|
0:48 'x' (noContraction temp int)
|
||||||
|
0:48 Constant:
|
||||||
|
0:48 22 (const int)
|
||||||
|
0:49 Sequence
|
||||||
|
0:49 move second child to first child (temp int)
|
||||||
|
0:49 'y' (noContraction temp int)
|
||||||
|
0:49 Constant:
|
||||||
|
0:49 33 (const int)
|
||||||
|
0:52 add second child into first child (noContraction temp float)
|
||||||
|
0:52 'result' (noContraction temp float)
|
||||||
|
0:52 add (noContraction temp float)
|
||||||
|
0:52 Convert int to float (temp float)
|
||||||
|
0:52 'x' (noContraction temp int)
|
||||||
|
0:52 Convert int to float (temp float)
|
||||||
|
0:52 'y' (noContraction temp int)
|
||||||
|
0:54 Sequence
|
||||||
|
0:54 Sequence
|
||||||
|
0:54 move second child to first child (temp int)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:54 Constant:
|
||||||
|
0:54 0 (const int)
|
||||||
|
0:54 Loop with condition tested first
|
||||||
|
0:54 Loop Condition
|
||||||
|
0:54 Compare Less Than (temp bool)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:54 Constant:
|
||||||
|
0:54 3 (const int)
|
||||||
|
0:54 Loop Body
|
||||||
|
0:56 Sequence
|
||||||
|
0:56 add second child into first child (noContraction temp float)
|
||||||
|
0:56 'result' (noContraction temp float)
|
||||||
|
0:56 add (noContraction temp float)
|
||||||
|
0:56 indirect index (noContraction temp float)
|
||||||
|
0:56 'a0' (temp 3-element array of float)
|
||||||
|
0:56 'i' (temp int)
|
||||||
|
0:56 Constant:
|
||||||
|
0:56 2.000000
|
||||||
|
0:58 move second child to first child (temp float)
|
||||||
|
0:58 indirect index (noContraction temp float)
|
||||||
|
0:58 'a0' (noContraction temp 3-element array of float)
|
||||||
|
0:58 'i' (temp int)
|
||||||
|
0:58 subtract (noContraction temp float)
|
||||||
|
0:58 Constant:
|
||||||
|
0:58 3.000000
|
||||||
|
0:58 Post-Increment (noContraction temp float)
|
||||||
|
0:58 'result' (noContraction temp float)
|
||||||
|
0:54 Loop Terminal Expression
|
||||||
|
0:54 Pre-Increment (temp int)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:62 Function Definition: loop_while( (global void)
|
||||||
|
0:62 Function Parameters:
|
||||||
|
0:63 Sequence
|
||||||
|
0:63 Sequence
|
||||||
|
0:63 move second child to first child (temp float)
|
||||||
|
0:63 'result' (noContraction temp float)
|
||||||
|
0:63 Constant:
|
||||||
|
0:63 5.000000
|
||||||
|
0:64 Sequence
|
||||||
|
0:64 move second child to first child (temp int)
|
||||||
|
0:64 'a' (noContraction temp int)
|
||||||
|
0:64 Constant:
|
||||||
|
0:64 10 (const int)
|
||||||
|
0:65 Sequence
|
||||||
|
0:65 move second child to first child (temp int)
|
||||||
|
0:65 'b' (noContraction temp int)
|
||||||
|
0:65 Constant:
|
||||||
|
0:65 20 (const int)
|
||||||
|
0:66 Loop with condition tested first
|
||||||
|
0:66 Loop Condition
|
||||||
|
0:66 Compare Less Than (temp bool)
|
||||||
|
0:66 'result' (noContraction temp float)
|
||||||
|
0:66 Constant:
|
||||||
|
0:66 10.000000
|
||||||
|
0:66 Loop Body
|
||||||
|
0:67 Sequence
|
||||||
|
0:67 add second child into first child (noContraction temp float)
|
||||||
|
0:67 'result' (noContraction temp float)
|
||||||
|
0:67 add (noContraction temp float)
|
||||||
|
0:67 Constant:
|
||||||
|
0:67 3.120000
|
||||||
|
0:67 Convert int to float (temp float)
|
||||||
|
0:67 'b' (noContraction temp int)
|
||||||
|
0:69 move second child to first child (temp float)
|
||||||
|
0:69 'result' (noContraction temp float)
|
||||||
|
0:69 Convert int to float (temp float)
|
||||||
|
0:69 add (temp int)
|
||||||
|
0:69 add (temp int)
|
||||||
|
0:69 'a' (noContraction temp int)
|
||||||
|
0:69 'b' (noContraction temp int)
|
||||||
|
0:69 Constant:
|
||||||
|
0:69 5 (const int)
|
||||||
|
0:70 move second child to first child (temp float)
|
||||||
|
0:70 'result' (noContraction temp float)
|
||||||
|
0:70 Constant:
|
||||||
|
0:70 11.100000
|
||||||
|
0:73 Function Definition: fma_not_decorated( (global float)
|
||||||
|
0:73 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:75 Sequence
|
||||||
|
0:75 move second child to first child (temp float)
|
||||||
|
0:75 'a' (noContraction temp float)
|
||||||
|
0:75 Constant:
|
||||||
|
0:75 1.000000
|
||||||
|
0:76 Sequence
|
||||||
|
0:76 move second child to first child (temp float)
|
||||||
|
0:76 'b' (noContraction temp float)
|
||||||
|
0:76 Constant:
|
||||||
|
0:76 2.000000
|
||||||
|
0:77 Sequence
|
||||||
|
0:77 move second child to first child (temp float)
|
||||||
|
0:77 'c' (noContraction temp float)
|
||||||
|
0:77 Constant:
|
||||||
|
0:77 3.000000
|
||||||
|
0:78 move second child to first child (temp float)
|
||||||
|
0:78 'b' (noContraction temp float)
|
||||||
|
0:78 add (noContraction temp float)
|
||||||
|
0:78 'b' (noContraction temp float)
|
||||||
|
0:78 'c' (noContraction temp float)
|
||||||
|
0:79 move second child to first child (temp float)
|
||||||
|
0:79 'result' (noContraction temp float)
|
||||||
|
0:79 fma (global float)
|
||||||
|
0:79 'a' (noContraction temp float)
|
||||||
|
0:79 'b' (noContraction temp float)
|
||||||
|
0:79 'c' (noContraction temp float)
|
||||||
|
0:80 Branch: Return with expression
|
||||||
|
0:80 'result' (noContraction temp float)
|
||||||
|
0:83 Function Definition: precise_return_exp_func( (noContraction temp float)
|
||||||
|
0:83 Function Parameters:
|
||||||
|
0:84 Sequence
|
||||||
|
0:84 Sequence
|
||||||
|
0:84 move second child to first child (temp float)
|
||||||
|
0:84 'a' (noContraction temp float)
|
||||||
|
0:84 Constant:
|
||||||
|
0:84 1.000000
|
||||||
|
0:85 Sequence
|
||||||
|
0:85 move second child to first child (temp float)
|
||||||
|
0:85 'b' (noContraction temp float)
|
||||||
|
0:85 Constant:
|
||||||
|
0:85 2.000000
|
||||||
|
0:86 Branch: Return with expression
|
||||||
|
0:86 add (noContraction temp float)
|
||||||
|
0:86 'a' (noContraction temp float)
|
||||||
|
0:86 'b' (noContraction temp float)
|
||||||
|
0:89 Function Definition: precise_return_val_func( (noContraction temp float)
|
||||||
|
0:89 Function Parameters:
|
||||||
|
0:90 Sequence
|
||||||
|
0:90 Sequence
|
||||||
|
0:90 move second child to first child (temp float)
|
||||||
|
0:90 'a' (noContraction temp float)
|
||||||
|
0:90 Constant:
|
||||||
|
0:90 1.000000
|
||||||
|
0:91 Sequence
|
||||||
|
0:91 move second child to first child (temp float)
|
||||||
|
0:91 'b' (noContraction temp float)
|
||||||
|
0:91 Constant:
|
||||||
|
0:91 2.000000
|
||||||
|
0:92 Sequence
|
||||||
|
0:92 move second child to first child (temp float)
|
||||||
|
0:92 'result' (noContraction temp float)
|
||||||
|
0:92 add (noContraction temp float)
|
||||||
|
0:92 'a' (noContraction temp float)
|
||||||
|
0:92 'b' (noContraction temp float)
|
||||||
|
0:93 Branch: Return with expression
|
||||||
|
0:93 'result' (noContraction temp float)
|
||||||
|
0:96 Function Definition: precise_func_parameter(f1;f1; (global float)
|
||||||
|
0:96 Function Parameters:
|
||||||
|
0:96 'b' (in float)
|
||||||
|
0:96 'c' (noContraction out float)
|
||||||
|
0:97 Sequence
|
||||||
|
0:97 Sequence
|
||||||
|
0:97 move second child to first child (temp float)
|
||||||
|
0:97 'a' (noContraction temp float)
|
||||||
|
0:97 Constant:
|
||||||
|
0:97 0.500000
|
||||||
|
0:98 move second child to first child (temp float)
|
||||||
|
0:98 'c' (noContraction out float)
|
||||||
|
0:98 add (noContraction temp float)
|
||||||
|
0:98 'a' (noContraction temp float)
|
||||||
|
0:98 'b' (noContraction in float)
|
||||||
|
0:99 Branch: Return with expression
|
||||||
|
0:99 subtract (temp float)
|
||||||
|
0:99 'a' (temp float)
|
||||||
|
0:99 'b' (in float)
|
||||||
|
0:102 Function Definition: matrix(mf23;mf32; (global 3X3 matrix of float)
|
||||||
|
0:102 Function Parameters:
|
||||||
|
0:102 'a' (in 2X3 matrix of float)
|
||||||
|
0:102 'b' (in 3X2 matrix of float)
|
||||||
|
0:103 Sequence
|
||||||
|
0:103 Sequence
|
||||||
|
0:103 move second child to first child (temp 2X3 matrix of float)
|
||||||
|
0:103 'c' (noContraction temp 2X3 matrix of float)
|
||||||
|
0:103 Constant:
|
||||||
|
0:103 1.000000
|
||||||
|
0:103 2.000000
|
||||||
|
0:103 3.000000
|
||||||
|
0:103 4.000000
|
||||||
|
0:103 5.000000
|
||||||
|
0:103 6.000000
|
||||||
|
0:105 move second child to first child (temp 3X3 matrix of float)
|
||||||
|
0:105 'result' (noContraction temp 3X3 matrix of float)
|
||||||
|
0:105 matrix-multiply (noContraction temp 3X3 matrix of float)
|
||||||
|
0:105 add (noContraction temp 2X3 matrix of float)
|
||||||
|
0:105 'a' (noContraction in 2X3 matrix of float)
|
||||||
|
0:105 'c' (noContraction temp 2X3 matrix of float)
|
||||||
|
0:105 'b' (noContraction in 3X2 matrix of float)
|
||||||
|
0:106 Branch: Return with expression
|
||||||
|
0:106 'result' (noContraction temp 3X3 matrix of float)
|
||||||
|
0:109 Function Definition: main( (global void)
|
||||||
|
0:109 Function Parameters:
|
||||||
|
0:? Linker Objects
|
||||||
|
|
||||||
|
|
||||||
|
Linked tessellation control stage:
|
||||||
|
|
||||||
|
ERROR: Linking tessellation control stage: At least one shader must specify an output layout(vertices=...)
|
||||||
|
|
||||||
|
Shader version: 450
|
||||||
|
Requested GL_EXT_gpu_shader5
|
||||||
|
Requested GL_EXT_shader_io_blocks
|
||||||
|
Requested GL_EXT_tessellation_shader
|
||||||
|
vertices = -1
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Function Definition: minimal( (global float)
|
||||||
|
0:5 Function Parameters:
|
||||||
|
0:6 Sequence
|
||||||
|
0:6 Sequence
|
||||||
|
0:6 move second child to first child (temp float)
|
||||||
|
0:6 'result' (noContraction temp float)
|
||||||
|
0:6 Constant:
|
||||||
|
0:6 5.000000
|
||||||
|
0:7 Sequence
|
||||||
|
0:7 move second child to first child (temp float)
|
||||||
|
0:7 'a' (noContraction temp float)
|
||||||
|
0:7 Constant:
|
||||||
|
0:7 10.000000
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 move second child to first child (temp float)
|
||||||
|
0:8 'b' (noContraction temp float)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 20.000000
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child (temp float)
|
||||||
|
0:9 'c' (noContraction temp float)
|
||||||
|
0:9 Constant:
|
||||||
|
0:9 30.000000
|
||||||
|
0:10 Sequence
|
||||||
|
0:10 move second child to first child (temp float)
|
||||||
|
0:10 'd' (noContraction temp float)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 40.000000
|
||||||
|
0:11 move second child to first child (temp float)
|
||||||
|
0:11 'result' (noContraction temp float)
|
||||||
|
0:11 add (noContraction temp float)
|
||||||
|
0:11 component-wise multiply (noContraction temp float)
|
||||||
|
0:11 'a' (noContraction temp float)
|
||||||
|
0:11 'b' (noContraction temp float)
|
||||||
|
0:11 component-wise multiply (noContraction temp float)
|
||||||
|
0:11 'c' (noContraction temp float)
|
||||||
|
0:11 'd' (noContraction temp float)
|
||||||
|
0:12 Branch: Return with expression
|
||||||
|
0:12 'result' (noContraction temp float)
|
||||||
|
0:15 Function Definition: continuous_assignment( (global void)
|
||||||
|
0:15 Function Parameters:
|
||||||
|
0:16 Sequence
|
||||||
|
0:16 Sequence
|
||||||
|
0:16 move second child to first child (temp float)
|
||||||
|
0:16 'result' (noContraction temp float)
|
||||||
|
0:16 Constant:
|
||||||
|
0:16 5.000000
|
||||||
|
0:17 Sequence
|
||||||
|
0:17 move second child to first child (temp float)
|
||||||
|
0:17 'a' (noContraction temp float)
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 10.000000
|
||||||
|
0:18 Sequence
|
||||||
|
0:18 move second child to first child (temp float)
|
||||||
|
0:18 'b' (noContraction temp float)
|
||||||
|
0:18 Constant:
|
||||||
|
0:18 20.000000
|
||||||
|
0:19 move second child to first child (temp float)
|
||||||
|
0:19 'result' (noContraction temp float)
|
||||||
|
0:19 move second child to first child (temp float)
|
||||||
|
0:19 'a' (noContraction temp float)
|
||||||
|
0:19 add (noContraction temp float)
|
||||||
|
0:19 'b' (noContraction temp float)
|
||||||
|
0:19 Constant:
|
||||||
|
0:19 4.000000
|
||||||
|
0:22 Function Definition: convert( (global void)
|
||||||
|
0:22 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:24 Sequence
|
||||||
|
0:24 move second child to first child (temp float)
|
||||||
|
0:24 'a' (noContraction temp float)
|
||||||
|
0:24 Constant:
|
||||||
|
0:24 10.000000
|
||||||
|
0:25 Sequence
|
||||||
|
0:25 move second child to first child (temp float)
|
||||||
|
0:25 'b' (noContraction temp float)
|
||||||
|
0:25 Constant:
|
||||||
|
0:25 20.000000
|
||||||
|
0:26 move second child to first child (temp float)
|
||||||
|
0:26 'b' (noContraction temp float)
|
||||||
|
0:26 add (noContraction temp float)
|
||||||
|
0:26 'a' (noContraction temp float)
|
||||||
|
0:26 'b' (noContraction temp float)
|
||||||
|
0:27 move second child to first child (temp double)
|
||||||
|
0:27 'result' (noContraction temp double)
|
||||||
|
0:27 Convert float to double (temp double)
|
||||||
|
0:27 'b' (noContraction temp float)
|
||||||
|
0:30 Function Definition: loop_for( (global float)
|
||||||
|
0:30 Function Parameters:
|
||||||
|
0:31 Sequence
|
||||||
|
0:31 Sequence
|
||||||
|
0:31 move second child to first child (temp float)
|
||||||
|
0:31 'r1' (noContraction temp float)
|
||||||
|
0:31 Constant:
|
||||||
|
0:31 5.000000
|
||||||
|
0:32 Sequence
|
||||||
|
0:32 move second child to first child (temp float)
|
||||||
|
0:32 'r2' (noContraction temp float)
|
||||||
|
0:32 Constant:
|
||||||
|
0:32 10.000000
|
||||||
|
0:33 Sequence
|
||||||
|
0:33 move second child to first child (temp int)
|
||||||
|
0:33 'a' (temp int)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 10 (const int)
|
||||||
|
0:34 Sequence
|
||||||
|
0:34 move second child to first child (temp int)
|
||||||
|
0:34 'b' (noContraction temp int)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 20 (const int)
|
||||||
|
0:35 Sequence
|
||||||
|
0:35 move second child to first child (temp int)
|
||||||
|
0:35 'c' (noContraction temp int)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 30 (const int)
|
||||||
|
0:36 Sequence
|
||||||
|
0:36 Sequence
|
||||||
|
0:36 move second child to first child (temp int)
|
||||||
|
0:36 'i' (noContraction temp int)
|
||||||
|
0:36 Constant:
|
||||||
|
0:36 0 (const int)
|
||||||
|
0:36 Loop with condition tested first
|
||||||
|
0:36 Loop Condition
|
||||||
|
0:36 Compare Less Than (temp bool)
|
||||||
|
0:36 'i' (temp int)
|
||||||
|
0:36 'a' (temp int)
|
||||||
|
0:36 Loop Body
|
||||||
|
0:37 Sequence
|
||||||
|
0:37 add second child into first child (noContraction temp float)
|
||||||
|
0:37 'r1' (noContraction temp float)
|
||||||
|
0:37 add (noContraction temp float)
|
||||||
|
0:37 add (noContraction temp float)
|
||||||
|
0:37 Constant:
|
||||||
|
0:37 3.120000
|
||||||
|
0:37 Convert int to float (temp float)
|
||||||
|
0:37 'b' (noContraction temp int)
|
||||||
|
0:37 Convert int to float (temp float)
|
||||||
|
0:37 'i' (noContraction temp int)
|
||||||
|
0:38 add second child into first child (noContraction temp int)
|
||||||
|
0:38 'c' (noContraction temp int)
|
||||||
|
0:38 Constant:
|
||||||
|
0:38 1 (const int)
|
||||||
|
0:36 Loop Terminal Expression
|
||||||
|
0:36 Post-Increment (noContraction temp int)
|
||||||
|
0:36 'i' (noContraction temp int)
|
||||||
|
0:40 add second child into first child (temp int)
|
||||||
|
0:40 'a' (temp int)
|
||||||
|
0:40 Constant:
|
||||||
|
0:40 1 (const int)
|
||||||
|
0:41 move second child to first child (temp float)
|
||||||
|
0:41 'r2' (noContraction temp float)
|
||||||
|
0:41 Convert int to float (temp float)
|
||||||
|
0:41 'c' (noContraction temp int)
|
||||||
|
0:42 Branch: Return with expression
|
||||||
|
0:42 Construct float (temp float)
|
||||||
|
0:42 add (temp float)
|
||||||
|
0:42 'r1' (noContraction temp float)
|
||||||
|
0:42 'r2' (noContraction temp float)
|
||||||
|
0:45 Function Definition: loop_array( (global void)
|
||||||
|
0:45 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:48 Sequence
|
||||||
|
0:48 move second child to first child (temp int)
|
||||||
|
0:48 'x' (noContraction temp int)
|
||||||
|
0:48 Constant:
|
||||||
|
0:48 22 (const int)
|
||||||
|
0:49 Sequence
|
||||||
|
0:49 move second child to first child (temp int)
|
||||||
|
0:49 'y' (noContraction temp int)
|
||||||
|
0:49 Constant:
|
||||||
|
0:49 33 (const int)
|
||||||
|
0:52 add second child into first child (noContraction temp float)
|
||||||
|
0:52 'result' (noContraction temp float)
|
||||||
|
0:52 add (noContraction temp float)
|
||||||
|
0:52 Convert int to float (temp float)
|
||||||
|
0:52 'x' (noContraction temp int)
|
||||||
|
0:52 Convert int to float (temp float)
|
||||||
|
0:52 'y' (noContraction temp int)
|
||||||
|
0:54 Sequence
|
||||||
|
0:54 Sequence
|
||||||
|
0:54 move second child to first child (temp int)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:54 Constant:
|
||||||
|
0:54 0 (const int)
|
||||||
|
0:54 Loop with condition tested first
|
||||||
|
0:54 Loop Condition
|
||||||
|
0:54 Compare Less Than (temp bool)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:54 Constant:
|
||||||
|
0:54 3 (const int)
|
||||||
|
0:54 Loop Body
|
||||||
|
0:56 Sequence
|
||||||
|
0:56 add second child into first child (noContraction temp float)
|
||||||
|
0:56 'result' (noContraction temp float)
|
||||||
|
0:56 add (noContraction temp float)
|
||||||
|
0:56 indirect index (noContraction temp float)
|
||||||
|
0:56 'a0' (temp 3-element array of float)
|
||||||
|
0:56 'i' (temp int)
|
||||||
|
0:56 Constant:
|
||||||
|
0:56 2.000000
|
||||||
|
0:58 move second child to first child (temp float)
|
||||||
|
0:58 indirect index (noContraction temp float)
|
||||||
|
0:58 'a0' (noContraction temp 3-element array of float)
|
||||||
|
0:58 'i' (temp int)
|
||||||
|
0:58 subtract (noContraction temp float)
|
||||||
|
0:58 Constant:
|
||||||
|
0:58 3.000000
|
||||||
|
0:58 Post-Increment (noContraction temp float)
|
||||||
|
0:58 'result' (noContraction temp float)
|
||||||
|
0:54 Loop Terminal Expression
|
||||||
|
0:54 Pre-Increment (temp int)
|
||||||
|
0:54 'i' (temp int)
|
||||||
|
0:62 Function Definition: loop_while( (global void)
|
||||||
|
0:62 Function Parameters:
|
||||||
|
0:63 Sequence
|
||||||
|
0:63 Sequence
|
||||||
|
0:63 move second child to first child (temp float)
|
||||||
|
0:63 'result' (noContraction temp float)
|
||||||
|
0:63 Constant:
|
||||||
|
0:63 5.000000
|
||||||
|
0:64 Sequence
|
||||||
|
0:64 move second child to first child (temp int)
|
||||||
|
0:64 'a' (noContraction temp int)
|
||||||
|
0:64 Constant:
|
||||||
|
0:64 10 (const int)
|
||||||
|
0:65 Sequence
|
||||||
|
0:65 move second child to first child (temp int)
|
||||||
|
0:65 'b' (noContraction temp int)
|
||||||
|
0:65 Constant:
|
||||||
|
0:65 20 (const int)
|
||||||
|
0:66 Loop with condition tested first
|
||||||
|
0:66 Loop Condition
|
||||||
|
0:66 Compare Less Than (temp bool)
|
||||||
|
0:66 'result' (noContraction temp float)
|
||||||
|
0:66 Constant:
|
||||||
|
0:66 10.000000
|
||||||
|
0:66 Loop Body
|
||||||
|
0:67 Sequence
|
||||||
|
0:67 add second child into first child (noContraction temp float)
|
||||||
|
0:67 'result' (noContraction temp float)
|
||||||
|
0:67 add (noContraction temp float)
|
||||||
|
0:67 Constant:
|
||||||
|
0:67 3.120000
|
||||||
|
0:67 Convert int to float (temp float)
|
||||||
|
0:67 'b' (noContraction temp int)
|
||||||
|
0:69 move second child to first child (temp float)
|
||||||
|
0:69 'result' (noContraction temp float)
|
||||||
|
0:69 Convert int to float (temp float)
|
||||||
|
0:69 add (temp int)
|
||||||
|
0:69 add (temp int)
|
||||||
|
0:69 'a' (noContraction temp int)
|
||||||
|
0:69 'b' (noContraction temp int)
|
||||||
|
0:69 Constant:
|
||||||
|
0:69 5 (const int)
|
||||||
|
0:70 move second child to first child (temp float)
|
||||||
|
0:70 'result' (noContraction temp float)
|
||||||
|
0:70 Constant:
|
||||||
|
0:70 11.100000
|
||||||
|
0:73 Function Definition: fma_not_decorated( (global float)
|
||||||
|
0:73 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:75 Sequence
|
||||||
|
0:75 move second child to first child (temp float)
|
||||||
|
0:75 'a' (noContraction temp float)
|
||||||
|
0:75 Constant:
|
||||||
|
0:75 1.000000
|
||||||
|
0:76 Sequence
|
||||||
|
0:76 move second child to first child (temp float)
|
||||||
|
0:76 'b' (noContraction temp float)
|
||||||
|
0:76 Constant:
|
||||||
|
0:76 2.000000
|
||||||
|
0:77 Sequence
|
||||||
|
0:77 move second child to first child (temp float)
|
||||||
|
0:77 'c' (noContraction temp float)
|
||||||
|
0:77 Constant:
|
||||||
|
0:77 3.000000
|
||||||
|
0:78 move second child to first child (temp float)
|
||||||
|
0:78 'b' (noContraction temp float)
|
||||||
|
0:78 add (noContraction temp float)
|
||||||
|
0:78 'b' (noContraction temp float)
|
||||||
|
0:78 'c' (noContraction temp float)
|
||||||
|
0:79 move second child to first child (temp float)
|
||||||
|
0:79 'result' (noContraction temp float)
|
||||||
|
0:79 fma (global float)
|
||||||
|
0:79 'a' (noContraction temp float)
|
||||||
|
0:79 'b' (noContraction temp float)
|
||||||
|
0:79 'c' (noContraction temp float)
|
||||||
|
0:80 Branch: Return with expression
|
||||||
|
0:80 'result' (noContraction temp float)
|
||||||
|
0:83 Function Definition: precise_return_exp_func( (noContraction temp float)
|
||||||
|
0:83 Function Parameters:
|
||||||
|
0:84 Sequence
|
||||||
|
0:84 Sequence
|
||||||
|
0:84 move second child to first child (temp float)
|
||||||
|
0:84 'a' (noContraction temp float)
|
||||||
|
0:84 Constant:
|
||||||
|
0:84 1.000000
|
||||||
|
0:85 Sequence
|
||||||
|
0:85 move second child to first child (temp float)
|
||||||
|
0:85 'b' (noContraction temp float)
|
||||||
|
0:85 Constant:
|
||||||
|
0:85 2.000000
|
||||||
|
0:86 Branch: Return with expression
|
||||||
|
0:86 add (noContraction temp float)
|
||||||
|
0:86 'a' (noContraction temp float)
|
||||||
|
0:86 'b' (noContraction temp float)
|
||||||
|
0:89 Function Definition: precise_return_val_func( (noContraction temp float)
|
||||||
|
0:89 Function Parameters:
|
||||||
|
0:90 Sequence
|
||||||
|
0:90 Sequence
|
||||||
|
0:90 move second child to first child (temp float)
|
||||||
|
0:90 'a' (noContraction temp float)
|
||||||
|
0:90 Constant:
|
||||||
|
0:90 1.000000
|
||||||
|
0:91 Sequence
|
||||||
|
0:91 move second child to first child (temp float)
|
||||||
|
0:91 'b' (noContraction temp float)
|
||||||
|
0:91 Constant:
|
||||||
|
0:91 2.000000
|
||||||
|
0:92 Sequence
|
||||||
|
0:92 move second child to first child (temp float)
|
||||||
|
0:92 'result' (noContraction temp float)
|
||||||
|
0:92 add (noContraction temp float)
|
||||||
|
0:92 'a' (noContraction temp float)
|
||||||
|
0:92 'b' (noContraction temp float)
|
||||||
|
0:93 Branch: Return with expression
|
||||||
|
0:93 'result' (noContraction temp float)
|
||||||
|
0:96 Function Definition: precise_func_parameter(f1;f1; (global float)
|
||||||
|
0:96 Function Parameters:
|
||||||
|
0:96 'b' (in float)
|
||||||
|
0:96 'c' (noContraction out float)
|
||||||
|
0:97 Sequence
|
||||||
|
0:97 Sequence
|
||||||
|
0:97 move second child to first child (temp float)
|
||||||
|
0:97 'a' (noContraction temp float)
|
||||||
|
0:97 Constant:
|
||||||
|
0:97 0.500000
|
||||||
|
0:98 move second child to first child (temp float)
|
||||||
|
0:98 'c' (noContraction out float)
|
||||||
|
0:98 add (noContraction temp float)
|
||||||
|
0:98 'a' (noContraction temp float)
|
||||||
|
0:98 'b' (noContraction in float)
|
||||||
|
0:99 Branch: Return with expression
|
||||||
|
0:99 subtract (temp float)
|
||||||
|
0:99 'a' (temp float)
|
||||||
|
0:99 'b' (in float)
|
||||||
|
0:102 Function Definition: matrix(mf23;mf32; (global 3X3 matrix of float)
|
||||||
|
0:102 Function Parameters:
|
||||||
|
0:102 'a' (in 2X3 matrix of float)
|
||||||
|
0:102 'b' (in 3X2 matrix of float)
|
||||||
|
0:103 Sequence
|
||||||
|
0:103 Sequence
|
||||||
|
0:103 move second child to first child (temp 2X3 matrix of float)
|
||||||
|
0:103 'c' (noContraction temp 2X3 matrix of float)
|
||||||
|
0:103 Constant:
|
||||||
|
0:103 1.000000
|
||||||
|
0:103 2.000000
|
||||||
|
0:103 3.000000
|
||||||
|
0:103 4.000000
|
||||||
|
0:103 5.000000
|
||||||
|
0:103 6.000000
|
||||||
|
0:105 move second child to first child (temp 3X3 matrix of float)
|
||||||
|
0:105 'result' (noContraction temp 3X3 matrix of float)
|
||||||
|
0:105 matrix-multiply (noContraction temp 3X3 matrix of float)
|
||||||
|
0:105 add (noContraction temp 2X3 matrix of float)
|
||||||
|
0:105 'a' (noContraction in 2X3 matrix of float)
|
||||||
|
0:105 'c' (noContraction temp 2X3 matrix of float)
|
||||||
|
0:105 'b' (noContraction in 3X2 matrix of float)
|
||||||
|
0:106 Branch: Return with expression
|
||||||
|
0:106 'result' (noContraction temp 3X3 matrix of float)
|
||||||
|
0:109 Function Definition: main( (global void)
|
||||||
|
0:109 Function Parameters:
|
||||||
|
0:? Linker Objects
|
||||||
|
|
1045
Test/baseResults/precise_struct_block.vert.out
Normal file
1045
Test/baseResults/precise_struct_block.vert.out
Normal file
File diff suppressed because it is too large
Load Diff
122
Test/baseResults/spv.precise.tesc.out
Normal file
122
Test/baseResults/spv.precise.tesc.out
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
spv.precise.tesc
|
||||||
|
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||||
|
|
||||||
|
|
||||||
|
Linked tessellation control stage:
|
||||||
|
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 72
|
||||||
|
|
||||||
|
Capability Tessellation
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint TessellationControl 4 "main" 12 15 20 30 40 45
|
||||||
|
ExecutionMode 4 OutputVertices 3
|
||||||
|
Source ESSL 310
|
||||||
|
SourceExtension "GL_EXT_gpu_shader5"
|
||||||
|
SourceExtension "GL_EXT_shader_io_blocks"
|
||||||
|
SourceExtension "GL_EXT_tessellation_shader"
|
||||||
|
Name 4 "main"
|
||||||
|
Name 12 "in_te_position"
|
||||||
|
Name 15 "gl_InvocationID"
|
||||||
|
Name 20 "in_tc_position"
|
||||||
|
Name 30 "gl_TessLevelInner"
|
||||||
|
Name 40 "gl_TessLevelOuter"
|
||||||
|
Name 45 "in_tc_tessParam"
|
||||||
|
Decorate 12(in_te_position) Location 0
|
||||||
|
Decorate 15(gl_InvocationID) BuiltIn InvocationId
|
||||||
|
Decorate 20(in_tc_position) Location 0
|
||||||
|
Decorate 30(gl_TessLevelInner) Patch
|
||||||
|
Decorate 30(gl_TessLevelInner) BuiltIn TessLevelInner
|
||||||
|
Decorate 40(gl_TessLevelOuter) Patch
|
||||||
|
Decorate 40(gl_TessLevelOuter) BuiltIn TessLevelOuter
|
||||||
|
Decorate 45(in_tc_tessParam) Location 1
|
||||||
|
Decorate 52 NoContraction
|
||||||
|
Decorate 53 NoContraction
|
||||||
|
Decorate 54 NoContraction
|
||||||
|
Decorate 60 NoContraction
|
||||||
|
Decorate 61 NoContraction
|
||||||
|
Decorate 62 NoContraction
|
||||||
|
Decorate 68 NoContraction
|
||||||
|
Decorate 69 NoContraction
|
||||||
|
Decorate 70 NoContraction
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeFloat 32
|
||||||
|
7: TypeVector 6(float) 2
|
||||||
|
8: TypeInt 32 0
|
||||||
|
9: 8(int) Constant 3
|
||||||
|
10: TypeArray 7(fvec2) 9
|
||||||
|
11: TypePointer Output 10
|
||||||
|
12(in_te_position): 11(ptr) Variable Output
|
||||||
|
13: TypeInt 32 1
|
||||||
|
14: TypePointer Input 13(int)
|
||||||
|
15(gl_InvocationID): 14(ptr) Variable Input
|
||||||
|
17: 8(int) Constant 32
|
||||||
|
18: TypeArray 7(fvec2) 17
|
||||||
|
19: TypePointer Input 18
|
||||||
|
20(in_tc_position): 19(ptr) Variable Input
|
||||||
|
22: TypePointer Input 7(fvec2)
|
||||||
|
25: TypePointer Output 7(fvec2)
|
||||||
|
27: 8(int) Constant 2
|
||||||
|
28: TypeArray 6(float) 27
|
||||||
|
29: TypePointer Output 28
|
||||||
|
30(gl_TessLevelInner): 29(ptr) Variable Output
|
||||||
|
31: 13(int) Constant 0
|
||||||
|
32: 6(float) Constant 1084227584
|
||||||
|
33: TypePointer Output 6(float)
|
||||||
|
35: 13(int) Constant 1
|
||||||
|
37: 8(int) Constant 4
|
||||||
|
38: TypeArray 6(float) 37
|
||||||
|
39: TypePointer Output 38
|
||||||
|
40(gl_TessLevelOuter): 39(ptr) Variable Output
|
||||||
|
41: 6(float) Constant 1065353216
|
||||||
|
42: 6(float) Constant 1105985536
|
||||||
|
43: TypeArray 6(float) 17
|
||||||
|
44: TypePointer Input 43
|
||||||
|
45(in_tc_tessParam): 44(ptr) Variable Input
|
||||||
|
46: TypePointer Input 6(float)
|
||||||
|
49: 13(int) Constant 2
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
16: 13(int) Load 15(gl_InvocationID)
|
||||||
|
21: 13(int) Load 15(gl_InvocationID)
|
||||||
|
23: 22(ptr) AccessChain 20(in_tc_position) 21
|
||||||
|
24: 7(fvec2) Load 23
|
||||||
|
26: 25(ptr) AccessChain 12(in_te_position) 16
|
||||||
|
Store 26 24
|
||||||
|
34: 33(ptr) AccessChain 30(gl_TessLevelInner) 31
|
||||||
|
Store 34 32
|
||||||
|
36: 33(ptr) AccessChain 30(gl_TessLevelInner) 35
|
||||||
|
Store 36 32
|
||||||
|
47: 46(ptr) AccessChain 45(in_tc_tessParam) 35
|
||||||
|
48: 6(float) Load 47
|
||||||
|
50: 46(ptr) AccessChain 45(in_tc_tessParam) 49
|
||||||
|
51: 6(float) Load 50
|
||||||
|
52: 6(float) FAdd 48 51
|
||||||
|
53: 6(float) FMul 42 52
|
||||||
|
54: 6(float) FAdd 41 53
|
||||||
|
55: 33(ptr) AccessChain 40(gl_TessLevelOuter) 31
|
||||||
|
Store 55 54
|
||||||
|
56: 46(ptr) AccessChain 45(in_tc_tessParam) 49
|
||||||
|
57: 6(float) Load 56
|
||||||
|
58: 46(ptr) AccessChain 45(in_tc_tessParam) 31
|
||||||
|
59: 6(float) Load 58
|
||||||
|
60: 6(float) FAdd 57 59
|
||||||
|
61: 6(float) FMul 42 60
|
||||||
|
62: 6(float) FAdd 41 61
|
||||||
|
63: 33(ptr) AccessChain 40(gl_TessLevelOuter) 35
|
||||||
|
Store 63 62
|
||||||
|
64: 46(ptr) AccessChain 45(in_tc_tessParam) 31
|
||||||
|
65: 6(float) Load 64
|
||||||
|
66: 46(ptr) AccessChain 45(in_tc_tessParam) 35
|
||||||
|
67: 6(float) Load 66
|
||||||
|
68: 6(float) FAdd 65 67
|
||||||
|
69: 6(float) FMul 42 68
|
||||||
|
70: 6(float) FAdd 41 69
|
||||||
|
71: 33(ptr) AccessChain 40(gl_TessLevelOuter) 49
|
||||||
|
Store 71 70
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
192
Test/baseResults/spv.precise.tese.out
Normal file
192
Test/baseResults/spv.precise.tese.out
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
spv.precise.tese
|
||||||
|
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||||
|
|
||||||
|
|
||||||
|
Linked tessellation evaluation stage:
|
||||||
|
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 119
|
||||||
|
|
||||||
|
Capability Tessellation
|
||||||
|
Capability TessellationPointSize
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint TessellationEvaluation 4 "main" 12 21 62 112
|
||||||
|
ExecutionMode 4 Triangles
|
||||||
|
ExecutionMode 4 SpacingEqual
|
||||||
|
ExecutionMode 4 VertexOrderCcw
|
||||||
|
Source ESSL 310
|
||||||
|
SourceExtension "GL_EXT_gpu_shader5"
|
||||||
|
SourceExtension "GL_EXT_shader_io_blocks"
|
||||||
|
SourceExtension "GL_EXT_tessellation_shader"
|
||||||
|
Name 4 "main"
|
||||||
|
Name 9 "pos"
|
||||||
|
Name 12 "gl_TessCoord"
|
||||||
|
Name 21 "in_te_position"
|
||||||
|
Name 45 "f"
|
||||||
|
Name 62 "in_f_color"
|
||||||
|
Name 73 "bits"
|
||||||
|
Name 77 "numBits"
|
||||||
|
Name 78 "i"
|
||||||
|
Name 110 "gl_PerVertex"
|
||||||
|
MemberName 110(gl_PerVertex) 0 "gl_Position"
|
||||||
|
MemberName 110(gl_PerVertex) 1 "gl_PointSize"
|
||||||
|
Name 112 ""
|
||||||
|
Decorate 12(gl_TessCoord) BuiltIn TessCoord
|
||||||
|
Decorate 21(in_te_position) Location 0
|
||||||
|
Decorate 27 NoContraction
|
||||||
|
Decorate 34 NoContraction
|
||||||
|
Decorate 35 NoContraction
|
||||||
|
Decorate 42 NoContraction
|
||||||
|
Decorate 43 NoContraction
|
||||||
|
Decorate 62(in_f_color) RelaxedPrecision
|
||||||
|
Decorate 62(in_f_color) Location 0
|
||||||
|
Decorate 67 RelaxedPrecision
|
||||||
|
Decorate 68 RelaxedPrecision
|
||||||
|
Decorate 69 RelaxedPrecision
|
||||||
|
Decorate 70 RelaxedPrecision
|
||||||
|
Decorate 97 NoContraction
|
||||||
|
Decorate 99 NoContraction
|
||||||
|
Decorate 101 NoContraction
|
||||||
|
Decorate 106 NoContraction
|
||||||
|
Decorate 109 NoContraction
|
||||||
|
MemberDecorate 110(gl_PerVertex) 0 BuiltIn Position
|
||||||
|
MemberDecorate 110(gl_PerVertex) 1 BuiltIn PointSize
|
||||||
|
Decorate 110(gl_PerVertex) Block
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeFloat 32
|
||||||
|
7: TypeVector 6(float) 2
|
||||||
|
8: TypePointer Function 7(fvec2)
|
||||||
|
10: TypeVector 6(float) 3
|
||||||
|
11: TypePointer Input 10(fvec3)
|
||||||
|
12(gl_TessCoord): 11(ptr) Variable Input
|
||||||
|
13: TypeInt 32 0
|
||||||
|
14: 13(int) Constant 0
|
||||||
|
15: TypePointer Input 6(float)
|
||||||
|
18: 13(int) Constant 32
|
||||||
|
19: TypeArray 7(fvec2) 18
|
||||||
|
20: TypePointer Input 19
|
||||||
|
21(in_te_position): 20(ptr) Variable Input
|
||||||
|
22: TypeInt 32 1
|
||||||
|
23: 22(int) Constant 0
|
||||||
|
24: TypePointer Input 7(fvec2)
|
||||||
|
28: 13(int) Constant 1
|
||||||
|
31: 22(int) Constant 1
|
||||||
|
36: 13(int) Constant 2
|
||||||
|
39: 22(int) Constant 2
|
||||||
|
44: TypePointer Function 6(float)
|
||||||
|
46: 6(float) Constant 1077936128
|
||||||
|
57: 6(float) Constant 1056964608
|
||||||
|
60: TypeVector 6(float) 4
|
||||||
|
61: TypePointer Output 60(fvec4)
|
||||||
|
62(in_f_color): 61(ptr) Variable Output
|
||||||
|
66: 6(float) Constant 1065353216
|
||||||
|
71: TypeVector 13(int) 2
|
||||||
|
72: TypePointer Function 71(ivec2)
|
||||||
|
76: TypePointer Function 13(int)
|
||||||
|
85: TypeBool
|
||||||
|
105: 6(float) Constant 1025758986
|
||||||
|
110(gl_PerVertex): TypeStruct 60(fvec4) 6(float)
|
||||||
|
111: TypePointer Output 110(gl_PerVertex)
|
||||||
|
112: 111(ptr) Variable Output
|
||||||
|
114: 6(float) Constant 0
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
9(pos): 8(ptr) Variable Function
|
||||||
|
45(f): 44(ptr) Variable Function
|
||||||
|
73(bits): 72(ptr) Variable Function
|
||||||
|
77(numBits): 76(ptr) Variable Function
|
||||||
|
78(i): 76(ptr) Variable Function
|
||||||
|
16: 15(ptr) AccessChain 12(gl_TessCoord) 14
|
||||||
|
17: 6(float) Load 16
|
||||||
|
25: 24(ptr) AccessChain 21(in_te_position) 23
|
||||||
|
26: 7(fvec2) Load 25
|
||||||
|
27: 7(fvec2) VectorTimesScalar 26 17
|
||||||
|
29: 15(ptr) AccessChain 12(gl_TessCoord) 28
|
||||||
|
30: 6(float) Load 29
|
||||||
|
32: 24(ptr) AccessChain 21(in_te_position) 31
|
||||||
|
33: 7(fvec2) Load 32
|
||||||
|
34: 7(fvec2) VectorTimesScalar 33 30
|
||||||
|
35: 7(fvec2) FAdd 27 34
|
||||||
|
37: 15(ptr) AccessChain 12(gl_TessCoord) 36
|
||||||
|
38: 6(float) Load 37
|
||||||
|
40: 24(ptr) AccessChain 21(in_te_position) 39
|
||||||
|
41: 7(fvec2) Load 40
|
||||||
|
42: 7(fvec2) VectorTimesScalar 41 38
|
||||||
|
43: 7(fvec2) FAdd 35 42
|
||||||
|
Store 9(pos) 43
|
||||||
|
47: 15(ptr) AccessChain 12(gl_TessCoord) 14
|
||||||
|
48: 6(float) Load 47
|
||||||
|
49: 15(ptr) AccessChain 12(gl_TessCoord) 28
|
||||||
|
50: 6(float) Load 49
|
||||||
|
51: 15(ptr) AccessChain 12(gl_TessCoord) 36
|
||||||
|
52: 6(float) Load 51
|
||||||
|
53: 6(float) ExtInst 1(GLSL.std.450) 37(FMin) 50 52
|
||||||
|
54: 6(float) ExtInst 1(GLSL.std.450) 37(FMin) 48 53
|
||||||
|
55: 6(float) FMul 46 54
|
||||||
|
56: 6(float) ExtInst 1(GLSL.std.450) 31(Sqrt) 55
|
||||||
|
58: 6(float) FMul 56 57
|
||||||
|
59: 6(float) FAdd 58 57
|
||||||
|
Store 45(f) 59
|
||||||
|
63: 10(fvec3) Load 12(gl_TessCoord)
|
||||||
|
64: 6(float) Load 45(f)
|
||||||
|
65: 10(fvec3) VectorTimesScalar 63 64
|
||||||
|
67: 6(float) CompositeExtract 65 0
|
||||||
|
68: 6(float) CompositeExtract 65 1
|
||||||
|
69: 6(float) CompositeExtract 65 2
|
||||||
|
70: 60(fvec4) CompositeConstruct 67 68 69 66
|
||||||
|
Store 62(in_f_color) 70
|
||||||
|
74: 7(fvec2) Load 9(pos)
|
||||||
|
75: 71(ivec2) Bitcast 74
|
||||||
|
Store 73(bits) 75
|
||||||
|
Store 77(numBits) 14
|
||||||
|
Store 78(i) 14
|
||||||
|
Branch 79
|
||||||
|
79: Label
|
||||||
|
LoopMerge 81 82 None
|
||||||
|
Branch 83
|
||||||
|
83: Label
|
||||||
|
84: 13(int) Load 78(i)
|
||||||
|
86: 85(bool) ULessThan 84 18
|
||||||
|
BranchConditional 86 80 81
|
||||||
|
80: Label
|
||||||
|
87: 76(ptr) AccessChain 73(bits) 14
|
||||||
|
88: 13(int) Load 87
|
||||||
|
89: 13(int) Load 78(i)
|
||||||
|
90: 13(int) ShiftLeftLogical 88 89
|
||||||
|
91: 13(int) BitwiseAnd 90 28
|
||||||
|
92: 76(ptr) AccessChain 73(bits) 28
|
||||||
|
93: 13(int) Load 92
|
||||||
|
94: 13(int) Load 78(i)
|
||||||
|
95: 13(int) ShiftLeftLogical 93 94
|
||||||
|
96: 13(int) BitwiseAnd 95 28
|
||||||
|
97: 13(int) IAdd 91 96
|
||||||
|
98: 13(int) Load 77(numBits)
|
||||||
|
99: 13(int) IAdd 98 97
|
||||||
|
Store 77(numBits) 99
|
||||||
|
Branch 82
|
||||||
|
82: Label
|
||||||
|
100: 13(int) Load 78(i)
|
||||||
|
101: 13(int) IAdd 100 31
|
||||||
|
Store 78(i) 101
|
||||||
|
Branch 79
|
||||||
|
81: Label
|
||||||
|
102: 13(int) Load 77(numBits)
|
||||||
|
103: 13(int) BitwiseAnd 102 28
|
||||||
|
104: 6(float) ConvertUToF 103
|
||||||
|
106: 6(float) FMul 104 105
|
||||||
|
107: 7(fvec2) Load 9(pos)
|
||||||
|
108: 7(fvec2) CompositeConstruct 106 106
|
||||||
|
109: 7(fvec2) FAdd 107 108
|
||||||
|
Store 9(pos) 109
|
||||||
|
113: 7(fvec2) Load 9(pos)
|
||||||
|
115: 6(float) CompositeExtract 113 0
|
||||||
|
116: 6(float) CompositeExtract 113 1
|
||||||
|
117: 60(fvec4) CompositeConstruct 115 116 114 66
|
||||||
|
118: 61(ptr) AccessChain 112 23
|
||||||
|
Store 118 117
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
109
Test/precise.tesc
Normal file
109
Test/precise.tesc
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#version 450
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
#extension GL_EXT_gpu_shader5 : require
|
||||||
|
|
||||||
|
float minimal() {
|
||||||
|
precise float result = 5.0;
|
||||||
|
float a = 10.0;
|
||||||
|
float b = 20.0;
|
||||||
|
float c = 30.0;
|
||||||
|
float d = 40.0;
|
||||||
|
result = a * b + c * d; // c * d, a * b and rvalue1 + rvalue2 should be 'noContraction'.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void continuous_assignment() {
|
||||||
|
precise float result = 5.0;
|
||||||
|
float a = 10.0;
|
||||||
|
float b = 20.0;
|
||||||
|
result = a = b + 4; // b + 4 should be 'noContraction'.
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert() {
|
||||||
|
precise double result;
|
||||||
|
float a = 10.0;
|
||||||
|
float b = 20.0;
|
||||||
|
b = a + b; // a + b should be 'noContraction'.
|
||||||
|
result = double(b); // convert operation should not be 'noContraction'.
|
||||||
|
}
|
||||||
|
|
||||||
|
float loop_for() {
|
||||||
|
precise float r1 = 5.0;
|
||||||
|
precise float r2 = 10.0;
|
||||||
|
int a = 10;
|
||||||
|
int b = 20;
|
||||||
|
int c = 30;
|
||||||
|
for (int i = 0; i < a; i++) {
|
||||||
|
r1 += 3.12 + b + i; // 'noContration', this make i++ also 'noContraction'
|
||||||
|
c += 1; // 'noContration'
|
||||||
|
}
|
||||||
|
a += 1; // a + 1 should not be 'noContraction'.
|
||||||
|
r2 = c; // The calculation of c should be 'noContration'.
|
||||||
|
return float(r1 + r2); // conversion should not be 'noContration'.
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop_array(void) {
|
||||||
|
precise float result;
|
||||||
|
|
||||||
|
int x = 22;
|
||||||
|
int y = 33;
|
||||||
|
|
||||||
|
float a0[3];
|
||||||
|
result += float(x) + float(y); // x + y should be 'noContraction' also result + rvalue.
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
// a's dereference + 2 should be 'noContraction'.
|
||||||
|
result += a0[i] + 2;
|
||||||
|
// result + 1 and 3 - rvalue should be 'noContraction'.
|
||||||
|
a0[i] = 3 - result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop_while() {
|
||||||
|
precise float result = 5.0;
|
||||||
|
int a = 10;
|
||||||
|
int b = 20;
|
||||||
|
while (result < 10) {
|
||||||
|
result += 3.12 + b; // result + 3.12 should be 'noContraction'.
|
||||||
|
}
|
||||||
|
result = a + b + 5; // b + 5 should not be 'noCtraction' because all operands are integers.
|
||||||
|
result = 11.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float fma_not_decorated() {
|
||||||
|
precise float result;
|
||||||
|
float a = 1.0;
|
||||||
|
float b = 2.0;
|
||||||
|
float c = 3.0;
|
||||||
|
b = b + c; // b + c should be decorated with 'noContraction'
|
||||||
|
result = fma(a, b, c); // fma() should not be decorated with 'noContradtion'
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
precise float precise_return_exp_func() {
|
||||||
|
float a = 1.0;
|
||||||
|
float b = 2.0;
|
||||||
|
return a + b; // the ADD operation should be 'noContraction'
|
||||||
|
}
|
||||||
|
|
||||||
|
precise float precise_return_val_func() {
|
||||||
|
float a = 1.0;
|
||||||
|
float b = 2.0;
|
||||||
|
float result = a + b; // the ADD operation should be 'noContraction'
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float precise_func_parameter(float b, precise out float c) {
|
||||||
|
float a = 0.5;
|
||||||
|
c = a + b; // noContration
|
||||||
|
return a - b; // Not noContraction
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 matrix (mat2x3 a, mat3x2 b) {
|
||||||
|
mat2x3 c = mat2x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
||||||
|
precise mat3 result;
|
||||||
|
result = (a + c) * b; // should be noContraction
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(){}
|
89
Test/precise_struct_block.vert
Normal file
89
Test/precise_struct_block.vert
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
struct T {
|
||||||
|
float f1;
|
||||||
|
float f2;
|
||||||
|
};
|
||||||
|
|
||||||
|
out B1 {precise T s; float x;} partial_precise_block;
|
||||||
|
precise out B2 {T s; float x;} all_precise_block;
|
||||||
|
|
||||||
|
float struct_member() {
|
||||||
|
float a = 1.0;
|
||||||
|
float b = 2.0;
|
||||||
|
float c = 3.0;
|
||||||
|
float d = 4.0;
|
||||||
|
|
||||||
|
precise float result;
|
||||||
|
|
||||||
|
T S, S2, S3;
|
||||||
|
|
||||||
|
S2.f1 = a + 0.2; // NoContraction
|
||||||
|
S2.f2 = b + 0.2; // NOT NoContraction
|
||||||
|
S3.f1 = a + b; // NOT NoContraction
|
||||||
|
S = S2; // "precise" propagated through parent object nodes
|
||||||
|
result = S.f1 + 0.1; // the ADD operation should be NoContraction
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float complex_array_struct() {
|
||||||
|
precise float result;
|
||||||
|
struct T1 {
|
||||||
|
float t1_array[3];
|
||||||
|
float t1_scalar;
|
||||||
|
};
|
||||||
|
struct T2 {
|
||||||
|
T1 t1a[5];
|
||||||
|
T1 t1b[6];
|
||||||
|
T1 t1c[7];
|
||||||
|
};
|
||||||
|
struct T3 {float f; T2 t2; vec4 v; int p;};
|
||||||
|
T3 t3[10];
|
||||||
|
for(int i=0; i<10; i++) {
|
||||||
|
t3[i].f = i / 3.0; // Not NoContraction
|
||||||
|
t3[i].v = vec4(i * 1.5); // NoContraction
|
||||||
|
t3[i].p = i + 1;
|
||||||
|
for(int j=0; j<5; j++) {
|
||||||
|
for(int k = 0; k<3; k++) {
|
||||||
|
t3[i].t2.t1a[j].t1_array[k] = i * j + k; // Not NoContraction
|
||||||
|
}
|
||||||
|
t3[i].t2.t1a[j].t1_scalar = j * 2.0 / i; // Not NoContration
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<6; j++) {
|
||||||
|
for(int k = 0; k<3; k++) {
|
||||||
|
t3[i].t2.t1b[j].t1_array[k] = i * j + k; // Not NoContraction
|
||||||
|
}
|
||||||
|
t3[i].t2.t1b[j].t1_scalar = j * 2.0 / i; // NoContraction
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<6; j++) {
|
||||||
|
for(int k = 0; k<3; k++) {
|
||||||
|
t3[i].t2.t1c[j].t1_array[k] = i * j + k; // Not NoContraction because all operands are integers
|
||||||
|
}
|
||||||
|
t3[i].t2.t1c[j].t1_scalar = j * 2.0 / i; // Not NoContraction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 2;
|
||||||
|
result = t3[5].t2.t1c[6].t1_array[1]
|
||||||
|
+ t3[2].t2.t1b[1].t1_scalar
|
||||||
|
+ t3[i - 1].v.xy.x; // NoContraction
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float out_block() {
|
||||||
|
float a = 0.1;
|
||||||
|
float b = 0.2;
|
||||||
|
partial_precise_block.s.f1 = a + b; // NoContraction
|
||||||
|
partial_precise_block.s.f2 = a - b; // NoContraction
|
||||||
|
partial_precise_block.x = a * b; // Not NoContraction
|
||||||
|
|
||||||
|
all_precise_block.s.f1 = a + b + 1.0; // NoContraction
|
||||||
|
all_precise_block.s.f2 = a - b - 1.0; // NoContraction
|
||||||
|
all_precise_block.x = a * b * 2.0; // Also NoContraction
|
||||||
|
|
||||||
|
return a + b; // Not NoContraction
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(){}
|
24
Test/spv.precise.tesc
Normal file
24
Test/spv.precise.tesc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
#extension GL_EXT_gpu_shader5 : require
|
||||||
|
|
||||||
|
layout(vertices = 3) out;
|
||||||
|
|
||||||
|
layout(location = 0) in highp vec2 in_tc_position[];
|
||||||
|
layout(location = 1) in highp float in_tc_tessParam[];
|
||||||
|
|
||||||
|
layout(location = 0) out highp vec2 in_te_position[];
|
||||||
|
|
||||||
|
precise gl_TessLevelOuter;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
in_te_position[gl_InvocationID] = in_tc_position[gl_InvocationID];
|
||||||
|
|
||||||
|
gl_TessLevelInner[0] = 5.0;
|
||||||
|
gl_TessLevelInner[1] = 5.0;
|
||||||
|
|
||||||
|
gl_TessLevelOuter[0] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[1] + in_tc_tessParam[2]);
|
||||||
|
gl_TessLevelOuter[1] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[2] + in_tc_tessParam[0]);
|
||||||
|
gl_TessLevelOuter[2] = 1.0 + 59.0 * 0.5 * (in_tc_tessParam[0] + in_tc_tessParam[1]);
|
||||||
|
}
|
36
Test/spv.precise.tese
Normal file
36
Test/spv.precise.tese
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
#extension GL_EXT_gpu_shader5 : require
|
||||||
|
|
||||||
|
layout(triangles, equal_spacing) in;
|
||||||
|
|
||||||
|
layout(location = 0) in highp vec2 in_te_position[];
|
||||||
|
|
||||||
|
layout(location = 0) out mediump vec4 in_f_color;
|
||||||
|
|
||||||
|
precise gl_Position;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
highp vec2 pos = gl_TessCoord.x * in_te_position[0] +
|
||||||
|
gl_TessCoord.y * in_te_position[1] +
|
||||||
|
gl_TessCoord.z * in_te_position[2];
|
||||||
|
|
||||||
|
highp float f =
|
||||||
|
sqrt(3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z))) *
|
||||||
|
0.5 +
|
||||||
|
0.5;
|
||||||
|
in_f_color = vec4(gl_TessCoord * f, 1.0);
|
||||||
|
|
||||||
|
// Offset the position slightly, based on the parity of the bits in the float
|
||||||
|
// representation.
|
||||||
|
// This is done to detect possible small differences in edge vertex positions
|
||||||
|
// between patches.
|
||||||
|
uvec2 bits = floatBitsToUint(pos);
|
||||||
|
uint numBits = 0u;
|
||||||
|
for (uint i = 0u; i < 32u; i++)
|
||||||
|
numBits +=
|
||||||
|
((bits[0] << i) & 1u) + ((bits[1] << i) & 1u);
|
||||||
|
pos += float(numBits & 1u) * 0.04;
|
||||||
|
|
||||||
|
gl_Position = vec4(pos, 0.0, 1.0);
|
||||||
|
}
|
@ -107,6 +107,8 @@ spv.specConstant.vert
|
|||||||
spv.specConstant.comp
|
spv.specConstant.comp
|
||||||
spv.specConstantComposite.vert
|
spv.specConstantComposite.vert
|
||||||
spv.specConstantOperations.vert
|
spv.specConstantOperations.vert
|
||||||
|
spv.precise.tese
|
||||||
|
spv.precise.tesc
|
||||||
# GLSL-level semantics
|
# GLSL-level semantics
|
||||||
vulkan.frag
|
vulkan.frag
|
||||||
vulkan.vert
|
vulkan.vert
|
||||||
|
@ -130,3 +130,5 @@ whileLoop.frag
|
|||||||
nonVulkan.frag
|
nonVulkan.frag
|
||||||
negativeArraySize.comp
|
negativeArraySize.comp
|
||||||
spv.atomic.comp
|
spv.atomic.comp
|
||||||
|
precise.tesc
|
||||||
|
precise_struct_block.vert
|
||||||
|
@ -33,6 +33,7 @@ set(SOURCES
|
|||||||
MachineIndependent/preprocessor/PpScanner.cpp
|
MachineIndependent/preprocessor/PpScanner.cpp
|
||||||
MachineIndependent/preprocessor/PpSymbols.cpp
|
MachineIndependent/preprocessor/PpSymbols.cpp
|
||||||
MachineIndependent/preprocessor/PpTokens.cpp
|
MachineIndependent/preprocessor/PpTokens.cpp
|
||||||
|
MachineIndependent/propagateNoContraction.cpp
|
||||||
GenericCodeGen/CodeGen.cpp
|
GenericCodeGen/CodeGen.cpp
|
||||||
GenericCodeGen/Link.cpp)
|
GenericCodeGen/Link.cpp)
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ set(HEADERS
|
|||||||
MachineIndependent/SymbolTable.h
|
MachineIndependent/SymbolTable.h
|
||||||
MachineIndependent/Versions.h
|
MachineIndependent/Versions.h
|
||||||
MachineIndependent/parseVersions.h
|
MachineIndependent/parseVersions.h
|
||||||
|
MachineIndependent/propagateNoContraction.h
|
||||||
MachineIndependent/preprocessor/PpContext.h
|
MachineIndependent/preprocessor/PpContext.h
|
||||||
MachineIndependent/preprocessor/PpTokens.h)
|
MachineIndependent/preprocessor/PpTokens.h)
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "localintermediate.h"
|
#include "localintermediate.h"
|
||||||
#include "RemoveTree.h"
|
#include "RemoveTree.h"
|
||||||
#include "SymbolTable.h"
|
#include "SymbolTable.h"
|
||||||
|
#include "propagateNoContraction.h"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
@ -1066,6 +1067,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
|
|||||||
if (aggRoot && aggRoot->getOp() == EOpNull)
|
if (aggRoot && aggRoot->getOp() == EOpNull)
|
||||||
aggRoot->setOperator(EOpSequence);
|
aggRoot->setOperator(EOpSequence);
|
||||||
|
|
||||||
|
// Propagate 'noContraction' label in backward from 'precise' variables.
|
||||||
|
glslang::PropagateNoContraction(*this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
858
glslang/MachineIndependent/propagateNoContraction.cpp
Normal file
858
glslang/MachineIndependent/propagateNoContraction.cpp
Normal file
@ -0,0 +1,858 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2015-2016 Google, Inc.
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Visit the nodes in the glslang intermediate tree representation to
|
||||||
|
// propagate 'noContraction' qualifier.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "propagateNoContraction.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "localintermediate.h"
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Use string to hold the accesschain information, as in most cases the
|
||||||
|
// accesschain is short and may contain only one element, which is the symbol
|
||||||
|
// ID.
|
||||||
|
// Example: struct {float a; float b;} s;
|
||||||
|
// Object s.a will be represented with: <symbol ID of s>/0
|
||||||
|
// Object s.b will be represented with: <symbol ID of s>/1
|
||||||
|
// Object s will be representend with: <symbol ID of s>
|
||||||
|
// For members of vector, matrix and arrays, they will be represented with the
|
||||||
|
// same symbol ID of their container symbol objects. This is because their
|
||||||
|
// precise'ness is always the same as their container symbol objects.
|
||||||
|
using ObjectAccessChain = std::string;
|
||||||
|
|
||||||
|
// The delimiter used in the ObjectAccessChain string to separate symbol ID and
|
||||||
|
// different level of struct indices.
|
||||||
|
const char ObjectAccesschainDelimiter = '/';
|
||||||
|
|
||||||
|
// Mapping from Symbol IDs of symbol nodes, to their defining operation
|
||||||
|
// nodes.
|
||||||
|
using NodeMapping = std::unordered_multimap<ObjectAccessChain, glslang::TIntermOperator*>;
|
||||||
|
// Mapping from object nodes to their accesschain info string.
|
||||||
|
using AccessChainMapping = std::unordered_map<glslang::TIntermTyped*, ObjectAccessChain>;
|
||||||
|
|
||||||
|
// Set of object IDs.
|
||||||
|
using ObjectAccesschainSet = std::unordered_set<ObjectAccessChain>;
|
||||||
|
// Set of return branch nodes.
|
||||||
|
using ReturnBranchNodeSet = std::unordered_set<glslang::TIntermBranch*>;
|
||||||
|
|
||||||
|
// A helper function to tell whether a node is 'noContraction'. Returns true if
|
||||||
|
// the node has 'noContraction' qualifier, otherwise false.
|
||||||
|
bool isPreciseObjectNode(glslang::TIntermTyped* node)
|
||||||
|
{
|
||||||
|
return node->getType().getQualifier().noContraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the opcode is a dereferencing one.
|
||||||
|
bool isDereferenceOperation(glslang::TOperator op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case glslang::EOpIndexDirect:
|
||||||
|
case glslang::EOpIndexDirectStruct:
|
||||||
|
case glslang::EOpIndexIndirect:
|
||||||
|
case glslang::EOpVectorSwizzle:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the opcode leads to an assignment operation.
|
||||||
|
bool isAssignOperation(glslang::TOperator op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case glslang::EOpAssign:
|
||||||
|
case glslang::EOpAddAssign:
|
||||||
|
case glslang::EOpSubAssign:
|
||||||
|
case glslang::EOpMulAssign:
|
||||||
|
case glslang::EOpVectorTimesMatrixAssign:
|
||||||
|
case glslang::EOpVectorTimesScalarAssign:
|
||||||
|
case glslang::EOpMatrixTimesScalarAssign:
|
||||||
|
case glslang::EOpMatrixTimesMatrixAssign:
|
||||||
|
case glslang::EOpDivAssign:
|
||||||
|
case glslang::EOpModAssign:
|
||||||
|
case glslang::EOpAndAssign:
|
||||||
|
case glslang::EOpLeftShiftAssign:
|
||||||
|
case glslang::EOpRightShiftAssign:
|
||||||
|
case glslang::EOpInclusiveOrAssign:
|
||||||
|
case glslang::EOpExclusiveOrAssign:
|
||||||
|
|
||||||
|
case glslang::EOpPostIncrement:
|
||||||
|
case glslang::EOpPostDecrement:
|
||||||
|
case glslang::EOpPreIncrement:
|
||||||
|
case glslang::EOpPreDecrement:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function to get the unsigned int from a given constant union node.
|
||||||
|
// Note the node should only holds a uint scalar.
|
||||||
|
unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
|
||||||
|
{
|
||||||
|
assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
|
||||||
|
unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst();
|
||||||
|
return struct_dereference_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function to generate symbol_label.
|
||||||
|
ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node)
|
||||||
|
{
|
||||||
|
ObjectAccessChain symbol_id =
|
||||||
|
std::to_string(node->getId()) + "(" + node->getName().c_str() + ")";
|
||||||
|
return symbol_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the operation is an arithmetic operation and valid for
|
||||||
|
// 'NoContraction' decoration.
|
||||||
|
bool isArithmeticOperation(glslang::TOperator op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case glslang::EOpAddAssign:
|
||||||
|
case glslang::EOpSubAssign:
|
||||||
|
case glslang::EOpMulAssign:
|
||||||
|
case glslang::EOpVectorTimesMatrixAssign:
|
||||||
|
case glslang::EOpVectorTimesScalarAssign:
|
||||||
|
case glslang::EOpMatrixTimesScalarAssign:
|
||||||
|
case glslang::EOpMatrixTimesMatrixAssign:
|
||||||
|
case glslang::EOpDivAssign:
|
||||||
|
case glslang::EOpModAssign:
|
||||||
|
|
||||||
|
case glslang::EOpNegative:
|
||||||
|
|
||||||
|
case glslang::EOpAdd:
|
||||||
|
case glslang::EOpSub:
|
||||||
|
case glslang::EOpMul:
|
||||||
|
case glslang::EOpDiv:
|
||||||
|
case glslang::EOpMod:
|
||||||
|
|
||||||
|
case glslang::EOpVectorTimesScalar:
|
||||||
|
case glslang::EOpVectorTimesMatrix:
|
||||||
|
case glslang::EOpMatrixTimesVector:
|
||||||
|
case glslang::EOpMatrixTimesScalar:
|
||||||
|
case glslang::EOpMatrixTimesMatrix:
|
||||||
|
|
||||||
|
case glslang::EOpDot:
|
||||||
|
|
||||||
|
case glslang::EOpPostIncrement:
|
||||||
|
case glslang::EOpPostDecrement:
|
||||||
|
case glslang::EOpPreIncrement:
|
||||||
|
case glslang::EOpPreDecrement:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper class to help managing populating_initial_no_contraction_ flag.
|
||||||
|
template <typename T> class StateSettingGuard {
|
||||||
|
public:
|
||||||
|
StateSettingGuard(T* state_ptr, T new_state_value)
|
||||||
|
: state_ptr_(state_ptr), previous_state_(*state_ptr)
|
||||||
|
{
|
||||||
|
*state_ptr = new_state_value;
|
||||||
|
}
|
||||||
|
StateSettingGuard(T* state_ptr) : state_ptr_(state_ptr), previous_state_(*state_ptr) {}
|
||||||
|
void setState(T new_state_value) { *state_ptr_ = new_state_value; }
|
||||||
|
~StateSettingGuard() { *state_ptr_ = previous_state_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* state_ptr_;
|
||||||
|
T previous_state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A helper function to get the front element from a given ObjectAccessChain
|
||||||
|
ObjectAccessChain getFrontElement(const ObjectAccessChain& chain)
|
||||||
|
{
|
||||||
|
size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
|
||||||
|
return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function to get the accesschain starting from the second element.
|
||||||
|
ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain)
|
||||||
|
{
|
||||||
|
size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
|
||||||
|
return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function to get the accesschain after removing a given prefix.
|
||||||
|
ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
|
||||||
|
const ObjectAccessChain& prefix)
|
||||||
|
{
|
||||||
|
size_t pos = chain.find(prefix);
|
||||||
|
if (pos != 0)
|
||||||
|
return chain;
|
||||||
|
return chain.substr(prefix.length() + sizeof(ObjectAccesschainDelimiter));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A traverser which traverses the whole AST and populates:
|
||||||
|
// 1) A mapping from symbol nodes' IDs to their defining operation nodes.
|
||||||
|
// 2) A set of accesschains of the initial precise object nodes.
|
||||||
|
//
|
||||||
|
class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TSymbolDefinitionCollectingTraverser(NodeMapping* symbol_definition_mapping,
|
||||||
|
AccessChainMapping* accesschain_mapping,
|
||||||
|
ObjectAccesschainSet* precise_objects,
|
||||||
|
ReturnBranchNodeSet* precise_return_nodes);
|
||||||
|
|
||||||
|
bool visitUnary(glslang::TVisit, glslang::TIntermUnary*) override;
|
||||||
|
bool visitBinary(glslang::TVisit, glslang::TIntermBinary*) override;
|
||||||
|
void visitSymbol(glslang::TIntermSymbol*) override;
|
||||||
|
bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*) override;
|
||||||
|
bool visitBranch(glslang::TVisit, glslang::TIntermBranch*) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// The mapping from symbol node IDs to their defining nodes. This should be
|
||||||
|
// populated along traversing the AST.
|
||||||
|
NodeMapping& symbol_definition_mapping_;
|
||||||
|
// The set of symbol node IDs for precise symbol nodes, the ones marked as
|
||||||
|
// 'noContraction'.
|
||||||
|
ObjectAccesschainSet& precise_objects_;
|
||||||
|
// The set of precise return nodes.
|
||||||
|
ReturnBranchNodeSet& precise_return_nodes_;
|
||||||
|
// A temporary cache of the symbol node whose defining node is to be found
|
||||||
|
// currently along traversing the AST.
|
||||||
|
ObjectAccessChain current_object_;
|
||||||
|
// A map from object node to its accesschain. This traverser stores
|
||||||
|
// the built accesschains into this map for each object node it has
|
||||||
|
// visited.
|
||||||
|
AccessChainMapping& accesschain_mapping_;
|
||||||
|
// The pointer to the Function Definition node, so we can get the
|
||||||
|
// precise'ness of the return expression from it when we traverse the
|
||||||
|
// return branch node.
|
||||||
|
glslang::TIntermAggregate* current_function_definition_node_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TSymbolDefinitionCollectingTraverser::TSymbolDefinitionCollectingTraverser(
|
||||||
|
NodeMapping* symbol_definition_mapping, AccessChainMapping* accesschain_mapping,
|
||||||
|
ObjectAccesschainSet* precise_objects,
|
||||||
|
std::unordered_set<glslang::TIntermBranch*>* precise_return_nodes)
|
||||||
|
: TIntermTraverser(true, false, false), symbol_definition_mapping_(*symbol_definition_mapping),
|
||||||
|
precise_objects_(*precise_objects), current_object_(),
|
||||||
|
accesschain_mapping_(*accesschain_mapping), current_function_definition_node_(nullptr),
|
||||||
|
precise_return_nodes_(*precise_return_nodes) {}
|
||||||
|
|
||||||
|
// Visits a symbol node, set the current_object_ to the
|
||||||
|
// current node symbol ID, and record a mapping from this node to the current
|
||||||
|
// current_object_, which is the just obtained symbol
|
||||||
|
// ID.
|
||||||
|
void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* node)
|
||||||
|
{
|
||||||
|
current_object_ = generateSymbolLabel(node);
|
||||||
|
accesschain_mapping_[node] = current_object_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits an aggregate node, traverses all of its children.
|
||||||
|
bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit,
|
||||||
|
glslang::TIntermAggregate* node)
|
||||||
|
{
|
||||||
|
// This aggreagate node might be a function definition node, in which case we need to
|
||||||
|
// cache this node, so we can get the precise'ness information of the return value
|
||||||
|
// of this function later.
|
||||||
|
StateSettingGuard<glslang::TIntermAggregate*> current_function_definition_node_setting_guard(
|
||||||
|
¤t_function_definition_node_);
|
||||||
|
if (node->getOp() == glslang::EOpFunction) {
|
||||||
|
// This is function definition node, we need to cache this node so that we can
|
||||||
|
// get the precise'ness of the return value later.
|
||||||
|
current_function_definition_node_setting_guard.setState(node);
|
||||||
|
}
|
||||||
|
// Traverse the items in the sequence.
|
||||||
|
glslang::TIntermSequence& seq = node->getSequence();
|
||||||
|
for (int i = 0; i < (int)seq.size(); ++i) {
|
||||||
|
current_object_.clear();
|
||||||
|
seq[i]->traverse(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit,
|
||||||
|
glslang::TIntermBranch* node)
|
||||||
|
{
|
||||||
|
if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() &&
|
||||||
|
current_function_definition_node_ &&
|
||||||
|
current_function_definition_node_->getType().getQualifier().noContraction) {
|
||||||
|
// This node is a return node with expression, and its function has
|
||||||
|
// precise return value. We need to find the involved objects in its
|
||||||
|
// expression and add them to the set of initial precise objects.
|
||||||
|
precise_return_nodes_.insert(node);
|
||||||
|
node->getExpression()->traverse(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits an unary node. This might be an implicit assignment like i++, i--. etc.
|
||||||
|
bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */,
|
||||||
|
glslang::TIntermUnary* node)
|
||||||
|
{
|
||||||
|
current_object_.clear();
|
||||||
|
node->getOperand()->traverse(this);
|
||||||
|
if (isAssignOperation(node->getOp())) {
|
||||||
|
// We should always be able to get an accesschain of the operand node.
|
||||||
|
assert(!current_object_.empty());
|
||||||
|
|
||||||
|
// If the operand node object is 'precise', we collect its accesschain
|
||||||
|
// for the initial set of 'precise' objects.
|
||||||
|
if (isPreciseObjectNode(node->getOperand())) {
|
||||||
|
// The operand node is an 'precise' object node, add its
|
||||||
|
// accesschain to the set of 'precise' objects. This is to collect
|
||||||
|
// the initial set of 'precise' objects.
|
||||||
|
precise_objects_.insert(current_object_);
|
||||||
|
}
|
||||||
|
// Gets the symbol ID from the object's accesschain.
|
||||||
|
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
||||||
|
// Add a mapping from the symbol ID to this assignment operation node.
|
||||||
|
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
||||||
|
}
|
||||||
|
// Unary node is not a dereference node, so we clear the accesschain which
|
||||||
|
// is under construction.
|
||||||
|
current_object_.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits a binary node and updates the mapping from symbol IDs to the definition
|
||||||
|
// nodes. Also collects the accesschains for the initial precise objects.
|
||||||
|
bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */,
|
||||||
|
glslang::TIntermBinary* node)
|
||||||
|
{
|
||||||
|
// Traverses the left node to build the accesschain info for the object.
|
||||||
|
current_object_.clear();
|
||||||
|
node->getLeft()->traverse(this);
|
||||||
|
|
||||||
|
if (isAssignOperation(node->getOp())) {
|
||||||
|
// We should always be able to get an accesschain for the left node.
|
||||||
|
assert(!current_object_.empty());
|
||||||
|
|
||||||
|
// If the left node object is 'precise', it is an initial precise object
|
||||||
|
// specified in the shader source. Adds it to the initial worklist to
|
||||||
|
// process later.
|
||||||
|
if (isPreciseObjectNode(node->getLeft())) {
|
||||||
|
// The left node is an 'precise' object node, add its accesschain to
|
||||||
|
// the set of 'precise' objects. This is to collect the initial set
|
||||||
|
// of 'precise' objects.
|
||||||
|
precise_objects_.insert(current_object_);
|
||||||
|
}
|
||||||
|
// Gets the symbol ID from the object accesschain, which should be the
|
||||||
|
// first element recorded in the accesschain.
|
||||||
|
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
||||||
|
// Adds a mapping from the symbol ID to this assignment operation node.
|
||||||
|
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
||||||
|
|
||||||
|
// Traverses the right node, there may be other 'assignment'
|
||||||
|
// operatrions in the right.
|
||||||
|
current_object_.clear();
|
||||||
|
node->getRight()->traverse(this);
|
||||||
|
|
||||||
|
} else if (isDereferenceOperation(node->getOp())) {
|
||||||
|
// The left node (parent node) is a struct type object. We need to
|
||||||
|
// record the accesschain information of the current node into its
|
||||||
|
// object id.
|
||||||
|
if (node->getOp() == glslang::EOpIndexDirectStruct) {
|
||||||
|
unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight());
|
||||||
|
current_object_.push_back(ObjectAccesschainDelimiter);
|
||||||
|
current_object_.append(std::to_string(struct_dereference_index));
|
||||||
|
}
|
||||||
|
accesschain_mapping_[node] = current_object_;
|
||||||
|
|
||||||
|
// For dereference node, there is no need to traverse the right child
|
||||||
|
// node as the right node should always be an integer type object.
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// For other binary nodes, still traverse the right node.
|
||||||
|
current_object_.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverses the AST and returns a tuple of four members:
|
||||||
|
// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols.
|
||||||
|
// 2) a mapping from object nodes in the AST to the accesschains of these objects.
|
||||||
|
// 3) a set of accesschains of precise objects.
|
||||||
|
// 4) a set of return nodes with precise expressions.
|
||||||
|
std::tuple<NodeMapping, AccessChainMapping, ObjectAccesschainSet, ReturnBranchNodeSet>
|
||||||
|
getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate)
|
||||||
|
{
|
||||||
|
auto result_tuple = std::make_tuple(NodeMapping(), AccessChainMapping(), ObjectAccesschainSet(),
|
||||||
|
ReturnBranchNodeSet());
|
||||||
|
|
||||||
|
TIntermNode* root = intermediate.getTreeRoot();
|
||||||
|
if (root == 0)
|
||||||
|
return result_tuple;
|
||||||
|
|
||||||
|
NodeMapping& symbol_definition_mapping = std::get<0>(result_tuple);
|
||||||
|
AccessChainMapping& accesschain_mapping = std::get<1>(result_tuple);
|
||||||
|
ObjectAccesschainSet& precise_objects = std::get<2>(result_tuple);
|
||||||
|
ReturnBranchNodeSet& precise_return_nodes = std::get<3>(result_tuple);
|
||||||
|
|
||||||
|
// Traverses the AST and populate the results.
|
||||||
|
TSymbolDefinitionCollectingTraverser collector(&symbol_definition_mapping, &accesschain_mapping,
|
||||||
|
&precise_objects, &precise_return_nodes);
|
||||||
|
root->traverse(&collector);
|
||||||
|
|
||||||
|
return result_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A traverser that determine whether the left node (or operand node for unary
|
||||||
|
// node) of an assignment node is 'precise', containing 'precise' or not,
|
||||||
|
// according to the accesschain a given precise object which share the same
|
||||||
|
// symbol as the left node.
|
||||||
|
//
|
||||||
|
// Post-orderly traverses the left node subtree of an binary assignment node and:
|
||||||
|
//
|
||||||
|
// 1) Propagates the 'precise' from the left object nodes to this object node.
|
||||||
|
//
|
||||||
|
// 2) Builds object accesschain along the traversal, and also compares with
|
||||||
|
// the accesschain of the given 'precise' object along with the traversal to
|
||||||
|
// tell if the node to be defined is 'precise' or not.
|
||||||
|
//
|
||||||
|
class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser {
|
||||||
|
|
||||||
|
enum DecisionStatus {
|
||||||
|
// The object node to be assigned to may contain 'precise' objects and also not 'precise' objects.
|
||||||
|
Mixed = 0,
|
||||||
|
// The object node to be assigned to is either a 'precise' object or a struct objects whose members are all 'precise'.
|
||||||
|
Precise = 1,
|
||||||
|
// The object node to be assigned to is not a 'precise' object.
|
||||||
|
NotPreicse = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
TNoContractionAssigneeCheckingTraverser(const AccessChainMapping& accesschain_mapping)
|
||||||
|
: TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping),
|
||||||
|
precise_object_(nullptr) {}
|
||||||
|
|
||||||
|
// Checks the precise'ness of a given assignment node with a precise object
|
||||||
|
// represented as accesschain. The precise object shares the same symbol
|
||||||
|
// with the assignee of the given assignment node. Return a tuple of two:
|
||||||
|
//
|
||||||
|
// 1) The precise'ness of the assignee node of this assignment node. True
|
||||||
|
// if the assignee contains 'precise' objects or is 'precise', false if
|
||||||
|
// the assignee is not 'precise' according to the accesschain of the given
|
||||||
|
// precise object.
|
||||||
|
//
|
||||||
|
// 2) The incremental accesschain from the assignee node to its nested
|
||||||
|
// 'precise' object, according to the accesschain of the given precise
|
||||||
|
// object. This incremental accesschain can be empty, which means the
|
||||||
|
// assignee is 'precise'. Otherwise it shows the path to the nested
|
||||||
|
// precise object.
|
||||||
|
std::tuple<bool, ObjectAccessChain>
|
||||||
|
getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node,
|
||||||
|
const ObjectAccessChain& precise_object)
|
||||||
|
{
|
||||||
|
assert(isAssignOperation(node->getOp()));
|
||||||
|
precise_object_ = &precise_object;
|
||||||
|
ObjectAccessChain assignee_object;
|
||||||
|
if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
|
||||||
|
// This is a binary assignment node, we need to check the
|
||||||
|
// precise'ness of the left node.
|
||||||
|
assert(accesschain_mapping_.count(BN->getLeft()));
|
||||||
|
// The left node (assignee node) is an object node, traverse the
|
||||||
|
// node to let the 'precise' of nesting objects being transfered to
|
||||||
|
// nested objects.
|
||||||
|
BN->getLeft()->traverse(this);
|
||||||
|
// After traversing the left node, if the left node is 'precise',
|
||||||
|
// we can conclude this assignment should propagate 'precise'.
|
||||||
|
if (isPreciseObjectNode(BN->getLeft())) {
|
||||||
|
return make_tuple(true, ObjectAccessChain());
|
||||||
|
}
|
||||||
|
// If the precise'ness of the left node (assignee node) can not
|
||||||
|
// be determined by now, we need to compare the accesschain string
|
||||||
|
// of the assignee object with the given precise object.
|
||||||
|
assignee_object = accesschain_mapping_.at(BN->getLeft());
|
||||||
|
|
||||||
|
} else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) {
|
||||||
|
// This is a unary assignment node, we need to check the
|
||||||
|
// precise'ness of the operand node. For unary assignment node, the
|
||||||
|
// operand node should always be an object node.
|
||||||
|
assert(accesschain_mapping_.count(UN->getOperand()));
|
||||||
|
// Traverse the operand node to let the 'precise' being propagated
|
||||||
|
// from lower nodes to upper nodes.
|
||||||
|
UN->getOperand()->traverse(this);
|
||||||
|
// After traversing the operand node, if the operand node is
|
||||||
|
// 'precise', this assignment should propagate 'precise'.
|
||||||
|
if (isPreciseObjectNode(UN->getOperand())) {
|
||||||
|
return make_tuple(true, ObjectAccessChain());
|
||||||
|
}
|
||||||
|
// If the precise'ness of the operand node (assignee node) can not
|
||||||
|
// be determined by now, we need to compare the accesschain string
|
||||||
|
// of the assignee object with the given precise object.
|
||||||
|
assignee_object = accesschain_mapping_.at(UN->getOperand());
|
||||||
|
} else {
|
||||||
|
// Not a binary or unary node, should not happen.
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the accesschain string of the assignee node with the given
|
||||||
|
// precise object to determine if this assignment should propagate
|
||||||
|
// 'precise'.
|
||||||
|
if (assignee_object.find(precise_object) == 0) {
|
||||||
|
// The accesschain string of the given precise object is a prefix
|
||||||
|
// of assignee's accesschain string. The assignee should be
|
||||||
|
// 'precise'.
|
||||||
|
return make_tuple(true, ObjectAccessChain());
|
||||||
|
} else if (precise_object.find(assignee_object) == 0) {
|
||||||
|
// The assignee's accesschain string is a prefix of the given
|
||||||
|
// precise object, the assignee object contains 'precise' object,
|
||||||
|
// and we need to pass the remained accesschain to the object nodes
|
||||||
|
// in the right.
|
||||||
|
return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object));
|
||||||
|
} else {
|
||||||
|
// The accesschain strings do not match, the assignee object can
|
||||||
|
// not be labelled as 'precise' according to the given precise
|
||||||
|
// object.
|
||||||
|
return make_tuple(false, ObjectAccessChain());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override;
|
||||||
|
void visitSymbol(glslang::TIntermSymbol* node) override;
|
||||||
|
|
||||||
|
// A map from object nodes to their accesschain string (used as object ID).
|
||||||
|
const AccessChainMapping& accesschain_mapping_;
|
||||||
|
// A given precise object, represented in it accesschain string. This
|
||||||
|
// precise object is used to be compared with the assignee node to tell if
|
||||||
|
// the assignee node is 'precise', contains 'precise' object or not
|
||||||
|
// 'precise'.
|
||||||
|
const ObjectAccessChain* precise_object_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Visits a binary node. If the node is an object node, it must be a dereference
|
||||||
|
// node. In such cases, if the left node is 'precise', this node should also be
|
||||||
|
// 'precise'.
|
||||||
|
bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
|
||||||
|
glslang::TIntermBinary* node)
|
||||||
|
{
|
||||||
|
// Traverses the left so that we transfer the 'precise' from nesting object
|
||||||
|
// to its nested object.
|
||||||
|
node->getLeft()->traverse(this);
|
||||||
|
// If this binary node is an object node, we should have it in the
|
||||||
|
// accesschain_mapping_.
|
||||||
|
if (accesschain_mapping_.count(node)) {
|
||||||
|
// A binary object node must be a dereference node.
|
||||||
|
assert(isDereferenceOperation(node->getOp()));
|
||||||
|
// If the left node is 'precise', this node should also be precise,
|
||||||
|
// otherwise, compare with the given precise_object_. If the
|
||||||
|
// accesschain of this node matches with the given precise_object_,
|
||||||
|
// this node should be marked as 'precise'.
|
||||||
|
if (isPreciseObjectNode(node->getLeft())) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
} else if (accesschain_mapping_.at(node) == *precise_object_) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits a symbol node, if the symbol node ID (its accesschain string) matches
|
||||||
|
// with the given precise object, this node should be 'precise'.
|
||||||
|
void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node)
|
||||||
|
{
|
||||||
|
// A symbol node should always be an object node, and should have been added
|
||||||
|
// to the map from object nodes to their accesschain strings.
|
||||||
|
assert(accesschain_mapping_.count(node));
|
||||||
|
if (accesschain_mapping_.at(node) == *precise_object_) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A traverser that only traverses the right side of binary assignment nodes
|
||||||
|
// and the operand node of unary assignment nodes.
|
||||||
|
//
|
||||||
|
// 1) Marks arithmetic operations 'NoContraction'.
|
||||||
|
//
|
||||||
|
// 2) Find the object which should be marked as 'precise' in the right and
|
||||||
|
// update the 'precise' object worklist.
|
||||||
|
//
|
||||||
|
class TNoContractionPropagator : public glslang::TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TNoContractionPropagator(ObjectAccesschainSet* precise_objects,
|
||||||
|
const AccessChainMapping& accesschain_mapping)
|
||||||
|
: TIntermTraverser(true, false, false), remained_accesschain_(),
|
||||||
|
precise_objects_(*precise_objects), accesschain_mapping_(accesschain_mapping),
|
||||||
|
added_precise_object_ids_() {}
|
||||||
|
|
||||||
|
// Propagates 'precise' in the right nodes of a given assignment node with
|
||||||
|
// accesschain record from the assignee node to a 'precise' object it
|
||||||
|
// contains.
|
||||||
|
void
|
||||||
|
propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node,
|
||||||
|
const ObjectAccessChain& assignee_remained_accesschain)
|
||||||
|
{
|
||||||
|
remained_accesschain_ = assignee_remained_accesschain;
|
||||||
|
if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) {
|
||||||
|
assert(isAssignOperation(BN->getOp()));
|
||||||
|
BN->getRight()->traverse(this);
|
||||||
|
if (isArithmeticOperation(BN->getOp())) {
|
||||||
|
BN->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
} else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) {
|
||||||
|
assert(isAssignOperation(UN->getOp()));
|
||||||
|
UN->getOperand()->traverse(this);
|
||||||
|
if (isArithmeticOperation(UN->getOp())) {
|
||||||
|
UN->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Propagates 'precise' in a given precise return node.
|
||||||
|
void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node)
|
||||||
|
{
|
||||||
|
remained_accesschain_ = "";
|
||||||
|
assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression());
|
||||||
|
return_node->getExpression()->traverse(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Visits an aggregate node. The node can be a initializer list, in which
|
||||||
|
// case we need to find the 'precise' or 'precise' containing object node
|
||||||
|
// with the accesschain record. In other cases, just need to traverse all
|
||||||
|
// the children nodes.
|
||||||
|
bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override
|
||||||
|
{
|
||||||
|
if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) {
|
||||||
|
// This is a struct initializer node, and the remained
|
||||||
|
// accesschain is not empty, we need to refer to the
|
||||||
|
// assignee_remained_access_chain_ to find the nested
|
||||||
|
// 'precise' object. And we don't need to visit other nodes in this
|
||||||
|
// aggreagate node.
|
||||||
|
|
||||||
|
// Gets the struct dereference index that leads to 'precise' object.
|
||||||
|
ObjectAccessChain precise_accesschain_index_str =
|
||||||
|
getFrontElement(remained_accesschain_);
|
||||||
|
unsigned precise_accesschain_index = std::stoul(precise_accesschain_index_str);
|
||||||
|
// Gets the node pointed by the accesschain index extracted before.
|
||||||
|
glslang::TIntermTyped* potential_precise_node =
|
||||||
|
node->getSequence()[precise_accesschain_index]->getAsTyped();
|
||||||
|
assert(potential_precise_node);
|
||||||
|
// Pop the front accesschain index from the path, and visit the nested node.
|
||||||
|
{
|
||||||
|
ObjectAccessChain next_level_accesschain =
|
||||||
|
subAccessChainFromSecondElement(remained_accesschain_);
|
||||||
|
StateSettingGuard<ObjectAccessChain> setup_remained_accesschain_for_next_level(
|
||||||
|
&remained_accesschain_, next_level_accesschain);
|
||||||
|
potential_precise_node->traverse(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits a binary node. A binary node can be an object node, e.g. a dereference node.
|
||||||
|
// As only the top object nodes in the right side of an assignment needs to be visited
|
||||||
|
// and added to 'precise' worklist, this traverser won't visit the children nodes of
|
||||||
|
// an object node. If the binary node does not represent an object node, it should
|
||||||
|
// go on to traverse its children nodes and if it is an arithmetic operation node, this
|
||||||
|
// operation should be marked as 'noContraction'.
|
||||||
|
bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override
|
||||||
|
{
|
||||||
|
if (isDereferenceOperation(node->getOp())) {
|
||||||
|
// This binary node is an object node. Need to update the precise
|
||||||
|
// object set with the accesschain of this node + remained
|
||||||
|
// accesschain .
|
||||||
|
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
||||||
|
if (remained_accesschain_.empty()) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
} else {
|
||||||
|
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
||||||
|
}
|
||||||
|
// Cache the accesschain as added precise object, so we won't add the
|
||||||
|
// same object to the worklist again.
|
||||||
|
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
||||||
|
precise_objects_.insert(new_precise_accesschain);
|
||||||
|
added_precise_object_ids_.insert(new_precise_accesschain);
|
||||||
|
}
|
||||||
|
// Only the upper-most object nodes should be visited, so do not
|
||||||
|
// visit children of this object node.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// If this is an arithmetic operation, marks this node as 'noContraction'.
|
||||||
|
if (isArithmeticOperation(node->getOp()) && node->getBasicType() != glslang::EbtInt) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
// As this node is not an object node, need to traverse the children nodes.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits an unary node. An unary node can not be an object node. If the operation
|
||||||
|
// is an arithmetic operation, need to mark this node as 'noContraction'.
|
||||||
|
bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override
|
||||||
|
{
|
||||||
|
// If this is an arithmetic operation, marks this with 'noContraction'
|
||||||
|
if (isArithmeticOperation(node->getOp())) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits a symbol node. A symbol node is always an object node. So we
|
||||||
|
// should always be able to find its in our colected mapping from object
|
||||||
|
// nodes to accesschains. As an object node, a symbol node can be either
|
||||||
|
// 'precise' or containing 'precise' objects according to unused
|
||||||
|
// accesschain information we have when we visit this node.
|
||||||
|
void visitSymbol(glslang::TIntermSymbol* node) override
|
||||||
|
{
|
||||||
|
// Symbol nodes are object nodes and should always have an
|
||||||
|
// accesschain collected before matches with it.
|
||||||
|
assert(accesschain_mapping_.count(node));
|
||||||
|
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
||||||
|
// If the unused accesschain is empty, this symbol node should be
|
||||||
|
// marked as 'precise'. Otherwise, the unused accesschain should be
|
||||||
|
// appended to the symbol ID to build a new accesschain which points to
|
||||||
|
// the nested 'precise' object in this symbol object.
|
||||||
|
if (remained_accesschain_.empty()) {
|
||||||
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
|
} else {
|
||||||
|
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
||||||
|
}
|
||||||
|
// Add the new 'precise' accesschain to the worklist and make sure we
|
||||||
|
// don't visit it again.
|
||||||
|
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
||||||
|
precise_objects_.insert(new_precise_accesschain);
|
||||||
|
added_precise_object_ids_.insert(new_precise_accesschain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A set of precise objects, represented as accesschains.
|
||||||
|
ObjectAccesschainSet& precise_objects_;
|
||||||
|
// Visited symbol nodes, should not revisit these nodes.
|
||||||
|
ObjectAccesschainSet added_precise_object_ids_;
|
||||||
|
// The left node of an assignment operation might be an parent of 'precise' objects.
|
||||||
|
// This means the left node might not be an 'precise' object node, but it may contains
|
||||||
|
// 'precise' qualifier which should be propagated to the corresponding child node in
|
||||||
|
// the right. So we need the path from the left node to its nested 'precise' node to
|
||||||
|
// tell us how to find the corresponding 'precise' node in the right.
|
||||||
|
ObjectAccessChain remained_accesschain_;
|
||||||
|
// A map from node pointers to their accesschains.
|
||||||
|
const AccessChainMapping& accesschain_mapping_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
void PropagateNoContraction(const glslang::TIntermediate& intermediate)
|
||||||
|
{
|
||||||
|
// First, traverses the AST, records symbols with their defining operations
|
||||||
|
// and collects the initial set of precise symbols (symbol nodes that marked
|
||||||
|
// as 'noContraction') and precise return nodes.
|
||||||
|
auto mappings_and_precise_objects =
|
||||||
|
getSymbolToDefinitionMappingAndPreciseSymbolIDs(intermediate);
|
||||||
|
|
||||||
|
// The mapping of symbol node IDs to their defining nodes. This enables us
|
||||||
|
// to get the defining node directly from a given symbol ID without
|
||||||
|
// traversing the tree again.
|
||||||
|
NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects);
|
||||||
|
|
||||||
|
// The mapping of object nodes to their accesschains recorded.
|
||||||
|
AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects);
|
||||||
|
|
||||||
|
// The initial set of 'precise' objects which are represented as the
|
||||||
|
// accesschain toward them.
|
||||||
|
ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects);
|
||||||
|
|
||||||
|
// The set of 'precise' return nodes.
|
||||||
|
ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects);
|
||||||
|
|
||||||
|
// Second, uses the initial set of precise objects as a worklist, pops an
|
||||||
|
// accesschain, extract the symbol ID from it. Then:
|
||||||
|
// 1) Check the assignee object, see if it is 'precise' object node or
|
||||||
|
// contains 'precise' object. Obtain the incremental accesschain from the
|
||||||
|
// assignee node to its nested 'precise' node (if any).
|
||||||
|
// 2) If the assignee object node is 'precise' or it contains 'precise'
|
||||||
|
// objects, traverses the right side of the assignment operation
|
||||||
|
// expression to mark arithmetic operations as 'noContration' and update
|
||||||
|
// 'precise' accesschain worklist with new found object nodes.
|
||||||
|
// Repeat above steps until the worklist is empty.
|
||||||
|
TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping);
|
||||||
|
TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping);
|
||||||
|
|
||||||
|
// We have two initial precise worklists to handle:
|
||||||
|
// 1) precise return nodes
|
||||||
|
// 2) precise object accesschains
|
||||||
|
// We should process the precise return nodes first and the involved
|
||||||
|
// objects in the return expression should be added to the precise object
|
||||||
|
// accesschain set.
|
||||||
|
while (!precise_return_nodes.empty()) {
|
||||||
|
glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin();
|
||||||
|
propagator.propagateNoContractionInReturnNode(precise_return_node);
|
||||||
|
precise_return_nodes.erase(precise_return_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!precise_object_accesschains.empty()) {
|
||||||
|
// Get the accesschain of a precise object from the worklist.
|
||||||
|
ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin();
|
||||||
|
// Get the symbol id from the accesschain.
|
||||||
|
ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain);
|
||||||
|
// Get all the defining nodes of that symbol ID.
|
||||||
|
std::pair<NodeMapping::iterator, NodeMapping::iterator> range =
|
||||||
|
symbol_definition_mapping.equal_range(symbol_id);
|
||||||
|
// Visits all the assignment nodes of that symbol ID and
|
||||||
|
// 1) Check if the assignee node is 'precise' or contains 'precise'
|
||||||
|
// objects.
|
||||||
|
// 2) Propagate the 'precise' to the top layer object ndoes
|
||||||
|
// in the right side of the assignment operation, update the 'precise'
|
||||||
|
// worklist with new accesschains representing the new 'precise'
|
||||||
|
// objects, and mark arithmetic operations as 'noContraction'.
|
||||||
|
for (NodeMapping::iterator defining_node_iter = range.first;
|
||||||
|
defining_node_iter != range.second; defining_node_iter++) {
|
||||||
|
TIntermOperator* defining_node = defining_node_iter->second;
|
||||||
|
// Check the assignee node.
|
||||||
|
auto checker_result = checker.getPrecisenessAndRemainedAccessChain(
|
||||||
|
defining_node, precise_object_accesschain);
|
||||||
|
bool& contain_precise = std::get<0>(checker_result);
|
||||||
|
ObjectAccessChain& remained_accesschain = std::get<1>(checker_result);
|
||||||
|
// If the assignee node is 'precise' or contains 'precise', propagate the
|
||||||
|
// 'precise' to the right. Otherwise just skip this assignment node.
|
||||||
|
if (contain_precise) {
|
||||||
|
propagator.propagateNoContractionInOneExpression(defining_node,
|
||||||
|
remained_accesschain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the last processed 'precise' object from the worklist.
|
||||||
|
precise_object_accesschains.erase(precise_object_accesschain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
53
glslang/MachineIndependent/propagateNoContraction.h
Normal file
53
glslang/MachineIndependent/propagateNoContraction.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2015-2016 Google, Inc.
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Visit the nodes in the glslang intermediate tree representation to
|
||||||
|
// propagate 'noContraction' qualifier.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "../Include/intermediate.h"
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
// Propagates the 'precise' qualifier for objects (objects marked with
|
||||||
|
// 'noContraction' qualifier) from the shader source specified 'precise'
|
||||||
|
// variables to all the involved objects, and add 'noContraction' qualifier for
|
||||||
|
// the involved arithmetic operations.
|
||||||
|
// Note that the same qualifier: 'noContraction' is used in both object nodes
|
||||||
|
// and arithmetic operation nodes, but has different meaning. For object nodes,
|
||||||
|
// 'noContraction' means the object is 'precise'; and for arithmetic operation
|
||||||
|
// nodes, it means the operation should not be contracted.
|
||||||
|
void PropagateNoContraction(const glslang::TIntermediate& intermediate);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user