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 shader interpolation qualifiers
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 constexpr int kPixelColorThreshhold = 8;
16
17 class ShaderInterpTest : public ANGLETest
18 {
19 protected:
ShaderInterpTest()20 ShaderInterpTest() : ANGLETest()
21 {
22 setWindowWidth(128);
23 setWindowHeight(128);
24 }
25
draw(GLuint program,float skew)26 void draw(GLuint program, float skew)
27 {
28 glUseProgram(program);
29
30 std::array<Vector4, 3> vertices;
31 vertices[0] = {-1.0, -1.0, 0.0, 1.0};
32 vertices[1] = {1.0, -1.0, 0.0, 1.0};
33 vertices[2] = {0.0, 1.0 * skew, 0.0, skew};
34
35 std::array<Vector4, 3> colors;
36 colors[0] = {1.0, 0.0, 0.0, 1.0};
37 colors[1] = {0.0, 1.0, 0.0, 1.0};
38 colors[2] = {0.0, 0.0, 1.0, 1.0};
39
40 GLint positionLocation = glGetAttribLocation(program, "position");
41 GLint colorLocation = glGetAttribLocation(program, "vertex_color");
42
43 glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.data());
44 glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, colors.data());
45
46 glEnableVertexAttribArray(positionLocation);
47 glEnableVertexAttribArray(colorLocation);
48
49 glDrawArrays(GL_TRIANGLES, 0, 3);
50 }
51 };
52
53 // Test that regular "smooth" interpolation works correctly
TEST_P(ShaderInterpTest,Smooth)54 TEST_P(ShaderInterpTest, Smooth)
55 {
56 const char *vertSrc = R"(#version 300 es
57 precision highp float;
58 in vec4 position;
59 in vec4 vertex_color;
60 smooth out vec4 interp_color;
61
62 void main()
63 {
64 gl_Position = position;
65 interp_color = vertex_color;
66 }
67 )";
68 const char *fragSrc = R"(#version 300 es
69 precision highp float;
70 smooth in vec4 interp_color;
71 out vec4 fragColor;
72
73 void main()
74 {
75 fragColor = interp_color;
76 }
77 )";
78
79 // iOS chokes on the "smooth" qualifier.
80 // TODO(anglebug.com/5491): Add shader compiler workaround that omits "smooth".
81 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
82
83 ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
84 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
85
86 glClear(GL_COLOR_BUFFER_BIT);
87 draw(program, 1.0);
88 EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(62, 64, 128, 255), kPixelColorThreshhold);
89
90 glClear(GL_COLOR_BUFFER_BIT);
91 draw(program, 2.0);
92 EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(83, 86, 86, 255), kPixelColorThreshhold);
93 }
94
95 // Test that uninterpolated "Flat" interpolation works correctly
TEST_P(ShaderInterpTest,Flat)96 TEST_P(ShaderInterpTest, Flat)
97 {
98 // TODO: anglebug.com/4085
99 // No vendors currently support VK_EXT_provoking_vertex, which is necessary for conformant flat
100 // shading. SwiftShader does technically support this extension, but as it has not yet been
101 // ratified by Khronos, the vulkan validation layers do not recognize the create info struct,
102 // causing it to be stripped and thus causing the extension to behave as if it is disabled.
103 ANGLE_SKIP_TEST_IF(IsVulkan());
104
105 const char *vertSrc = R"(#version 300 es
106 precision highp float;
107 in vec4 position;
108 in vec4 vertex_color;
109 flat out vec4 interp_color;
110
111 void main()
112 {
113 gl_Position = position;
114 interp_color = vertex_color;
115 }
116 )";
117 const char *fragSrc = R"(#version 300 es
118 precision highp float;
119 flat in vec4 interp_color;
120 out vec4 fragColor;
121
122 void main()
123 {
124 fragColor = interp_color;
125 }
126 )";
127
128 ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
129 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
130
131 glClear(GL_COLOR_BUFFER_BIT);
132 draw(program, 1.0);
133 GLColor smooth_reference;
134 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
135 EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor(0, 0, 255, 255));
136 }
137
138 // Test that "noperspective" interpolation correctly interpolates in screenspace
TEST_P(ShaderInterpTest,NoPerspective)139 TEST_P(ShaderInterpTest, NoPerspective)
140 {
141 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
142
143 const char *vertSrcSmooth = R"(#version 300 es
144 precision highp float;
145 in vec4 position;
146 in vec4 vertex_color;
147 smooth out vec4 interp_color;
148
149 void main()
150 {
151 gl_Position = position;
152 interp_color = vertex_color;
153 }
154 )";
155 const char *fragSrcSmooth = R"(#version 300 es
156 precision highp float;
157 smooth in vec4 interp_color;
158 out vec4 fragColor;
159
160 void main()
161 {
162 fragColor = interp_color;
163 }
164 )";
165 ANGLE_GL_PROGRAM(programSmooth, vertSrcSmooth, fragSrcSmooth);
166 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
167 glClear(GL_COLOR_BUFFER_BIT);
168 draw(programSmooth, 1.0);
169 GLColor smooth_reference;
170 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
171
172 const char *vertSrcNoPerspective = R"(#version 300 es
173 #extension GL_NV_shader_noperspective_interpolation : require
174
175 #ifndef GL_NV_shader_noperspective_interpolation
176 #error GL_NV_shader_noperspective_interpolation is not defined
177 #endif
178
179 precision highp float;
180 in vec4 position;
181 in vec4 vertex_color;
182 noperspective out vec4 interp_color;
183
184 void main()
185 {
186 gl_Position = position;
187 interp_color = vertex_color;
188 }
189 )";
190 const char *fragSrcNoPerspective = R"(#version 300 es
191 #extension GL_NV_shader_noperspective_interpolation : require
192
193 #ifndef GL_NV_shader_noperspective_interpolation
194 #error GL_NV_shader_noperspective_interpolation is not defined
195 #endif
196
197 precision highp float;
198 noperspective in vec4 interp_color;
199 out vec4 fragColor;
200
201 void main()
202 {
203 fragColor = interp_color;
204 }
205 )";
206 ANGLE_GL_PROGRAM(programNoPerspective, vertSrcNoPerspective, fragSrcNoPerspective);
207 glClear(GL_COLOR_BUFFER_BIT);
208 draw(programNoPerspective, 1.0);
209 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
210
211 glClear(GL_COLOR_BUFFER_BIT);
212 draw(programNoPerspective, 2.0);
213 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
214 }
215
216 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderInterpTest);
217 ANGLE_INSTANTIATE_TEST_ES3(ShaderInterpTest);