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