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