GLES2: sequence operator (,) eval order and side effects
authorKai Ninomiya <kainino@chromium.org>
Sat, 27 Jan 2018 00:02:25 +0000 (16:02 -0800)
committerKai Ninomiya <kainino@chromium.org>
Sat, 27 Jan 2018 02:42:59 +0000 (02:42 +0000)
Ported from:
https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance/glsl/bugs/sequence-operator-evaluation-order.html
Which was added in:
https://github.com/KhronosGroup/WebGL/pull/981
https://github.com/KhronosGroup/WebGL/pull/1932

These tests were known to fail in on Pixel 2016 / Android 7.1.1.

New tests:
  dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_ternary
  dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_and
  dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_or
Components: AOSP

Change-Id: I7bbcaecc08279df6f30b6855cc99b19b402892c7

android/cts/master/gles2-master.txt
modules/gles2/functional/es2fShaderOperatorTests.cpp

index 483dfdd..6264211 100644 (file)
@@ -5777,6 +5777,9 @@ dEQP-GLES2.functional.shaders.operator.sequence.side_effects.highp_bool_vec2_fra
 dEQP-GLES2.functional.shaders.operator.sequence.side_effects.lowp_vec4_ivec4_bvec4_fragment
 dEQP-GLES2.functional.shaders.operator.sequence.side_effects.mediump_vec4_ivec4_bvec4_fragment
 dEQP-GLES2.functional.shaders.operator.sequence.side_effects.highp_vec4_ivec4_bvec4_fragment
+dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_ternary
+dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_and
+dEQP-GLES2.functional.shaders.operator.sequence.side_effects.affect_or
 dEQP-GLES2.functional.shaders.matrix.add.const_lowp_mat2_float_vertex
 dEQP-GLES2.functional.shaders.matrix.add.const_lowp_mat2_float_fragment
 dEQP-GLES2.functional.shaders.matrix.add.const_lowp_mat2_mat2_vertex
index efe933c..46ef98d 100644 (file)
@@ -1523,6 +1523,90 @@ void ShaderOperatorTests::init (void)
                        }
                }
        }
+
+       // Regression tests for sequence operator.
+       // http://khronos.org/registry/webgl/sdk/tests/conformance/glsl/bugs/sequence-operator-evaluation-order.html
+       {
+               class Case : public ShaderRenderCase
+               {
+                       static void evalFunc(ShaderEvalContext& c) {
+                               c.color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); // green
+                       }
+
+               public:
+                       Case(Context& context, const char* name, const char* description, const char* fragShaderSource)
+                               : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, false, &evalFunc)
+                       {
+                               m_vertShaderSource =
+                                       "attribute vec4 a_position;\n"
+                                       "void main()\n"
+                                       "{\n"
+                                       "       gl_Position = a_position;\n"
+                                       "}\n";
+                               m_fragShaderSource = fragShaderSource;
+                       }
+               };
+
+               // ESSL 1.00 section 5.9, about sequence operator:
+               // "All expressions are evaluated, in order, from left to right"
+               // Also use a ternary operator where the third operand has side effects to make sure
+               // only the second operand is evaluated.
+               sequenceSideEffGroup->addChild(new Case(m_context, "affect_ternary",
+                       "Expression where first operand of a sequence operator has side effects which affect the second operand that is a ternary operator", (
+                               "precision mediump float;\n"
+                               "bool correct = true;\n"
+                               "uniform float u_zero;\n"
+                               "float wrong() {\n"
+                               "       correct = false;\n"
+                               "       return 0.0;\n"
+                               "}\n"
+                               "void main() {\n"
+                               "       float a = u_zero - 0.5; // Result should be -0.5.\n"
+                               "       float green = (a++, a > 0.0 ? 1.0 : wrong());\n"
+                               "       gl_FragColor = vec4(0.0, correct ? green : 0.0, 0.0, 1.0);\n"
+                               "}\n"
+                       )));
+
+               sequenceSideEffGroup->addChild(new Case(m_context, "affect_and",
+                       "Expression where first operand of a sequence operator has side effects which affect the second operand that is an and operator", (
+                               "precision mediump float;\n"
+                               "uniform bool u_false;\n"
+                               "bool sideEffectA = false;\n"
+                               "bool funcA() {\n"
+                               "       sideEffectA = true;\n"
+                               "       return true;\n"
+                               "}\n"
+                               "bool sideEffectB = false;\n"
+                               "bool funcB() {\n"
+                               "       sideEffectB = true;\n"
+                               "       return true;\n"
+                               "}\n"
+                               "void main() {\n"
+                               "       bool b = (funcA(), u_false == sideEffectA && funcB());\n"
+                               "       gl_FragColor = (!b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+                               "}\n"
+                       )));
+
+               sequenceSideEffGroup->addChild(new Case(m_context, "affect_or",
+                       "Expression where first operand of a sequence operator has side effects which affect the second operand that is an or operator", (
+                               "precision mediump float;\n"
+                               "uniform bool u_false;\n"
+                               "bool sideEffectA = false;\n"
+                               "bool funcA() {\n"
+                               "       sideEffectA = true;\n"
+                               "       return false;\n"
+                               "}\n"
+                               "bool sideEffectB = false;\n"
+                               "bool funcB() {\n"
+                               "       sideEffectB = true;\n"
+                               "       return false;\n"
+                               "}\n"
+                               "void main() {\n"
+                               "       bool b = (funcA(), (u_false == !sideEffectA) || funcB());\n"
+                               "       gl_FragColor = (b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+                               "}\n"
+                       )));
+       }
 }
 
 } // Functional