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