1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // TextureMultisampleTest: Tests of multisampled texture
8
9 #include "test_utils/ANGLETest.h"
10
11 #include "test_utils/gl_raii.h"
12 #include "util/shader_utils.h"
13
14 using namespace angle;
15
16 namespace
17 {
18 // Sample positions of d3d standard pattern. Some of the sample positions might not the same as
19 // opengl.
20 using SamplePositionsArray = std::array<float, 32>;
21 static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
22 {{{0.5f, 0.5f}},
23 {{0.75f, 0.75f, 0.25f, 0.25f}},
24 {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
25 {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
26 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
27 {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
28 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
29 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
30 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
31
32 class TextureMultisampleTest : public ANGLETest
33 {
34 protected:
TextureMultisampleTest()35 TextureMultisampleTest()
36 {
37 setWindowWidth(64);
38 setWindowHeight(64);
39 setConfigRedBits(8);
40 setConfigGreenBits(8);
41 setConfigBlueBits(8);
42 setConfigAlphaBits(8);
43 }
44
testSetUp()45 void testSetUp() override
46 {
47 glGenFramebuffers(1, &mFramebuffer);
48 glGenTextures(1, &mTexture);
49
50 ASSERT_GL_NO_ERROR();
51 }
52
testTearDown()53 void testTearDown() override
54 {
55 glDeleteFramebuffers(1, &mFramebuffer);
56 mFramebuffer = 0;
57 glDeleteTextures(1, &mTexture);
58 mTexture = 0;
59 }
60
61 void texStorageMultisample(GLenum target,
62 GLint samples,
63 GLenum format,
64 GLsizei width,
65 GLsizei height,
66 GLboolean fixedsamplelocations);
67
68 void getTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params);
69 void getTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
70
71 void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
72 void sampleMaski(GLuint maskNumber, GLbitfield mask);
73
74 GLuint mFramebuffer = 0;
75 GLuint mTexture = 0;
76
77 // Returns a sample count that can be used with the given texture target for all the given
78 // formats. Assumes that if format A supports a number of samples N and another format B
79 // supports a number of samples M > N then format B also supports number of samples N.
getSamplesToUse(GLenum texTarget,const std::vector<GLenum> & formats)80 GLint getSamplesToUse(GLenum texTarget, const std::vector<GLenum> &formats)
81 {
82 GLint maxSamples = 65536;
83 for (GLenum format : formats)
84 {
85 GLint maxSamplesFormat = 0;
86 glGetInternalformativ(texTarget, format, GL_SAMPLES, 1, &maxSamplesFormat);
87 maxSamples = std::min(maxSamples, maxSamplesFormat);
88 }
89 return maxSamples;
90 }
91
lessThanES31MultisampleExtNotSupported()92 bool lessThanES31MultisampleExtNotSupported()
93 {
94 return getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
95 !EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample");
96 }
97
multisampleTextureFragmentShader()98 const char *multisampleTextureFragmentShader()
99 {
100 return R"(#version 300 es
101 #extension GL_ANGLE_texture_multisample : require
102 precision highp float;
103 precision highp int;
104
105 uniform highp sampler2DMS tex;
106 uniform int sampleNum;
107
108 in vec4 v_position;
109 out vec4 my_FragColor;
110
111 void main() {
112 ivec2 texSize = textureSize(tex);
113 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
114 my_FragColor = texelFetch(tex, sampleCoords, sampleNum);
115 }
116 )";
117 }
118
blitArrayTextureLayerFragmentShader()119 const char *blitArrayTextureLayerFragmentShader()
120 {
121 return R"(#version 310 es
122 #extension GL_OES_texture_storage_multisample_2d_array : require
123 precision highp float;
124 precision highp int;
125
126 uniform highp sampler2DMSArray tex;
127 uniform int layer;
128 uniform int sampleNum;
129
130 in vec4 v_position;
131 out vec4 my_FragColor;
132
133 void main() {
134 ivec3 texSize = textureSize(tex);
135 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
136 my_FragColor = texelFetch(tex, ivec3(sampleCoords, layer), sampleNum);
137 }
138 )";
139 }
140
blitIntArrayTextureLayerFragmentShader()141 const char *blitIntArrayTextureLayerFragmentShader()
142 {
143 return R"(#version 310 es
144 #extension GL_OES_texture_storage_multisample_2d_array : require
145 precision highp float;
146 precision highp int;
147
148 uniform highp isampler2DMSArray tex;
149 uniform int layer;
150 uniform int sampleNum;
151
152 in vec4 v_position;
153 out vec4 my_FragColor;
154
155 void main() {
156 ivec3 texSize = textureSize(tex);
157 ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
158 my_FragColor = vec4(texelFetch(tex, ivec3(sampleCoords, layer), sampleNum));
159 }
160 )";
161 }
162 };
163
164 class NegativeTextureMultisampleTest : public TextureMultisampleTest
165 {
166 protected:
NegativeTextureMultisampleTest()167 NegativeTextureMultisampleTest() : TextureMultisampleTest() {}
168 };
169
170 class TextureMultisampleArrayWebGLTest : public TextureMultisampleTest
171 {
172 protected:
TextureMultisampleArrayWebGLTest()173 TextureMultisampleArrayWebGLTest() : TextureMultisampleTest()
174 {
175 // These tests run in WebGL mode so we can test with both extension off and on.
176 setWebGLCompatibilityEnabled(true);
177 }
178
179 // Requests the ANGLE_texture_multisample_array extension and returns true if the operation
180 // succeeds.
requestArrayExtension()181 bool requestArrayExtension()
182 {
183 if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
184 {
185 glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
186 }
187
188 if (!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"))
189 {
190 return false;
191 }
192 return true;
193 }
194 };
195
texStorageMultisample(GLenum target,GLint samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)196 void TextureMultisampleTest::texStorageMultisample(GLenum target,
197 GLint samples,
198 GLenum internalformat,
199 GLsizei width,
200 GLsizei height,
201 GLboolean fixedsamplelocations)
202 {
203 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
204 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
205 {
206 glTexStorage2DMultisampleANGLE(target, samples, internalformat, width, height,
207 fixedsamplelocations);
208 }
209 else
210 {
211 glTexStorage2DMultisample(target, samples, internalformat, width, height,
212 fixedsamplelocations);
213 }
214 }
215
getTexLevelParameterfv(GLenum target,GLint level,GLenum pname,GLfloat * params)216 void TextureMultisampleTest::getTexLevelParameterfv(GLenum target,
217 GLint level,
218 GLenum pname,
219 GLfloat *params)
220 {
221 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
222 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
223 {
224 glGetTexLevelParameterfvANGLE(target, level, pname, params);
225 }
226 else
227 {
228 glGetTexLevelParameterfv(target, level, pname, params);
229 }
230 }
231
getTexLevelParameteriv(GLenum target,GLint level,GLenum pname,GLint * params)232 void TextureMultisampleTest::getTexLevelParameteriv(GLenum target,
233 GLint level,
234 GLenum pname,
235 GLint *params)
236 {
237 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
238 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
239 {
240 glGetTexLevelParameterivANGLE(target, level, pname, params);
241 }
242 else
243 {
244 glGetTexLevelParameteriv(target, level, pname, params);
245 }
246 }
247
getMultisamplefv(GLenum pname,GLuint index,GLfloat * val)248 void TextureMultisampleTest::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
249 {
250 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
251 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
252 {
253 glGetMultisamplefvANGLE(pname, index, val);
254 }
255 else
256 {
257 glGetMultisamplefv(pname, index, val);
258 }
259 }
260
sampleMaski(GLuint maskNumber,GLbitfield mask)261 void TextureMultisampleTest::sampleMaski(GLuint maskNumber, GLbitfield mask)
262 {
263 if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
264 EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
265 {
266 glSampleMaskiANGLE(maskNumber, mask);
267 }
268 else
269 {
270 glSampleMaski(maskNumber, mask);
271 }
272 }
273
274 // Tests that if es version < 3.1, GL_TEXTURE_2D_MULTISAMPLE is not supported in
275 // GetInternalformativ. Checks that the number of samples returned is valid in case of ES >= 3.1.
TEST_P(TextureMultisampleTest,MultisampleTargetGetInternalFormativBase)276 TEST_P(TextureMultisampleTest, MultisampleTargetGetInternalFormativBase)
277 {
278 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
279
280 // This query returns supported sample counts in descending order. If only one sample count is
281 // queried, it should be the maximum one.
282 GLint maxSamplesR8 = 0;
283 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamplesR8);
284
285 // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
286 GLint maxColorTextureSamples;
287 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
288 GLint maxSamples;
289 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
290 GLint maxSamplesR8Required = std::min(maxColorTextureSamples, maxSamples);
291
292 EXPECT_GE(maxSamplesR8, maxSamplesR8Required);
293 ASSERT_GL_NO_ERROR();
294 }
295
296 // Tests that if es version < 3.1 and multisample extension is unsupported,
297 // GL_TEXTURE_2D_MULTISAMPLE_ANGLE is not supported in FramebufferTexture2D.
TEST_P(TextureMultisampleTest,MultisampleTargetFramebufferTexture2D)298 TEST_P(TextureMultisampleTest, MultisampleTargetFramebufferTexture2D)
299 {
300 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
301 // http://anglebug.com/4092
302 ANGLE_SKIP_TEST_IF(IsVulkan());
303 GLint samples = 1;
304 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
305 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, 64, 64, GL_FALSE);
306
307 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
308 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
309 mTexture, 0);
310
311 ASSERT_GL_NO_ERROR();
312 }
313
314 // Tests basic functionality of glTexStorage2DMultisample.
TEST_P(TextureMultisampleTest,ValidateTextureStorageMultisampleParameters)315 TEST_P(TextureMultisampleTest, ValidateTextureStorageMultisampleParameters)
316 {
317 // http://anglebug.com/4092
318 ANGLE_SKIP_TEST_IF(IsVulkan());
319 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
320
321 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
322 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
323 ASSERT_GL_NO_ERROR();
324
325 GLint params = 0;
326 glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, ¶ms);
327 EXPECT_EQ(1, params);
328
329 texStorageMultisample(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, GL_FALSE);
330 ASSERT_GL_ERROR(GL_INVALID_ENUM);
331
332 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 0, 0, GL_FALSE);
333 ASSERT_GL_ERROR(GL_INVALID_VALUE);
334
335 GLint maxSize = 0;
336 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
337 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, maxSize + 1, 1, GL_FALSE);
338 ASSERT_GL_ERROR(GL_INVALID_VALUE);
339
340 GLint maxSamples = 0;
341 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
342 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples + 1, GL_RGBA8, 1, 1, GL_FALSE);
343 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
344
345 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_RGBA8, 1, 1, GL_FALSE);
346 ASSERT_GL_ERROR(GL_INVALID_VALUE);
347
348 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA, 0, 0, GL_FALSE);
349 ASSERT_GL_ERROR(GL_INVALID_VALUE);
350
351 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
352 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
353 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
354 }
355
356 // Tests the value of MAX_INTEGER_SAMPLES is no less than 1.
357 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxIntegerSamples)358 TEST_P(TextureMultisampleTest, MaxIntegerSamples)
359 {
360 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
361 GLint maxIntegerSamples;
362 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
363 EXPECT_GE(maxIntegerSamples, 1);
364 EXPECT_NE(std::numeric_limits<GLint>::max(), maxIntegerSamples);
365 }
366
367 // Tests the value of MAX_COLOR_TEXTURE_SAMPLES is no less than 1.
368 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxColorTextureSamples)369 TEST_P(TextureMultisampleTest, MaxColorTextureSamples)
370 {
371 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
372 GLint maxColorTextureSamples;
373 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
374 EXPECT_GE(maxColorTextureSamples, 1);
375 EXPECT_NE(std::numeric_limits<GLint>::max(), maxColorTextureSamples);
376 }
377
378 // Tests the value of MAX_DEPTH_TEXTURE_SAMPLES is no less than 1.
379 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxDepthTextureSamples)380 TEST_P(TextureMultisampleTest, MaxDepthTextureSamples)
381 {
382 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
383 GLint maxDepthTextureSamples;
384 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
385 EXPECT_GE(maxDepthTextureSamples, 1);
386 EXPECT_NE(std::numeric_limits<GLint>::max(), maxDepthTextureSamples);
387 }
388
389 // Tests that getTexLevelParameter is supported by ES 3.1 or ES 3.0 and ANGLE_texture_multisample
TEST_P(TextureMultisampleTest,GetTexLevelParameter)390 TEST_P(TextureMultisampleTest, GetTexLevelParameter)
391 {
392 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
393 // http://anglebug.com/4092
394 ANGLE_SKIP_TEST_IF(IsVulkan());
395
396 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
397 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, GL_TRUE);
398 ASSERT_GL_NO_ERROR();
399
400 GLfloat levelSamples = 0;
401 getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
402 EXPECT_EQ(levelSamples, 4);
403
404 GLint fixedSampleLocation = false;
405 getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
406 &fixedSampleLocation);
407 EXPECT_EQ(fixedSampleLocation, 1);
408
409 ASSERT_GL_NO_ERROR();
410 }
411
412 // The value of sample position should be equal to standard pattern on D3D.
TEST_P(TextureMultisampleTest,CheckSamplePositions)413 TEST_P(TextureMultisampleTest, CheckSamplePositions)
414 {
415 ANGLE_SKIP_TEST_IF(!IsD3D11());
416
417 GLsizei maxSamples = 0;
418 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
419
420 GLfloat samplePosition[2];
421
422 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
423
424 for (int sampleCount = 1; sampleCount <= maxSamples; sampleCount++)
425 {
426 GLTexture texture;
427 size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
428 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
429 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE);
430 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
431 texture, 0);
432 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
433 ASSERT_GL_NO_ERROR();
434
435 for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
436 {
437 getMultisamplefv(GL_SAMPLE_POSITION, sampleIndex, samplePosition);
438 EXPECT_EQ(samplePosition[0], kSamplePositions[indexKey][2 * sampleIndex]);
439 EXPECT_EQ(samplePosition[1], kSamplePositions[indexKey][2 * sampleIndex + 1]);
440 }
441 }
442
443 ASSERT_GL_NO_ERROR();
444 }
445
446 // Test textureSize and texelFetch when using ANGLE_texture_multisample extension
TEST_P(TextureMultisampleTest,SimpleTexelFetch)447 TEST_P(TextureMultisampleTest, SimpleTexelFetch)
448 {
449 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
450
451 ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(),
452 multisampleTextureFragmentShader());
453
454 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
455 ASSERT_GE(texLocation, 0);
456 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
457 ASSERT_GE(sampleNumLocation, 0);
458
459 const GLsizei kWidth = 4;
460 const GLsizei kHeight = 4;
461
462 std::vector<GLenum> testFormats = {GL_RGBA8};
463 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, testFormats);
464
465 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, mTexture);
466 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, samplesToUse, GL_RGBA8, kWidth, kHeight,
467 GL_TRUE);
468 ASSERT_GL_NO_ERROR();
469
470 // Clear texture zero to green.
471 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
472 GLColor clearColor = GLColor::green;
473
474 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE_ANGLE,
475 mTexture, 0);
476 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
477 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
478 glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
479 clearColor.A / 255.0f);
480 glClear(GL_COLOR_BUFFER_BIT);
481 ASSERT_GL_NO_ERROR();
482
483 glBindFramebuffer(GL_FRAMEBUFFER, 0);
484 glUseProgram(texelFetchProgram);
485 glViewport(0, 0, kWidth, kHeight);
486
487 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
488 {
489 glUniform1i(sampleNumLocation, sampleNum);
490 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
491 ASSERT_GL_NO_ERROR();
492 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColor);
493 }
494 }
495
TEST_P(TextureMultisampleTest,SampleMaski)496 TEST_P(TextureMultisampleTest, SampleMaski)
497 {
498 ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
499
500 GLint maxSampleMaskWords = 0;
501 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
502 sampleMaski(maxSampleMaskWords - 1, 0x1);
503 ASSERT_GL_NO_ERROR();
504
505 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
506 sampleMaski(maxSampleMaskWords, 0x1);
507 ASSERT_GL_ERROR(GL_INVALID_VALUE);
508 }
509
510 // Negative tests of multisample texture. When context less than ES 3.1 and ANGLE_texture_multsample
511 // not enabled, the feature isn't supported.
TEST_P(NegativeTextureMultisampleTest,Negtive)512 TEST_P(NegativeTextureMultisampleTest, Negtive)
513 {
514 ANGLE_SKIP_TEST_IF(EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
515
516 GLint maxSamples = 0;
517 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
518 ASSERT_GL_ERROR(GL_INVALID_ENUM);
519
520 GLint maxColorTextureSamples;
521 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
522 ASSERT_GL_ERROR(GL_INVALID_ENUM);
523
524 GLint maxDepthTextureSamples;
525 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
526 ASSERT_GL_ERROR(GL_INVALID_ENUM);
527
528 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
529 ASSERT_GL_ERROR(GL_INVALID_ENUM);
530
531 texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 64, 64, GL_FALSE);
532 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
533
534 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
535 mTexture, 0);
536 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
537
538 GLint params = 0;
539 glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, ¶ms);
540 ASSERT_GL_ERROR(GL_INVALID_ENUM);
541
542 GLfloat levelSamples = 0;
543 getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
544 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
545
546 GLint fixedSampleLocation = false;
547 getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
548 &fixedSampleLocation);
549 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
550
551 GLint maxSampleMaskWords = 0;
552 glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
553 ASSERT_GL_ERROR(GL_INVALID_ENUM);
554 sampleMaski(maxSampleMaskWords - 1, 0x1);
555 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
556 }
557
558 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GetInternalformativ when the
559 // extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativWithoutExtension)560 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativWithoutExtension)
561 {
562 GLint maxSamples = 0;
563 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
564 &maxSamples);
565 ASSERT_GL_ERROR(GL_INVALID_ENUM);
566 }
567
568 // Attempt to bind a texture to multisample array binding point when extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,BindMultisampleArrayTextureWithoutExtension)569 TEST_P(TextureMultisampleArrayWebGLTest, BindMultisampleArrayTextureWithoutExtension)
570 {
571 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
572 ASSERT_GL_ERROR(GL_INVALID_ENUM);
573 }
574
575 // Try to compile shaders using GL_OES_texture_storage_multisample_2d_array when the extension is
576 // not enabled.
TEST_P(TextureMultisampleArrayWebGLTest,ShaderWithoutExtension)577 TEST_P(TextureMultisampleArrayWebGLTest, ShaderWithoutExtension)
578 {
579 constexpr char kFSRequiresExtension[] = R"(#version 310 es
580 #extension GL_OES_texture_storage_multisample_2d_array : require
581 out highp vec4 my_FragColor;
582
583 void main() {
584 my_FragColor = vec4(0.0);
585 })";
586
587 GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFSRequiresExtension);
588 EXPECT_EQ(0u, program);
589
590 constexpr char kFSEnableAndUseExtension[] = R"(#version 310 es
591 #extension GL_OES_texture_storage_multisample_2d_array : enable
592
593 uniform highp sampler2DMSArray tex;
594 out highp ivec4 outSize;
595
596 void main() {
597 outSize = ivec4(textureSize(tex), 0);
598 })";
599
600 program = CompileProgram(essl31_shaders::vs::Simple(), kFSEnableAndUseExtension);
601 EXPECT_EQ(0u, program);
602 }
603
604 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is supported in GetInternalformativ.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativ)605 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativ)
606 {
607 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
608
609 // This query returns supported sample counts in descending order. If only one sample count is
610 // queried, it should be the maximum one.
611 GLint maxSamplesRGBA8 = 0;
612 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
613 &maxSamplesRGBA8);
614 GLint maxSamplesDepth = 0;
615 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_DEPTH_COMPONENT24, GL_SAMPLES, 1,
616 &maxSamplesDepth);
617 ASSERT_GL_NO_ERROR();
618
619 // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
620 GLint maxColorTextureSamples;
621 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
622 GLint maxDepthTextureSamples;
623 glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
624 GLint maxSamples;
625 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
626
627 GLint maxSamplesRGBA8Required = std::min(maxColorTextureSamples, maxSamples);
628 EXPECT_GE(maxSamplesRGBA8, maxSamplesRGBA8Required);
629
630 GLint maxSamplesDepthRequired = std::min(maxDepthTextureSamples, maxSamples);
631 EXPECT_GE(maxSamplesDepth, maxSamplesDepthRequired);
632 }
633
634 // Tests that TexImage3D call cannot be used for GL_TEXTURE_2D_MULTISAMPLE_ARRAY.
TEST_P(TextureMultisampleArrayWebGLTest,MultiSampleArrayTexImage)635 TEST_P(TextureMultisampleArrayWebGLTest, MultiSampleArrayTexImage)
636 {
637 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
638
639 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
640 ASSERT_GL_NO_ERROR();
641
642 glTexImage3D(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA,
643 GL_UNSIGNED_BYTE, nullptr);
644 EXPECT_GL_ERROR(GL_INVALID_ENUM);
645 }
646
647 // Tests passing invalid parameters to TexStorage3DMultisample.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexStorage3DMultisample)648 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexStorage3DMultisample)
649 {
650 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
651
652 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
653 ASSERT_GL_NO_ERROR();
654
655 // Invalid target
656 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, 1, GL_TRUE);
657 EXPECT_GL_ERROR(GL_INVALID_ENUM);
658
659 // Samples 0
660 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1,
661 GL_TRUE);
662 EXPECT_GL_ERROR(GL_INVALID_VALUE);
663
664 // Unsized internalformat
665 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA, 1, 1, 1, GL_TRUE);
666 EXPECT_GL_ERROR(GL_INVALID_ENUM);
667
668 // Width 0
669 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 0, 1, 1,
670 GL_TRUE);
671 EXPECT_GL_ERROR(GL_INVALID_VALUE);
672
673 // Height 0
674 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 0, 1,
675 GL_TRUE);
676 EXPECT_GL_ERROR(GL_INVALID_VALUE);
677
678 // Depth 0
679 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 1, 0,
680 GL_TRUE);
681 EXPECT_GL_ERROR(GL_INVALID_VALUE);
682 }
683
684 // Tests passing invalid parameters to TexParameteri.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexParameteri)685 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexParameteri)
686 {
687 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
688
689 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
690 ASSERT_GL_NO_ERROR();
691
692 // None of the sampler parameters can be set on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES.
693 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
694 EXPECT_GL_ERROR(GL_INVALID_ENUM);
695 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
696 EXPECT_GL_ERROR(GL_INVALID_ENUM);
697
698 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
699 EXPECT_GL_ERROR(GL_INVALID_ENUM);
700 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
701 EXPECT_GL_ERROR(GL_INVALID_ENUM);
702 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
703 EXPECT_GL_ERROR(GL_INVALID_ENUM);
704
705 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_LOD, 0);
706 EXPECT_GL_ERROR(GL_INVALID_ENUM);
707 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAX_LOD, 0);
708 EXPECT_GL_ERROR(GL_INVALID_ENUM);
709
710 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_MODE, GL_NONE);
711 EXPECT_GL_ERROR(GL_INVALID_ENUM);
712 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
713 EXPECT_GL_ERROR(GL_INVALID_ENUM);
714
715 // Only valid base level on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is 0.
716 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 1);
717 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
718 }
719
720 // Test a valid TexStorage3DMultisample call and check that the queried texture level parameters
721 // match. Does not do any drawing.
TEST_P(TextureMultisampleArrayWebGLTest,TexStorage3DMultisample)722 TEST_P(TextureMultisampleArrayWebGLTest, TexStorage3DMultisample)
723 {
724 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
725
726 GLint maxSamplesRGBA8 = 0;
727 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
728 &maxSamplesRGBA8);
729
730 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
731 ASSERT_GL_NO_ERROR();
732
733 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 8,
734 4, 2, GL_TRUE);
735 ASSERT_GL_NO_ERROR();
736
737 GLint width = 0, height = 0, depth = 0, samples = 0;
738 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_WIDTH, &width);
739 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_HEIGHT, &height);
740 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_DEPTH, &depth);
741 glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_SAMPLES, &samples);
742 ASSERT_GL_NO_ERROR();
743
744 EXPECT_EQ(8, width);
745 EXPECT_EQ(4, height);
746 EXPECT_EQ(2, depth);
747 EXPECT_EQ(maxSamplesRGBA8, samples);
748 }
749
750 // Test for invalid FramebufferTextureLayer calls with GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES
751 // textures.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidFramebufferTextureLayer)752 TEST_P(TextureMultisampleArrayWebGLTest, InvalidFramebufferTextureLayer)
753 {
754 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
755
756 GLint maxSamplesRGBA8 = 0;
757 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
758 &maxSamplesRGBA8);
759
760 GLint maxArrayTextureLayers;
761 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
762
763 // Test framebuffer status with just a color texture attached.
764 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
765 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 4,
766 4, 2, GL_TRUE);
767 ASSERT_GL_NO_ERROR();
768
769 // Test with mip level 1 and -1 (only level 0 is valid for multisample textures).
770 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
771 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 1, 0);
772 EXPECT_GL_ERROR(GL_INVALID_VALUE);
773 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, -1, 0);
774 EXPECT_GL_ERROR(GL_INVALID_VALUE);
775
776 // Test with layer -1 and layer == MAX_ARRAY_TEXTURE_LAYERS
777 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
778 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, -1);
779 EXPECT_GL_ERROR(GL_INVALID_VALUE);
780 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0,
781 maxArrayTextureLayers);
782 EXPECT_GL_ERROR(GL_INVALID_VALUE);
783 }
784
785 // Attach layers of TEXTURE_2D_MULTISAMPLE_ARRAY textures to a framebuffer and check for
786 // completeness.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferCompleteness)787 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferCompleteness)
788 {
789 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
790
791 std::vector<GLenum> testFormats = {{GL_RGBA8, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8}};
792 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
793
794 // Test framebuffer status with just a color texture attached.
795 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
796 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8, 4, 4,
797 2, GL_TRUE);
798 ASSERT_GL_NO_ERROR();
799
800 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
801 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
802 ASSERT_GL_NO_ERROR();
803
804 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
805 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
806
807 // Test framebuffer status with both color and depth textures attached.
808 GLTexture depthTexture;
809 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthTexture);
810 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
811 GL_DEPTH_COMPONENT24, 4, 4, 2, GL_TRUE);
812 ASSERT_GL_NO_ERROR();
813
814 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0);
815 ASSERT_GL_NO_ERROR();
816
817 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
818 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
819
820 // Test with color and depth/stencil textures attached.
821 GLTexture depthStencilTexture;
822 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthStencilTexture);
823 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
824 GL_DEPTH24_STENCIL8, 4, 4, 2, GL_TRUE);
825 ASSERT_GL_NO_ERROR();
826
827 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0,
828 0);
829 ASSERT_GL_NO_ERROR();
830
831 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
832 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
833 }
834
835 // Attach a layer of TEXTURE_2D_MULTISAMPLE_ARRAY texture to a framebuffer, clear it, and resolve by
836 // blitting.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferColorClearAndBlit)837 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferColorClearAndBlit)
838 {
839 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
840
841 const GLsizei kWidth = 4;
842 const GLsizei kHeight = 4;
843
844 std::vector<GLenum> testFormats = {GL_RGBA8};
845 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
846
847 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
848 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
849 kWidth, kHeight, 2, GL_TRUE);
850
851 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
852 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
853
854 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
855 ASSERT_GL_NO_ERROR();
856 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
857
858 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
859 glClear(GL_COLOR_BUFFER_BIT);
860
861 GLFramebuffer resolveFramebuffer;
862 GLTexture resolveTexture;
863 glBindTexture(GL_TEXTURE_2D, resolveTexture);
864 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
865 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
866 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
867 0);
868 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
869 GL_NEAREST);
870 ASSERT_GL_NO_ERROR();
871
872 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
873 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
874 }
875
876 // Check the size of a multisample array texture in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,TextureSizeInShader)877 TEST_P(TextureMultisampleArrayWebGLTest, TextureSizeInShader)
878 {
879 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
880
881 constexpr char kFS[] = R"(#version 310 es
882 #extension GL_OES_texture_storage_multisample_2d_array : require
883
884 uniform highp sampler2DMSArray tex;
885 out highp vec4 my_FragColor;
886
887 void main() {
888 my_FragColor = (textureSize(tex) == ivec3(8, 4, 2)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
889 })";
890
891 ANGLE_GL_PROGRAM(texSizeProgram, essl31_shaders::vs::Simple(), kFS);
892
893 GLint texLocation = glGetUniformLocation(texSizeProgram, "tex");
894 ASSERT_GE(texLocation, 0);
895
896 const GLsizei kWidth = 8;
897 const GLsizei kHeight = 4;
898
899 std::vector<GLenum> testFormats = {GL_RGBA8};
900 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
901
902 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
903 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
904 kWidth, kHeight, 2, GL_TRUE);
905 ASSERT_GL_NO_ERROR();
906
907 drawQuad(texSizeProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
908 ASSERT_GL_NO_ERROR();
909
910 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
911 }
912
913 // Clear the layers of a multisample array texture, and then sample all the samples from all the
914 // layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,SimpleTexelFetch)915 TEST_P(TextureMultisampleArrayWebGLTest, SimpleTexelFetch)
916 {
917 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
918
919 ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
920 blitArrayTextureLayerFragmentShader());
921
922 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
923 ASSERT_GE(texLocation, 0);
924 GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
925 ASSERT_GE(layerLocation, 0);
926 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
927 ASSERT_GE(layerLocation, 0);
928
929 const GLsizei kWidth = 4;
930 const GLsizei kHeight = 4;
931 const GLsizei kLayerCount = 2;
932
933 std::vector<GLenum> testFormats = {GL_RGBA8};
934 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
935
936 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
937 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
938 kWidth, kHeight, kLayerCount, GL_TRUE);
939 ASSERT_GL_NO_ERROR();
940
941 // Clear layer zero to green and layer one to blue.
942 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
943 std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
944 for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
945 {
946 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
947 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
948 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
949 const GLColor &clearColor = clearColors[i];
950 glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
951 clearColor.A / 255.0f);
952 glClear(GL_COLOR_BUFFER_BIT);
953 ASSERT_GL_NO_ERROR();
954 }
955
956 glBindFramebuffer(GL_FRAMEBUFFER, 0);
957 glUseProgram(texelFetchProgram);
958 glViewport(0, 0, kWidth, kHeight);
959 for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
960 {
961 glUniform1i(layerLocation, layer);
962 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
963 {
964 glUniform1i(sampleNumLocation, sampleNum);
965 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
966 ASSERT_GL_NO_ERROR();
967 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
968 }
969 }
970 }
971
972 // Clear the layers of an integer multisample array texture, and then sample all the samples from
973 // all the layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,IntegerTexelFetch)974 TEST_P(TextureMultisampleArrayWebGLTest, IntegerTexelFetch)
975 {
976 ANGLE_SKIP_TEST_IF(!requestArrayExtension());
977
978 ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
979 blitIntArrayTextureLayerFragmentShader());
980
981 GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
982 ASSERT_GE(texLocation, 0);
983 GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
984 ASSERT_GE(layerLocation, 0);
985 GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
986 ASSERT_GE(layerLocation, 0);
987
988 const GLsizei kWidth = 4;
989 const GLsizei kHeight = 4;
990 const GLsizei kLayerCount = 2;
991
992 std::vector<GLenum> testFormats = {GL_RGBA8I};
993 GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
994
995 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
996 glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8I,
997 kWidth, kHeight, kLayerCount, GL_TRUE);
998 ASSERT_GL_NO_ERROR();
999
1000 // Clear layer zero to green and layer one to blue.
1001 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1002 std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1003 for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1004 {
1005 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1006 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1007 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1008 std::array<GLint, 4> intColor;
1009 for (size_t j = 0; j < intColor.size(); ++j)
1010 {
1011 intColor[j] = clearColors[i][j] / 255;
1012 }
1013 glClearBufferiv(GL_COLOR, 0, intColor.data());
1014 ASSERT_GL_NO_ERROR();
1015 }
1016
1017 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1018 glUseProgram(texelFetchProgram);
1019 glViewport(0, 0, kWidth, kHeight);
1020 for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1021 {
1022 glUniform1i(layerLocation, layer);
1023 for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1024 {
1025 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1026 glClear(GL_COLOR_BUFFER_BIT);
1027 glUniform1i(sampleNumLocation, sampleNum);
1028 drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1029 ASSERT_GL_NO_ERROR();
1030 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1031 }
1032 }
1033 }
1034
1035 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(TextureMultisampleTest);
1036 ANGLE_INSTANTIATE_TEST_ES3(NegativeTextureMultisampleTest);
1037 ANGLE_INSTANTIATE_TEST_ES31(TextureMultisampleArrayWebGLTest);
1038 } // anonymous namespace
1039