diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7aa62fbd..d160e36e 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -385,6 +385,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) { @@ -612,7 +621,8 @@ bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier) // - struct members can inherit from a struct declaration // - effect decorations on the struct members (note smooth does not, and expecting something like volatile to effect the whole object) // - are not part of the offset/st430/etc or row/column-major layout - return qualifier.invariant || qualifier.nopersp || qualifier.flat || qualifier.centroid || qualifier.patch || qualifier.sample || qualifier.hasLocation(); + return qualifier.invariant || qualifier.nopersp || qualifier.flat || qualifier.centroid || qualifier.patch || qualifier.sample || qualifier.hasLocation() || + qualifier.noContraction; } // @@ -877,6 +887,9 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T convertGlslangToSpvType(node->getType()), leftRValue, rValue, node->getType().getBasicType()); + // Decorate this instruction, if this node has 'noContraction' qualifier. + addDecoration(rValue, TranslateNoContractionDecoration(node->getType().getQualifier())); + // these all need their counterparts in createBinaryOperation() assert(rValue != spv::NoResult); } @@ -1000,6 +1013,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T logger->missingFunctionality("unknown glslang binary operation"); return true; // pick up a child as the place-holder result } else { + // Decorate this instruction, if this node has 'noContraction' qualifier. + addDecoration(result, TranslateNoContractionDecoration(node->getType().getQualifier())); builder.setAccessChainRValue(result); return false; } @@ -1068,6 +1083,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType()); if (result) { + // Decorate this instruction, if this node has 'noContraction' qualifier. + addDecoration(result, TranslateNoContractionDecoration(node->getType().getQualifier())); builder.clearAccessChain(); builder.setAccessChainRValue(result); @@ -1100,6 +1117,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI convertGlslangToSpvType(node->getType()), operand, one, node->getType().getBasicType()); assert(result != spv::NoResult); + // Decorate this instruction, if this node has 'noContraction' qualifier. + addDecoration(result, TranslateNoContractionDecoration(node->getType().getQualifier())); // The result of operation is always stored, but conditionally the // consumed result. The consumed result is always an r-value. diff --git a/Test/baseResults/precise.tesc.out b/Test/baseResults/precise.tesc.out new file mode 100644 index 00000000..d14af90e --- /dev/null +++ b/Test/baseResults/precise.tesc.out @@ -0,0 +1,728 @@ +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 int) +0:17 'a' (noContraction temp int) +0:17 Constant: +0:17 10 (const int) +0:18 Sequence +0:18 move second child to first child (temp int) +0:18 'b' (noContraction temp int) +0:18 Constant: +0:18 20 (const int) +0:19 move second child to first child (temp float) +0:19 'result' (noContraction temp float) +0:19 Convert int to float (temp float) +0:19 move second child to first child (temp int) +0:19 'a' (noContraction temp int) +0:19 add (noContraction temp int) +0:19 'b' (noContraction temp int) +0:19 Constant: +0:19 4 (const int) +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 int) +0:24 'a' (noContraction temp int) +0:24 Constant: +0:24 10 (const int) +0:25 Sequence +0:25 move second child to first child (temp int) +0:25 'b' (noContraction temp int) +0:25 Constant: +0:25 20 (const int) +0:26 move second child to first child (temp int) +0:26 'b' (noContraction temp int) +0:26 add (noContraction temp int) +0:26 'a' (noContraction temp int) +0:26 'b' (noContraction temp int) +0:27 move second child to first child (temp float) +0:27 'result' (noContraction temp float) +0:27 Convert int to float (temp float) +0:27 'b' (noContraction temp int) +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:46 Sequence +0:46 Sequence +0:46 move second child to first child (temp int) +0:46 'result' (noContraction temp int) +0:46 Constant: +0:46 5 (const int) +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 int) +0:52 'result' (noContraction temp int) +0:52 add (noContraction temp int) +0:52 'x' (noContraction temp int) +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 int) +0:56 'result' (noContraction temp int) +0:56 add (noContraction temp int) +0:56 indirect index (noContraction temp int) +0:56 'a0' (temp 3-element array of int) +0:56 'i' (temp int) +0:56 Constant: +0:56 2 (const int) +0:58 move second child to first child (temp int) +0:58 indirect index (noContraction temp int) +0:58 'a0' (noContraction temp 3-element array of int) +0:58 'i' (temp int) +0:58 subtract (noContraction temp int) +0:58 Constant: +0:58 3 (const int) +0:58 Post-Increment (noContraction temp int) +0:58 'result' (noContraction temp int) +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 (noContraction temp int) +0:69 add (noContraction 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' (out float) +0:97 Sequence +0:97 Sequence +0:97 move second child to first child (temp float) +0:97 'a' (temp float) +0:97 Constant: +0:97 0.500000 +0:98 move second child to first child (temp float) +0:98 'c' (out float) +0:98 add (temp float) +0:98 'a' (temp float) +0:98 'b' (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: main( (global void) +0:102 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 int) +0:17 'a' (noContraction temp int) +0:17 Constant: +0:17 10 (const int) +0:18 Sequence +0:18 move second child to first child (temp int) +0:18 'b' (noContraction temp int) +0:18 Constant: +0:18 20 (const int) +0:19 move second child to first child (temp float) +0:19 'result' (noContraction temp float) +0:19 Convert int to float (temp float) +0:19 move second child to first child (temp int) +0:19 'a' (noContraction temp int) +0:19 add (noContraction temp int) +0:19 'b' (noContraction temp int) +0:19 Constant: +0:19 4 (const int) +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 int) +0:24 'a' (noContraction temp int) +0:24 Constant: +0:24 10 (const int) +0:25 Sequence +0:25 move second child to first child (temp int) +0:25 'b' (noContraction temp int) +0:25 Constant: +0:25 20 (const int) +0:26 move second child to first child (temp int) +0:26 'b' (noContraction temp int) +0:26 add (noContraction temp int) +0:26 'a' (noContraction temp int) +0:26 'b' (noContraction temp int) +0:27 move second child to first child (temp float) +0:27 'result' (noContraction temp float) +0:27 Convert int to float (temp float) +0:27 'b' (noContraction temp int) +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:46 Sequence +0:46 Sequence +0:46 move second child to first child (temp int) +0:46 'result' (noContraction temp int) +0:46 Constant: +0:46 5 (const int) +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 int) +0:52 'result' (noContraction temp int) +0:52 add (noContraction temp int) +0:52 'x' (noContraction temp int) +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 int) +0:56 'result' (noContraction temp int) +0:56 add (noContraction temp int) +0:56 indirect index (noContraction temp int) +0:56 'a0' (temp 3-element array of int) +0:56 'i' (temp int) +0:56 Constant: +0:56 2 (const int) +0:58 move second child to first child (temp int) +0:58 indirect index (noContraction temp int) +0:58 'a0' (noContraction temp 3-element array of int) +0:58 'i' (temp int) +0:58 subtract (noContraction temp int) +0:58 Constant: +0:58 3 (const int) +0:58 Post-Increment (noContraction temp int) +0:58 'result' (noContraction temp int) +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 (noContraction temp int) +0:69 add (noContraction 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' (out float) +0:97 Sequence +0:97 Sequence +0:97 move second child to first child (temp float) +0:97 'a' (temp float) +0:97 Constant: +0:97 0.500000 +0:98 move second child to first child (temp float) +0:98 'c' (out float) +0:98 add (temp float) +0:98 'a' (temp float) +0:98 'b' (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: main( (global void) +0:102 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..7d783e55 --- /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 (noContraction temp int) +0:63 component-wise multiply (noContraction 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 (noContraction temp int) +0:63 component-wise multiply (noContraction 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..71a71e48 --- /dev/null +++ b/Test/precise.tesc @@ -0,0 +1,102 @@ +#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; + int a = 10; + int b = 20; + result = a = b + 4; // b + 4 should be 'noContraction'. +} + +void convert() { + precise float result; + int a = 10; + int b = 20; + b = a + b; // a + b should be 'noContraction'. + result = float(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 int result = 5; + + int x = 22; + int y = 33; + + int a0[3]; + result += x + 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 be 'noCtraction' and also a + rvalue. + 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 +} + +void main(){} diff --git a/Test/precise_struct_block.vert b/Test/precise_struct_block.vert new file mode 100644 index 00000000..a050ccd0 --- /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; // NoContraction + } + 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 d60fbca4..ecb99d1a 100644 --- a/Test/testlist +++ b/Test/testlist @@ -129,3 +129,5 @@ voidFunction.frag whileLoop.frag nonVulkan.frag 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..044ecbf3 --- /dev/null +++ b/glslang/MachineIndependent/propagateNoContraction.cpp @@ -0,0 +1,886 @@ +// +// 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 we the +// accesschain is short and may contain only one element, which is the symbol ID. +using ObjectAccessChain = std::string; +#ifndef StructAccessChainDelimiter +#define StructAccessChainDelimiter '/' +#endif + +// 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; +} + +// Return 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::EOpDot: + + case glslang::EOpAddCarry: + case glslang::EOpSubBorrow: + case glslang::EOpUMulExtended: + case glslang::EOpIMulExtended: + + 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(StructAccessChainDelimiter); + 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(StructAccessChainDelimiter); + return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1); +} + +// +// 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 visitAggregate(glslang::TVisit, glslang::TIntermAggregate *) override; + 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 object_to_be_defined_; + // 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), object_to_be_defined_(), + accesschain_mapping_(*accesschain_mapping), current_function_definition_node_(nullptr), + precise_return_nodes_(*precise_return_nodes) {} + +// Visits a symbol node, set the object_to_be_defined_ to the +// current node symbol ID, and record a mapping from this node to the current +// object_to_be_defined_, which is the just obtained symbol +// ID. +void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol *node) +{ + object_to_be_defined_ = generateSymbolLabel(node); + accesschain_mapping_[node] = object_to_be_defined_; +} + +// 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) { + object_to_be_defined_.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) +{ + object_to_be_defined_.clear(); + node->getOperand()->traverse(this); + if (isAssignOperation(node->getOp())) { + // We should always be able to get an accesschain of the operand node. + // But we have some tests in which it is intented to have invalid operand + // nodes, so just return for now. + if (object_to_be_defined_.empty()) return false; + + // 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(object_to_be_defined_); + } + // Gets the symbol ID from the object's accesschain. + ObjectAccessChain id_symbol = getFrontElement(object_to_be_defined_); + // 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. + object_to_be_defined_.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. + object_to_be_defined_.clear(); + node->getLeft()->traverse(this); + + if (isAssignOperation(node->getOp())) { + // We should always be able to get an accesschain for the left node. + // But we have some tests in which it is intented to have invalid left + // nodes, so just return false in such cases for now. + if (object_to_be_defined_.empty()) return false; + + // 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(object_to_be_defined_); + } + // Gets the symbol ID from the object accesschain, which should be the + // first element recorded in the accesschain. + ObjectAccessChain id_symbol = getFrontElement(object_to_be_defined_); + // 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. + object_to_be_defined_.clear(); + node->getRight()->traverse(this); + + return false; + } else if (isDereferenceOperation(node->getOp())) { + // If the left node is 'precise' object node, this node should also + // be 'precise' object node, and all the members of this node too. There + // is no need to append accesschain information into the object id. + if (isPreciseObjectNode(node->getLeft())) { + node->getWritableType().getQualifier().noContraction = true; + accesschain_mapping_[node] = object_to_be_defined_; + return false; + } + + // If the opcode is not EOpIndexDirectStruct, the left node is not be a + // struct type object, hence there is no need to append dereference + // indices. For other composite type objects, the precise'ness of + // members should always matches with the 'precise'ness of the + // composite type object. + if (node->getOp() != glslang::EOpIndexDirectStruct) { + accesschain_mapping_[node] = object_to_be_defined_; + return false; + } + + // The left node (parent node) is not 'precise' and it is a struct type + // object. We need to record the accesschain information of the current + // node into its object id. + unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight()); + object_to_be_defined_.push_back(StructAccessChainDelimiter); + object_to_be_defined_.append(std::to_string(struct_dereference_index)); + accesschain_mapping_[node] = object_to_be_defined_; + + // For dereference node, there is no need to traverse the right child + // node as the right node should always be an integer type object. + return false; + } else { + // For other binary nodes, still traverse the right node. + object_to_be_defined_.clear(); + node->getRight()->traverse(this); + return false; + } +} + +// Traverses the AST and returns a tuple of three 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. +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() + : TIntermTraverser(true, false, false), accesschain_to_precise_object_(), decision_(Mixed) {} + + // 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())); + accesschain_to_precise_object_ = precise_object; + decision_ = Mixed; + node->traverse(this); + return make_tuple(decision_ != NotPreicse, accesschain_to_precise_object_); + } + +protected: + bool visitBinary(glslang::TVisit, glslang::TIntermBinary *node) override; + bool visitUnary(glslang::TVisit, glslang::TIntermUnary *node) override; + void visitSymbol(glslang::TIntermSymbol *node) override; + + // The accesschain toward the given precise object. It will be iniailized + // with the accesschain of a given precise object, then trimmed along the + // traversal of the assignee subtree. The remained accesschain at the end + // of traversal shows the path from the assignee node to its nested + // 'precise' object. If the assignee node is 'precise' object object, this + // should be empty. + ObjectAccessChain accesschain_to_precise_object_; + // A state to tell the precise'ness of the assignee node according to the + // accesschain of the given precise object: + // + // 'Mixed': contains both 'precise' and 'non-precise' object + // (accesschain_to_precise_object_ is not empty), + // + // 'Precise': is precise object (accesschain_to_precise_object is empty), + // + // 'NotPrecise': is not precise object (mismatch in the struct dereference + // indices). + DecisionStatus decision_; +}; + +// Visit a binary node. As this traverser's job is to check the precise'ness of +// the assignee node in an assignment operation, it only needs to traverse the +// object nodes along the left branches. For struct type object nodes, it needs +// to obtain the struct dereference index from the right node to build the +// accesschain for this node. +bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit, + glslang::TIntermBinary *node) +{ + node->getLeft()->traverse(this); + // For dereference operation nodes, we may need to check if the accesschain + // of the given precise object matches with the struct dereference indices + // of the assignee subtree. + if (isDereferenceOperation(node->getOp())) { + if (isPreciseObjectNode(node->getLeft())) { + // The left node is 'precise', which means the object node in the + // left contains the object represented in this node. If the left node + // is 'precise', this object node should also be 'precise' and no need + // to check the accesschain and struct deference indices anymore. + node->getWritableType().getQualifier().noContraction = true; + decision_ = Precise; + return false; + } + if (node->getOp() == glslang::EOpIndexDirectStruct && decision_ == Mixed) { + std::string struct_index = + std::to_string(getStructIndexFromConstantUnion(node->getRight())); + ObjectAccessChain precise_struct_index = getFrontElement(accesschain_to_precise_object_); + if (precise_struct_index == struct_index) { + // The struct dereference index matches with the record in the + // accesschain to the precise object. Pop the front access + // chain index from the precise object access chain. + accesschain_to_precise_object_ = + subAccessChainFromSecondElement(accesschain_to_precise_object_); + // If the given access chain to precise object is empty now, + // it means we've found the corresponding precise object in + // the assignee subtree. + if (accesschain_to_precise_object_.empty()) { + node->getWritableType().getQualifier().noContraction = true; + decision_ = Precise; + } + } else { + // The access chain index does not match with the record in the precise object id. + // This object should not be labelled as 'precise' here. + decision_ = NotPreicse; + } + } + } + return false; +} + +// Visits an unary node, traverses its operand. If the node is an assignment node, +// determines the precise'ness of the assignee directly based on the assignee node's +// precise'ness. +bool TNoContractionAssigneeCheckingTraverser::visitUnary(glslang::TVisit, + glslang::TIntermUnary *node) +{ + node->getOperand()->traverse(this); + if (isAssignOperation(node->getOp())) { + if (isPreciseObjectNode(node->getOperand())) { + decision_ = Precise; + // As the assignee node is 'precise', all (if any) the + // member objects the that node should also be 'precise'. This means + // we won't need to propagate extra access chain info. + accesschain_to_precise_object_.clear(); + } else { + decision_ = NotPreicse; + } + } + return false; +} + +// Visits a symbol node. The symbol ID of this node should match with the symbol ID, which is +// the front element, in the accesschain of the given 'precise' object. +void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol *node) +{ + ObjectAccessChain symbol_id = generateSymbolLabel(node); + // The root symbol of the given access chain should be the same with the one represented by the symbol node here. + assert(symbol_id == getFrontElement(accesschain_to_precise_object_)); + // Pop the symbol node part from the front end of the accesschain string. + accesschain_to_precise_object_ = + subAccessChainFromSecondElement(accesschain_to_precise_object_); + if (accesschain_to_precise_object_.empty()) { + node->getWritableType().getQualifier().noContraction = true; + decision_ = Precise; + } + // If this symbol node is 'precise', all its members should be 'precise' so the assignee of the processing + // assignment operations is 'precise'. + if (isPreciseObjectNode(node)) { + decision_ = Precise; + } +} + +// +// 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: + // Visit 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); + } + + } else { + // If this is not a struct constructor, just visit each nested node. + glslang::TIntermSequence &seq = node->getSequence(); + for (int i = 0; i < (int)seq.size(); ++i) { + seq[i]->traverse(this); + } + } + + return false; + } + + // Visit 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 += + StructAccessChainDelimiter + 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->getWritableType().getQualifier().noContraction = true; + } + // As this node is not an object node, need to traverse the children nodes. + node->getLeft()->traverse(this); + node->getRight()->traverse(this); + return false; + } + + // 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; + } + node->getOperand()->traverse(this); + return false; + } + + // 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 += StructAccessChainDelimiter + 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_; +}; + +#undef StructAccessChainDelimiter +} + +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'). + 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; + TNoContractionPropagator propagator(&precise_object_accesschains, + accesschain_mapping); + + // We have to initial precise worklist 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); + // Visit 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); +};