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