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, ¶ms);
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, ¶ms);
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