1 //
2 // Copyright 2017 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
7 // TextureMultisampleTest: Tests of multisampled texture
8
9 #include "test_utils/ANGLETest.h"
10
11 #include "test_utils/gl_raii.h"
12 #include "util/shader_utils.h"
13
14 using namespace angle;
15
16 namespace
17 {
18 // Sample positions of d3d standard pattern. Some of the sample positions might not the same as
19 // opengl.
20 using SamplePositionsArray = std::array<float, 32>;
21 static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
22 {{{0.5f, 0.5f}},
23 {{0.75f, 0.75f, 0.25f, 0.25f}},
24 {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
25 {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
26 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
27 {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
28 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
29 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
30 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
31
32 class TextureMultisampleTest : public ANGLETest<>
33 {
34 protected:
TextureMultisampleTest()35 TextureMultisampleTest()
36 {
37 setWindowWidth(64);
38 setWindowHeight(64);
39 setConfigRedBits(8);
40 setConfigGreenBits(8);
41 setConfigBlueBits(8);
42 setConfigAlphaBits(8);
43 }
44
testSetUp()45 void testSetUp() override
46 {
47 glGenFramebuffers(1, &mFramebuffer);
48 glGenTextures(1, &mTexture);
49
50 ASSERT_GL_NO_ERROR();
51 }
52
testTearDown()53 void testTearDown() override
54 {
55 glDeleteFramebuffers(1, &mFramebuffer);
56 mFramebuffer = 0;
57 glDeleteTextures(1, &mTexture);
58 mTexture = 0;
59 }
60
61 void texStorageMultisample(GLenum target,
62 GLint samples,
63 GLenum format,
64 GLsizei width,
65 GLsizei height,
66 GLboolean fixedsamplelocations);
67
68 void getTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params);
69 void getTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
70
71 void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
72 void sampleMaski(GLuint maskNumber, GLbitfield mask);
73
74 GLuint mFramebuffer = 0;
75 GLuint mTexture = 0;
76
77 // Returns a sample count that can be used with the given texture target for all the given
78 // formats. Assumes that if format A supports a number of samples N and another format B
79 // supports a number of samples M > N then format B also supports number of samples N.
getSamplesToUse(GLenum texTarget,const std::vector<GLenum> & formats)80 GLint getSamplesToUse(GLenum texTarget, const std::vector<GLenum> &formats)
81 {
82 GLint maxSamples = 65536;
83 for (GLenum format : formats)
84 {
85 GLint maxSamplesFormat = 0;
86 glGetInternalformativ(texTarget, format, GL_SAMPLES, 1, &maxSamplesFormat);
87 maxSamples = std::min(maxSamples, maxSamplesFormat);
88 }
89 return maxSamples;
90 }
91
lessThanES31MultisampleExtNotSupported()92 bool lessThanES31MultisampleExtNotSupported()
93 {
94 return getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
95 !EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample");
96 }
97
multisampleTextureFragmentShader()98 const char *multisampleTextureFragmentShader()
99 {
100 return R"(#version 300 es
101 #extension GL_ANGLE_texture_multisample : require
102 precision highp float;
103 precision highp int;
104
105 uniform highp sampler2DMS tex;
106 uniform int sampleNum;
107
108 in vec4 v_position;
109 out vec4 my_FragColor;
110
111 void main() {
112 ivec2 texSize = textureSize(tex);
113 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
114 my_FragColor = texelFetch(tex, sampleCoords, sampleNum);
115 }
116 )";
117 }
118
blitArrayTextureLayerFragmentShader()119 const char *blitArrayTextureLayerFragmentShader()
120 {
121 return R"(#version 310 es
122 #extension GL_OES_texture_storage_multisample_2d_array : require
123 precision highp float;
124 precision highp int;
125
126 uniform highp sampler2DMSArray tex;
127 uniform int layer;
128 uniform int sampleNum;
129
130 in vec4 v_position;
131 out vec4 my_FragColor;
132
133 void main() {
134 ivec3 texSize = textureSize(tex);
135 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
136 my_FragColor = texelFetch(tex, ivec3(sampleCoords, layer), sampleNum);
137 }
138 )";
139 }
140
blitIntArrayTextureLayerFragmentShader()141 const char *blitIntArrayTextureLayerFragmentShader()
142 {
143 return R"(#version 310 es
144 #extension GL_OES_texture_storage_multisample_2d_array : require
145 precision highp float;
146 precision highp int;
147
148 uniform highp isampler2DMSArray tex;
149 uniform int layer;
150 uniform int sampleNum;
151
152 in vec4 v_position;
153 out vec4 my_FragColor;
154
155 void main() {
156 ivec3 texSize = textureSize(tex);
157 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
158 my_FragColor = vec4(texelFetch(tex, ivec3(sampleCoords, layer), sampleNum));
159 }
160 )";
161 }
162 };
163
164 class NegativeTextureMultisampleTest : public TextureMultisampleTest
165 {
166 protected:
NegativeTextureMultisampleTest()167 NegativeTextureMultisampleTest() : TextureMultisampleTest() {}
168 };
169
170 class TextureMultisampleArrayWebGLTest : public TextureMultisampleTest
171 {
172 protected:
TextureMultisampleArrayWebGLTest()173 TextureMultisampleArrayWebGLTest() : TextureMultisampleTest()
174 {
175 // These tests run in WebGL mode so we can test with both extension off and on.
176 setWebGLCompatibilityEnabled(true);
177 }
178
179 // Requests the ANGLE_texture_multisample_array extension and returns true if the operation
180 // succeeds.
requestArrayExtension()181 bool requestArrayExtension()
182 {
183 if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
184 {
185 glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
186 }
187
188 if (!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"))
189 {
190 return false;
191 }
192 return true;
193 }
194 };
195
texStorageMultisample(GLenum target,GLint samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)196 void TextureMultisampleTest::texStorageMultisample(GLenum target,
197 GLint samples,
198 GLenum internalformat,
199 GLsizei width,
200 GLsizei height,
201 GLboolean fixedsamplelocations)
202 {
203 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
204 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
205 {
206 glTexStorage2DMultisampleANGLE(target, samples, internalformat, width, height,
207 fixedsamplelocations);
208 }
209 else
210 {
211 glTexStorage2DMultisample(target, samples, internalformat, width, height,
212 fixedsamplelocations);
213 }
214 }
215
getTexLevelParameterfv(GLenum target,GLint level,GLenum pname,GLfloat * params)216 void TextureMultisampleTest::getTexLevelParameterfv(GLenum target,
217 GLint level,
218 GLenum pname,
219 GLfloat *params)
220 {
221 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
222 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
223 {
224 glGetTexLevelParameterfvANGLE(target, level, pname, params);
225 }
226 else
227 {
228 glGetTexLevelParameterfv(target, level, pname, params);
229 }
230 }
231
getTexLevelParameteriv(GLenum target,GLint level,GLenum pname,GLint * params)232 void TextureMultisampleTest::getTexLevelParameteriv(GLenum target,
233 GLint level,
234 GLenum pname,
235 GLint *params)
236 {
237 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
238 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
239 {
240 glGetTexLevelParameterivANGLE(target, level, pname, params);
241 }
242 else
243 {
244 glGetTexLevelParameteriv(target, level, pname, params);
245 }
246 }
247
getMultisamplefv(GLenum pname,GLuint index,GLfloat * val)248 void TextureMultisampleTest::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
249 {
250 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
251 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
252 {
253 glGetMultisamplefvANGLE(pname, index, val);
254 }
255 else
256 {
257 glGetMultisamplefv(pname, index, val);
258 }
259 }
260
sampleMaski(GLuint maskNumber,GLbitfield mask)261 void TextureMultisampleTest::sampleMaski(GLuint maskNumber, GLbitfield mask)
262 {
263 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
264 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
265 {
266 glSampleMaskiANGLE(maskNumber, mask);
267 }
268 else
269 {
270 glSampleMaski(maskNumber, mask);
271 }
272 }
273
274 // Tests that if es version < 3.1, GL_TEXTURE_2D_MULTISAMPLE is not supported in
275 // GetInternalformativ. Checks that the number of samples returned is valid in case of ES >= 3.1.
TEST_P(TextureMultisampleTest,MultisampleTargetGetInternalFormativBase)276 TEST_P(TextureMultisampleTest, MultisampleTargetGetInternalFormativBase)
277 {
278 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
279
280 // This query returns supported sample counts in descending order. If only one sample count is
281 // queried, it should be the maximum one.
282 GLint maxSamplesR8 = 0;
283 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamplesR8);
284
285 // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
286 GLint maxColorTextureSamples;
287 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
288 GLint maxSamples;
289 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
290 GLint maxSamplesR8Required = std::min(maxColorTextureSamples, maxSamples);
291
292 EXPECT_GE(maxSamplesR8, maxSamplesR8Required);
293 ASSERT_GL_NO_ERROR();
294 }
295
296 // Tests that if es version < 3.1 and multisample extension is unsupported,
297 // GL_TEXTURE_2D_MULTISAMPLE_ANGLE is not supported in FramebufferTexture2D.
TEST_P(TextureMultisampleTest,MultisampleTargetFramebufferTexture2D)298 TEST_P(TextureMultisampleTest, MultisampleTargetFramebufferTexture2D)
299 {
300 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
301 GLint samples = 1;
302 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
303 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, 64, 64, GL_FALSE);
304
305 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
306 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
307 mTexture, 0);
308
309 ASSERT_GL_NO_ERROR();
310 }
311
312 // Tests basic functionality of glTexStorage2DMultisample.
TEST_P(TextureMultisampleTest,ValidateTextureStorageMultisampleParameters)313 TEST_P(TextureMultisampleTest, ValidateTextureStorageMultisampleParameters)
314 {
315 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
316
317 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
318 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
319 ASSERT_GL_NO_ERROR();
320
321 GLint params = 0;
322 glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, ¶ms);
323 EXPECT_EQ(1, params);
324
325 texStorageMultisample(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, GL_FALSE);
326 ASSERT_GL_ERROR(GL_INVALID_ENUM);
327
328 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 0, 0, GL_FALSE);
329 ASSERT_GL_ERROR(GL_INVALID_VALUE);
330
331 GLint maxSize = 0;
332 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
333 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, maxSize + 1, 1, GL_FALSE);
334 ASSERT_GL_ERROR(GL_INVALID_VALUE);
335
336 GLint maxSamples = 0;
337 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
338 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples + 1, GL_RGBA8, 1, 1, GL_FALSE);
339 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
340
341 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_RGBA8, 1, 1, GL_FALSE);
342 ASSERT_GL_ERROR(GL_INVALID_VALUE);
343
344 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA, 0, 0, GL_FALSE);
345 ASSERT_GL_ERROR(GL_INVALID_VALUE);
346
347 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
348 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
349 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
350 }
351
352 // Tests the value of MAX_INTEGER_SAMPLES is no less than 1.
353 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxIntegerSamples)354 TEST_P(TextureMultisampleTest, MaxIntegerSamples)
355 {
356 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
357
358 // Fixed in recent mesa. http://crbug.com/1071142
359 ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && (IsIntel() || IsAMD()));
360
361 GLint maxIntegerSamples;
362 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
363 EXPECT_GE(maxIntegerSamples, 1);
364 EXPECT_NE(std::numeric_limits<GLint>::max(), maxIntegerSamples);
365 }
366
367 // Tests the value of MAX_COLOR_TEXTURE_SAMPLES is no less than 1.
368 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxColorTextureSamples)369 TEST_P(TextureMultisampleTest, MaxColorTextureSamples)
370 {
371 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
372 GLint maxColorTextureSamples;
373 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
374 EXPECT_GE(maxColorTextureSamples, 1);
375 EXPECT_NE(std::numeric_limits<GLint>::max(), maxColorTextureSamples);
376 }
377
378 // Tests the value of MAX_DEPTH_TEXTURE_SAMPLES is no less than 1.
379 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxDepthTextureSamples)380 TEST_P(TextureMultisampleTest, MaxDepthTextureSamples)
381 {
382 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
383 GLint maxDepthTextureSamples;
384 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
385 EXPECT_GE(maxDepthTextureSamples, 1);
386 EXPECT_NE(std::numeric_limits<GLint>::max(), maxDepthTextureSamples);
387 }
388
389 // Tests the maximum value of MAX_INTEGER_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxIntegerSamplesValid)390 TEST_P(TextureMultisampleTest, MaxIntegerSamplesValid)
391 {
392 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
393
394 // Fixed in recent mesa. http://crbug.com/1071142
395 ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && (IsIntel() || IsAMD()));
396
397 GLint maxIntegerSamples;
398 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
399
400 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
401
402 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxIntegerSamples, GL_RGBA8I, 1, 1, GL_FALSE);
403 ASSERT_GL_NO_ERROR();
404 }
405
406 // Tests the maximum value of MAX_COLOR_TEXTURE_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxColorTextureSamplesValid)407 TEST_P(TextureMultisampleTest, MaxColorTextureSamplesValid)
408 {
409 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
410 GLint maxColorTextureSamples;
411 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
412
413 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
414 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxColorTextureSamples, GL_RGBA8, 1, 1,
415 GL_FALSE);
416 ASSERT_GL_NO_ERROR();
417 }
418
419 // Tests the maximum value of MAX_DEPTH_TEXTURE_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxDepthTextureSamplesValid)420 TEST_P(TextureMultisampleTest, MaxDepthTextureSamplesValid)
421 {
422 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
423 GLint maxDepthTextureSamples;
424 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
425
426 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
427 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxDepthTextureSamples, GL_DEPTH_COMPONENT16,
428 1, 1, GL_FALSE);
429 ASSERT_GL_NO_ERROR();
430 }
431
432 // Tests that getTexLevelParameter is supported by ES 3.1 or ES 3.0 and ANGLE_texture_multisample
TEST_P(TextureMultisampleTest,GetTexLevelParameter)433 TEST_P(TextureMultisampleTest, GetTexLevelParameter)
434 {
435 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
436
437 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
438 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, GL_TRUE);
439 ASSERT_GL_NO_ERROR();
440
441 GLfloat levelSamples = 0;
442 getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
443 EXPECT_EQ(levelSamples, 4);
444
445 GLint fixedSampleLocation = false;
446 getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
447 &fixedSampleLocation);
448 EXPECT_EQ(fixedSampleLocation, 1);
449
450 ASSERT_GL_NO_ERROR();
451 }
452
453 // The value of sample position should be equal to standard pattern on D3D.
TEST_P(TextureMultisampleTest,CheckSamplePositions)454 TEST_P(TextureMultisampleTest, CheckSamplePositions)
455 {
456 ANGLE_SKIP_TEST_IF(!IsD3D11());
457
458 GLsizei maxSamples = 0;
459 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
460
461 GLfloat samplePosition[2];
462
463 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
464
465 for (int sampleCount = 1; sampleCount <= maxSamples; sampleCount++)
466 {
467 GLTexture texture;
468 size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
469 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
470 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE);
471 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
472 texture, 0);
473 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
474 ASSERT_GL_NO_ERROR();
475
476 for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
477 {
478 getMultisamplefv(GL_SAMPLE_POSITION, sampleIndex, samplePosition);
479 EXPECT_EQ(samplePosition[0], kSamplePositions[indexKey][2 * sampleIndex]);
480 EXPECT_EQ(samplePosition[1], kSamplePositions[indexKey][2 * sampleIndex + 1]);
481 }
482 }
483
484 ASSERT_GL_NO_ERROR();
485 }
486
487 // Test textureSize and texelFetch when using ANGLE_texture_multisample extension
TEST_P(TextureMultisampleTest,SimpleTexelFetch)488 TEST_P(TextureMultisampleTest, SimpleTexelFetch)
489 {
490 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
491
492 ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(),
493 multisampleTextureFragmentShader());
494
495 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
496 ASSERT_GE(texLocation, 0);
497 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
498 ASSERT_GE(sampleNumLocation, 0);
499
500 const GLsizei kWidth = 4;
501 const GLsizei kHeight = 4;
502
503 std::vector<GLenum> testFormats = {GL_RGBA8};
504 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, testFormats);
505
506 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, mTexture);
507 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, samplesToUse, GL_RGBA8, kWidth, kHeight,
508 GL_TRUE);
509 ASSERT_GL_NO_ERROR();
510
511 // Clear texture zero to green.
512 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
513 GLColor clearColor = GLColor::green;
514
515 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE_ANGLE,
516 mTexture, 0);
517 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
518 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
519 glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
520 clearColor.A / 255.0f);
521 glClear(GL_COLOR_BUFFER_BIT);
522 ASSERT_GL_NO_ERROR();
523
524 glBindFramebuffer(GL_FRAMEBUFFER, 0);
525 glUseProgram(texelFetchProgram);
526 glViewport(0, 0, kWidth, kHeight);
527
528 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
529 {
530 glUniform1i(sampleNumLocation, sampleNum);
531 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
532 ASSERT_GL_NO_ERROR();
533 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColor);
534 }
535 }
536
TEST_P(TextureMultisampleTest,SampleMaski)537 TEST_P(TextureMultisampleTest, SampleMaski)
538 {
539 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
540
541 GLint maxSampleMaskWords = 0;
542 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
543 sampleMaski(maxSampleMaskWords - 1, 0x1);
544 ASSERT_GL_NO_ERROR();
545
546 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
547 sampleMaski(maxSampleMaskWords, 0x1);
548 ASSERT_GL_ERROR(GL_INVALID_VALUE);
549 }
550
TEST_P(TextureMultisampleTest,ResolveToDefaultFramebuffer)551 TEST_P(TextureMultisampleTest, ResolveToDefaultFramebuffer)
552 {
553 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
554
555 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
556 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
557 getWindowHeight(), GL_TRUE);
558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
560
561 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
562 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
563 mTexture, 0);
564 ASSERT_GL_NO_ERROR();
565
566 // Clear the framebuffer
567 glClearColor(0.25, 0.5, 0.75, 0.25);
568 glClear(GL_COLOR_BUFFER_BIT);
569
570 // Resolve into default framebuffer
571 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
572 glClearColor(1, 0, 0, 1);
573 glClear(GL_COLOR_BUFFER_BIT);
574 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
575 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
576 ASSERT_GL_NO_ERROR();
577
578 const GLColor kResult = GLColor(63, 127, 191, 63);
579 const int w = getWindowWidth() - 1;
580 const int h = getWindowHeight() - 1;
581 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
582 EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
583 EXPECT_PIXEL_COLOR_NEAR(w, 0, kResult, 1);
584 EXPECT_PIXEL_COLOR_NEAR(0, h, kResult, 1);
585 EXPECT_PIXEL_COLOR_NEAR(w, h, kResult, 1);
586 EXPECT_PIXEL_COLOR_NEAR(w / 2, h / 2, kResult, 1);
587 }
588
589 // Negative tests of multisample texture. When context less than ES 3.1 and ANGLE_texture_multsample
590 // not enabled, the feature isn't supported.
TEST_P(NegativeTextureMultisampleTest,Negtive)591 TEST_P(NegativeTextureMultisampleTest, Negtive)
592 {
593 ANGLE_SKIP_TEST_IF(EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
594
595 GLint maxSamples = 0;
596 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
597 ASSERT_GL_ERROR(GL_INVALID_ENUM);
598
599 GLint maxColorTextureSamples;
600 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
601 ASSERT_GL_ERROR(GL_INVALID_ENUM);
602
603 GLint maxDepthTextureSamples;
604 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
605 ASSERT_GL_ERROR(GL_INVALID_ENUM);
606
607 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
608 ASSERT_GL_ERROR(GL_INVALID_ENUM);
609
610 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 64, 64, GL_FALSE);
611 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
612
613 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
614 mTexture, 0);
615 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
616
617 GLint params = 0;
618 glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, ¶ms);
619 ASSERT_GL_ERROR(GL_INVALID_ENUM);
620
621 GLfloat levelSamples = 0;
622 getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
623 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
624
625 GLint fixedSampleLocation = false;
626 getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
627 &fixedSampleLocation);
628 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
629
630 GLint maxSampleMaskWords = 0;
631 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
632 ASSERT_GL_ERROR(GL_INVALID_ENUM);
633 sampleMaski(maxSampleMaskWords - 1, 0x1);
634 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
635 }
636
637 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GetInternalformativ when the
638 // extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativWithoutExtension)639 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativWithoutExtension)
640 {
641 GLint maxSamples = 0;
642 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
643 &maxSamples);
644 ASSERT_GL_ERROR(GL_INVALID_ENUM);
645 }
646
647 // Attempt to bind a texture to multisample array binding point when extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,BindMultisampleArrayTextureWithoutExtension)648 TEST_P(TextureMultisampleArrayWebGLTest, BindMultisampleArrayTextureWithoutExtension)
649 {
650 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
651 ASSERT_GL_ERROR(GL_INVALID_ENUM);
652 }
653
654 // Try to compile shaders using GL_OES_texture_storage_multisample_2d_array when the extension is
655 // not enabled.
TEST_P(TextureMultisampleArrayWebGLTest,ShaderWithoutExtension)656 TEST_P(TextureMultisampleArrayWebGLTest, ShaderWithoutExtension)
657 {
658 constexpr char kFSRequiresExtension[] = R"(#version 310 es
659 #extension GL_OES_texture_storage_multisample_2d_array : require
660 out highp vec4 my_FragColor;
661
662 void main() {
663 my_FragColor = vec4(0.0);
664 })";
665
666 GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFSRequiresExtension);
667 EXPECT_EQ(0u, program);
668
669 constexpr char kFSEnableAndUseExtension[] = R"(#version 310 es
670 #extension GL_OES_texture_storage_multisample_2d_array : enable
671
672 uniform highp sampler2DMSArray tex;
673 out highp ivec4 outSize;
674
675 void main() {
676 outSize = ivec4(textureSize(tex), 0);
677 })";
678
679 program = CompileProgram(essl31_shaders::vs::Simple(), kFSEnableAndUseExtension);
680 EXPECT_EQ(0u, program);
681 }
682
683 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is supported in GetInternalformativ.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativ)684 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativ)
685 {
686 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
687
688 // This query returns supported sample counts in descending order. If only one sample count is
689 // queried, it should be the maximum one.
690 GLint maxSamplesRGBA8 = 0;
691 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
692 &maxSamplesRGBA8);
693 GLint maxSamplesDepth = 0;
694 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_DEPTH_COMPONENT24, GL_SAMPLES, 1,
695 &maxSamplesDepth);
696 ASSERT_GL_NO_ERROR();
697
698 // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
699 GLint maxColorTextureSamples;
700 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
701 GLint maxDepthTextureSamples;
702 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
703 GLint maxSamples;
704 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
705
706 GLint maxSamplesRGBA8Required = std::min(maxColorTextureSamples, maxSamples);
707 EXPECT_GE(maxSamplesRGBA8, maxSamplesRGBA8Required);
708
709 GLint maxSamplesDepthRequired = std::min(maxDepthTextureSamples, maxSamples);
710 EXPECT_GE(maxSamplesDepth, maxSamplesDepthRequired);
711 }
712
713 // Tests that TexImage3D call cannot be used for GL_TEXTURE_2D_MULTISAMPLE_ARRAY.
TEST_P(TextureMultisampleArrayWebGLTest,MultiSampleArrayTexImage)714 TEST_P(TextureMultisampleArrayWebGLTest, MultiSampleArrayTexImage)
715 {
716 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
717
718 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
719 ASSERT_GL_NO_ERROR();
720
721 glTexImage3D(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA,
722 GL_UNSIGNED_BYTE, nullptr);
723 EXPECT_GL_ERROR(GL_INVALID_ENUM);
724 }
725
726 // Tests passing invalid parameters to TexStorage3DMultisample.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexStorage3DMultisample)727 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexStorage3DMultisample)
728 {
729 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
730
731 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
732 ASSERT_GL_NO_ERROR();
733
734 // Invalid target
735 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, 1, GL_TRUE);
736 EXPECT_GL_ERROR(GL_INVALID_ENUM);
737
738 // Samples 0
739 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1,
740 GL_TRUE);
741 EXPECT_GL_ERROR(GL_INVALID_VALUE);
742
743 // Unsized internalformat
744 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA, 1, 1, 1, GL_TRUE);
745 EXPECT_GL_ERROR(GL_INVALID_ENUM);
746
747 // Width 0
748 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 0, 1, 1,
749 GL_TRUE);
750 EXPECT_GL_ERROR(GL_INVALID_VALUE);
751
752 // Height 0
753 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 0, 1,
754 GL_TRUE);
755 EXPECT_GL_ERROR(GL_INVALID_VALUE);
756
757 // Depth 0
758 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 1, 0,
759 GL_TRUE);
760 EXPECT_GL_ERROR(GL_INVALID_VALUE);
761 }
762
763 // Tests passing invalid parameters to TexParameteri.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexParameteri)764 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexParameteri)
765 {
766 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
767
768 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
769 ASSERT_GL_NO_ERROR();
770
771 // None of the sampler parameters can be set on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES.
772 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
773 EXPECT_GL_ERROR(GL_INVALID_ENUM);
774 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
775 EXPECT_GL_ERROR(GL_INVALID_ENUM);
776
777 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
778 EXPECT_GL_ERROR(GL_INVALID_ENUM);
779 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
780 EXPECT_GL_ERROR(GL_INVALID_ENUM);
781 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
782 EXPECT_GL_ERROR(GL_INVALID_ENUM);
783
784 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_LOD, 0);
785 EXPECT_GL_ERROR(GL_INVALID_ENUM);
786 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAX_LOD, 0);
787 EXPECT_GL_ERROR(GL_INVALID_ENUM);
788
789 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_MODE, GL_NONE);
790 EXPECT_GL_ERROR(GL_INVALID_ENUM);
791 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
792 EXPECT_GL_ERROR(GL_INVALID_ENUM);
793
794 // Only valid base level on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is 0.
795 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 1);
796 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
797 }
798
799 // Test a valid TexStorage3DMultisample call and check that the queried texture level parameters
800 // match. Does not do any drawing.
TEST_P(TextureMultisampleArrayWebGLTest,TexStorage3DMultisample)801 TEST_P(TextureMultisampleArrayWebGLTest, TexStorage3DMultisample)
802 {
803 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
804
805 GLint maxSamplesRGBA8 = 0;
806 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
807 &maxSamplesRGBA8);
808
809 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
810 ASSERT_GL_NO_ERROR();
811
812 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 8,
813 4, 2, GL_TRUE);
814 ASSERT_GL_NO_ERROR();
815
816 GLint width = 0, height = 0, depth = 0, samples = 0;
817 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_WIDTH, &width);
818 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_HEIGHT, &height);
819 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_DEPTH, &depth);
820 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_SAMPLES, &samples);
821 ASSERT_GL_NO_ERROR();
822
823 EXPECT_EQ(8, width);
824 EXPECT_EQ(4, height);
825 EXPECT_EQ(2, depth);
826 EXPECT_EQ(maxSamplesRGBA8, samples);
827 }
828
829 // Test for invalid FramebufferTextureLayer calls with GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES
830 // textures.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidFramebufferTextureLayer)831 TEST_P(TextureMultisampleArrayWebGLTest, InvalidFramebufferTextureLayer)
832 {
833 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
834
835 GLint maxSamplesRGBA8 = 0;
836 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
837 &maxSamplesRGBA8);
838
839 GLint maxArrayTextureLayers;
840 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
841
842 // Test framebuffer status with just a color texture attached.
843 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
844 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 4,
845 4, 2, GL_TRUE);
846 ASSERT_GL_NO_ERROR();
847
848 // Test with mip level 1 and -1 (only level 0 is valid for multisample textures).
849 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
850 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 1, 0);
851 EXPECT_GL_ERROR(GL_INVALID_VALUE);
852 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, -1, 0);
853 EXPECT_GL_ERROR(GL_INVALID_VALUE);
854
855 // Test with layer -1 and layer == MAX_ARRAY_TEXTURE_LAYERS
856 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
857 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, -1);
858 EXPECT_GL_ERROR(GL_INVALID_VALUE);
859 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0,
860 maxArrayTextureLayers);
861 EXPECT_GL_ERROR(GL_INVALID_VALUE);
862 }
863
864 // Attach layers of TEXTURE_2D_MULTISAMPLE_ARRAY textures to a framebuffer and check for
865 // completeness.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferCompleteness)866 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferCompleteness)
867 {
868 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
869
870 std::vector<GLenum> testFormats = {{GL_RGBA8, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8}};
871 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
872
873 // Test framebuffer status with just a color texture attached.
874 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
875 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8, 4, 4,
876 2, GL_TRUE);
877 ASSERT_GL_NO_ERROR();
878
879 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
880 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
881 ASSERT_GL_NO_ERROR();
882
883 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
884 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
885
886 // Test framebuffer status with both color and depth textures attached.
887 GLTexture depthTexture;
888 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthTexture);
889 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
890 GL_DEPTH_COMPONENT24, 4, 4, 2, GL_TRUE);
891 ASSERT_GL_NO_ERROR();
892
893 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0);
894 ASSERT_GL_NO_ERROR();
895
896 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
897 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
898
899 // Test with color and depth/stencil textures attached.
900 GLTexture depthStencilTexture;
901 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthStencilTexture);
902 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
903 GL_DEPTH24_STENCIL8, 4, 4, 2, GL_TRUE);
904 ASSERT_GL_NO_ERROR();
905
906 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0,
907 0);
908 ASSERT_GL_NO_ERROR();
909
910 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
911 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
912 }
913
914 // Attach a layer of TEXTURE_2D_MULTISAMPLE_ARRAY texture to a framebuffer, clear it, and resolve by
915 // blitting.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferColorClearAndBlit)916 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferColorClearAndBlit)
917 {
918 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
919
920 const GLsizei kWidth = 4;
921 const GLsizei kHeight = 4;
922
923 std::vector<GLenum> testFormats = {GL_RGBA8};
924 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
925
926 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
927 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
928 kWidth, kHeight, 2, GL_TRUE);
929
930 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
931 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
932
933 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
934 ASSERT_GL_NO_ERROR();
935 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
936
937 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
938 glClear(GL_COLOR_BUFFER_BIT);
939
940 GLFramebuffer resolveFramebuffer;
941 GLTexture resolveTexture;
942 glBindTexture(GL_TEXTURE_2D, resolveTexture);
943 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
944 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
945 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
946 0);
947 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
948 GL_NEAREST);
949 ASSERT_GL_NO_ERROR();
950
951 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
952 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
953 }
954
955 // Check the size of a multisample array texture in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,TextureSizeInShader)956 TEST_P(TextureMultisampleArrayWebGLTest, TextureSizeInShader)
957 {
958 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
959
960 constexpr char kFS[] = R"(#version 310 es
961 #extension GL_OES_texture_storage_multisample_2d_array : require
962
963 uniform highp sampler2DMSArray tex;
964 out highp vec4 my_FragColor;
965
966 void main() {
967 my_FragColor = (textureSize(tex) == ivec3(8, 4, 2)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
968 })";
969
970 ANGLE_GL_PROGRAM(texSizeProgram, essl31_shaders::vs::Simple(), kFS);
971
972 GLint texLocation = glGetUniformLocation(texSizeProgram, "tex");
973 ASSERT_GE(texLocation, 0);
974
975 const GLsizei kWidth = 8;
976 const GLsizei kHeight = 4;
977
978 std::vector<GLenum> testFormats = {GL_RGBA8};
979 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
980
981 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
982 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
983 kWidth, kHeight, 2, GL_TRUE);
984 ASSERT_GL_NO_ERROR();
985
986 drawQuad(texSizeProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
987 ASSERT_GL_NO_ERROR();
988
989 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
990 }
991
992 // Clear the layers of a multisample array texture, and then sample all the samples from all the
993 // layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,SimpleTexelFetch)994 TEST_P(TextureMultisampleArrayWebGLTest, SimpleTexelFetch)
995 {
996 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
997
998 ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
999 blitArrayTextureLayerFragmentShader());
1000
1001 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
1002 ASSERT_GE(texLocation, 0);
1003 GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
1004 ASSERT_GE(layerLocation, 0);
1005 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
1006 ASSERT_GE(layerLocation, 0);
1007
1008 const GLsizei kWidth = 4;
1009 const GLsizei kHeight = 4;
1010 const GLsizei kLayerCount = 2;
1011
1012 std::vector<GLenum> testFormats = {GL_RGBA8};
1013 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
1014
1015 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
1016 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
1017 kWidth, kHeight, kLayerCount, GL_TRUE);
1018 ASSERT_GL_NO_ERROR();
1019
1020 // Clear layer zero to green and layer one to blue.
1021 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1022 std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1023 for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1024 {
1025 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1026 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1027 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1028 const GLColor &clearColor = clearColors[i];
1029 glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
1030 clearColor.A / 255.0f);
1031 glClear(GL_COLOR_BUFFER_BIT);
1032 ASSERT_GL_NO_ERROR();
1033 }
1034
1035 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1036 glUseProgram(texelFetchProgram);
1037 glViewport(0, 0, kWidth, kHeight);
1038 for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1039 {
1040 glUniform1i(layerLocation, layer);
1041 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1042 {
1043 glUniform1i(sampleNumLocation, sampleNum);
1044 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1045 ASSERT_GL_NO_ERROR();
1046 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1047 }
1048 }
1049 }
1050
1051 // Clear the layers of an integer multisample array texture, and then sample all the samples from
1052 // all the layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,IntegerTexelFetch)1053 TEST_P(TextureMultisampleArrayWebGLTest, IntegerTexelFetch)
1054 {
1055 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
1056
1057 ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
1058 blitIntArrayTextureLayerFragmentShader());
1059
1060 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
1061 ASSERT_GE(texLocation, 0);
1062 GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
1063 ASSERT_GE(layerLocation, 0);
1064 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
1065 ASSERT_GE(layerLocation, 0);
1066
1067 const GLsizei kWidth = 4;
1068 const GLsizei kHeight = 4;
1069 const GLsizei kLayerCount = 2;
1070
1071 std::vector<GLenum> testFormats = {GL_RGBA8I};
1072 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
1073
1074 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
1075 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8I,
1076 kWidth, kHeight, kLayerCount, GL_TRUE);
1077 ASSERT_GL_NO_ERROR();
1078
1079 // Clear layer zero to green and layer one to blue.
1080 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1081 std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1082 for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1083 {
1084 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1085 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1086 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1087 std::array<GLint, 4> intColor;
1088 for (size_t j = 0; j < intColor.size(); ++j)
1089 {
1090 intColor[j] = clearColors[i][j] / 255;
1091 }
1092 glClearBufferiv(GL_COLOR, 0, intColor.data());
1093 ASSERT_GL_NO_ERROR();
1094 }
1095
1096 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1097 glUseProgram(texelFetchProgram);
1098 glViewport(0, 0, kWidth, kHeight);
1099 for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1100 {
1101 glUniform1i(layerLocation, layer);
1102 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1103 {
1104 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1105 glClear(GL_COLOR_BUFFER_BIT);
1106 glUniform1i(sampleNumLocation, sampleNum);
1107 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1108 ASSERT_GL_NO_ERROR();
1109 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1110 }
1111 }
1112 }
1113
1114 class TextureSampleShadingTest : public ANGLETest<>
1115 {
1116 protected:
TextureSampleShadingTest()1117 TextureSampleShadingTest() {}
1118 };
1119
1120 // Test that sample shading actually produces different interpolations per sample. Note that
1121 // variables such as gl_SampleID and gl_SamplePosition are avoided, as well as the |sample|
1122 // qualifier as they automatically enable sample shading.
TEST_P(TextureSampleShadingTest,Basic)1123 TEST_P(TextureSampleShadingTest, Basic)
1124 {
1125 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
1126
1127 constexpr GLsizei kSize = 1;
1128 constexpr GLsizei kSampleCount = 4;
1129
1130 // Create a multisampled texture and framebuffer.
1131 GLFramebuffer msaaFBO;
1132 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1133
1134 GLTexture msaaTexture;
1135 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1136 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
1137 false);
1138 ASSERT_GL_NO_ERROR();
1139 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1140 msaaTexture, 0);
1141 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1142
1143 // Enable sample shading and draw a gradient.
1144 glEnable(GL_SAMPLE_SHADING_OES);
1145 glMinSampleShadingOES(1.0f);
1146
1147 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1148 essl31_shaders::fs::RedGreenGradient());
1149 glViewport(0, 0, kSize, kSize);
1150 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1151 ASSERT_GL_NO_ERROR();
1152
1153 // Create a buffer for verification.
1154 constexpr GLsizei kPixelChannels = 4;
1155 constexpr GLsizei kBufferSize =
1156 kSize * kSize * kSampleCount * kPixelChannels * sizeof(uint32_t);
1157 GLBuffer buffer;
1158 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1159 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
1160 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
1161
1162 // Issue a dispatch call that copies the multisampled texture into a buffer.
1163 constexpr char kCS[] = R"(#version 310 es
1164 layout(local_size_x=4, local_size_y=1, local_size_z=1) in;
1165
1166 uniform highp sampler2DMS imageIn;
1167 layout(std430, binding = 0) buffer dataOut {
1168 uint data[];
1169 };
1170
1171 void main()
1172 {
1173 int sampleIndex = int(gl_GlobalInvocationID.x) % 4;
1174
1175 vec4 color = texelFetch(imageIn, ivec2(0), sampleIndex);
1176 uvec4 unnormalized = uvec4(color * 255.0);
1177
1178 int outIndex = sampleIndex * 4;
1179
1180 data[outIndex ] = unnormalized.r;
1181 data[outIndex + 1] = unnormalized.g;
1182 data[outIndex + 2] = unnormalized.b;
1183 data[outIndex + 3] = unnormalized.a;
1184 })";
1185
1186 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1187 glUseProgram(program);
1188
1189 // Bind the multisampled texture as sampler.
1190 GLint imageLocation = glGetUniformLocation(program, "imageIn");
1191 ASSERT_GE(imageLocation, 0);
1192
1193 glActiveTexture(GL_TEXTURE0);
1194 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1195 glUniform1i(imageLocation, 0);
1196
1197 glDispatchCompute(1, 1, 1);
1198 EXPECT_GL_NO_ERROR();
1199
1200 // Verify that the buffer has correct data.
1201 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1202
1203 const uint32_t *ptr = reinterpret_cast<uint32_t *>(
1204 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
1205 constexpr GLColor kExpectedColors[4] = {
1206 GLColor(96, 32, 0, 255),
1207 GLColor(223, 96, 0, 255),
1208 GLColor(32, 159, 0, 255),
1209 GLColor(159, 223, 0, 255),
1210 };
1211 for (GLsizei pixel = 0; pixel < kSampleCount; ++pixel)
1212 {
1213 for (GLsizei channel = 0; channel < kPixelChannels; ++channel)
1214 {
1215 EXPECT_NEAR(ptr[pixel * kPixelChannels + channel], kExpectedColors[pixel][channel], 1)
1216 << pixel << " " << channel;
1217 }
1218 }
1219
1220 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1221 }
1222
1223 // Test that sample shading actually produces different interpolations per sample when |sample| is
1224 // missing from the shader. Both varyings and I/O blocks are tested. When |centroid| is specified,
1225 // |sample| shouldn't be added.
TEST_P(TextureSampleShadingTest,NoSampleQualifier)1226 TEST_P(TextureSampleShadingTest, NoSampleQualifier)
1227 {
1228 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
1229 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
1230 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
1231 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1232
1233 constexpr GLsizei kSize = 1;
1234 constexpr GLsizei kSampleCount = 4;
1235
1236 // Create a multisampled texture and framebuffer.
1237 GLFramebuffer msaaFBO;
1238 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1239
1240 GLTexture msaaTexture;
1241 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1242 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
1243 false);
1244 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1245 msaaTexture, 0);
1246 ASSERT_GL_NO_ERROR();
1247 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1248
1249 // Enable sample shading and draw
1250 glEnable(GL_SAMPLE_SHADING_OES);
1251 glMinSampleShadingOES(1.0f);
1252
1253 constexpr char kVS[] = R"(#version 310 es
1254 #extension GL_OES_shader_multisample_interpolation : require
1255 #extension GL_EXT_shader_io_blocks : require
1256
1257 in mediump vec2 position;
1258 out mediump vec2 gradient;
1259 centroid out mediump vec2 constant;
1260 out Block
1261 {
1262 centroid mediump vec2 constant2;
1263 mediump vec2 gradient2;
1264 sample mediump vec2 gradient3;
1265 };
1266
1267 out Inactive
1268 {
1269 mediump vec2 gradient4;
1270 };
1271
1272 void main()
1273 {
1274 gradient = position;
1275 gradient2 = position;
1276 gradient3 = position;
1277 constant = position;
1278 constant2 = position;
1279 gl_Position = vec4(position, 0, 1);
1280 })";
1281
1282 constexpr char kFS[] = R"(#version 310 es
1283 #extension GL_OES_shader_multisample_interpolation : require
1284 #extension GL_OES_sample_variables : require
1285 #extension GL_EXT_shader_io_blocks : require
1286
1287 in highp vec2 gradient;
1288 centroid in highp vec2 constant;
1289 in Block
1290 {
1291 centroid mediump vec2 constant2;
1292 mediump vec2 gradient2;
1293 sample mediump vec2 gradient3;
1294 };
1295
1296 in Inactive2
1297 {
1298 mediump vec2 gradient4;
1299 };
1300
1301 out mediump vec4 color;
1302
1303 void main()
1304 {
1305 bool left = gl_SampleID == 0 || gl_SampleID == 2;
1306 bool top = gl_SampleID == 0 || gl_SampleID == 1;
1307
1308 color = vec4(0);
1309
1310 if (left)
1311 color.r = gradient.x < -0.1 && gradient2.x < -0.1 && gradient3.x < -0.1 ? 1. : 0.;
1312 else
1313 color.r = gradient.x > 0.1 && gradient2.x > 0.1 && gradient3.x > 0.1 ? 1. : 0.;
1314
1315 if (top)
1316 color.g = gradient.y < -0.1 && gradient2.y < -0.1 && gradient3.y < -0.1 ? 1. : 0.;
1317 else
1318 color.g = gradient.y > 0.1 && gradient2.y > 0.1 && gradient3.y > 0.1 ? 1. : 0.;
1319
1320 // centroid doesn't exactly behave consistently between implementations. In particular, it does
1321 // _not_ necessarily evaluage the varying at the pixel center. As a result, there isn't much
1322 // that can be verified here. We'd rely on SPIR-V validation to make sure Sample is not added
1323 // to ids that already have Centroid specified (in the Vulkan backend)
1324 color.b = abs(constant.x) < 1. && abs(constant.y) < 1. ? 1. : 0.;
1325 color.a = abs(constant2.x) < 1. && abs(constant2.y) < 1. ? 1. : 0.;
1326 })";
1327
1328 ANGLE_GL_PROGRAM(program, kVS, kFS);
1329 glViewport(0, 0, kSize, kSize);
1330 drawQuad(program, "position", 0.5f);
1331 ASSERT_GL_NO_ERROR();
1332
1333 // Resolve the framebuffer
1334 GLFramebuffer fbo;
1335 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1336
1337 GLTexture texture;
1338 glBindTexture(GL_TEXTURE_2D, texture);
1339 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1340 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1341 ASSERT_GL_NO_ERROR();
1342 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1343
1344 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
1345
1346 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1347
1348 // Ensure the test passed on every sample location
1349 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
1350 ASSERT_GL_NO_ERROR();
1351 }
1352
1353 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleTest);
1354 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(TextureMultisampleTest);
1355
1356 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NegativeTextureMultisampleTest);
1357 ANGLE_INSTANTIATE_TEST_ES3(NegativeTextureMultisampleTest);
1358
1359 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleArrayWebGLTest);
1360 ANGLE_INSTANTIATE_TEST_ES31(TextureMultisampleArrayWebGLTest);
1361
1362 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSampleShadingTest);
1363 ANGLE_INSTANTIATE_TEST_ES31(TextureSampleShadingTest);
1364 } // anonymous namespace
1365