diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7aa62fbd..22575b5a 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -33,8 +33,6 @@ //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //POSSIBILITY OF SUCH DAMAGE. -// -// Author: John Kessenich, LunarG // // Visit the nodes in the glslang intermediate tree representation to // translate them to SPIR-V. @@ -135,10 +133,10 @@ protected: spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); - spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true); - spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right); - spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); - spv::Id createUnaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); + spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true); + spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right); + spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); + spv::Id createUnaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand); spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); @@ -244,7 +242,7 @@ spv::StorageClass TranslateStorageClass(const glslang::TType& type) case glslang::EvqGlobal: return spv::StorageClassPrivate; case glslang::EvqConstReadOnly: return spv::StorageClassFunction; case glslang::EvqTemporary: return spv::StorageClassFunction; - default: + default: assert(0); return spv::StorageClassFunction; } @@ -385,6 +383,15 @@ spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifie return (spv::Decoration)spv::BadValue; } +// If glslang type is noContraction, return SPIR-V NoContraction decoration. +spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) +{ + if (qualifier.noContraction) + return spv::DecorationNoContraction; + else + return (spv::Decoration)spv::BadValue; +} + // Translate glslang built-in variable to SPIR-V built in decoration. spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn) { @@ -558,7 +565,7 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy } } -// Return whether or not the given type is something that should be tied to a +// Return whether or not the given type is something that should be tied to a // descriptor set. bool IsDescriptorResource(const glslang::TType& type) { @@ -782,7 +789,7 @@ TGlslangToSpvTraverser::~TGlslangToSpvTraverser() // // -// Symbols can turn into +// Symbols can turn into // - uniform/input reads // - output writes // - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain @@ -873,7 +880,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); // 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, node->getType().getBasicType()); @@ -992,6 +1000,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // get result spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()), + TranslateNoContractionDecoration(node->getType().getQualifier()), convertGlslangToSpvType(node->getType()), left, right, node->getLeft()->getType().getBasicType()); @@ -1058,6 +1067,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI operand = accessChainLoad(node->getOperand()->getType()); spv::Decoration precision = TranslatePrecisionDecoration(node->getType()); + spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier()); // it could be a conversion if (! result) @@ -1065,7 +1075,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // if not, then possibly an operation if (! result) - result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType()); + result = createUnaryOperation(node->getOp(), precision, noContraction, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType()); if (result) { builder.clearAccessChain(); @@ -1096,7 +1106,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI else 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, node->getType().getBasicType()); assert(result != spv::NoResult); @@ -1331,7 +1342,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; } case glslang::EOpMul: - // compontent-wise matrix multiply + // compontent-wise matrix multiply binOp = glslang::EOpMul; break; case glslang::EOpOuterProduct: @@ -1340,7 +1351,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; case glslang::EOpDot: { - // for scalar dot product, use multiply + // for scalar dot product, use multiply glslang::TIntermSequence& glslangOperands = node->getSequence(); if (! glslangOperands[0]->getAsTyped()->isVector()) binOp = glslang::EOpMul; @@ -1395,8 +1406,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt right->traverse(this); spv::Id rightId = accessChainLoad(right->getType()); - result = createBinaryOperation(binOp, precision, - convertGlslangToSpvType(node->getType()), leftId, rightId, + result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()), + convertGlslangToSpvType(node->getType()), leftId, rightId, left->getType().getBasicType(), reduceComparison); // code above should only make binOp that exists in createBinaryOperation @@ -1469,7 +1480,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt result = createNoArgOperation(node->getOp()); break; case 1: - result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), glslangOperands[0]->getAsTyped()->getBasicType()); + result = createUnaryOperation( + node->getOp(), precision, + TranslateNoContractionDecoration(node->getType().getQualifier()), + convertGlslangToSpvType(node->getType()), operands.front(), + glslangOperands[0]->getAsTyped()->getBasicType()); break; default: result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType()); @@ -1560,7 +1575,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T codeSegments.push_back(child); } - // handle the case where the last code segment is missing, due to no code + // handle the case where the last code segment is missing, due to no code // statements between the last case and the end of the switch statement if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) || (int)codeSegments.size() == defaultSegment) @@ -1695,7 +1710,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node) { - // First, steer off constants, which are not SPIR-V variables, but + // First, steer off constants, which are not SPIR-V variables, but // can still have a mapping to a SPIR-V Id. // This includes specialization constants. if (node->getQualifier().isConstant()) { @@ -1999,7 +2014,7 @@ spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arra specNode->traverse(this); return accessChainLoad(specNode->getAsTyped()->getType()); } - + // Otherwise, need a compile-time (front end) size, get it: int size = arraySizes.getDimSize(dim); assert(size > 0); @@ -2146,7 +2161,7 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structTy // Getting this far means we need explicit offsets if (currentOffset < 0) currentOffset = 0; - + // Now, currentOffset is valid (either 0, or from a previous nextOffset), // but possibly not yet correctly aligned. @@ -2176,7 +2191,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF // so that it's available to call. // Translating the body will happen later. // - // Typically (except for a "const in" parameter), an address will be passed to the + // Typically (except for a "const in" parameter), an address will be passed to the // function. What it is an address of varies: // // - "in" parameters not marked as "const" can be written to without modifying the argument, @@ -2246,7 +2261,7 @@ void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glsl void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node) { - // SPIR-V functions should already be in the functionMap from the prepass + // SPIR-V functions should already be in the functionMap from the prepass // that called makeFunctions(). spv::Function* function = functionMap[node->getName().c_str()]; spv::Block* functionBlock = function->getEntryBlock(); @@ -2660,7 +2675,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg } // Translate AST operation to SPV operation, already having SPV-based operands/types. -spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision, +spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision, + spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison) { @@ -2797,13 +2813,15 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv if (binOp != spv::OpNop) { assert(comparison == false); if (builder.isMatrix(left) || builder.isMatrix(right)) - return createBinaryMatrixOperation(binOp, precision, typeId, left, right); + return createBinaryMatrixOperation(binOp, precision, noContraction, typeId, left, right); // No matrix involved; make both operands be the same number of components, if needed if (needMatchingVectors) builder.promoteScalar(precision, left, right); - return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision); + spv::Id result = builder.createBinOp(binOp, typeId, left, right); + addDecoration(result, noContraction); + return builder.setPrecision(result, precision); } if (! comparison) @@ -2872,8 +2890,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv break; } - if (binOp != spv::OpNop) - return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision); + if (binOp != spv::OpNop) { + spv::Id result = builder.createBinOp(binOp, typeId, left, right); + addDecoration(result, noContraction); + return builder.setPrecision(result, precision); + } return 0; } @@ -2892,7 +2913,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv // matrix op scalar op in {+, -, /} // scalar op matrix op in {+, -, /} // -spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right) +spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right) { bool firstClass = true; @@ -2928,8 +2949,11 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec break; } - if (firstClass) - return builder.setPrecision(builder.createBinOp(op, typeId, left, right), precision); + if (firstClass) { + spv::Id result = builder.createBinOp(op, typeId, left, right); + addDecoration(result, noContraction); + return builder.setPrecision(result, precision); + } // Handle component-wise +, -, *, and / for all combinations of type. // The result type of all of them is the same type as the (a) matrix operand. @@ -2964,8 +2988,9 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec indexes.push_back(c); spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; - results.push_back(builder.createBinOp(op, vecType, leftVec, rightVec)); - builder.setPrecision(results.back(), precision); + spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); + addDecoration(result, noContraction); + results.push_back(builder.setPrecision(result, precision)); } // put the pieces together @@ -2977,7 +3002,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec } } -spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy) { spv::Op unaryOp = spv::OpNop; int libCall = -1; @@ -2989,7 +3014,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: if (isFloat) { unaryOp = spv::OpFNegate; if (builder.isMatrixType(typeId)) - return createUnaryMatrixOperation(unaryOp, precision, typeId, operand, typeProxy); + return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy); } else unaryOp = spv::OpSNegate; break; @@ -3271,11 +3296,12 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: id = builder.createUnaryOp(unaryOp, typeId, operand); } + addDecoration(id, noContraction); return builder.setPrecision(id, precision); } // Create a unary operation on a matrix -spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */) +spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */) { // Handle unary operations vector by vector. // The result type is the same type as the original type. @@ -3296,8 +3322,9 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Deco std::vector indexes; indexes.push_back(c); spv::Id vec = builder.createCompositeExtract(operand, vecType, indexes); - results.push_back(builder.createUnaryOp(op, vecType, vec)); - builder.setPrecision(results.back(), precision); + spv::Id vec_result = builder.createUnaryOp(op, vecType, vec); + addDecoration(vec_result, noContraction); + results.push_back(builder.setPrecision(vec_result, precision)); } // put the pieces together @@ -4125,7 +4152,7 @@ bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) default: return false; } -} +} // A node is trivial if it is a single operation with no side effects. // Error on the side of saying non-trivial. diff --git a/Test/baseResults/precise.tesc.out b/Test/baseResults/precise.tesc.out new file mode 100644 index 00000000..962a3c98 --- /dev/null +++ b/Test/baseResults/precise.tesc.out @@ -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 + diff --git a/Test/baseResults/precise_struct_block.vert.out b/Test/baseResults/precise_struct_block.vert.out new file mode 100644 index 00000000..9d726d65 --- /dev/null +++ b/Test/baseResults/precise_struct_block.vert.out @@ -0,0 +1,1045 @@ +precise_struct_block.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +Shader version: 450 +0:? Sequence +0:11 Function Definition: struct_member( (global float) +0:11 Function Parameters: +0:12 Sequence +0:12 Sequence +0:12 move second child to first child (temp float) +0:12 'a' (noContraction temp float) +0:12 Constant: +0:12 1.000000 +0:13 Sequence +0:13 move second child to first child (temp float) +0:13 'b' (temp float) +0:13 Constant: +0:13 2.000000 +0:14 Sequence +0:14 move second child to first child (temp float) +0:14 'c' (temp float) +0:14 Constant: +0:14 3.000000 +0:15 Sequence +0:15 move second child to first child (temp float) +0:15 'd' (temp float) +0:15 Constant: +0:15 4.000000 +0:21 move second child to first child (temp float) +0:21 f1: direct index for structure (noContraction global float) +0:21 'S2' (temp structure{global float f1, global float f2}) +0:21 Constant: +0:21 0 (const int) +0:21 add (noContraction temp float) +0:21 'a' (noContraction temp float) +0:21 Constant: +0:21 0.200000 +0:22 move second child to first child (temp float) +0:22 f2: direct index for structure (global float) +0:22 'S2' (temp structure{global float f1, global float f2}) +0:22 Constant: +0:22 1 (const int) +0:22 add (temp float) +0:22 'b' (temp float) +0:22 Constant: +0:22 0.200000 +0:23 move second child to first child (temp float) +0:23 f1: direct index for structure (global float) +0:23 'S3' (temp structure{global float f1, global float f2}) +0:23 Constant: +0:23 0 (const int) +0:23 add (temp float) +0:23 'a' (temp float) +0:23 'b' (temp float) +0:24 move second child to first child (temp structure{global float f1, global float f2}) +0:24 'S' (temp structure{global float f1, global float f2}) +0:24 'S2' (temp structure{global float f1, global float f2}) +0:25 move second child to first child (temp float) +0:25 'result' (noContraction temp float) +0:25 add (noContraction temp float) +0:25 f1: direct index for structure (noContraction global float) +0:25 'S' (temp structure{global float f1, global float f2}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 0.100000 +0:27 Branch: Return with expression +0:27 'result' (noContraction temp float) +0:30 Function Definition: complex_array_struct( (global float) +0:30 Function Parameters: +0:? Sequence +0:43 Sequence +0:43 Sequence +0:43 move second child to first child (temp int) +0:43 'i' (noContraction temp int) +0:43 Constant: +0:43 0 (const int) +0:43 Loop with condition tested first +0:43 Loop Condition +0:43 Compare Less Than (temp bool) +0:43 'i' (temp int) +0:43 Constant: +0:43 10 (const int) +0:43 Loop Body +0:44 Sequence +0:44 move second child to first child (temp float) +0:44 f: direct index for structure (temp float) +0:44 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:44 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:44 'i' (temp int) +0:44 Constant: +0:44 0 (const int) +0:44 divide (temp float) +0:44 Convert int to float (temp float) +0:44 'i' (temp int) +0:44 Constant: +0:44 3.000000 +0:45 move second child to first child (temp 4-component vector of float) +0:45 v: direct index for structure (noContraction temp 4-component vector of float) +0:45 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:45 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:45 'i' (temp int) +0:45 Constant: +0:45 2 (const int) +0:45 Construct vec4 (temp 4-component vector of float) +0:45 component-wise multiply (noContraction temp float) +0:45 Convert int to float (temp float) +0:45 'i' (noContraction temp int) +0:45 Constant: +0:45 1.500000 +0:46 move second child to first child (temp int) +0:46 p: direct index for structure (temp int) +0:46 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:46 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:46 'i' (temp int) +0:46 Constant: +0:46 3 (const int) +0:46 add (temp int) +0:46 'i' (temp int) +0:46 Constant: +0:46 1 (const int) +0:47 Sequence +0:47 Sequence +0:47 move second child to first child (temp int) +0:47 'j' (temp int) +0:47 Constant: +0:47 0 (const int) +0:47 Loop with condition tested first +0:47 Loop Condition +0:47 Compare Less Than (temp bool) +0:47 'j' (temp int) +0:47 Constant: +0:47 5 (const int) +0:47 Loop Body +0:48 Sequence +0:48 Sequence +0:48 Sequence +0:48 move second child to first child (temp int) +0:48 'k' (temp int) +0:48 Constant: +0:48 0 (const int) +0:48 Loop with condition tested first +0:48 Loop Condition +0:48 Compare Less Than (temp bool) +0:48 'k' (temp int) +0:48 Constant: +0:48 3 (const int) +0:48 Loop Body +0:49 Sequence +0:49 move second child to first child (temp float) +0:49 indirect index (temp float) +0:49 t1_array: direct index for structure (temp 3-element array of float) +0:49 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:49 t1a: direct index for structure (temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:49 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:49 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:49 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:49 'i' (temp int) +0:49 Constant: +0:49 1 (const int) +0:49 Constant: +0:49 0 (const int) +0:49 'j' (temp int) +0:49 Constant: +0:49 0 (const int) +0:49 'k' (temp int) +0:49 Convert int to float (temp float) +0:49 add (temp int) +0:49 component-wise multiply (temp int) +0:49 'i' (temp int) +0:49 'j' (temp int) +0:49 'k' (temp int) +0:48 Loop Terminal Expression +0:48 Post-Increment (temp int) +0:48 'k' (temp int) +0:51 move second child to first child (temp float) +0:51 t1_scalar: direct index for structure (temp float) +0:51 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:51 t1a: direct index for structure (temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:51 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:51 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:51 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:51 'i' (temp int) +0:51 Constant: +0:51 1 (const int) +0:51 Constant: +0:51 0 (const int) +0:51 'j' (temp int) +0:51 Constant: +0:51 1 (const int) +0:51 divide (temp float) +0:51 component-wise multiply (temp float) +0:51 Convert int to float (temp float) +0:51 'j' (temp int) +0:51 Constant: +0:51 2.000000 +0:51 Convert int to float (temp float) +0:51 'i' (temp int) +0:47 Loop Terminal Expression +0:47 Post-Increment (temp int) +0:47 'j' (temp int) +0:54 Sequence +0:54 Sequence +0:54 move second child to first child (temp int) +0:54 'j' (noContraction 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 'j' (temp int) +0:54 Constant: +0:54 6 (const int) +0:54 Loop Body +0:55 Sequence +0:55 Sequence +0:55 Sequence +0:55 move second child to first child (temp int) +0:55 'k' (temp int) +0:55 Constant: +0:55 0 (const int) +0:55 Loop with condition tested first +0:55 Loop Condition +0:55 Compare Less Than (temp bool) +0:55 'k' (temp int) +0:55 Constant: +0:55 3 (const int) +0:55 Loop Body +0:56 Sequence +0:56 move second child to first child (temp float) +0:56 indirect index (temp float) +0:56 t1_array: direct index for structure (temp 3-element array of float) +0:56 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:56 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:56 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:56 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:56 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:56 'i' (temp int) +0:56 Constant: +0:56 1 (const int) +0:56 Constant: +0:56 1 (const int) +0:56 'j' (temp int) +0:56 Constant: +0:56 0 (const int) +0:56 'k' (temp int) +0:56 Convert int to float (temp float) +0:56 add (temp int) +0:56 component-wise multiply (temp int) +0:56 'i' (temp int) +0:56 'j' (temp int) +0:56 'k' (temp int) +0:55 Loop Terminal Expression +0:55 Post-Increment (temp int) +0:55 'k' (temp int) +0:58 move second child to first child (temp float) +0:58 t1_scalar: direct index for structure (noContraction temp float) +0:58 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:58 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:58 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:58 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:58 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:58 'i' (temp int) +0:58 Constant: +0:58 1 (const int) +0:58 Constant: +0:58 1 (const int) +0:58 'j' (temp int) +0:58 Constant: +0:58 1 (const int) +0:58 divide (noContraction temp float) +0:58 component-wise multiply (noContraction temp float) +0:58 Convert int to float (temp float) +0:58 'j' (noContraction temp int) +0:58 Constant: +0:58 2.000000 +0:58 Convert int to float (temp float) +0:58 'i' (noContraction temp int) +0:54 Loop Terminal Expression +0:54 Post-Increment (noContraction temp int) +0:54 'j' (noContraction temp int) +0:61 Sequence +0:61 Sequence +0:61 move second child to first child (temp int) +0:61 'j' (noContraction temp int) +0:61 Constant: +0:61 0 (const int) +0:61 Loop with condition tested first +0:61 Loop Condition +0:61 Compare Less Than (temp bool) +0:61 'j' (temp int) +0:61 Constant: +0:61 6 (const int) +0:61 Loop Body +0:62 Sequence +0:62 Sequence +0:62 Sequence +0:62 move second child to first child (temp int) +0:62 'k' (noContraction temp int) +0:62 Constant: +0:62 0 (const int) +0:62 Loop with condition tested first +0:62 Loop Condition +0:62 Compare Less Than (temp bool) +0:62 'k' (temp int) +0:62 Constant: +0:62 3 (const int) +0:62 Loop Body +0:63 Sequence +0:63 move second child to first child (temp float) +0:63 indirect index (noContraction temp float) +0:63 t1_array: direct index for structure (noContraction temp 3-element array of float) +0:63 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:63 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:63 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:63 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:63 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:63 'i' (temp int) +0:63 Constant: +0:63 1 (const int) +0:63 Constant: +0:63 2 (const int) +0:63 'j' (temp int) +0:63 Constant: +0:63 0 (const int) +0:63 'k' (temp int) +0:63 Convert int to float (temp float) +0:63 add (temp int) +0:63 component-wise multiply (temp int) +0:63 'i' (noContraction temp int) +0:63 'j' (noContraction temp int) +0:63 'k' (noContraction temp int) +0:62 Loop Terminal Expression +0:62 Post-Increment (noContraction temp int) +0:62 'k' (noContraction temp int) +0:65 move second child to first child (temp float) +0:65 t1_scalar: direct index for structure (temp float) +0:65 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:65 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:65 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:65 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:65 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:65 'i' (temp int) +0:65 Constant: +0:65 1 (const int) +0:65 Constant: +0:65 2 (const int) +0:65 'j' (temp int) +0:65 Constant: +0:65 1 (const int) +0:65 divide (temp float) +0:65 component-wise multiply (temp float) +0:65 Convert int to float (temp float) +0:65 'j' (temp int) +0:65 Constant: +0:65 2.000000 +0:65 Convert int to float (temp float) +0:65 'i' (temp int) +0:61 Loop Terminal Expression +0:61 Post-Increment (noContraction temp int) +0:61 'j' (noContraction temp int) +0:43 Loop Terminal Expression +0:43 Post-Increment (noContraction temp int) +0:43 'i' (noContraction temp int) +0:68 Sequence +0:68 move second child to first child (temp int) +0:68 'i' (temp int) +0:68 Constant: +0:68 2 (const int) +0:69 move second child to first child (temp float) +0:69 'result' (noContraction temp float) +0:71 add (noContraction temp float) +0:70 add (noContraction temp float) +0:69 direct index (noContraction temp float) +0:69 t1_array: direct index for structure (temp 3-element array of float) +0:69 direct index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:69 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:69 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:69 direct index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:69 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:69 Constant: +0:69 5 (const int) +0:69 Constant: +0:69 1 (const int) +0:69 Constant: +0:69 2 (const int) +0:69 Constant: +0:69 6 (const int) +0:69 Constant: +0:69 0 (const int) +0:69 Constant: +0:69 1 (const int) +0:70 t1_scalar: direct index for structure (noContraction temp float) +0:70 direct index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:70 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:70 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:70 direct index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:70 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:70 Constant: +0:70 2 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:71 direct index (noContraction temp float) +0:71 vector swizzle (temp 2-component vector of float) +0:71 v: direct index for structure (temp 4-component vector of float) +0:71 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:71 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:71 subtract (temp int) +0:71 'i' (temp int) +0:71 Constant: +0:71 1 (const int) +0:71 Constant: +0:71 2 (const int) +0:71 Sequence +0:71 Constant: +0:71 0 (const int) +0:71 Constant: +0:71 1 (const int) +0:71 Constant: +0:71 0 (const int) +0:72 Branch: Return with expression +0:72 'result' (noContraction temp float) +0:75 Function Definition: out_block( (global float) +0:75 Function Parameters: +0:76 Sequence +0:76 Sequence +0:76 move second child to first child (temp float) +0:76 'a' (noContraction temp float) +0:76 Constant: +0:76 0.100000 +0:77 Sequence +0:77 move second child to first child (temp float) +0:77 'b' (noContraction temp float) +0:77 Constant: +0:77 0.200000 +0:78 move second child to first child (temp float) +0:78 f1: direct index for structure (noContraction global float) +0:78 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:78 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:78 Constant: +0:78 0 (const int) +0:78 Constant: +0:78 0 (const int) +0:78 add (noContraction temp float) +0:78 'a' (noContraction temp float) +0:78 'b' (noContraction temp float) +0:79 move second child to first child (temp float) +0:79 f2: direct index for structure (noContraction global float) +0:79 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:79 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:79 Constant: +0:79 0 (const int) +0:79 Constant: +0:79 1 (const int) +0:79 subtract (noContraction temp float) +0:79 'a' (noContraction temp float) +0:79 'b' (noContraction temp float) +0:80 move second child to first child (temp float) +0:80 x: direct index for structure (out float) +0:80 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:80 Constant: +0:80 1 (const int) +0:80 component-wise multiply (temp float) +0:80 'a' (temp float) +0:80 'b' (temp float) +0:82 move second child to first child (temp float) +0:82 f1: direct index for structure (noContraction global float) +0:82 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:82 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:82 Constant: +0:82 0 (const int) +0:82 Constant: +0:82 0 (const int) +0:82 add (noContraction temp float) +0:82 add (noContraction temp float) +0:82 'a' (noContraction temp float) +0:82 'b' (noContraction temp float) +0:82 Constant: +0:82 1.000000 +0:83 move second child to first child (temp float) +0:83 f2: direct index for structure (noContraction global float) +0:83 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:83 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:83 Constant: +0:83 0 (const int) +0:83 Constant: +0:83 1 (const int) +0:83 subtract (noContraction temp float) +0:83 subtract (noContraction temp float) +0:83 'a' (noContraction temp float) +0:83 'b' (noContraction temp float) +0:83 Constant: +0:83 1.000000 +0:84 move second child to first child (temp float) +0:84 x: direct index for structure (noContraction out float) +0:84 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:84 Constant: +0:84 1 (const int) +0:84 component-wise multiply (noContraction temp float) +0:84 component-wise multiply (noContraction temp float) +0:84 'a' (noContraction temp float) +0:84 'b' (noContraction temp float) +0:84 Constant: +0:84 2.000000 +0:86 Branch: Return with expression +0:86 add (temp float) +0:86 'a' (temp float) +0:86 'b' (temp float) +0:89 Function Definition: main( (global void) +0:89 Function Parameters: +0:? Linker Objects +0:? 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:? 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:? 'gl_VertexID' (gl_VertexId int VertexId) +0:? 'gl_InstanceID' (gl_InstanceId int InstanceId) + + +Linked vertex stage: + + +Shader version: 450 +0:? Sequence +0:11 Function Definition: struct_member( (global float) +0:11 Function Parameters: +0:12 Sequence +0:12 Sequence +0:12 move second child to first child (temp float) +0:12 'a' (noContraction temp float) +0:12 Constant: +0:12 1.000000 +0:13 Sequence +0:13 move second child to first child (temp float) +0:13 'b' (temp float) +0:13 Constant: +0:13 2.000000 +0:14 Sequence +0:14 move second child to first child (temp float) +0:14 'c' (temp float) +0:14 Constant: +0:14 3.000000 +0:15 Sequence +0:15 move second child to first child (temp float) +0:15 'd' (temp float) +0:15 Constant: +0:15 4.000000 +0:21 move second child to first child (temp float) +0:21 f1: direct index for structure (noContraction global float) +0:21 'S2' (temp structure{global float f1, global float f2}) +0:21 Constant: +0:21 0 (const int) +0:21 add (noContraction temp float) +0:21 'a' (noContraction temp float) +0:21 Constant: +0:21 0.200000 +0:22 move second child to first child (temp float) +0:22 f2: direct index for structure (global float) +0:22 'S2' (temp structure{global float f1, global float f2}) +0:22 Constant: +0:22 1 (const int) +0:22 add (temp float) +0:22 'b' (temp float) +0:22 Constant: +0:22 0.200000 +0:23 move second child to first child (temp float) +0:23 f1: direct index for structure (global float) +0:23 'S3' (temp structure{global float f1, global float f2}) +0:23 Constant: +0:23 0 (const int) +0:23 add (temp float) +0:23 'a' (temp float) +0:23 'b' (temp float) +0:24 move second child to first child (temp structure{global float f1, global float f2}) +0:24 'S' (temp structure{global float f1, global float f2}) +0:24 'S2' (temp structure{global float f1, global float f2}) +0:25 move second child to first child (temp float) +0:25 'result' (noContraction temp float) +0:25 add (noContraction temp float) +0:25 f1: direct index for structure (noContraction global float) +0:25 'S' (temp structure{global float f1, global float f2}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 0.100000 +0:27 Branch: Return with expression +0:27 'result' (noContraction temp float) +0:30 Function Definition: complex_array_struct( (global float) +0:30 Function Parameters: +0:? Sequence +0:43 Sequence +0:43 Sequence +0:43 move second child to first child (temp int) +0:43 'i' (noContraction temp int) +0:43 Constant: +0:43 0 (const int) +0:43 Loop with condition tested first +0:43 Loop Condition +0:43 Compare Less Than (temp bool) +0:43 'i' (temp int) +0:43 Constant: +0:43 10 (const int) +0:43 Loop Body +0:44 Sequence +0:44 move second child to first child (temp float) +0:44 f: direct index for structure (temp float) +0:44 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:44 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:44 'i' (temp int) +0:44 Constant: +0:44 0 (const int) +0:44 divide (temp float) +0:44 Convert int to float (temp float) +0:44 'i' (temp int) +0:44 Constant: +0:44 3.000000 +0:45 move second child to first child (temp 4-component vector of float) +0:45 v: direct index for structure (noContraction temp 4-component vector of float) +0:45 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:45 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:45 'i' (temp int) +0:45 Constant: +0:45 2 (const int) +0:45 Construct vec4 (temp 4-component vector of float) +0:45 component-wise multiply (noContraction temp float) +0:45 Convert int to float (temp float) +0:45 'i' (noContraction temp int) +0:45 Constant: +0:45 1.500000 +0:46 move second child to first child (temp int) +0:46 p: direct index for structure (temp int) +0:46 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:46 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:46 'i' (temp int) +0:46 Constant: +0:46 3 (const int) +0:46 add (temp int) +0:46 'i' (temp int) +0:46 Constant: +0:46 1 (const int) +0:47 Sequence +0:47 Sequence +0:47 move second child to first child (temp int) +0:47 'j' (temp int) +0:47 Constant: +0:47 0 (const int) +0:47 Loop with condition tested first +0:47 Loop Condition +0:47 Compare Less Than (temp bool) +0:47 'j' (temp int) +0:47 Constant: +0:47 5 (const int) +0:47 Loop Body +0:48 Sequence +0:48 Sequence +0:48 Sequence +0:48 move second child to first child (temp int) +0:48 'k' (temp int) +0:48 Constant: +0:48 0 (const int) +0:48 Loop with condition tested first +0:48 Loop Condition +0:48 Compare Less Than (temp bool) +0:48 'k' (temp int) +0:48 Constant: +0:48 3 (const int) +0:48 Loop Body +0:49 Sequence +0:49 move second child to first child (temp float) +0:49 indirect index (temp float) +0:49 t1_array: direct index for structure (temp 3-element array of float) +0:49 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:49 t1a: direct index for structure (temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:49 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:49 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:49 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:49 'i' (temp int) +0:49 Constant: +0:49 1 (const int) +0:49 Constant: +0:49 0 (const int) +0:49 'j' (temp int) +0:49 Constant: +0:49 0 (const int) +0:49 'k' (temp int) +0:49 Convert int to float (temp float) +0:49 add (temp int) +0:49 component-wise multiply (temp int) +0:49 'i' (temp int) +0:49 'j' (temp int) +0:49 'k' (temp int) +0:48 Loop Terminal Expression +0:48 Post-Increment (temp int) +0:48 'k' (temp int) +0:51 move second child to first child (temp float) +0:51 t1_scalar: direct index for structure (temp float) +0:51 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:51 t1a: direct index for structure (temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:51 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:51 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:51 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:51 'i' (temp int) +0:51 Constant: +0:51 1 (const int) +0:51 Constant: +0:51 0 (const int) +0:51 'j' (temp int) +0:51 Constant: +0:51 1 (const int) +0:51 divide (temp float) +0:51 component-wise multiply (temp float) +0:51 Convert int to float (temp float) +0:51 'j' (temp int) +0:51 Constant: +0:51 2.000000 +0:51 Convert int to float (temp float) +0:51 'i' (temp int) +0:47 Loop Terminal Expression +0:47 Post-Increment (temp int) +0:47 'j' (temp int) +0:54 Sequence +0:54 Sequence +0:54 move second child to first child (temp int) +0:54 'j' (noContraction 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 'j' (temp int) +0:54 Constant: +0:54 6 (const int) +0:54 Loop Body +0:55 Sequence +0:55 Sequence +0:55 Sequence +0:55 move second child to first child (temp int) +0:55 'k' (temp int) +0:55 Constant: +0:55 0 (const int) +0:55 Loop with condition tested first +0:55 Loop Condition +0:55 Compare Less Than (temp bool) +0:55 'k' (temp int) +0:55 Constant: +0:55 3 (const int) +0:55 Loop Body +0:56 Sequence +0:56 move second child to first child (temp float) +0:56 indirect index (temp float) +0:56 t1_array: direct index for structure (temp 3-element array of float) +0:56 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:56 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:56 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:56 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:56 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:56 'i' (temp int) +0:56 Constant: +0:56 1 (const int) +0:56 Constant: +0:56 1 (const int) +0:56 'j' (temp int) +0:56 Constant: +0:56 0 (const int) +0:56 'k' (temp int) +0:56 Convert int to float (temp float) +0:56 add (temp int) +0:56 component-wise multiply (temp int) +0:56 'i' (temp int) +0:56 'j' (temp int) +0:56 'k' (temp int) +0:55 Loop Terminal Expression +0:55 Post-Increment (temp int) +0:55 'k' (temp int) +0:58 move second child to first child (temp float) +0:58 t1_scalar: direct index for structure (noContraction temp float) +0:58 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:58 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:58 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:58 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:58 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:58 'i' (temp int) +0:58 Constant: +0:58 1 (const int) +0:58 Constant: +0:58 1 (const int) +0:58 'j' (temp int) +0:58 Constant: +0:58 1 (const int) +0:58 divide (noContraction temp float) +0:58 component-wise multiply (noContraction temp float) +0:58 Convert int to float (temp float) +0:58 'j' (noContraction temp int) +0:58 Constant: +0:58 2.000000 +0:58 Convert int to float (temp float) +0:58 'i' (noContraction temp int) +0:54 Loop Terminal Expression +0:54 Post-Increment (noContraction temp int) +0:54 'j' (noContraction temp int) +0:61 Sequence +0:61 Sequence +0:61 move second child to first child (temp int) +0:61 'j' (noContraction temp int) +0:61 Constant: +0:61 0 (const int) +0:61 Loop with condition tested first +0:61 Loop Condition +0:61 Compare Less Than (temp bool) +0:61 'j' (temp int) +0:61 Constant: +0:61 6 (const int) +0:61 Loop Body +0:62 Sequence +0:62 Sequence +0:62 Sequence +0:62 move second child to first child (temp int) +0:62 'k' (noContraction temp int) +0:62 Constant: +0:62 0 (const int) +0:62 Loop with condition tested first +0:62 Loop Condition +0:62 Compare Less Than (temp bool) +0:62 'k' (temp int) +0:62 Constant: +0:62 3 (const int) +0:62 Loop Body +0:63 Sequence +0:63 move second child to first child (temp float) +0:63 indirect index (noContraction temp float) +0:63 t1_array: direct index for structure (noContraction temp 3-element array of float) +0:63 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:63 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:63 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:63 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:63 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:63 'i' (temp int) +0:63 Constant: +0:63 1 (const int) +0:63 Constant: +0:63 2 (const int) +0:63 'j' (temp int) +0:63 Constant: +0:63 0 (const int) +0:63 'k' (temp int) +0:63 Convert int to float (temp float) +0:63 add (temp int) +0:63 component-wise multiply (temp int) +0:63 'i' (noContraction temp int) +0:63 'j' (noContraction temp int) +0:63 'k' (noContraction temp int) +0:62 Loop Terminal Expression +0:62 Post-Increment (noContraction temp int) +0:62 'k' (noContraction temp int) +0:65 move second child to first child (temp float) +0:65 t1_scalar: direct index for structure (temp float) +0:65 indirect index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:65 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:65 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:65 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:65 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:65 'i' (temp int) +0:65 Constant: +0:65 1 (const int) +0:65 Constant: +0:65 2 (const int) +0:65 'j' (temp int) +0:65 Constant: +0:65 1 (const int) +0:65 divide (temp float) +0:65 component-wise multiply (temp float) +0:65 Convert int to float (temp float) +0:65 'j' (temp int) +0:65 Constant: +0:65 2.000000 +0:65 Convert int to float (temp float) +0:65 'i' (temp int) +0:61 Loop Terminal Expression +0:61 Post-Increment (noContraction temp int) +0:61 'j' (noContraction temp int) +0:43 Loop Terminal Expression +0:43 Post-Increment (noContraction temp int) +0:43 'i' (noContraction temp int) +0:68 Sequence +0:68 move second child to first child (temp int) +0:68 'i' (temp int) +0:68 Constant: +0:68 2 (const int) +0:69 move second child to first child (temp float) +0:69 'result' (noContraction temp float) +0:71 add (noContraction temp float) +0:70 add (noContraction temp float) +0:69 direct index (noContraction temp float) +0:69 t1_array: direct index for structure (temp 3-element array of float) +0:69 direct index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:69 t1c: direct index for structure (temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:69 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:69 direct index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:69 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:69 Constant: +0:69 5 (const int) +0:69 Constant: +0:69 1 (const int) +0:69 Constant: +0:69 2 (const int) +0:69 Constant: +0:69 6 (const int) +0:69 Constant: +0:69 0 (const int) +0:69 Constant: +0:69 1 (const int) +0:70 t1_scalar: direct index for structure (noContraction temp float) +0:70 direct index (temp structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:70 t1b: direct index for structure (temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar}) +0:70 t2: direct index for structure (temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c}) +0:70 direct index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:70 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:70 Constant: +0:70 2 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:70 Constant: +0:70 1 (const int) +0:71 direct index (noContraction temp float) +0:71 vector swizzle (temp 2-component vector of float) +0:71 v: direct index for structure (temp 4-component vector of float) +0:71 indirect index (temp structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:71 't3' (temp 10-element array of structure{temp float f, temp structure{temp 5-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1a, temp 6-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1b, temp 7-element array of structure{temp 3-element array of float t1_array, temp float t1_scalar} t1c} t2, temp 4-component vector of float v, temp int p}) +0:71 subtract (temp int) +0:71 'i' (temp int) +0:71 Constant: +0:71 1 (const int) +0:71 Constant: +0:71 2 (const int) +0:71 Sequence +0:71 Constant: +0:71 0 (const int) +0:71 Constant: +0:71 1 (const int) +0:71 Constant: +0:71 0 (const int) +0:72 Branch: Return with expression +0:72 'result' (noContraction temp float) +0:75 Function Definition: out_block( (global float) +0:75 Function Parameters: +0:76 Sequence +0:76 Sequence +0:76 move second child to first child (temp float) +0:76 'a' (noContraction temp float) +0:76 Constant: +0:76 0.100000 +0:77 Sequence +0:77 move second child to first child (temp float) +0:77 'b' (noContraction temp float) +0:77 Constant: +0:77 0.200000 +0:78 move second child to first child (temp float) +0:78 f1: direct index for structure (noContraction global float) +0:78 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:78 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:78 Constant: +0:78 0 (const int) +0:78 Constant: +0:78 0 (const int) +0:78 add (noContraction temp float) +0:78 'a' (noContraction temp float) +0:78 'b' (noContraction temp float) +0:79 move second child to first child (temp float) +0:79 f2: direct index for structure (noContraction global float) +0:79 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:79 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:79 Constant: +0:79 0 (const int) +0:79 Constant: +0:79 1 (const int) +0:79 subtract (noContraction temp float) +0:79 'a' (noContraction temp float) +0:79 'b' (noContraction temp float) +0:80 move second child to first child (temp float) +0:80 x: direct index for structure (out float) +0:80 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:80 Constant: +0:80 1 (const int) +0:80 component-wise multiply (temp float) +0:80 'a' (temp float) +0:80 'b' (temp float) +0:82 move second child to first child (temp float) +0:82 f1: direct index for structure (noContraction global float) +0:82 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:82 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:82 Constant: +0:82 0 (const int) +0:82 Constant: +0:82 0 (const int) +0:82 add (noContraction temp float) +0:82 add (noContraction temp float) +0:82 'a' (noContraction temp float) +0:82 'b' (noContraction temp float) +0:82 Constant: +0:82 1.000000 +0:83 move second child to first child (temp float) +0:83 f2: direct index for structure (noContraction global float) +0:83 s: direct index for structure (noContraction out structure{global float f1, global float f2}) +0:83 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:83 Constant: +0:83 0 (const int) +0:83 Constant: +0:83 1 (const int) +0:83 subtract (noContraction temp float) +0:83 subtract (noContraction temp float) +0:83 'a' (noContraction temp float) +0:83 'b' (noContraction temp float) +0:83 Constant: +0:83 1.000000 +0:84 move second child to first child (temp float) +0:84 x: direct index for structure (noContraction out float) +0:84 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:84 Constant: +0:84 1 (const int) +0:84 component-wise multiply (noContraction temp float) +0:84 component-wise multiply (noContraction temp float) +0:84 'a' (noContraction temp float) +0:84 'b' (noContraction temp float) +0:84 Constant: +0:84 2.000000 +0:86 Branch: Return with expression +0:86 add (temp float) +0:86 'a' (temp float) +0:86 'b' (temp float) +0:89 Function Definition: main( (global void) +0:89 Function Parameters: +0:? Linker Objects +0:? 'partial_precise_block' (out block{noContraction out structure{global float f1, global float f2} s, out float x}) +0:? 'all_precise_block' (noContraction out block{out structure{global float f1, global float f2} s, out float x}) +0:? 'gl_VertexID' (gl_VertexId int VertexId) +0:? 'gl_InstanceID' (gl_InstanceId int InstanceId) + diff --git a/Test/baseResults/spv.precise.tesc.out b/Test/baseResults/spv.precise.tesc.out new file mode 100644 index 00000000..0331a14a --- /dev/null +++ b/Test/baseResults/spv.precise.tesc.out @@ -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 diff --git a/Test/baseResults/spv.precise.tese.out b/Test/baseResults/spv.precise.tese.out new file mode 100644 index 00000000..231ea333 --- /dev/null +++ b/Test/baseResults/spv.precise.tese.out @@ -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 diff --git a/Test/precise.tesc b/Test/precise.tesc new file mode 100644 index 00000000..c541540c --- /dev/null +++ b/Test/precise.tesc @@ -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(){} diff --git a/Test/precise_struct_block.vert b/Test/precise_struct_block.vert new file mode 100644 index 00000000..279b4b09 --- /dev/null +++ b/Test/precise_struct_block.vert @@ -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(){} diff --git a/Test/spv.precise.tesc b/Test/spv.precise.tesc new file mode 100644 index 00000000..35de26b8 --- /dev/null +++ b/Test/spv.precise.tesc @@ -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]); +} diff --git a/Test/spv.precise.tese b/Test/spv.precise.tese new file mode 100644 index 00000000..874ea840 --- /dev/null +++ b/Test/spv.precise.tese @@ -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); +} diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 703607da..03f4432e 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -107,6 +107,8 @@ spv.specConstant.vert spv.specConstant.comp spv.specConstantComposite.vert spv.specConstantOperations.vert +spv.precise.tese +spv.precise.tesc # GLSL-level semantics vulkan.frag vulkan.vert diff --git a/Test/testlist b/Test/testlist index 1be8b8e2..dd682b2d 100644 --- a/Test/testlist +++ b/Test/testlist @@ -130,3 +130,5 @@ whileLoop.frag nonVulkan.frag negativeArraySize.comp spv.atomic.comp +precise.tesc +precise_struct_block.vert diff --git a/glslang/CMakeLists.txt b/glslang/CMakeLists.txt index 7015e304..f431cc11 100644 --- a/glslang/CMakeLists.txt +++ b/glslang/CMakeLists.txt @@ -33,6 +33,7 @@ set(SOURCES MachineIndependent/preprocessor/PpScanner.cpp MachineIndependent/preprocessor/PpSymbols.cpp MachineIndependent/preprocessor/PpTokens.cpp + MachineIndependent/propagateNoContraction.cpp GenericCodeGen/CodeGen.cpp GenericCodeGen/Link.cpp) @@ -62,6 +63,7 @@ set(HEADERS MachineIndependent/SymbolTable.h MachineIndependent/Versions.h MachineIndependent/parseVersions.h + MachineIndependent/propagateNoContraction.h MachineIndependent/preprocessor/PpContext.h MachineIndependent/preprocessor/PpTokens.h) diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 47a93670..d3aa5853 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -42,6 +42,7 @@ #include "localintermediate.h" #include "RemoveTree.h" #include "SymbolTable.h" +#include "propagateNoContraction.h" #include @@ -1066,6 +1067,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) if (aggRoot && aggRoot->getOp() == EOpNull) aggRoot->setOperator(EOpSequence); + // Propagate 'noContraction' label in backward from 'precise' variables. + glslang::PropagateNoContraction(*this); + return true; } diff --git a/glslang/MachineIndependent/propagateNoContraction.cpp b/glslang/MachineIndependent/propagateNoContraction.cpp new file mode 100644 index 00000000..ab00829b --- /dev/null +++ b/glslang/MachineIndependent/propagateNoContraction.cpp @@ -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 +#include +#include +#include + +#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: /0 +// Object s.b will be represented with: /1 +// Object s will be representend with: +// 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; +// Mapping from object nodes to their accesschain info string. +using AccessChainMapping = std::unordered_map; + +// Set of object IDs. +using ObjectAccesschainSet = std::unordered_set; +// Set of return branch nodes. +using ReturnBranchNodeSet = std::unordered_set; + +// 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 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* 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 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 +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 + 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 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 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); + } +} +}; diff --git a/glslang/MachineIndependent/propagateNoContraction.h b/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..43c2116b --- /dev/null +++ b/glslang/MachineIndependent/propagateNoContraction.h @@ -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); +};