xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ShaderMultisampleInterpolation.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2023 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 // Test state requests and compilation of tokens added by OES_shader_multisample_interpolation
7 
8 #include "common/mathutil.h"
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 
12 using namespace angle;
13 
14 namespace
15 {
16 
17 class SampleMultisampleInterpolationTest : public ANGLETest<>
18 {
19   protected:
SampleMultisampleInterpolationTest()20     SampleMultisampleInterpolationTest()
21     {
22         setConfigRedBits(8);
23         setConfigGreenBits(8);
24         setConfigBlueBits(8);
25         setConfigAlphaBits(8);
26         setExtensionsEnabled(false);
27     }
28 };
29 
30 // Test state queries
TEST_P(SampleMultisampleInterpolationTest,StateQueries)31 TEST_P(SampleMultisampleInterpolationTest, StateQueries)
32 {
33     // New state queries fail without the extension
34     {
35         GLint bits = 0;
36         glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits);
37         EXPECT_GL_ERROR(GL_INVALID_ENUM);
38         EXPECT_EQ(bits, 0);
39 
40         GLfloat minOffset = 0.0f;
41         glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset);
42         EXPECT_GL_ERROR(GL_INVALID_ENUM);
43         EXPECT_EQ(minOffset, 0.0f);
44 
45         GLfloat maxOffset = 0.0f;
46         glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset);
47         EXPECT_GL_ERROR(GL_INVALID_ENUM);
48         EXPECT_EQ(maxOffset, 0.0f);
49 
50         ASSERT_GL_NO_ERROR();
51     }
52 
53     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
54 
55     // Implementation-dependent values
56     {
57         GLint bits = 0;
58         glGetIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES, &bits);
59         EXPECT_GE(bits, 4);
60 
61         GLfloat minOffset = 0.0f;
62         glGetFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES, &minOffset);
63         EXPECT_LE(minOffset, -0.5f + std::pow(2, -bits));
64 
65         GLfloat maxOffset = 0.0f;
66         glGetFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES, &maxOffset);
67         EXPECT_GE(maxOffset, 0.5f - std::pow(2, -bits));
68 
69         ASSERT_GL_NO_ERROR();
70     }
71 }
72 
73 // Test gl_SampleMaskIn values with per-sample shading
TEST_P(SampleMultisampleInterpolationTest,SampleMaskInPerSample)74 TEST_P(SampleMultisampleInterpolationTest, SampleMaskInPerSample)
75 {
76     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables"));
77     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
78 
79     const char kVS[] = R"(#version 300 es
80 #extension GL_OES_shader_multisample_interpolation : require
81 
82 in vec4 a_position;
83 sample out float interpolant;
84 
85 void main()
86 {
87     gl_Position = a_position;
88     interpolant = 0.5;
89 })";
90 
91     const char kFS[] = R"(#version 300 es
92 #extension GL_OES_sample_variables : require
93 #extension GL_OES_shader_multisample_interpolation : require
94 
95 precision highp float;
96 sample in float interpolant;
97 out vec4 color;
98 
99 bool isPow2(int v)
100 {
101     return v != 0 && (v & (v - 1)) == 0;
102 }
103 
104 void main()
105 {
106     float r = float(isPow2(gl_SampleMaskIn[0]));
107     color = vec4(r, interpolant, 0, 1);
108 })";
109 
110     ANGLE_GL_PROGRAM(program, kVS, kFS);
111     glUseProgram(program);
112 
113     for (GLint sampleCount : {0, 4})
114     {
115         GLFramebuffer fbo;
116         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
117 
118         GLRenderbuffer rbo;
119         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
120         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA8, 1, 1);
121         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
122         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
123 
124         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
125         drawQuad(program, "a_position", 0.0);
126         ASSERT_GL_NO_ERROR();
127 
128         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
129         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
130         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
131 
132         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
133         GLubyte pixel[4];
134         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
135         ASSERT_GL_NO_ERROR();
136 
137         EXPECT_EQ(pixel[0], 255) << "Samples: " << sampleCount;
138     }
139 }
140 
141 // Test gl_SampleMaskIn values with per-sample noperspective shading
TEST_P(SampleMultisampleInterpolationTest,SampleMaskInPerSampleNoPerspective)142 TEST_P(SampleMultisampleInterpolationTest, SampleMaskInPerSampleNoPerspective)
143 {
144     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_sample_variables"));
145     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
146     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
147 
148     const char kVS[] = R"(#version 300 es
149 #extension GL_OES_shader_multisample_interpolation : require
150 #extension GL_NV_shader_noperspective_interpolation : require
151 
152 in vec4 a_position;
153 noperspective sample out float interpolant;
154 
155 void main()
156 {
157     gl_Position = a_position;
158     interpolant = 0.5;
159 })";
160 
161     const char kFS[] = R"(#version 300 es
162 #extension GL_OES_sample_variables : require
163 #extension GL_OES_shader_multisample_interpolation : require
164 #extension GL_NV_shader_noperspective_interpolation : require
165 
166 precision highp float;
167 noperspective sample in float interpolant;
168 out vec4 color;
169 
170 bool isPow2(int v)
171 {
172     return v != 0 && (v & (v - 1)) == 0;
173 }
174 
175 void main()
176 {
177     float r = float(isPow2(gl_SampleMaskIn[0]));
178     color = vec4(r, interpolant, 0, 1);
179 })";
180 
181     ANGLE_GL_PROGRAM(program, kVS, kFS);
182     glUseProgram(program);
183 
184     for (GLint sampleCount : {0, 4})
185     {
186         GLFramebuffer fbo;
187         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
188 
189         GLRenderbuffer rbo;
190         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
191         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA8, 1, 1);
192         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
193         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
194 
195         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
196         drawQuad(program, "a_position", 0.0);
197         ASSERT_GL_NO_ERROR();
198 
199         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
200         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
201         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
202 
203         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
204         GLubyte pixel[4];
205         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
206         ASSERT_GL_NO_ERROR();
207 
208         EXPECT_EQ(pixel[0], 255) << "Samples: " << sampleCount;
209     }
210 }
211 
212 // Test that a shader with interpolateAt* calls and directly used interpolants compiles
213 // successfully.
TEST_P(SampleMultisampleInterpolationTest,CompileInterpolateAt)214 TEST_P(SampleMultisampleInterpolationTest, CompileInterpolateAt)
215 {
216     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
217 
218     EnsureGLExtensionEnabled("GL_NV_shader_noperspective_interpolation");
219 
220     constexpr char kVS[] = R"(#version 300 es
221 #extension GL_OES_shader_multisample_interpolation : require
222 #extension GL_NV_shader_noperspective_interpolation : enable
223 
224 precision highp float;
225 
226 out float interpolant;
227 out float interpolantArray[2];
228 
229 centroid out float interpolantCentroid;
230 centroid out float interpolantCentroidArray[2];
231 
232 sample out float interpolantSample;
233 sample out float interpolantSampleArray[2];
234 
235 smooth out float interpolantSmooth;
236 smooth out float interpolantSmoothArray[2];
237 
238 flat out float interpolantFlat;
239 flat out float interpolantFlatArray[2];
240 
241 #ifdef GL_NV_shader_noperspective_interpolation
242 noperspective out float interpolantNp;
243 noperspective out float interpolantNpArray[2];
244 
245 noperspective centroid out float interpolantNpCentroid;
246 noperspective centroid out float interpolantNpCentroidArray[2];
247 
248 noperspective sample out float interpolantNpSample;
249 noperspective sample out float interpolantNpSampleArray[2];
250 #endif
251 
252 void main()
253 {
254     gl_Position = vec4(0, 0, 0, 1);
255 
256     interpolant = 1.0;
257     interpolantArray[1] = 2.0;
258 
259     interpolantCentroid = 3.0;
260     interpolantCentroidArray[1] = 4.0;
261 
262     interpolantSample = 5.0;
263     interpolantSampleArray[1] = 6.0;
264 
265     interpolantSmooth = 7.0;
266     interpolantSmoothArray[1] = 8.0;
267 
268     interpolantFlat = 9.0;
269     interpolantFlatArray[1] = 10.0;
270 
271 #ifdef GL_NV_shader_noperspective_interpolation
272     interpolantNp = 11.0;
273     interpolantNpArray[1] = 12.0;
274 
275     interpolantNpCentroid = 13.0;
276     interpolantNpCentroidArray[1] = 14.0;
277 
278     interpolantNpSample = 15.0;
279     interpolantNpSampleArray[1] = 16.0;
280 #endif
281 })";
282 
283     constexpr char kFS[] = R"(#version 300 es
284 #extension GL_OES_shader_multisample_interpolation : require
285 #extension GL_NV_shader_noperspective_interpolation : enable
286 
287 precision highp float;
288 
289 in float interpolant;
290 in float interpolantArray[2];
291 
292 centroid in float interpolantCentroid;
293 centroid in float interpolantCentroidArray[2];
294 
295 sample in float interpolantSample;
296 sample in float interpolantSampleArray[2];
297 
298 smooth in float interpolantSmooth;
299 smooth in float interpolantSmoothArray[2];
300 
301 flat in float interpolantFlat;
302 flat in float interpolantFlatArray[2];
303 
304 #ifdef GL_NV_shader_noperspective_interpolation
305 noperspective in float interpolantNp;
306 noperspective in float interpolantNpArray[2];
307 
308 noperspective centroid in float interpolantNpCentroid;
309 noperspective centroid in float interpolantNpCentroidArray[2];
310 
311 noperspective sample in float interpolantNpSample;
312 noperspective sample in float interpolantNpSampleArray[2];
313 #endif
314 
315 out vec4 color;
316 
317 void main()
318 {
319     float r;
320 
321     r += interpolateAtCentroid(interpolant);
322     r += interpolateAtSample(interpolant, int(interpolant));
323     r += interpolateAtOffset(interpolant, vec2(interpolant));
324 
325     r += interpolateAtCentroid(interpolantArray[1]);
326     r += interpolateAtSample(interpolantArray[1], int(interpolantArray[0]));
327     r += interpolateAtOffset(interpolantArray[1], vec2(interpolantArray[0]));
328 
329     r += interpolateAtCentroid(interpolantCentroid);
330     r += interpolateAtSample(interpolantCentroid, int(interpolantCentroid));
331     r += interpolateAtOffset(interpolantCentroid, vec2(interpolantCentroid));
332 
333     r += interpolateAtCentroid(interpolantCentroidArray[1]);
334     r += interpolateAtSample(interpolantCentroidArray[1], int(interpolantCentroidArray[0]));
335     r += interpolateAtOffset(interpolantCentroidArray[1], vec2(interpolantCentroidArray[0]));
336 
337     r += interpolateAtCentroid(interpolantSample);
338     r += interpolateAtSample(interpolantSample, int(interpolantSample));
339     r += interpolateAtOffset(interpolantSample, vec2(interpolantSample));
340 
341     r += interpolateAtCentroid(interpolantSampleArray[1]);
342     r += interpolateAtSample(interpolantSampleArray[1], int(interpolantSampleArray[0]));
343     r += interpolateAtOffset(interpolantSampleArray[1], vec2(interpolantSampleArray[0]));
344 
345     r += interpolateAtCentroid(interpolantSmooth);
346     r += interpolateAtSample(interpolantSmooth, int(interpolantSmooth));
347     r += interpolateAtOffset(interpolantSmooth, vec2(interpolantSmooth));
348 
349     r += interpolateAtCentroid(interpolantSmoothArray[1]);
350     r += interpolateAtSample(interpolantSmoothArray[1], int(interpolantSmoothArray[0]));
351     r += interpolateAtOffset(interpolantSmoothArray[1], vec2(interpolantSmoothArray[0]));
352 
353     r += interpolateAtCentroid(interpolantFlat);
354     r += interpolateAtSample(interpolantFlat, int(interpolantFlat));
355     r += interpolateAtOffset(interpolantFlat, vec2(interpolantFlat));
356 
357     r += interpolateAtCentroid(interpolantFlatArray[1]);
358     r += interpolateAtSample(interpolantFlatArray[1], int(interpolantFlatArray[0]));
359     r += interpolateAtOffset(interpolantFlatArray[1], vec2(interpolantFlatArray[0]));
360 
361 #ifdef GL_NV_shader_noperspective_interpolation
362     r += interpolateAtCentroid(interpolantNp);
363     r += interpolateAtSample(interpolantNp, int(interpolantNp));
364     r += interpolateAtOffset(interpolantNp, vec2(interpolantNp));
365 
366     r += interpolateAtCentroid(interpolantNpArray[1]);
367     r += interpolateAtSample(interpolantNpArray[1], int(interpolantNpArray[0]));
368     r += interpolateAtOffset(interpolantNpArray[1], vec2(interpolantNpArray[0]));
369 
370     r += interpolateAtCentroid(interpolantNpCentroid);
371     r += interpolateAtSample(interpolantNpCentroid, int(interpolantNpCentroid));
372     r += interpolateAtOffset(interpolantNpCentroid, vec2(interpolantNpCentroid));
373 
374     r += interpolateAtCentroid(interpolantNpCentroidArray[1]);
375     r += interpolateAtSample(interpolantNpCentroidArray[1], int(interpolantNpCentroidArray[0]));
376     r += interpolateAtOffset(interpolantNpCentroidArray[1], vec2(interpolantNpCentroidArray[0]));
377 
378     r += interpolateAtCentroid(interpolantNpSample);
379     r += interpolateAtSample(interpolantNpSample, int(interpolantNpSample));
380     r += interpolateAtOffset(interpolantNpSample, vec2(interpolantNpSample));
381 
382     r += interpolateAtCentroid(interpolantNpSampleArray[1]);
383     r += interpolateAtSample(interpolantNpSampleArray[1], int(interpolantNpSampleArray[0]));
384     r += interpolateAtOffset(interpolantNpSampleArray[1], vec2(interpolantNpSampleArray[0]));
385 #endif
386 
387     color = vec4(r);
388 })";
389 
390     ANGLE_GL_PROGRAM(program, kVS, kFS);
391 }
392 
393 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleMultisampleInterpolationTest);
394 ANGLE_INSTANTIATE_TEST_ES3(SampleMultisampleInterpolationTest);
395 
396 }  // anonymous namespace
397