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 ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
80 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
81
82 glClear(GL_COLOR_BUFFER_BIT);
83 draw(program, 1.0);
84 EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(62, 64, 128, 255), kPixelColorThreshhold);
85
86 glClear(GL_COLOR_BUFFER_BIT);
87 draw(program, 2.0);
88 EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(83, 86, 86, 255), kPixelColorThreshhold);
89 }
90
91 // Test that uninterpolated "Flat" interpolation works correctly
TEST_P(ShaderInterpTest,Flat)92 TEST_P(ShaderInterpTest, Flat)
93 {
94 // TODO: anglebug.com/42262721
95 // No vendors currently support VK_EXT_provoking_vertex, which is necessary for conformant flat
96 // shading. SwiftShader does technically support this extension, but as it has not yet been
97 // ratified by Khronos, the vulkan validation layers do not recognize the create info struct,
98 // causing it to be stripped and thus causing the extension to behave as if it is disabled.
99 ANGLE_SKIP_TEST_IF(IsVulkan());
100
101 const char *vertSrc = R"(#version 300 es
102 precision highp float;
103 in vec4 position;
104 in vec4 vertex_color;
105 flat out vec4 interp_color;
106
107 void main()
108 {
109 gl_Position = position;
110 interp_color = vertex_color;
111 }
112 )";
113 const char *fragSrc = R"(#version 300 es
114 precision highp float;
115 flat in vec4 interp_color;
116 out vec4 fragColor;
117
118 void main()
119 {
120 fragColor = interp_color;
121 }
122 )";
123
124 ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
125 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
126
127 glClear(GL_COLOR_BUFFER_BIT);
128 draw(program, 1.0);
129 GLColor smooth_reference;
130 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
131 EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor(0, 0, 255, 255));
132 }
133
134 // Test that "noperspective" interpolation correctly interpolates in screenspace
TEST_P(ShaderInterpTest,NoPerspective)135 TEST_P(ShaderInterpTest, NoPerspective)
136 {
137 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
138
139 const char *vertSrcSmooth = R"(#version 300 es
140 precision highp float;
141 in vec4 position;
142 in vec4 vertex_color;
143 smooth out vec4 interp_color;
144
145 void main()
146 {
147 gl_Position = position;
148 interp_color = vertex_color;
149 }
150 )";
151 const char *fragSrcSmooth = R"(#version 300 es
152 precision highp float;
153 smooth in vec4 interp_color;
154 out vec4 fragColor;
155
156 void main()
157 {
158 fragColor = interp_color;
159 }
160 )";
161 ANGLE_GL_PROGRAM(programSmooth, vertSrcSmooth, fragSrcSmooth);
162 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
163 glClear(GL_COLOR_BUFFER_BIT);
164 draw(programSmooth, 1.0);
165 GLColor smooth_reference;
166 glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
167
168 const char *vertSrcNoPerspective = R"(#version 300 es
169 #extension GL_NV_shader_noperspective_interpolation : require
170
171 #ifndef GL_NV_shader_noperspective_interpolation
172 #error GL_NV_shader_noperspective_interpolation is not defined
173 #endif
174
175 precision highp float;
176 in vec4 position;
177 in vec4 vertex_color;
178 noperspective out vec4 interp_color;
179
180 void main()
181 {
182 gl_Position = position;
183 interp_color = vertex_color;
184 }
185 )";
186 const char *fragSrcNoPerspective = R"(#version 300 es
187 #extension GL_NV_shader_noperspective_interpolation : require
188
189 #ifndef GL_NV_shader_noperspective_interpolation
190 #error GL_NV_shader_noperspective_interpolation is not defined
191 #endif
192
193 precision highp float;
194 noperspective in vec4 interp_color;
195 out vec4 fragColor;
196
197 void main()
198 {
199 fragColor = interp_color;
200 }
201 )";
202 ANGLE_GL_PROGRAM(programNoPerspective, vertSrcNoPerspective, fragSrcNoPerspective);
203 glClear(GL_COLOR_BUFFER_BIT);
204 draw(programNoPerspective, 1.0);
205 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
206
207 glClear(GL_COLOR_BUFFER_BIT);
208 draw(programNoPerspective, 2.0);
209 EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
210 }
211
212 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderInterpTest);
213 ANGLE_INSTANTIATE_TEST_ES3(ShaderInterpTest);