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, &params);
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 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 
394     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
395     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, GL_TRUE);
396     ASSERT_GL_NO_ERROR();
397 
398     GLfloat levelSamples = 0;
399     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
400     EXPECT_EQ(levelSamples, 4);
401 
402     GLint fixedSampleLocation = false;
403     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
404                            &fixedSampleLocation);
405     EXPECT_EQ(fixedSampleLocation, 1);
406 
407     ASSERT_GL_NO_ERROR();
408 }
409 
410 // The value of sample position should be equal to standard pattern on D3D.
TEST_P(TextureMultisampleTest,CheckSamplePositions)411 TEST_P(TextureMultisampleTest, CheckSamplePositions)
412 {
413     ANGLE_SKIP_TEST_IF(!IsD3D11());
414 
415     GLsizei maxSamples = 0;
416     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
417 
418     GLfloat samplePosition[2];
419 
420     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
421 
422     for (int sampleCount = 1; sampleCount <= maxSamples; sampleCount++)
423     {
424         GLTexture texture;
425         size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
426         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
427         texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE);
428         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
429                                texture, 0);
430         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
431         ASSERT_GL_NO_ERROR();
432 
433         for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
434         {
435             getMultisamplefv(GL_SAMPLE_POSITION, sampleIndex, samplePosition);
436             EXPECT_EQ(samplePosition[0], kSamplePositions[indexKey][2 * sampleIndex]);
437             EXPECT_EQ(samplePosition[1], kSamplePositions[indexKey][2 * sampleIndex + 1]);
438         }
439     }
440 
441     ASSERT_GL_NO_ERROR();
442 }
443 
444 // Test textureSize and texelFetch when using ANGLE_texture_multisample extension
TEST_P(TextureMultisampleTest,SimpleTexelFetch)445 TEST_P(TextureMultisampleTest, SimpleTexelFetch)
446 {
447     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
448 
449     ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(),
450                      multisampleTextureFragmentShader());
451 
452     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
453     ASSERT_GE(texLocation, 0);
454     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
455     ASSERT_GE(sampleNumLocation, 0);
456 
457     const GLsizei kWidth  = 4;
458     const GLsizei kHeight = 4;
459 
460     std::vector<GLenum> testFormats = {GL_RGBA8};
461     GLint samplesToUse              = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, testFormats);
462 
463     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, mTexture);
464     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, samplesToUse, GL_RGBA8, kWidth, kHeight,
465                           GL_TRUE);
466     ASSERT_GL_NO_ERROR();
467 
468     // Clear texture zero to green.
469     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
470     GLColor clearColor = GLColor::green;
471 
472     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE_ANGLE,
473                            mTexture, 0);
474     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
475     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
476     glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
477                  clearColor.A / 255.0f);
478     glClear(GL_COLOR_BUFFER_BIT);
479     ASSERT_GL_NO_ERROR();
480 
481     glBindFramebuffer(GL_FRAMEBUFFER, 0);
482     glUseProgram(texelFetchProgram);
483     glViewport(0, 0, kWidth, kHeight);
484 
485     for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
486     {
487         glUniform1i(sampleNumLocation, sampleNum);
488         drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
489         ASSERT_GL_NO_ERROR();
490         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColor);
491     }
492 }
493 
TEST_P(TextureMultisampleTest,SampleMaski)494 TEST_P(TextureMultisampleTest, SampleMaski)
495 {
496     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
497 
498     GLint maxSampleMaskWords = 0;
499     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
500     sampleMaski(maxSampleMaskWords - 1, 0x1);
501     ASSERT_GL_NO_ERROR();
502 
503     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
504     sampleMaski(maxSampleMaskWords, 0x1);
505     ASSERT_GL_ERROR(GL_INVALID_VALUE);
506 }
507 
TEST_P(TextureMultisampleTest,ResolveToDefaultFramebuffer)508 TEST_P(TextureMultisampleTest, ResolveToDefaultFramebuffer)
509 {
510     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
511 
512     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
513     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
514                           getWindowHeight(), GL_TRUE);
515     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
516     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
517 
518     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
519     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
520                            mTexture, 0);
521     ASSERT_GL_NO_ERROR();
522 
523     // Clear the framebuffer
524     glClearColor(0.25, 0.5, 0.75, 0.25);
525     glClear(GL_COLOR_BUFFER_BIT);
526 
527     // Resolve into default framebuffer
528     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
529     glClearColor(1, 0, 0, 1);
530     glClear(GL_COLOR_BUFFER_BIT);
531     glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
532                       getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
533     ASSERT_GL_NO_ERROR();
534 
535     const GLColor kResult = GLColor(63, 127, 191, 63);
536     const int w           = getWindowWidth() - 1;
537     const int h           = getWindowHeight() - 1;
538     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
539     EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
540     EXPECT_PIXEL_COLOR_NEAR(w, 0, kResult, 1);
541     EXPECT_PIXEL_COLOR_NEAR(0, h, kResult, 1);
542     EXPECT_PIXEL_COLOR_NEAR(w, h, kResult, 1);
543     EXPECT_PIXEL_COLOR_NEAR(w / 2, h / 2, kResult, 1);
544 }
545 
546 // Negative tests of multisample texture. When context less than ES 3.1 and ANGLE_texture_multsample
547 // not enabled, the feature isn't supported.
TEST_P(NegativeTextureMultisampleTest,Negtive)548 TEST_P(NegativeTextureMultisampleTest, Negtive)
549 {
550     ANGLE_SKIP_TEST_IF(EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
551 
552     GLint maxSamples = 0;
553     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
554     ASSERT_GL_ERROR(GL_INVALID_ENUM);
555 
556     GLint maxColorTextureSamples;
557     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
558     ASSERT_GL_ERROR(GL_INVALID_ENUM);
559 
560     GLint maxDepthTextureSamples;
561     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
562     ASSERT_GL_ERROR(GL_INVALID_ENUM);
563 
564     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
565     ASSERT_GL_ERROR(GL_INVALID_ENUM);
566 
567     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 64, 64, GL_FALSE);
568     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
569 
570     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
571                            mTexture, 0);
572     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
573 
574     GLint params = 0;
575     glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
576     ASSERT_GL_ERROR(GL_INVALID_ENUM);
577 
578     GLfloat levelSamples = 0;
579     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
580     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
581 
582     GLint fixedSampleLocation = false;
583     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
584                            &fixedSampleLocation);
585     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
586 
587     GLint maxSampleMaskWords = 0;
588     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
589     ASSERT_GL_ERROR(GL_INVALID_ENUM);
590     sampleMaski(maxSampleMaskWords - 1, 0x1);
591     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
592 }
593 
594 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GetInternalformativ when the
595 // extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativWithoutExtension)596 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativWithoutExtension)
597 {
598     GLint maxSamples = 0;
599     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
600                           &maxSamples);
601     ASSERT_GL_ERROR(GL_INVALID_ENUM);
602 }
603 
604 // Attempt to bind a texture to multisample array binding point when extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,BindMultisampleArrayTextureWithoutExtension)605 TEST_P(TextureMultisampleArrayWebGLTest, BindMultisampleArrayTextureWithoutExtension)
606 {
607     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
608     ASSERT_GL_ERROR(GL_INVALID_ENUM);
609 }
610 
611 // Try to compile shaders using GL_OES_texture_storage_multisample_2d_array when the extension is
612 // not enabled.
TEST_P(TextureMultisampleArrayWebGLTest,ShaderWithoutExtension)613 TEST_P(TextureMultisampleArrayWebGLTest, ShaderWithoutExtension)
614 {
615     constexpr char kFSRequiresExtension[] = R"(#version 310 es
616 #extension GL_OES_texture_storage_multisample_2d_array : require
617 out highp vec4 my_FragColor;
618 
619 void main() {
620         my_FragColor = vec4(0.0);
621 })";
622 
623     GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFSRequiresExtension);
624     EXPECT_EQ(0u, program);
625 
626     constexpr char kFSEnableAndUseExtension[] = R"(#version 310 es
627 #extension GL_OES_texture_storage_multisample_2d_array : enable
628 
629 uniform highp sampler2DMSArray tex;
630 out highp ivec4 outSize;
631 
632 void main() {
633         outSize = ivec4(textureSize(tex), 0);
634 })";
635 
636     program = CompileProgram(essl31_shaders::vs::Simple(), kFSEnableAndUseExtension);
637     EXPECT_EQ(0u, program);
638 }
639 
640 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is supported in GetInternalformativ.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativ)641 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativ)
642 {
643     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
644 
645     // This query returns supported sample counts in descending order. If only one sample count is
646     // queried, it should be the maximum one.
647     GLint maxSamplesRGBA8 = 0;
648     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
649                           &maxSamplesRGBA8);
650     GLint maxSamplesDepth = 0;
651     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_DEPTH_COMPONENT24, GL_SAMPLES, 1,
652                           &maxSamplesDepth);
653     ASSERT_GL_NO_ERROR();
654 
655     // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
656     GLint maxColorTextureSamples;
657     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
658     GLint maxDepthTextureSamples;
659     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
660     GLint maxSamples;
661     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
662 
663     GLint maxSamplesRGBA8Required = std::min(maxColorTextureSamples, maxSamples);
664     EXPECT_GE(maxSamplesRGBA8, maxSamplesRGBA8Required);
665 
666     GLint maxSamplesDepthRequired = std::min(maxDepthTextureSamples, maxSamples);
667     EXPECT_GE(maxSamplesDepth, maxSamplesDepthRequired);
668 }
669 
670 // Tests that TexImage3D call cannot be used for GL_TEXTURE_2D_MULTISAMPLE_ARRAY.
TEST_P(TextureMultisampleArrayWebGLTest,MultiSampleArrayTexImage)671 TEST_P(TextureMultisampleArrayWebGLTest, MultiSampleArrayTexImage)
672 {
673     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
674 
675     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
676     ASSERT_GL_NO_ERROR();
677 
678     glTexImage3D(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA,
679                  GL_UNSIGNED_BYTE, nullptr);
680     EXPECT_GL_ERROR(GL_INVALID_ENUM);
681 }
682 
683 // Tests passing invalid parameters to TexStorage3DMultisample.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexStorage3DMultisample)684 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexStorage3DMultisample)
685 {
686     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
687 
688     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
689     ASSERT_GL_NO_ERROR();
690 
691     // Invalid target
692     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, 1, GL_TRUE);
693     EXPECT_GL_ERROR(GL_INVALID_ENUM);
694 
695     // Samples 0
696     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1,
697                                  GL_TRUE);
698     EXPECT_GL_ERROR(GL_INVALID_VALUE);
699 
700     // Unsized internalformat
701     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA, 1, 1, 1, GL_TRUE);
702     EXPECT_GL_ERROR(GL_INVALID_ENUM);
703 
704     // Width 0
705     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 0, 1, 1,
706                                  GL_TRUE);
707     EXPECT_GL_ERROR(GL_INVALID_VALUE);
708 
709     // Height 0
710     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 0, 1,
711                                  GL_TRUE);
712     EXPECT_GL_ERROR(GL_INVALID_VALUE);
713 
714     // Depth 0
715     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 1, 0,
716                                  GL_TRUE);
717     EXPECT_GL_ERROR(GL_INVALID_VALUE);
718 }
719 
720 // Tests passing invalid parameters to TexParameteri.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexParameteri)721 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexParameteri)
722 {
723     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
724 
725     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
726     ASSERT_GL_NO_ERROR();
727 
728     // None of the sampler parameters can be set on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES.
729     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
730     EXPECT_GL_ERROR(GL_INVALID_ENUM);
731     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
732     EXPECT_GL_ERROR(GL_INVALID_ENUM);
733 
734     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
735     EXPECT_GL_ERROR(GL_INVALID_ENUM);
736     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
737     EXPECT_GL_ERROR(GL_INVALID_ENUM);
738     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
739     EXPECT_GL_ERROR(GL_INVALID_ENUM);
740 
741     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_LOD, 0);
742     EXPECT_GL_ERROR(GL_INVALID_ENUM);
743     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAX_LOD, 0);
744     EXPECT_GL_ERROR(GL_INVALID_ENUM);
745 
746     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_MODE, GL_NONE);
747     EXPECT_GL_ERROR(GL_INVALID_ENUM);
748     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
749     EXPECT_GL_ERROR(GL_INVALID_ENUM);
750 
751     // Only valid base level on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is 0.
752     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 1);
753     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
754 }
755 
756 // Test a valid TexStorage3DMultisample call and check that the queried texture level parameters
757 // match. Does not do any drawing.
TEST_P(TextureMultisampleArrayWebGLTest,TexStorage3DMultisample)758 TEST_P(TextureMultisampleArrayWebGLTest, TexStorage3DMultisample)
759 {
760     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
761 
762     GLint maxSamplesRGBA8 = 0;
763     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
764                           &maxSamplesRGBA8);
765 
766     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
767     ASSERT_GL_NO_ERROR();
768 
769     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 8,
770                                  4, 2, GL_TRUE);
771     ASSERT_GL_NO_ERROR();
772 
773     GLint width = 0, height = 0, depth = 0, samples = 0;
774     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_WIDTH, &width);
775     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_HEIGHT, &height);
776     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_DEPTH, &depth);
777     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_SAMPLES, &samples);
778     ASSERT_GL_NO_ERROR();
779 
780     EXPECT_EQ(8, width);
781     EXPECT_EQ(4, height);
782     EXPECT_EQ(2, depth);
783     EXPECT_EQ(maxSamplesRGBA8, samples);
784 }
785 
786 // Test for invalid FramebufferTextureLayer calls with GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES
787 // textures.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidFramebufferTextureLayer)788 TEST_P(TextureMultisampleArrayWebGLTest, InvalidFramebufferTextureLayer)
789 {
790     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
791 
792     GLint maxSamplesRGBA8 = 0;
793     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
794                           &maxSamplesRGBA8);
795 
796     GLint maxArrayTextureLayers;
797     glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
798 
799     // Test framebuffer status with just a color texture attached.
800     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
801     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 4,
802                                  4, 2, GL_TRUE);
803     ASSERT_GL_NO_ERROR();
804 
805     // Test with mip level 1 and -1 (only level 0 is valid for multisample textures).
806     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
807     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 1, 0);
808     EXPECT_GL_ERROR(GL_INVALID_VALUE);
809     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, -1, 0);
810     EXPECT_GL_ERROR(GL_INVALID_VALUE);
811 
812     // Test with layer -1 and layer == MAX_ARRAY_TEXTURE_LAYERS
813     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
814     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, -1);
815     EXPECT_GL_ERROR(GL_INVALID_VALUE);
816     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0,
817                               maxArrayTextureLayers);
818     EXPECT_GL_ERROR(GL_INVALID_VALUE);
819 }
820 
821 // Attach layers of TEXTURE_2D_MULTISAMPLE_ARRAY textures to a framebuffer and check for
822 // completeness.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferCompleteness)823 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferCompleteness)
824 {
825     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
826 
827     std::vector<GLenum> testFormats = {{GL_RGBA8, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8}};
828     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
829 
830     // Test framebuffer status with just a color texture attached.
831     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
832     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8, 4, 4,
833                                  2, GL_TRUE);
834     ASSERT_GL_NO_ERROR();
835 
836     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
837     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
838     ASSERT_GL_NO_ERROR();
839 
840     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
841     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
842 
843     // Test framebuffer status with both color and depth textures attached.
844     GLTexture depthTexture;
845     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthTexture);
846     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
847                                  GL_DEPTH_COMPONENT24, 4, 4, 2, GL_TRUE);
848     ASSERT_GL_NO_ERROR();
849 
850     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0);
851     ASSERT_GL_NO_ERROR();
852 
853     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
854     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
855 
856     // Test with color and depth/stencil textures attached.
857     GLTexture depthStencilTexture;
858     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthStencilTexture);
859     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
860                                  GL_DEPTH24_STENCIL8, 4, 4, 2, GL_TRUE);
861     ASSERT_GL_NO_ERROR();
862 
863     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0,
864                               0);
865     ASSERT_GL_NO_ERROR();
866 
867     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
868     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
869 }
870 
871 // Attach a layer of TEXTURE_2D_MULTISAMPLE_ARRAY texture to a framebuffer, clear it, and resolve by
872 // blitting.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferColorClearAndBlit)873 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferColorClearAndBlit)
874 {
875     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
876 
877     const GLsizei kWidth  = 4;
878     const GLsizei kHeight = 4;
879 
880     std::vector<GLenum> testFormats = {GL_RGBA8};
881     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
882 
883     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
884     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
885                                  kWidth, kHeight, 2, GL_TRUE);
886 
887     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
888     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
889 
890     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
891     ASSERT_GL_NO_ERROR();
892     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
893 
894     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
895     glClear(GL_COLOR_BUFFER_BIT);
896 
897     GLFramebuffer resolveFramebuffer;
898     GLTexture resolveTexture;
899     glBindTexture(GL_TEXTURE_2D, resolveTexture);
900     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
901     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
902     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
903                            0);
904     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
905                       GL_NEAREST);
906     ASSERT_GL_NO_ERROR();
907 
908     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
909     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
910 }
911 
912 // Check the size of a multisample array texture in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,TextureSizeInShader)913 TEST_P(TextureMultisampleArrayWebGLTest, TextureSizeInShader)
914 {
915     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
916 
917     constexpr char kFS[] = R"(#version 310 es
918 #extension GL_OES_texture_storage_multisample_2d_array : require
919 
920 uniform highp sampler2DMSArray tex;
921 out highp vec4 my_FragColor;
922 
923 void main() {
924         my_FragColor = (textureSize(tex) == ivec3(8, 4, 2)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
925 })";
926 
927     ANGLE_GL_PROGRAM(texSizeProgram, essl31_shaders::vs::Simple(), kFS);
928 
929     GLint texLocation = glGetUniformLocation(texSizeProgram, "tex");
930     ASSERT_GE(texLocation, 0);
931 
932     const GLsizei kWidth  = 8;
933     const GLsizei kHeight = 4;
934 
935     std::vector<GLenum> testFormats = {GL_RGBA8};
936     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
937 
938     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
939     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
940                                  kWidth, kHeight, 2, GL_TRUE);
941     ASSERT_GL_NO_ERROR();
942 
943     drawQuad(texSizeProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
944     ASSERT_GL_NO_ERROR();
945 
946     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
947 }
948 
949 // Clear the layers of a multisample array texture, and then sample all the samples from all the
950 // layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,SimpleTexelFetch)951 TEST_P(TextureMultisampleArrayWebGLTest, SimpleTexelFetch)
952 {
953     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
954 
955     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
956                      blitArrayTextureLayerFragmentShader());
957 
958     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
959     ASSERT_GE(texLocation, 0);
960     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
961     ASSERT_GE(layerLocation, 0);
962     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
963     ASSERT_GE(layerLocation, 0);
964 
965     const GLsizei kWidth      = 4;
966     const GLsizei kHeight     = 4;
967     const GLsizei kLayerCount = 2;
968 
969     std::vector<GLenum> testFormats = {GL_RGBA8};
970     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
971 
972     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
973     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
974                                  kWidth, kHeight, kLayerCount, GL_TRUE);
975     ASSERT_GL_NO_ERROR();
976 
977     // Clear layer zero to green and layer one to blue.
978     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
979     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
980     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
981     {
982         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
983         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
984         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
985         const GLColor &clearColor = clearColors[i];
986         glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
987                      clearColor.A / 255.0f);
988         glClear(GL_COLOR_BUFFER_BIT);
989         ASSERT_GL_NO_ERROR();
990     }
991 
992     glBindFramebuffer(GL_FRAMEBUFFER, 0);
993     glUseProgram(texelFetchProgram);
994     glViewport(0, 0, kWidth, kHeight);
995     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
996     {
997         glUniform1i(layerLocation, layer);
998         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
999         {
1000             glUniform1i(sampleNumLocation, sampleNum);
1001             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1002             ASSERT_GL_NO_ERROR();
1003             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1004         }
1005     }
1006 }
1007 
1008 // Clear the layers of an integer multisample array texture, and then sample all the samples from
1009 // all the layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,IntegerTexelFetch)1010 TEST_P(TextureMultisampleArrayWebGLTest, IntegerTexelFetch)
1011 {
1012     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
1013 
1014     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
1015                      blitIntArrayTextureLayerFragmentShader());
1016 
1017     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
1018     ASSERT_GE(texLocation, 0);
1019     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
1020     ASSERT_GE(layerLocation, 0);
1021     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
1022     ASSERT_GE(layerLocation, 0);
1023 
1024     const GLsizei kWidth      = 4;
1025     const GLsizei kHeight     = 4;
1026     const GLsizei kLayerCount = 2;
1027 
1028     std::vector<GLenum> testFormats = {GL_RGBA8I};
1029     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
1030 
1031     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
1032     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8I,
1033                                  kWidth, kHeight, kLayerCount, GL_TRUE);
1034     ASSERT_GL_NO_ERROR();
1035 
1036     // Clear layer zero to green and layer one to blue.
1037     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1038     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1039     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1040     {
1041         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1042         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1043         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1044         std::array<GLint, 4> intColor;
1045         for (size_t j = 0; j < intColor.size(); ++j)
1046         {
1047             intColor[j] = clearColors[i][j] / 255;
1048         }
1049         glClearBufferiv(GL_COLOR, 0, intColor.data());
1050         ASSERT_GL_NO_ERROR();
1051     }
1052 
1053     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1054     glUseProgram(texelFetchProgram);
1055     glViewport(0, 0, kWidth, kHeight);
1056     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1057     {
1058         glUniform1i(layerLocation, layer);
1059         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1060         {
1061             glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1062             glClear(GL_COLOR_BUFFER_BIT);
1063             glUniform1i(sampleNumLocation, sampleNum);
1064             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1065             ASSERT_GL_NO_ERROR();
1066             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1067         }
1068     }
1069 }
1070 
1071 class TextureSampleShadingTest : public ANGLETest
1072 {
1073   protected:
TextureSampleShadingTest()1074     TextureSampleShadingTest() {}
1075 };
1076 
1077 // Test that sample shading actually produces different interpolations per sample.  Note that
1078 // variables such as gl_SampleID and gl_SamplePosition are avoided, as well as the |sample|
1079 // qualifier as they automatically enable sample shading.
TEST_P(TextureSampleShadingTest,Basic)1080 TEST_P(TextureSampleShadingTest, Basic)
1081 {
1082     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
1083 
1084     // http://anglebug.com/5410
1085     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
1086     // http://anglebug.com/5412
1087     ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
1088 
1089     constexpr GLsizei kSize        = 1;
1090     constexpr GLsizei kSampleCount = 4;
1091 
1092     // Create a multisampled texture and framebuffer.
1093     GLFramebuffer msaaFBO;
1094     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1095 
1096     GLTexture msaaTexture;
1097     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1098     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
1099                               false);
1100     ASSERT_GL_NO_ERROR();
1101     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1102                            msaaTexture, 0);
1103     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1104 
1105     // Enable sample shading and draw a gradient.
1106     glEnable(GL_SAMPLE_SHADING_OES);
1107     glMinSampleShadingOES(1.0f);
1108 
1109     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1110                      essl31_shaders::fs::RedGreenGradient());
1111     glViewport(0, 0, kSize, kSize);
1112     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1113     ASSERT_GL_NO_ERROR();
1114 
1115     // Create a buffer for verification.
1116     constexpr GLsizei kPixelChannels = 4;
1117     constexpr GLsizei kBufferSize =
1118         kSize * kSize * kSampleCount * kPixelChannels * sizeof(uint32_t);
1119     GLBuffer buffer;
1120     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1121     glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
1122     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
1123 
1124     // Issue a dispatch call that copies the multisampled texture into a buffer.
1125     constexpr char kCS[] = R"(#version 310 es
1126 layout(local_size_x=4, local_size_y=1, local_size_z=1) in;
1127 
1128 uniform highp sampler2DMS imageIn;
1129 layout(std430, binding = 0) buffer dataOut {
1130     uint data[];
1131 };
1132 
1133 void main()
1134 {
1135     int sampleIndex = int(gl_GlobalInvocationID.x) % 4;
1136 
1137     vec4 color = texelFetch(imageIn, ivec2(0), sampleIndex);
1138     uvec4 unnormalized = uvec4(color * 255.0);
1139 
1140     int outIndex = sampleIndex * 4;
1141 
1142     data[outIndex    ] = unnormalized.r;
1143     data[outIndex + 1] = unnormalized.g;
1144     data[outIndex + 2] = unnormalized.b;
1145     data[outIndex + 3] = unnormalized.a;
1146 })";
1147 
1148     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1149     glUseProgram(program);
1150 
1151     // Bind the multisampled texture as sampler.
1152     GLint imageLocation = glGetUniformLocation(program, "imageIn");
1153     ASSERT_GE(imageLocation, 0);
1154 
1155     glActiveTexture(GL_TEXTURE0);
1156     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1157     glUniform1i(imageLocation, 0);
1158 
1159     glDispatchCompute(1, 1, 1);
1160     EXPECT_GL_NO_ERROR();
1161 
1162     // Verify that the buffer has correct data.
1163     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1164 
1165     const uint32_t *ptr = reinterpret_cast<uint32_t *>(
1166         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
1167     constexpr GLColor kExpectedColors[4] = {
1168         GLColor(96, 32, 0, 255),
1169         GLColor(223, 96, 0, 255),
1170         GLColor(32, 159, 0, 255),
1171         GLColor(159, 223, 0, 255),
1172     };
1173     for (GLsizei pixel = 0; pixel < kSampleCount; ++pixel)
1174     {
1175         for (GLsizei channel = 0; channel < kPixelChannels; ++channel)
1176         {
1177             EXPECT_NEAR(ptr[pixel * kPixelChannels + channel], kExpectedColors[pixel][channel], 1)
1178                 << pixel << " " << channel;
1179         }
1180     }
1181 
1182     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1183 }
1184 
1185 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleTest);
1186 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(TextureMultisampleTest);
1187 
1188 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NegativeTextureMultisampleTest);
1189 ANGLE_INSTANTIATE_TEST_ES3(NegativeTextureMultisampleTest);
1190 
1191 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleArrayWebGLTest);
1192 ANGLE_INSTANTIATE_TEST_ES31(TextureMultisampleArrayWebGLTest);
1193 
1194 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSampleShadingTest);
1195 ANGLE_INSTANTIATE_TEST_ES31(TextureSampleShadingTest);
1196 }  // anonymous namespace
1197