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