xref: /aosp_15_r20/external/angle/src/tests/gl_tests/SampleVariablesTest.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 built-in variables added by OES_sample_variables
7 
8 #include <unordered_set>
9 
10 #include "common/mathutil.h"
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 
14 using namespace angle;
15 
16 namespace
17 {
18 
19 class SampleVariablesTest : public ANGLETest<>
20 {
21   protected:
SampleVariablesTest()22     SampleVariablesTest()
23     {
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28     }
29 };
30 
31 // Test gl_MaxSamples == GL_MAX_SAMPLES
TEST_P(SampleVariablesTest,MaxSamples)32 TEST_P(SampleVariablesTest, MaxSamples)
33 {
34     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
35 
36     GLint maxSamples = -1;
37     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
38     ASSERT_GT(maxSamples, 0);
39     ASSERT_LE(maxSamples, 32);
40 
41     const char kFS[] = R"(#version 300 es
42 #extension GL_OES_sample_variables : require
43 precision highp float;
44 out vec4 color;
45 void main()
46 {
47     color = vec4(float(gl_MaxSamples * 4) / 255.0, 0.0, 0.0, 1.0);
48 })";
49 
50     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
51     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
52 
53     EXPECT_PIXEL_NEAR(0, 0, maxSamples * 4, 0, 0, 255, 1.0);
54 }
55 
56 // Test gl_NumSamples == GL_SAMPLES
TEST_P(SampleVariablesTest,NumSamples)57 TEST_P(SampleVariablesTest, NumSamples)
58 {
59     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
60 
61     const char kFS[] = R"(#version 300 es
62 #extension GL_OES_sample_variables : require
63 precision highp float;
64 out vec4 color;
65 void main()
66 {
67     color = vec4(float(gl_NumSamples * 4) / 255.0, 0.0, 0.0, 1.0);
68 })";
69     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
70 
71     GLint numSampleCounts = 0;
72     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
73     ASSERT_GT(numSampleCounts, 0);
74 
75     std::vector<GLint> sampleCounts;
76     sampleCounts.resize(numSampleCounts);
77     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numSampleCounts,
78                           sampleCounts.data());
79 
80     sampleCounts.push_back(0);
81 
82     for (GLint sampleCount : sampleCounts)
83     {
84         GLFramebuffer fbo;
85         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
86 
87         GLRenderbuffer rbo;
88         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
89         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA8, 1, 1);
90         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
91         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
92 
93         GLint samples = -1;
94         glGetIntegerv(GL_SAMPLES, &samples);
95         EXPECT_EQ(samples, sampleCount);
96 
97         drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
98         ASSERT_GL_NO_ERROR();
99 
100         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
101         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
102         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
103 
104         GLubyte pixel[4];
105         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
106         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
107 
108         EXPECT_NEAR(std::max(samples, 1) * 4, pixel[0], 1.0) << "Samples: " << sampleCount;
109     }
110 }
111 
112 // Test gl_SampleID values
TEST_P(SampleVariablesTest,SampleID)113 TEST_P(SampleVariablesTest, SampleID)
114 {
115     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
116     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
117 
118     const char kFS[] = R"(#version 300 es
119 #extension GL_OES_sample_variables : require
120 precision highp float;
121 out vec4 color;
122 uniform int id;
123 void main()
124 {
125     // 1.0 when the selected sample is processed, 0.0 otherwise
126     float r = float(gl_SampleID == id);
127     // Must always be 0.0
128     float g = float(gl_SampleID < 0 || gl_SampleID >= gl_NumSamples);
129 
130     color = vec4(r, g, 0.0, 1.0);
131 })";
132     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
133     glUseProgram(program);
134 
135     GLint numSampleCounts = 0;
136     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
137     ASSERT_GT(numSampleCounts, 0);
138 
139     std::vector<GLint> sampleCounts;
140     sampleCounts.resize(numSampleCounts);
141     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_SAMPLES, numSampleCounts,
142                           sampleCounts.data());
143 
144     sampleCounts.push_back(0);
145 
146     GLFramebuffer fboResolve;
147     glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
148 
149     GLRenderbuffer rboResolve;
150     glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
151     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA16F, 1, 1);
152     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboResolve);
153     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
154 
155     ASSERT_GL_NO_ERROR();
156 
157     for (GLint sampleCount : sampleCounts)
158     {
159         GLFramebuffer fbo;
160         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
161 
162         GLRenderbuffer rbo;
163         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
164         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA16F, 1, 1);
165         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
166         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
167 
168         for (int sample = 0; sample < std::max(sampleCount, 1); sample++)
169         {
170             glUniform1i(glGetUniformLocation(program, "id"), sample);
171 
172             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
173             drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
174             ASSERT_GL_NO_ERROR();
175 
176             glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
177             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
178             glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
179 
180             GLfloat pixel[4];
181             glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
182             glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
183             EXPECT_GL_NO_ERROR();
184 
185             // Only one sample has 1.0 value
186             EXPECT_NEAR(1.0 / std::max(sampleCount, 1), pixel[0], 0.001)
187                 << "Samples: " << sampleCount << ", SampleID: " << sample;
188             EXPECT_EQ(0.0, pixel[1]);
189         }
190     }
191 }
192 
193 // Test gl_SamplePosition values
TEST_P(SampleVariablesTest,SamplePosition)194 TEST_P(SampleVariablesTest, SamplePosition)
195 {
196     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
197     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
198 
199     const char kFS[] = R"(#version 300 es
200 #extension GL_OES_sample_variables : require
201 precision highp float;
202 out vec4 color;
203 uniform int id;
204 void main()
205 {
206     vec2 rg = (gl_SampleID == id) ? gl_SamplePosition : vec2(0.0, 0.0);
207 
208     // Must always be 0.0
209     float b = float(gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0);
210     float a = float(gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0);
211 
212     color = vec4(rg, b, a);
213 })";
214     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
215     glUseProgram(program);
216 
217     GLint numSampleCounts = 0;
218     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
219     ASSERT_GT(numSampleCounts, 0);
220 
221     std::vector<GLint> sampleCounts;
222     sampleCounts.resize(numSampleCounts);
223     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_SAMPLES, numSampleCounts,
224                           sampleCounts.data());
225 
226     sampleCounts.push_back(0);
227 
228     GLFramebuffer fboResolve;
229     glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
230 
231     GLRenderbuffer rboResolve;
232     glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
233     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA16F, 1, 1);
234     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboResolve);
235     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
236 
237     for (GLint sampleCount : sampleCounts)
238     {
239         if (sampleCount > 16)
240         {
241             // Sample positions for MSAAx32 are not defined.
242             continue;
243         }
244         GLFramebuffer fbo;
245         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
246 
247         GLRenderbuffer rbo;
248         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
249         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA16F, 1, 1);
250         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
251         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
252 
253         std::unordered_set<GLfloat> positionX;
254         std::unordered_set<GLfloat> positionY;
255         for (int sample = 0; sample < std::max(sampleCount, 1); sample++)
256         {
257             glUniform1i(glGetUniformLocation(program, "id"), sample);
258 
259             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
260             drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
261             ASSERT_GL_NO_ERROR();
262 
263             glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
264             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
265             glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
266 
267             GLfloat pixel[4];
268             glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
269             glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
270             EXPECT_GL_NO_ERROR();
271 
272             // Check that positions are unique for each sample
273             const int realSampleCount = std::max(sampleCount, 1);
274             EXPECT_TRUE(positionX.insert(pixel[0]).second)
275                 << "Samples: " << realSampleCount << " SampleID: " << sample
276                 << " X: " << (pixel[0] * realSampleCount);
277             EXPECT_TRUE(positionY.insert(pixel[1]).second)
278                 << "Samples: " << realSampleCount << " SampleID: " << sample
279                 << " Y: " << (pixel[1] * realSampleCount);
280 
281             // Check that sample positions are in the normalized range
282             EXPECT_EQ(0, pixel[2]);
283             EXPECT_EQ(0, pixel[3]);
284         }
285     }
286 }
287 
288 // Test gl_SampleMaskIn values
TEST_P(SampleVariablesTest,SampleMaskIn)289 TEST_P(SampleVariablesTest, SampleMaskIn)
290 {
291     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
292 
293     const char kFS[] = R"(#version 300 es
294 #extension GL_OES_sample_variables : require
295 precision highp float;
296 out vec4 color;
297 
298 uint popcount(uint v)
299 {
300     uint c = 0u;
301     for (; v != 0u; v >>= 1) c += v & 1u;
302     return c;
303 }
304 
305 void main()
306 {
307     float r = 0.0;
308     r = float(popcount(uint(gl_SampleMaskIn[0])));
309 
310     color = vec4(r * 4.0 / 255.0, 0, 0, 1);
311 })";
312     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
313     glUseProgram(program);
314 
315     GLint numSampleCounts = 0;
316     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
317     ASSERT_GT(numSampleCounts, 0);
318 
319     std::vector<GLint> sampleCounts;
320     sampleCounts.resize(numSampleCounts);
321     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numSampleCounts,
322                           sampleCounts.data());
323 
324     sampleCounts.push_back(0);
325 
326     auto test = [&](GLint sampleCount, bool sampleCoverageEnabled, GLfloat coverage) {
327         if (sampleCoverageEnabled)
328         {
329             glEnable(GL_SAMPLE_COVERAGE);
330         }
331         else
332         {
333             glDisable(GL_SAMPLE_COVERAGE);
334         }
335 
336         glSampleCoverage(coverage, false);
337 
338         GLFramebuffer fbo;
339         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
340 
341         GLRenderbuffer rbo;
342         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
343         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA8, 1, 1);
344         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
345         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
346 
347         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
348         glClear(GL_COLOR_BUFFER_BIT);
349         drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
350         ASSERT_GL_NO_ERROR();
351 
352         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
353         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
354         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
355 
356         GLubyte pixel[4];
357         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
358         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
359         EXPECT_GL_NO_ERROR();
360 
361         // Shader scales up the number of input samples to increase precision in unorm8 space.
362         int expected = std::max(sampleCount, 1) * 4;
363 
364         // Sample coverage must not affect single sampled buffers
365         if (sampleCoverageEnabled && sampleCount > 0)
366         {
367             // The number of samples in gl_SampleMaskIn must be affected by the sample
368             // coverage GL state and then the resolved value must be scaled down again.
369             expected *= coverage * coverage;
370         }
371         EXPECT_NEAR(expected, pixel[0], 1.0)
372             << "Samples: " << sampleCount
373             << ", Sample Coverage: " << (sampleCoverageEnabled ? "Enabled" : "Disabled")
374             << ", Coverage: " << coverage;
375     };
376 
377     for (GLint sampleCount : sampleCounts)
378     {
379         if (sampleCount > 32)
380         {
381             // The test shader will not work with MSAAx64.
382             continue;
383         }
384 
385         for (bool sampleCoverageEnabled : {false, true})
386         {
387             for (GLfloat coverage : {0.0, 0.5, 1.0})
388             {
389                 if (sampleCount == 1 && coverage != 0.0 && coverage != 1.0)
390                 {
391                     continue;
392                 }
393                 test(sampleCount, sampleCoverageEnabled, coverage);
394             }
395         }
396     }
397 }
398 
399 // Test gl_SampleMaskIn values with per-sample shading
TEST_P(SampleVariablesTest,SampleMaskInPerSample)400 TEST_P(SampleVariablesTest, SampleMaskInPerSample)
401 {
402     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
403 
404     const char kFS[] = R"(#version 300 es
405 #extension GL_OES_sample_variables : require
406 precision highp float;
407 out vec4 color;
408 
409 void main()
410 {
411     float r = float(gl_SampleMaskIn[0] == (1 << gl_SampleID));
412     color = vec4(r, 0, 0, 1);
413 })";
414     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
415     glUseProgram(program);
416 
417     GLint numSampleCounts = 0;
418     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
419     ASSERT_GT(numSampleCounts, 0);
420 
421     std::vector<GLint> sampleCounts;
422     sampleCounts.resize(numSampleCounts);
423     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numSampleCounts,
424                           sampleCounts.data());
425 
426     sampleCounts.push_back(0);
427 
428     for (GLint sampleCount : sampleCounts)
429     {
430         if (sampleCount > 32)
431         {
432             // The test shader will not work with MSAAx64.
433             continue;
434         }
435 
436         GLFramebuffer fbo;
437         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
438 
439         GLRenderbuffer rbo;
440         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
441         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA8, 1, 1);
442         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
443         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
444 
445         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
446         drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
447         ASSERT_GL_NO_ERROR();
448 
449         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
450         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
451         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
452 
453         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
454         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "Samples: " << sampleCount;
455     }
456 }
457 
458 // Test writing gl_SampleMask
TEST_P(SampleVariablesTest,SampleMask)459 TEST_P(SampleVariablesTest, SampleMask)
460 {
461     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
462     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
463 
464     const char kFS[] = R"(#version 300 es
465 #extension GL_OES_sample_variables : require
466 precision highp float;
467 uniform highp int sampleMask;
468 
469 out vec4 color;
470 
471 void main()
472 {
473     gl_SampleMask[0] = sampleMask;
474     color = vec4(1, 0, 0, 1);
475 })";
476     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
477     glUseProgram(program);
478 
479     GLint numSampleCounts = 0;
480     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
481     ASSERT_GT(numSampleCounts, 0);
482 
483     std::vector<GLint> sampleCounts;
484     sampleCounts.resize(numSampleCounts);
485     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA16F, GL_SAMPLES, numSampleCounts,
486                           sampleCounts.data());
487 
488     sampleCounts.push_back(0);
489 
490     GLFramebuffer fboResolve;
491     glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
492 
493     GLRenderbuffer rboResolve;
494     glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
495     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA16F, 1, 1);
496     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboResolve);
497     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
498 
499     auto test = [&](GLint sampleCount, GLint sampleMask, bool sampleCoverageEnabled,
500                     GLfloat coverage) {
501         if (sampleCoverageEnabled)
502         {
503             glEnable(GL_SAMPLE_COVERAGE);
504         }
505         else
506         {
507             glDisable(GL_SAMPLE_COVERAGE);
508         }
509 
510         ASSERT(coverage == 0.0 || coverage == 1.0);
511         glSampleCoverage(coverage, false);
512 
513         GLFramebuffer fbo;
514         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
515 
516         GLRenderbuffer rbo;
517         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
518         glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_RGBA16F, 1, 1);
519         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
520         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
521 
522         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
523         glClear(GL_COLOR_BUFFER_BIT);
524         glUniform1i(glGetUniformLocation(program, "sampleMask"), sampleMask);
525         drawQuad(program, essl3_shaders::PositionAttrib(), 0.0);
526         ASSERT_GL_NO_ERROR();
527 
528         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
529         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
530         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
531 
532         GLfloat pixel[4];
533         glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
534         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
535         EXPECT_GL_NO_ERROR();
536 
537         float expected = 1.0;
538         if (sampleCount > 0)
539         {
540             if (sampleCoverageEnabled && coverage == 0.0)
541             {
542                 expected = 0.0;
543             }
544             else
545             {
546                 uint32_t fullSampleCount = std::max(sampleCount, 1);
547                 uint32_t realSampleMask  = sampleMask & (0xFFFFFFFFu >> (32 - fullSampleCount));
548                 expected = static_cast<float>(gl::BitCount(realSampleMask)) / fullSampleCount;
549             }
550         }
551         EXPECT_EQ(expected, pixel[0])
552             << "Samples: " << sampleCount << ", gl_SampleMask[0]: " << sampleMask
553             << ", Sample Coverage: " << (sampleCoverageEnabled ? "Enabled" : "Disabled")
554             << ", Coverage: " << coverage;
555     };
556 
557     for (GLint sampleCount : sampleCounts)
558     {
559         if (sampleCount > 32)
560         {
561             // The test shader will not work with MSAAx64.
562             continue;
563         }
564 
565         for (bool sampleCoverageEnabled : {false, true})
566         {
567             for (GLfloat coverage : {0.0, 1.0})
568             {
569                 for (GLint sampleMask : {0xFFFFFFFFu, 0x55555555u, 0xAAAAAAAAu, 0x00000000u})
570                 {
571                     test(sampleCount, sampleMask, sampleCoverageEnabled, coverage);
572                 }
573             }
574         }
575     }
576 }
577 
578 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SampleVariablesTest);
579 ANGLE_INSTANTIATE_TEST_ES3(SampleVariablesTest);
580 
581 }  // anonymous namespace
582