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
 | 
			
		||||
//POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Author: John Kessenich, LunarG
 | 
			
		||||
//
 | 
			
		||||
// Visit the nodes in the glslang intermediate tree representation to
 | 
			
		||||
// translate them to SPIR-V.
 | 
			
		||||
@ -135,10 +133,10 @@ protected:
 | 
			
		||||
    spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
 | 
			
		||||
    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 createBinaryMatrixOperation(spv::Op, spv::Decoration precision, 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 createUnaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
 | 
			
		||||
    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::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right);
 | 
			
		||||
    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::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 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);
 | 
			
		||||
@ -385,6 +383,15 @@ spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifie
 | 
			
		||||
        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.
 | 
			
		||||
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn)
 | 
			
		||||
{
 | 
			
		||||
@ -874,6 +881,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
 | 
			
		||||
 | 
			
		||||
                // do the operation
 | 
			
		||||
                rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
 | 
			
		||||
                                               TranslateNoContractionDecoration(node->getType().getQualifier()),
 | 
			
		||||
                                               convertGlslangToSpvType(node->getType()), leftRValue, rValue,
 | 
			
		||||
                                               node->getType().getBasicType());
 | 
			
		||||
 | 
			
		||||
@ -992,6 +1000,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
 | 
			
		||||
 | 
			
		||||
    // get result
 | 
			
		||||
    spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
 | 
			
		||||
                                           TranslateNoContractionDecoration(node->getType().getQualifier()),
 | 
			
		||||
                                           convertGlslangToSpvType(node->getType()), left, right,
 | 
			
		||||
                                           node->getLeft()->getType().getBasicType());
 | 
			
		||||
 | 
			
		||||
@ -1058,6 +1067,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 | 
			
		||||
        operand = accessChainLoad(node->getOperand()->getType());
 | 
			
		||||
 | 
			
		||||
    spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
 | 
			
		||||
    spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier());
 | 
			
		||||
 | 
			
		||||
    // it could be a conversion
 | 
			
		||||
    if (! result)
 | 
			
		||||
@ -1065,7 +1075,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 | 
			
		||||
 | 
			
		||||
    // if not, then possibly an operation
 | 
			
		||||
    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) {
 | 
			
		||||
        builder.clearAccessChain();
 | 
			
		||||
@ -1097,6 +1107,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 | 
			
		||||
                op = glslang::EOpSub;
 | 
			
		||||
 | 
			
		||||
            spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()),
 | 
			
		||||
                                                   TranslateNoContractionDecoration(node->getType().getQualifier()),
 | 
			
		||||
                                                   convertGlslangToSpvType(node->getType()), operand, one,
 | 
			
		||||
                                                   node->getType().getBasicType());
 | 
			
		||||
            assert(result != spv::NoResult);
 | 
			
		||||
@ -1395,7 +1406,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 | 
			
		||||
        right->traverse(this);
 | 
			
		||||
        spv::Id rightId = accessChainLoad(right->getType());
 | 
			
		||||
 | 
			
		||||
        result = createBinaryOperation(binOp, precision, 
 | 
			
		||||
        result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
 | 
			
		||||
                                       convertGlslangToSpvType(node->getType()), leftId, rightId,
 | 
			
		||||
                                       left->getType().getBasicType(), reduceComparison);
 | 
			
		||||
 | 
			
		||||
@ -1469,7 +1480,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 | 
			
		||||
            result = createNoArgOperation(node->getOp());
 | 
			
		||||
            break;
 | 
			
		||||
        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;
 | 
			
		||||
        default:
 | 
			
		||||
            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.
 | 
			
		||||
spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision,
 | 
			
		||||
                                                      spv::Decoration noContraction,
 | 
			
		||||
                                                      spv::Id typeId, spv::Id left, spv::Id right,
 | 
			
		||||
                                                      glslang::TBasicType typeProxy, bool reduceComparison)
 | 
			
		||||
{
 | 
			
		||||
@ -2797,13 +2813,15 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
 | 
			
		||||
    if (binOp != spv::OpNop) {
 | 
			
		||||
        assert(comparison == false);
 | 
			
		||||
        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
 | 
			
		||||
        if (needMatchingVectors)
 | 
			
		||||
            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)
 | 
			
		||||
@ -2872,8 +2890,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (binOp != spv::OpNop)
 | 
			
		||||
        return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision);
 | 
			
		||||
    if (binOp != spv::OpNop) {
 | 
			
		||||
        spv::Id result = builder.createBinOp(binOp, typeId, left, right);
 | 
			
		||||
        addDecoration(result, noContraction);
 | 
			
		||||
        return builder.setPrecision(result, precision);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -2892,7 +2913,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
 | 
			
		||||
//   matrix op scalar    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;
 | 
			
		||||
 | 
			
		||||
@ -2928,8 +2949,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (firstClass)
 | 
			
		||||
        return builder.setPrecision(builder.createBinOp(op, typeId, left, right), precision);
 | 
			
		||||
    if (firstClass) {
 | 
			
		||||
        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.
 | 
			
		||||
    // 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);
 | 
			
		||||
            spv::Id  leftVec =  leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
 | 
			
		||||
            spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
 | 
			
		||||
            results.push_back(builder.createBinOp(op, vecType, leftVec, rightVec));
 | 
			
		||||
            builder.setPrecision(results.back(), precision);
 | 
			
		||||
            spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
 | 
			
		||||
            addDecoration(result, noContraction);
 | 
			
		||||
            results.push_back(builder.setPrecision(result, precision));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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;
 | 
			
		||||
    int libCall = -1;
 | 
			
		||||
@ -2989,7 +3014,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
 | 
			
		||||
        if (isFloat) {
 | 
			
		||||
            unaryOp = spv::OpFNegate;
 | 
			
		||||
            if (builder.isMatrixType(typeId))
 | 
			
		||||
                return createUnaryMatrixOperation(unaryOp, precision, typeId, operand, typeProxy);
 | 
			
		||||
                return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy);
 | 
			
		||||
        } else
 | 
			
		||||
            unaryOp = spv::OpSNegate;
 | 
			
		||||
        break;
 | 
			
		||||
@ -3271,11 +3296,12 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
 | 
			
		||||
        id = builder.createUnaryOp(unaryOp, typeId, operand);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addDecoration(id, noContraction);
 | 
			
		||||
    return builder.setPrecision(id, precision);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
    // 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;
 | 
			
		||||
        indexes.push_back(c);
 | 
			
		||||
        spv::Id vec =  builder.createCompositeExtract(operand, vecType, indexes);
 | 
			
		||||
        results.push_back(builder.createUnaryOp(op, vecType, vec));
 | 
			
		||||
        builder.setPrecision(results.back(), precision);
 | 
			
		||||
        spv::Id vec_result = builder.createUnaryOp(op, vecType, vec);
 | 
			
		||||
        addDecoration(vec_result, noContraction);
 | 
			
		||||
        results.push_back(builder.setPrecision(vec_result, precision));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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.specConstantComposite.vert
 | 
			
		||||
spv.specConstantOperations.vert
 | 
			
		||||
spv.precise.tese
 | 
			
		||||
spv.precise.tesc
 | 
			
		||||
# GLSL-level semantics
 | 
			
		||||
vulkan.frag
 | 
			
		||||
vulkan.vert
 | 
			
		||||
 | 
			
		||||
@ -130,3 +130,5 @@ whileLoop.frag
 | 
			
		||||
nonVulkan.frag
 | 
			
		||||
negativeArraySize.comp
 | 
			
		||||
spv.atomic.comp
 | 
			
		||||
precise.tesc
 | 
			
		||||
precise_struct_block.vert
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,7 @@ set(SOURCES
 | 
			
		||||
    MachineIndependent/preprocessor/PpScanner.cpp
 | 
			
		||||
    MachineIndependent/preprocessor/PpSymbols.cpp
 | 
			
		||||
    MachineIndependent/preprocessor/PpTokens.cpp
 | 
			
		||||
    MachineIndependent/propagateNoContraction.cpp
 | 
			
		||||
    GenericCodeGen/CodeGen.cpp
 | 
			
		||||
    GenericCodeGen/Link.cpp)
 | 
			
		||||
 | 
			
		||||
@ -62,6 +63,7 @@ set(HEADERS
 | 
			
		||||
    MachineIndependent/SymbolTable.h
 | 
			
		||||
    MachineIndependent/Versions.h
 | 
			
		||||
    MachineIndependent/parseVersions.h
 | 
			
		||||
    MachineIndependent/propagateNoContraction.h
 | 
			
		||||
    MachineIndependent/preprocessor/PpContext.h
 | 
			
		||||
    MachineIndependent/preprocessor/PpTokens.h)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@
 | 
			
		||||
#include "localintermediate.h"
 | 
			
		||||
#include "RemoveTree.h"
 | 
			
		||||
#include "SymbolTable.h"
 | 
			
		||||
#include "propagateNoContraction.h"
 | 
			
		||||
 | 
			
		||||
#include <float.h>
 | 
			
		||||
 | 
			
		||||
@ -1066,6 +1067,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
 | 
			
		||||
    if (aggRoot && aggRoot->getOp() == EOpNull)
 | 
			
		||||
        aggRoot->setOperator(EOpSequence);
 | 
			
		||||
 | 
			
		||||
    // Propagate 'noContraction' label in backward from 'precise' variables.
 | 
			
		||||
    glslang::PropagateNoContraction(*this);
 | 
			
		||||
 | 
			
		||||
    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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user