• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     // http://anglebug.com/4092
302     ANGLE_SKIP_TEST_IF(IsVulkan());
303     GLint samples = 1;
304     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
305     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, 64, 64, GL_FALSE);
306 
307     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
308     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
309                            mTexture, 0);
310 
311     ASSERT_GL_NO_ERROR();
312 }
313 
314 // Tests basic functionality of glTexStorage2DMultisample.
TEST_P(TextureMultisampleTest,ValidateTextureStorageMultisampleParameters)315 TEST_P(TextureMultisampleTest, ValidateTextureStorageMultisampleParameters)
316 {
317     // http://anglebug.com/4092
318     ANGLE_SKIP_TEST_IF(IsVulkan());
319     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
320 
321     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
322     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
323     ASSERT_GL_NO_ERROR();
324 
325     GLint params = 0;
326     glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
327     EXPECT_EQ(1, params);
328 
329     texStorageMultisample(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, GL_FALSE);
330     ASSERT_GL_ERROR(GL_INVALID_ENUM);
331 
332     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 0, 0, GL_FALSE);
333     ASSERT_GL_ERROR(GL_INVALID_VALUE);
334 
335     GLint maxSize = 0;
336     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
337     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, maxSize + 1, 1, GL_FALSE);
338     ASSERT_GL_ERROR(GL_INVALID_VALUE);
339 
340     GLint maxSamples = 0;
341     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
342     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples + 1, GL_RGBA8, 1, 1, GL_FALSE);
343     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
344 
345     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_RGBA8, 1, 1, GL_FALSE);
346     ASSERT_GL_ERROR(GL_INVALID_VALUE);
347 
348     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA, 0, 0, GL_FALSE);
349     ASSERT_GL_ERROR(GL_INVALID_VALUE);
350 
351     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
352     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
353     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
354 }
355 
356 // Tests the value of MAX_INTEGER_SAMPLES is no less than 1.
357 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxIntegerSamples)358 TEST_P(TextureMultisampleTest, MaxIntegerSamples)
359 {
360     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
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 that getTexLevelParameter is supported by ES 3.1 or ES 3.0 and ANGLE_texture_multisample
TEST_P(TextureMultisampleTest,GetTexLevelParameter)390 TEST_P(TextureMultisampleTest, GetTexLevelParameter)
391 {
392     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
393     // http://anglebug.com/4092
394     ANGLE_SKIP_TEST_IF(IsVulkan());
395 
396     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
397     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, GL_TRUE);
398     ASSERT_GL_NO_ERROR();
399 
400     GLfloat levelSamples = 0;
401     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
402     EXPECT_EQ(levelSamples, 4);
403 
404     GLint fixedSampleLocation = false;
405     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
406                            &fixedSampleLocation);
407     EXPECT_EQ(fixedSampleLocation, 1);
408 
409     ASSERT_GL_NO_ERROR();
410 }
411 
412 // The value of sample position should be equal to standard pattern on D3D.
TEST_P(TextureMultisampleTest,CheckSamplePositions)413 TEST_P(TextureMultisampleTest, CheckSamplePositions)
414 {
415     ANGLE_SKIP_TEST_IF(!IsD3D11());
416 
417     GLsizei maxSamples = 0;
418     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
419 
420     GLfloat samplePosition[2];
421 
422     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
423 
424     for (int sampleCount = 1; sampleCount <= maxSamples; sampleCount++)
425     {
426         GLTexture texture;
427         size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
428         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
429         texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE);
430         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
431                                texture, 0);
432         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
433         ASSERT_GL_NO_ERROR();
434 
435         for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
436         {
437             getMultisamplefv(GL_SAMPLE_POSITION, sampleIndex, samplePosition);
438             EXPECT_EQ(samplePosition[0], kSamplePositions[indexKey][2 * sampleIndex]);
439             EXPECT_EQ(samplePosition[1], kSamplePositions[indexKey][2 * sampleIndex + 1]);
440         }
441     }
442 
443     ASSERT_GL_NO_ERROR();
444 }
445 
446 // Test textureSize and texelFetch when using ANGLE_texture_multisample extension
TEST_P(TextureMultisampleTest,SimpleTexelFetch)447 TEST_P(TextureMultisampleTest, SimpleTexelFetch)
448 {
449     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
450 
451     ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(),
452                      multisampleTextureFragmentShader());
453 
454     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
455     ASSERT_GE(texLocation, 0);
456     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
457     ASSERT_GE(sampleNumLocation, 0);
458 
459     const GLsizei kWidth  = 4;
460     const GLsizei kHeight = 4;
461 
462     std::vector<GLenum> testFormats = {GL_RGBA8};
463     GLint samplesToUse              = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, testFormats);
464 
465     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, mTexture);
466     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, samplesToUse, GL_RGBA8, kWidth, kHeight,
467                           GL_TRUE);
468     ASSERT_GL_NO_ERROR();
469 
470     // Clear texture zero to green.
471     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
472     GLColor clearColor = GLColor::green;
473 
474     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE_ANGLE,
475                            mTexture, 0);
476     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
477     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
478     glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
479                  clearColor.A / 255.0f);
480     glClear(GL_COLOR_BUFFER_BIT);
481     ASSERT_GL_NO_ERROR();
482 
483     glBindFramebuffer(GL_FRAMEBUFFER, 0);
484     glUseProgram(texelFetchProgram);
485     glViewport(0, 0, kWidth, kHeight);
486 
487     for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
488     {
489         glUniform1i(sampleNumLocation, sampleNum);
490         drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
491         ASSERT_GL_NO_ERROR();
492         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColor);
493     }
494 }
495 
TEST_P(TextureMultisampleTest,SampleMaski)496 TEST_P(TextureMultisampleTest, SampleMaski)
497 {
498     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
499 
500     GLint maxSampleMaskWords = 0;
501     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
502     sampleMaski(maxSampleMaskWords - 1, 0x1);
503     ASSERT_GL_NO_ERROR();
504 
505     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
506     sampleMaski(maxSampleMaskWords, 0x1);
507     ASSERT_GL_ERROR(GL_INVALID_VALUE);
508 }
509 
510 // Negative tests of multisample texture. When context less than ES 3.1 and ANGLE_texture_multsample
511 // not enabled, the feature isn't supported.
TEST_P(NegativeTextureMultisampleTest,Negtive)512 TEST_P(NegativeTextureMultisampleTest, Negtive)
513 {
514     ANGLE_SKIP_TEST_IF(EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
515 
516     GLint maxSamples = 0;
517     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
518     ASSERT_GL_ERROR(GL_INVALID_ENUM);
519 
520     GLint maxColorTextureSamples;
521     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
522     ASSERT_GL_ERROR(GL_INVALID_ENUM);
523 
524     GLint maxDepthTextureSamples;
525     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
526     ASSERT_GL_ERROR(GL_INVALID_ENUM);
527 
528     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
529     ASSERT_GL_ERROR(GL_INVALID_ENUM);
530 
531     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 64, 64, GL_FALSE);
532     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
533 
534     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
535                            mTexture, 0);
536     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
537 
538     GLint params = 0;
539     glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
540     ASSERT_GL_ERROR(GL_INVALID_ENUM);
541 
542     GLfloat levelSamples = 0;
543     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
544     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
545 
546     GLint fixedSampleLocation = false;
547     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
548                            &fixedSampleLocation);
549     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
550 
551     GLint maxSampleMaskWords = 0;
552     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
553     ASSERT_GL_ERROR(GL_INVALID_ENUM);
554     sampleMaski(maxSampleMaskWords - 1, 0x1);
555     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
556 }
557 
558 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GetInternalformativ when the
559 // extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativWithoutExtension)560 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativWithoutExtension)
561 {
562     GLint maxSamples = 0;
563     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
564                           &maxSamples);
565     ASSERT_GL_ERROR(GL_INVALID_ENUM);
566 }
567 
568 // Attempt to bind a texture to multisample array binding point when extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,BindMultisampleArrayTextureWithoutExtension)569 TEST_P(TextureMultisampleArrayWebGLTest, BindMultisampleArrayTextureWithoutExtension)
570 {
571     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
572     ASSERT_GL_ERROR(GL_INVALID_ENUM);
573 }
574 
575 // Try to compile shaders using GL_OES_texture_storage_multisample_2d_array when the extension is
576 // not enabled.
TEST_P(TextureMultisampleArrayWebGLTest,ShaderWithoutExtension)577 TEST_P(TextureMultisampleArrayWebGLTest, ShaderWithoutExtension)
578 {
579     constexpr char kFSRequiresExtension[] = R"(#version 310 es
580 #extension GL_OES_texture_storage_multisample_2d_array : require
581 out highp vec4 my_FragColor;
582 
583 void main() {
584         my_FragColor = vec4(0.0);
585 })";
586 
587     GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFSRequiresExtension);
588     EXPECT_EQ(0u, program);
589 
590     constexpr char kFSEnableAndUseExtension[] = R"(#version 310 es
591 #extension GL_OES_texture_storage_multisample_2d_array : enable
592 
593 uniform highp sampler2DMSArray tex;
594 out highp ivec4 outSize;
595 
596 void main() {
597         outSize = ivec4(textureSize(tex), 0);
598 })";
599 
600     program = CompileProgram(essl31_shaders::vs::Simple(), kFSEnableAndUseExtension);
601     EXPECT_EQ(0u, program);
602 }
603 
604 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is supported in GetInternalformativ.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativ)605 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativ)
606 {
607     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
608 
609     // This query returns supported sample counts in descending order. If only one sample count is
610     // queried, it should be the maximum one.
611     GLint maxSamplesRGBA8 = 0;
612     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
613                           &maxSamplesRGBA8);
614     GLint maxSamplesDepth = 0;
615     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_DEPTH_COMPONENT24, GL_SAMPLES, 1,
616                           &maxSamplesDepth);
617     ASSERT_GL_NO_ERROR();
618 
619     // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
620     GLint maxColorTextureSamples;
621     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
622     GLint maxDepthTextureSamples;
623     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
624     GLint maxSamples;
625     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
626 
627     GLint maxSamplesRGBA8Required = std::min(maxColorTextureSamples, maxSamples);
628     EXPECT_GE(maxSamplesRGBA8, maxSamplesRGBA8Required);
629 
630     GLint maxSamplesDepthRequired = std::min(maxDepthTextureSamples, maxSamples);
631     EXPECT_GE(maxSamplesDepth, maxSamplesDepthRequired);
632 }
633 
634 // Tests that TexImage3D call cannot be used for GL_TEXTURE_2D_MULTISAMPLE_ARRAY.
TEST_P(TextureMultisampleArrayWebGLTest,MultiSampleArrayTexImage)635 TEST_P(TextureMultisampleArrayWebGLTest, MultiSampleArrayTexImage)
636 {
637     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
638 
639     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
640     ASSERT_GL_NO_ERROR();
641 
642     glTexImage3D(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA,
643                  GL_UNSIGNED_BYTE, nullptr);
644     EXPECT_GL_ERROR(GL_INVALID_ENUM);
645 }
646 
647 // Tests passing invalid parameters to TexStorage3DMultisample.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexStorage3DMultisample)648 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexStorage3DMultisample)
649 {
650     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
651 
652     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
653     ASSERT_GL_NO_ERROR();
654 
655     // Invalid target
656     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, 1, GL_TRUE);
657     EXPECT_GL_ERROR(GL_INVALID_ENUM);
658 
659     // Samples 0
660     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1,
661                                  GL_TRUE);
662     EXPECT_GL_ERROR(GL_INVALID_VALUE);
663 
664     // Unsized internalformat
665     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA, 1, 1, 1, GL_TRUE);
666     EXPECT_GL_ERROR(GL_INVALID_ENUM);
667 
668     // Width 0
669     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 0, 1, 1,
670                                  GL_TRUE);
671     EXPECT_GL_ERROR(GL_INVALID_VALUE);
672 
673     // Height 0
674     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 0, 1,
675                                  GL_TRUE);
676     EXPECT_GL_ERROR(GL_INVALID_VALUE);
677 
678     // Depth 0
679     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 1, 0,
680                                  GL_TRUE);
681     EXPECT_GL_ERROR(GL_INVALID_VALUE);
682 }
683 
684 // Tests passing invalid parameters to TexParameteri.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexParameteri)685 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexParameteri)
686 {
687     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
688 
689     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
690     ASSERT_GL_NO_ERROR();
691 
692     // None of the sampler parameters can be set on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES.
693     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
694     EXPECT_GL_ERROR(GL_INVALID_ENUM);
695     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
696     EXPECT_GL_ERROR(GL_INVALID_ENUM);
697 
698     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
699     EXPECT_GL_ERROR(GL_INVALID_ENUM);
700     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
701     EXPECT_GL_ERROR(GL_INVALID_ENUM);
702     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
703     EXPECT_GL_ERROR(GL_INVALID_ENUM);
704 
705     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_LOD, 0);
706     EXPECT_GL_ERROR(GL_INVALID_ENUM);
707     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAX_LOD, 0);
708     EXPECT_GL_ERROR(GL_INVALID_ENUM);
709 
710     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_MODE, GL_NONE);
711     EXPECT_GL_ERROR(GL_INVALID_ENUM);
712     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
713     EXPECT_GL_ERROR(GL_INVALID_ENUM);
714 
715     // Only valid base level on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is 0.
716     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 1);
717     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
718 }
719 
720 // Test a valid TexStorage3DMultisample call and check that the queried texture level parameters
721 // match. Does not do any drawing.
TEST_P(TextureMultisampleArrayWebGLTest,TexStorage3DMultisample)722 TEST_P(TextureMultisampleArrayWebGLTest, TexStorage3DMultisample)
723 {
724     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
725 
726     GLint maxSamplesRGBA8 = 0;
727     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
728                           &maxSamplesRGBA8);
729 
730     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
731     ASSERT_GL_NO_ERROR();
732 
733     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 8,
734                                  4, 2, GL_TRUE);
735     ASSERT_GL_NO_ERROR();
736 
737     GLint width = 0, height = 0, depth = 0, samples = 0;
738     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_WIDTH, &width);
739     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_HEIGHT, &height);
740     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_DEPTH, &depth);
741     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_SAMPLES, &samples);
742     ASSERT_GL_NO_ERROR();
743 
744     EXPECT_EQ(8, width);
745     EXPECT_EQ(4, height);
746     EXPECT_EQ(2, depth);
747     EXPECT_EQ(maxSamplesRGBA8, samples);
748 }
749 
750 // Test for invalid FramebufferTextureLayer calls with GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES
751 // textures.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidFramebufferTextureLayer)752 TEST_P(TextureMultisampleArrayWebGLTest, InvalidFramebufferTextureLayer)
753 {
754     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
755 
756     GLint maxSamplesRGBA8 = 0;
757     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
758                           &maxSamplesRGBA8);
759 
760     GLint maxArrayTextureLayers;
761     glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
762 
763     // Test framebuffer status with just a color texture attached.
764     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
765     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 4,
766                                  4, 2, GL_TRUE);
767     ASSERT_GL_NO_ERROR();
768 
769     // Test with mip level 1 and -1 (only level 0 is valid for multisample textures).
770     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
771     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 1, 0);
772     EXPECT_GL_ERROR(GL_INVALID_VALUE);
773     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, -1, 0);
774     EXPECT_GL_ERROR(GL_INVALID_VALUE);
775 
776     // Test with layer -1 and layer == MAX_ARRAY_TEXTURE_LAYERS
777     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
778     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, -1);
779     EXPECT_GL_ERROR(GL_INVALID_VALUE);
780     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0,
781                               maxArrayTextureLayers);
782     EXPECT_GL_ERROR(GL_INVALID_VALUE);
783 }
784 
785 // Attach layers of TEXTURE_2D_MULTISAMPLE_ARRAY textures to a framebuffer and check for
786 // completeness.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferCompleteness)787 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferCompleteness)
788 {
789     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
790 
791     std::vector<GLenum> testFormats = {{GL_RGBA8, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8}};
792     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
793 
794     // Test framebuffer status with just a color texture attached.
795     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
796     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8, 4, 4,
797                                  2, GL_TRUE);
798     ASSERT_GL_NO_ERROR();
799 
800     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
801     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
802     ASSERT_GL_NO_ERROR();
803 
804     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
805     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
806 
807     // Test framebuffer status with both color and depth textures attached.
808     GLTexture depthTexture;
809     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthTexture);
810     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
811                                  GL_DEPTH_COMPONENT24, 4, 4, 2, GL_TRUE);
812     ASSERT_GL_NO_ERROR();
813 
814     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0);
815     ASSERT_GL_NO_ERROR();
816 
817     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
818     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
819 
820     // Test with color and depth/stencil textures attached.
821     GLTexture depthStencilTexture;
822     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthStencilTexture);
823     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
824                                  GL_DEPTH24_STENCIL8, 4, 4, 2, GL_TRUE);
825     ASSERT_GL_NO_ERROR();
826 
827     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0,
828                               0);
829     ASSERT_GL_NO_ERROR();
830 
831     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
832     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
833 }
834 
835 // Attach a layer of TEXTURE_2D_MULTISAMPLE_ARRAY texture to a framebuffer, clear it, and resolve by
836 // blitting.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferColorClearAndBlit)837 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferColorClearAndBlit)
838 {
839     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
840 
841     const GLsizei kWidth  = 4;
842     const GLsizei kHeight = 4;
843 
844     std::vector<GLenum> testFormats = {GL_RGBA8};
845     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
846 
847     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
848     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
849                                  kWidth, kHeight, 2, GL_TRUE);
850 
851     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
852     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
853 
854     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
855     ASSERT_GL_NO_ERROR();
856     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
857 
858     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
859     glClear(GL_COLOR_BUFFER_BIT);
860 
861     GLFramebuffer resolveFramebuffer;
862     GLTexture resolveTexture;
863     glBindTexture(GL_TEXTURE_2D, resolveTexture);
864     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
865     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
866     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
867                            0);
868     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
869                       GL_NEAREST);
870     ASSERT_GL_NO_ERROR();
871 
872     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
873     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
874 }
875 
876 // Check the size of a multisample array texture in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,TextureSizeInShader)877 TEST_P(TextureMultisampleArrayWebGLTest, TextureSizeInShader)
878 {
879     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
880 
881     constexpr char kFS[] = R"(#version 310 es
882 #extension GL_OES_texture_storage_multisample_2d_array : require
883 
884 uniform highp sampler2DMSArray tex;
885 out highp vec4 my_FragColor;
886 
887 void main() {
888         my_FragColor = (textureSize(tex) == ivec3(8, 4, 2)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
889 })";
890 
891     ANGLE_GL_PROGRAM(texSizeProgram, essl31_shaders::vs::Simple(), kFS);
892 
893     GLint texLocation = glGetUniformLocation(texSizeProgram, "tex");
894     ASSERT_GE(texLocation, 0);
895 
896     const GLsizei kWidth  = 8;
897     const GLsizei kHeight = 4;
898 
899     std::vector<GLenum> testFormats = {GL_RGBA8};
900     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
901 
902     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
903     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
904                                  kWidth, kHeight, 2, GL_TRUE);
905     ASSERT_GL_NO_ERROR();
906 
907     drawQuad(texSizeProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
908     ASSERT_GL_NO_ERROR();
909 
910     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
911 }
912 
913 // Clear the layers of a multisample array texture, and then sample all the samples from all the
914 // layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,SimpleTexelFetch)915 TEST_P(TextureMultisampleArrayWebGLTest, SimpleTexelFetch)
916 {
917     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
918 
919     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
920                      blitArrayTextureLayerFragmentShader());
921 
922     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
923     ASSERT_GE(texLocation, 0);
924     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
925     ASSERT_GE(layerLocation, 0);
926     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
927     ASSERT_GE(layerLocation, 0);
928 
929     const GLsizei kWidth      = 4;
930     const GLsizei kHeight     = 4;
931     const GLsizei kLayerCount = 2;
932 
933     std::vector<GLenum> testFormats = {GL_RGBA8};
934     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
935 
936     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
937     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
938                                  kWidth, kHeight, kLayerCount, GL_TRUE);
939     ASSERT_GL_NO_ERROR();
940 
941     // Clear layer zero to green and layer one to blue.
942     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
943     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
944     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
945     {
946         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
947         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
948         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
949         const GLColor &clearColor = clearColors[i];
950         glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
951                      clearColor.A / 255.0f);
952         glClear(GL_COLOR_BUFFER_BIT);
953         ASSERT_GL_NO_ERROR();
954     }
955 
956     glBindFramebuffer(GL_FRAMEBUFFER, 0);
957     glUseProgram(texelFetchProgram);
958     glViewport(0, 0, kWidth, kHeight);
959     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
960     {
961         glUniform1i(layerLocation, layer);
962         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
963         {
964             glUniform1i(sampleNumLocation, sampleNum);
965             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
966             ASSERT_GL_NO_ERROR();
967             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
968         }
969     }
970 }
971 
972 // Clear the layers of an integer multisample array texture, and then sample all the samples from
973 // all the layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,IntegerTexelFetch)974 TEST_P(TextureMultisampleArrayWebGLTest, IntegerTexelFetch)
975 {
976     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
977 
978     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
979                      blitIntArrayTextureLayerFragmentShader());
980 
981     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
982     ASSERT_GE(texLocation, 0);
983     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
984     ASSERT_GE(layerLocation, 0);
985     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
986     ASSERT_GE(layerLocation, 0);
987 
988     const GLsizei kWidth      = 4;
989     const GLsizei kHeight     = 4;
990     const GLsizei kLayerCount = 2;
991 
992     std::vector<GLenum> testFormats = {GL_RGBA8I};
993     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
994 
995     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
996     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8I,
997                                  kWidth, kHeight, kLayerCount, GL_TRUE);
998     ASSERT_GL_NO_ERROR();
999 
1000     // Clear layer zero to green and layer one to blue.
1001     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1002     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1003     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1004     {
1005         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1006         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1007         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1008         std::array<GLint, 4> intColor;
1009         for (size_t j = 0; j < intColor.size(); ++j)
1010         {
1011             intColor[j] = clearColors[i][j] / 255;
1012         }
1013         glClearBufferiv(GL_COLOR, 0, intColor.data());
1014         ASSERT_GL_NO_ERROR();
1015     }
1016 
1017     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1018     glUseProgram(texelFetchProgram);
1019     glViewport(0, 0, kWidth, kHeight);
1020     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1021     {
1022         glUniform1i(layerLocation, layer);
1023         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1024         {
1025             glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1026             glClear(GL_COLOR_BUFFER_BIT);
1027             glUniform1i(sampleNumLocation, sampleNum);
1028             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1029             ASSERT_GL_NO_ERROR();
1030             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1031         }
1032     }
1033 }
1034 
1035 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(TextureMultisampleTest);
1036 ANGLE_INSTANTIATE_TEST_ES3(NegativeTextureMultisampleTest);
1037 ANGLE_INSTANTIATE_TEST_ES31(TextureMultisampleArrayWebGLTest);
1038 }  // anonymous namespace
1039