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);