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 // http://anglebug.com/5232. Metal doesn't support last provoking vertex yet.
106 ANGLE_SKIP_TEST_IF(IsMetal());
107
108 const char *vertSrc = R"(#version 300 es
109 precision highp float;
110 in vec4 position;
111 in vec4 vertex_color;
112 flat out vec4 interp_color;
113
114 void main()
115 {
116 gl_Position = position;
117 interp_color = vertex_color;
118 }
119 )";
120 const char *fragSrc = R"(#version 300 es
121 precision highp float;
122 flat in vec4 interp_color;
123 out vec4 fragColor;
124
125 void main()
126 {
127 fragColor = interp_color;
128 }
129 )";
130
131 ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
132 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
133
134 glClear(GL_COLOR_BUFFER_BIT);
135 draw(program, 1.0);
136 GLColor smooth_reference;
137 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
138 EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor(0, 0, 255, 255));
139 }
140
141 // Test that "noperspective" interpolation correctly interpolates in screenspace
TEST_P(ShaderInterpTest,NoPerspective)142 TEST_P(ShaderInterpTest, NoPerspective)
143 {
144 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
145
146 const char *vertSrcSmooth = R"(#version 300 es
147 precision highp float;
148 in vec4 position;
149 in vec4 vertex_color;
150 smooth out vec4 interp_color;
151
152 void main()
153 {
154 gl_Position = position;
155 interp_color = vertex_color;
156 }
157 )";
158 const char *fragSrcSmooth = R"(#version 300 es
159 precision highp float;
160 smooth in vec4 interp_color;
161 out vec4 fragColor;
162
163 void main()
164 {
165 fragColor = interp_color;
166 }
167 )";
168 ANGLE_GL_PROGRAM(programSmooth, vertSrcSmooth, fragSrcSmooth);
169 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
170 glClear(GL_COLOR_BUFFER_BIT);
171 draw(programSmooth, 1.0);
172 GLColor smooth_reference;
173 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
174
175 const char *vertSrcNoPerspective = R"(#version 300 es
176 #extension GL_NV_shader_noperspective_interpolation : require
177
178 #ifndef GL_NV_shader_noperspective_interpolation
179 #error GL_NV_shader_noperspective_interpolation is not defined
180 #endif
181
182 precision highp float;
183 in vec4 position;
184 in vec4 vertex_color;
185 noperspective out vec4 interp_color;
186
187 void main()
188 {
189 gl_Position = position;
190 interp_color = vertex_color;
191 }
192 )";
193 const char *fragSrcNoPerspective = R"(#version 300 es
194 #extension GL_NV_shader_noperspective_interpolation : require
195
196 #ifndef GL_NV_shader_noperspective_interpolation
197 #error GL_NV_shader_noperspective_interpolation is not defined
198 #endif
199
200 precision highp float;
201 noperspective in vec4 interp_color;
202 out vec4 fragColor;
203
204 void main()
205 {
206 fragColor = interp_color;
207 }
208 )";
209 ANGLE_GL_PROGRAM(programNoPerspective, vertSrcNoPerspective, fragSrcNoPerspective);
210 glClear(GL_COLOR_BUFFER_BIT);
211 draw(programNoPerspective, 1.0);
212 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
213
214 glClear(GL_COLOR_BUFFER_BIT);
215 draw(programNoPerspective, 2.0);
216 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
217 }
218
219 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderInterpTest);
220 ANGLE_INSTANTIATE_TEST_ES3(ShaderInterpTest);