1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Tests for GL_EXT_shader_non_constant_global_initializers
7 //
8 
9 #include "common/mathutil.h"
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 class ShaderNonConstGlobalInitializerTest : public ANGLETest
16 {
17   protected:
ShaderNonConstGlobalInitializerTest()18     ShaderNonConstGlobalInitializerTest() : ANGLETest()
19     {
20         setWindowWidth(128);
21         setWindowHeight(128);
22     }
23 
draw(GLuint program)24     void draw(GLuint program)
25     {
26         std::array<Vector4, 3> vertices;
27         vertices[0] = {-1.0, -1.0, 0.0, 1.0};
28         vertices[1] = {1.0, -1.0, 0.0, 1.0};
29         vertices[2] = {0.0, 1.0, 0.0, 2.0};
30 
31         GLint positionLocation = glGetAttribLocation(program, "a_position");
32 
33         glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.data());
34 
35         glEnableVertexAttribArray(positionLocation);
36 
37         glDrawArrays(GL_TRIANGLES, 0, 3);
38     }
39 };
40 
41 // Tests that the extension is disabled if not explicitly enabled- non constant initializers should
42 // be forbidden in all cases unless this extension is explicitly requested
TEST_P(ShaderNonConstGlobalInitializerTest,Disabled)43 TEST_P(ShaderNonConstGlobalInitializerTest, Disabled)
44 {
45     const char *fragSrc = R"(#version 100
46 
47 precision lowp float;
48 
49 uniform float nondeterministic_uniform;
50 
51 float nonConstInitializer();
52 
53 float nonConstGlobal = nonConstInitializer();
54 float sideEffectGlobal = 0.0;
55 
56 float nonConstInitializer() {
57     sideEffectGlobal = 1.0;
58     return nondeterministic_uniform;
59 }
60 
61 void main()
62 {
63     gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
64 }
65 )";
66 
67     GLShader badFragment(GL_FRAGMENT_SHADER);
68     glShaderSource(badFragment, 1, &fragSrc, nullptr);
69     glCompileShader(badFragment);
70 
71     GLint compileResult;
72     glGetShaderiv(badFragment, GL_COMPILE_STATUS, &compileResult);
73     EXPECT_EQ(compileResult, 0);
74 
75     EXPECT_GL_NO_ERROR();
76 }
77 
78 // Test that non constant initializers are evaluated correctly in ESSL 100
TEST_P(ShaderNonConstGlobalInitializerTest,v100)79 TEST_P(ShaderNonConstGlobalInitializerTest, v100)
80 {
81     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
82 
83     const char *fragSrc = R"(#version 100
84 #extension GL_EXT_shader_non_constant_global_initializers : require
85 
86 precision lowp float;
87 
88 #ifndef GL_EXT_shader_non_constant_global_initializers
89 #error GL_EXT_shader_non_constant_global_initializers is not defined
90 #endif
91 
92 uniform float nondeterministic_uniform;
93 
94 float nonConstInitializer();
95 
96 float nonConstGlobal = nonConstInitializer();
97 float sideEffectGlobal = 0.0;
98 
99 float nonConstInitializer() {
100     sideEffectGlobal = 1.0;
101     return nondeterministic_uniform;
102 }
103 
104 void main()
105 {
106     gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
107 }
108 )";
109 
110     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragSrc);
111     EXPECT_GL_NO_ERROR();
112 
113     glUseProgram(program);
114     glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
115     ASSERT_GL_NO_ERROR();
116 
117     draw(program);
118     EXPECT_GL_NO_ERROR();
119 
120     EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
121 }
122 
123 // Test that non constant initializers are evaluated correctly in ESSL 300
TEST_P(ShaderNonConstGlobalInitializerTest,v300es)124 TEST_P(ShaderNonConstGlobalInitializerTest, v300es)
125 {
126     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
127 
128     const char *fragSrc = R"(#version 300 es
129 #extension GL_EXT_shader_non_constant_global_initializers : require
130 
131 precision highp float;
132 out vec4 fragColor;
133 
134 #ifndef GL_EXT_shader_non_constant_global_initializers
135 #error GL_EXT_shader_non_constant_global_initializers is not defined
136 #endif
137 
138 uniform float nondeterministic_uniform;
139 
140 float nonConstInitializer();
141 
142 float nonConstGlobal = nonConstInitializer();
143 float sideEffectGlobal = 0.0;
144 
145 float nonConstInitializer() {
146     sideEffectGlobal = 1.0;
147     return nondeterministic_uniform;
148 }
149 
150 void main()
151 {
152     fragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
153 }
154 )";
155 
156     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragSrc);
157     EXPECT_GL_NO_ERROR();
158 
159     glUseProgram(program);
160     glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
161     ASSERT_GL_NO_ERROR();
162 
163     draw(program);
164     EXPECT_GL_NO_ERROR();
165 
166     EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
167 }
168 
169 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderNonConstGlobalInitializerTest);
170 ANGLE_INSTANTIATE_TEST_ES3(ShaderNonConstGlobalInitializerTest);