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