1 //
2 // Copyright 2015 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 // StateChangeTest:
7 // Specifically designed for an ANGLE implementation of GL, these tests validate that
8 // ANGLE's dirty bits systems don't get confused by certain sequences of state changes.
9 //
10
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 #include "util/random_utils.h"
14
15 #include <thread>
16
17 using namespace angle;
18
19 namespace
20 {
21
22 class StateChangeTest : public ANGLETest<>
23 {
24 protected:
StateChangeTest()25 StateChangeTest()
26 {
27 setWindowWidth(64);
28 setWindowHeight(64);
29 setConfigRedBits(8);
30 setConfigGreenBits(8);
31 setConfigBlueBits(8);
32 setConfigAlphaBits(8);
33 setConfigDepthBits(24);
34 setConfigStencilBits(8);
35
36 // Enable the no error extension to avoid syncing the FBO state on validation.
37 setNoErrorEnabled(true);
38 }
39
testSetUp()40 void testSetUp() override
41 {
42 glGenFramebuffers(1, &mFramebuffer);
43 glGenTextures(2, mTextures.data());
44 glGenRenderbuffers(1, &mRenderbuffer);
45
46 ASSERT_GL_NO_ERROR();
47 }
48
testTearDown()49 void testTearDown() override
50 {
51 if (mFramebuffer != 0)
52 {
53 glDeleteFramebuffers(1, &mFramebuffer);
54 mFramebuffer = 0;
55 }
56
57 if (!mTextures.empty())
58 {
59 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
60 mTextures.clear();
61 }
62
63 glDeleteRenderbuffers(1, &mRenderbuffer);
64 }
65
66 GLuint mFramebuffer = 0;
67 GLuint mRenderbuffer = 0;
68 std::vector<GLuint> mTextures = {0, 0};
69 };
70
71 class StateChangeTestES3 : public StateChangeTest
72 {
73 protected:
StateChangeTestES3()74 StateChangeTestES3() {}
75 };
76
77 class StateChangeTestES31 : public StateChangeTest
78 {
79 protected:
StateChangeTestES31()80 StateChangeTestES31() {}
81 };
82
83 // Ensure that CopyTexImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexImage2DSync)84 TEST_P(StateChangeTest, CopyTexImage2DSync)
85 {
86 // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/42260302)
87 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
88
89 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
90
91 // Init first texture to red
92 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
93 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
94 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
95 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
96 glClear(GL_COLOR_BUFFER_BIT);
97 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
98
99 // Init second texture to green
100 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
101 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
102 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
103 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
104 glClear(GL_COLOR_BUFFER_BIT);
105 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
106
107 // Copy in the red texture to the green one.
108 // CopyTexImage should sync the framebuffer attachment change.
109 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
110 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
111 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
112 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
113
114 ASSERT_GL_NO_ERROR();
115 }
116
117 // Ensure that CopyTexSubImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexSubImage2DSync)118 TEST_P(StateChangeTest, CopyTexSubImage2DSync)
119 {
120 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
121
122 // Init first texture to red
123 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
124 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
125 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
126 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
127 glClear(GL_COLOR_BUFFER_BIT);
128 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
129
130 // Init second texture to green
131 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
132 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
133 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
134 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
135 glClear(GL_COLOR_BUFFER_BIT);
136 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
137
138 // Copy in the red texture to the green one.
139 // CopyTexImage should sync the framebuffer attachment change.
140 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
141 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
142 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
143 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
144
145 ASSERT_GL_NO_ERROR();
146 }
147
148 // Test that Framebuffer completeness caching works when color attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteColorAttachment)149 TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
150 {
151 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
152 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
154 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
155 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
156
157 // Change the texture at color attachment 0 to be non-color-renderable.
158 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
159 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
160 glCheckFramebufferStatus(GL_FRAMEBUFFER));
161
162 ASSERT_GL_NO_ERROR();
163 }
164
165 // Test that caching works when color attachments change with TexStorage.
TEST_P(StateChangeTest,FramebufferIncompleteWithTexStorage)166 TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
167 {
168 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
169
170 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
171 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
172 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
173 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
174 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
175
176 // Change the texture at color attachment 0 to be non-color-renderable.
177 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
178 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
179 glCheckFramebufferStatus(GL_FRAMEBUFFER));
180
181 ASSERT_GL_NO_ERROR();
182 }
183
184 // Test that caching works when color attachments change with CompressedTexImage2D.
TEST_P(StateChangeTestES3,FramebufferIncompleteWithCompressedTex)185 TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
186 {
187 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
188 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
189
190 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
191 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
192 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
193 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
194 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
195
196 // Change the texture at color attachment 0 to be non-color-renderable.
197 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 128, nullptr);
198 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
199 glCheckFramebufferStatus(GL_FRAMEBUFFER));
200
201 ASSERT_GL_NO_ERROR();
202 }
203
204 // Test that caching works when color attachments are deleted.
TEST_P(StateChangeTestES3,FramebufferIncompleteWhenAttachmentDeleted)205 TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
206 {
207 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
208 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
209 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
210 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
211 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
212
213 // Delete the texture at color attachment 0.
214 glDeleteTextures(1, &mTextures[0]);
215 mTextures[0] = 0;
216 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
217 glCheckFramebufferStatus(GL_FRAMEBUFFER));
218
219 ASSERT_GL_NO_ERROR();
220 }
221
222 // Test that Framebuffer completeness caching works when depth attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthAttachment)223 TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
224 {
225 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
226 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
227 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
228 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
229 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
230 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
231 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
232 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
233
234 // Change the texture at color attachment 0 to be non-depth-renderable.
235 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
236 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
237 glCheckFramebufferStatus(GL_FRAMEBUFFER));
238
239 ASSERT_GL_NO_ERROR();
240 }
241
242 // Test that Framebuffer completeness caching works when stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteStencilAttachment)243 TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
244 {
245 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
246 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
247 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
248 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
249 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
250 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
251 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
252 mRenderbuffer);
253 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
254
255 // Change the texture at the stencil attachment to be non-stencil-renderable.
256 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
257 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
258 glCheckFramebufferStatus(GL_FRAMEBUFFER));
259
260 ASSERT_GL_NO_ERROR();
261 }
262
263 // Test that Framebuffer completeness caching works when depth-stencil attachments change.
TEST_P(StateChangeTestES3,FramebufferIncompleteDepthStencilAttachment)264 TEST_P(StateChangeTestES3, FramebufferIncompleteDepthStencilAttachment)
265 {
266 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
267 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
268 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
269 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
270 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
271 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
272 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
273 mRenderbuffer);
274 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
275
276 // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
277 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
278 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
279 glCheckFramebufferStatus(GL_FRAMEBUFFER));
280
281 ASSERT_GL_NO_ERROR();
282 }
283
284 // Test that enabling GL_SAMPLE_ALPHA_TO_COVERAGE doesn't generate errors.
TEST_P(StateChangeTest,AlphaToCoverageEnable)285 TEST_P(StateChangeTest, AlphaToCoverageEnable)
286 {
287 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
288
289 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
290 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
292 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
293 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
294 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
295
296 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
297
298 // We don't actually care that this does anything, just that it can be enabled without causing
299 // an error.
300 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
301
302 glUseProgram(greenProgram);
303 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
304 ASSERT_GL_NO_ERROR();
305 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
306 }
307
308 const char kSimpleAttributeVS[] = R"(attribute vec2 position;
309 attribute vec4 testAttrib;
310 varying vec4 testVarying;
311 void main()
312 {
313 gl_Position = vec4(position, 0, 1);
314 testVarying = testAttrib;
315 })";
316
317 const char kSimpleAttributeFS[] = R"(precision mediump float;
318 varying vec4 testVarying;
319 void main()
320 {
321 gl_FragColor = testVarying;
322 })";
323
324 // Tests that using a buffered attribute, then disabling it and using current value, works.
TEST_P(StateChangeTest,DisablingBufferedVertexAttribute)325 TEST_P(StateChangeTest, DisablingBufferedVertexAttribute)
326 {
327 ANGLE_GL_PROGRAM(program, kSimpleAttributeVS, kSimpleAttributeFS);
328 glUseProgram(program);
329 GLint attribLoc = glGetAttribLocation(program, "testAttrib");
330 GLint positionLoc = glGetAttribLocation(program, "position");
331 ASSERT_NE(-1, attribLoc);
332 ASSERT_NE(-1, positionLoc);
333
334 // Set up the buffered attribute.
335 std::vector<GLColor> red(6, GLColor::red);
336 GLBuffer attribBuffer;
337 glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
338 glBufferData(GL_ARRAY_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
339 glEnableVertexAttribArray(attribLoc);
340 glVertexAttribPointer(attribLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
341
342 // Also set the current value to green now.
343 glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
344
345 // Set up the position attribute as well.
346 setupQuadVertexBuffer(0.5f, 1.0f);
347 glEnableVertexAttribArray(positionLoc);
348 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
349
350 // Draw with the buffered attribute. Verify red.
351 glDrawArrays(GL_TRIANGLES, 0, 6);
352 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
353
354 // Draw with the disabled "current value attribute". Verify green.
355 glDisableVertexAttribArray(attribLoc);
356 glDrawArrays(GL_TRIANGLES, 0, 6);
357 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
358
359 // Verify setting buffer data on the disabled buffer doesn't change anything.
360 std::vector<GLColor> blue(128, GLColor::blue);
361 glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
362 glBufferData(GL_ARRAY_BUFFER, blue.size() * sizeof(GLColor), blue.data(), GL_STATIC_DRAW);
363 glDrawArrays(GL_TRIANGLES, 0, 6);
364 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
365 }
366
367 // Tests that setting value for a subset of default attributes doesn't affect others.
TEST_P(StateChangeTest,SetCurrentAttribute)368 TEST_P(StateChangeTest, SetCurrentAttribute)
369 {
370 constexpr char kVS[] = R"(attribute vec4 position;
371 attribute mat4 testAttrib; // Note that this generates 4 attributes
372 varying vec4 testVarying;
373 void main (void)
374 {
375 gl_Position = position;
376
377 testVarying = position.y < 0.0 ?
378 position.x < 0.0 ? testAttrib[0] : testAttrib[1] :
379 position.x < 0.0 ? testAttrib[2] : testAttrib[3];
380 })";
381
382 ANGLE_GL_PROGRAM(program, kVS, kSimpleAttributeFS);
383 glUseProgram(program);
384 GLint attribLoc = glGetAttribLocation(program, "testAttrib");
385 GLint positionLoc = glGetAttribLocation(program, "position");
386 ASSERT_NE(-1, attribLoc);
387 ASSERT_NE(-1, positionLoc);
388
389 // Set the current value of two of the test attributes, while leaving the other two as default.
390 glVertexAttrib4f(attribLoc + 1, 0.0f, 1.0f, 0.0f, 1.0f);
391 glVertexAttrib4f(attribLoc + 2, 0.0f, 0.0f, 1.0f, 1.0f);
392
393 // Set up the position attribute.
394 setupQuadVertexBuffer(0.5f, 1.0f);
395 glEnableVertexAttribArray(positionLoc);
396 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
397
398 // Draw and verify the four section in the output:
399 //
400 // +---------------+
401 // | Black | Green |
402 // +-------+-------+
403 // | Blue | Black |
404 // +---------------+
405 //
406 glDrawArrays(GL_TRIANGLES, 0, 6);
407
408 const int w = getWindowWidth();
409 const int h = getWindowHeight();
410 constexpr unsigned int kPixelTolerance = 5u;
411 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, kPixelTolerance);
412 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::green, kPixelTolerance);
413 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::blue, kPixelTolerance);
414 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::black, kPixelTolerance);
415 }
416
417 // Tests that drawing with transform feedback paused, then lines without transform feedback works
418 // without Vulkan validation errors.
TEST_P(StateChangeTestES3,DrawPausedXfbThenNonXfbLines)419 TEST_P(StateChangeTestES3, DrawPausedXfbThenNonXfbLines)
420 {
421 // glTransformFeedbackVaryings for program2 returns GL_INVALID_OPERATION on both Linux and
422 // windows. http://anglebug.com/42262893
423 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
424 // http://anglebug.com/42263928
425 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
426
427 std::vector<std::string> tfVaryings = {"gl_Position"};
428 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, essl1_shaders::vs::Simple(),
429 essl1_shaders::fs::Blue(), tfVaryings, GL_SEPARATE_ATTRIBS);
430
431 GLBuffer xfbBuffer;
432 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
433 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * sizeof(float[4]), nullptr, GL_STATIC_DRAW);
434
435 GLTransformFeedback xfb;
436 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
437 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
438
439 glUseProgram(program1);
440 glBeginTransformFeedback(GL_TRIANGLES);
441 glPauseTransformFeedback();
442 glDrawArrays(GL_TRIANGLES, 0, 6);
443
444 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
445 glUseProgram(program2);
446 glDrawArrays(GL_LINES, 0, 6);
447 glEndTransformFeedback();
448
449 ASSERT_GL_NO_ERROR();
450 }
451
452 // Tests that vertex attribute value is preserved across context switches.
TEST_P(StateChangeTest,MultiContextVertexAttribute)453 TEST_P(StateChangeTest, MultiContextVertexAttribute)
454 {
455 EGLWindow *window = getEGLWindow();
456 EGLDisplay display = window->getDisplay();
457 EGLConfig config = window->getConfig();
458 EGLSurface surface = window->getSurface();
459 EGLContext context1 = window->getContext();
460
461 // Set up program in primary context
462 ANGLE_GL_PROGRAM(program1, kSimpleAttributeVS, kSimpleAttributeFS);
463 glUseProgram(program1);
464 GLint attribLoc = glGetAttribLocation(program1, "testAttrib");
465 GLint positionLoc = glGetAttribLocation(program1, "position");
466 ASSERT_NE(-1, attribLoc);
467 ASSERT_NE(-1, positionLoc);
468
469 // Set up the position attribute in primary context
470 setupQuadVertexBuffer(0.5f, 1.0f);
471 glEnableVertexAttribArray(positionLoc);
472 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
473
474 // Set primary context attribute to green and draw quad
475 glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
476 glDrawArrays(GL_TRIANGLES, 0, 6);
477 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
478
479 // Set up and switch to secondary context
480 EGLint contextAttributes[] = {
481 EGL_CONTEXT_MAJOR_VERSION_KHR,
482 GetParam().majorVersion,
483 EGL_CONTEXT_MINOR_VERSION_KHR,
484 GetParam().minorVersion,
485 EGL_NONE,
486 };
487 EGLContext context2 = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
488 ASSERT_NE(context2, EGL_NO_CONTEXT);
489 eglMakeCurrent(display, surface, surface, context2);
490
491 // Set up program in secondary context
492 ANGLE_GL_PROGRAM(program2, kSimpleAttributeVS, kSimpleAttributeFS);
493 glUseProgram(program2);
494 ASSERT_EQ(attribLoc, glGetAttribLocation(program2, "testAttrib"));
495 ASSERT_EQ(positionLoc, glGetAttribLocation(program2, "position"));
496
497 // Set up the position attribute in secondary context
498 setupQuadVertexBuffer(0.5f, 1.0f);
499 glEnableVertexAttribArray(positionLoc);
500 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
501
502 // attribLoc current value should be default - (0,0,0,1)
503 glDrawArrays(GL_TRIANGLES, 0, 6);
504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
505
506 // Restore primary context
507 eglMakeCurrent(display, surface, surface, context1);
508 // ReadPixels to ensure context is switched
509 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
510
511 // Switch to secondary context second time
512 eglMakeCurrent(display, surface, surface, context2);
513 // Check that it still draws black
514 glDrawArrays(GL_TRIANGLES, 0, 6);
515 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
516
517 // Restore primary context second time
518 eglMakeCurrent(display, surface, surface, context1);
519 // Check if it still draws green
520 glDrawArrays(GL_TRIANGLES, 0, 6);
521 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
522
523 // Clean up
524 eglDestroyContext(display, context2);
525 }
526
527 // Ensure that CopyTexSubImage3D syncs framebuffer changes.
TEST_P(StateChangeTestES3,CopyTexSubImage3DSync)528 TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
529 {
530 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
531
532 // Init first texture to red
533 glBindTexture(GL_TEXTURE_3D, mTextures[0]);
534 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
535 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
536 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
537 glClear(GL_COLOR_BUFFER_BIT);
538 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
539
540 // Init second texture to green
541 glBindTexture(GL_TEXTURE_3D, mTextures[1]);
542 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
543 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
544 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
545 glClear(GL_COLOR_BUFFER_BIT);
546 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
547
548 // Copy in the red texture to the green one.
549 // CopyTexImage should sync the framebuffer attachment change.
550 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
551 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
552 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
553 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
554
555 ASSERT_GL_NO_ERROR();
556 }
557
558 // Ensure that BlitFramebuffer syncs framebuffer changes.
TEST_P(StateChangeTestES3,BlitFramebufferSync)559 TEST_P(StateChangeTestES3, BlitFramebufferSync)
560 {
561 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
562
563 // Init first texture to red
564 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
565 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
566 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
567 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
568 glClear(GL_COLOR_BUFFER_BIT);
569 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
570
571 // Init second texture to green
572 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
573 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
574 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
575 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
576 glClear(GL_COLOR_BUFFER_BIT);
577 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
578
579 // Change to the red textures and blit.
580 // BlitFramebuffer should sync the framebuffer attachment change.
581 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
582 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
583 0);
584 glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
585 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
586 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
587
588 ASSERT_GL_NO_ERROR();
589 }
590
591 // Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
TEST_P(StateChangeTestES3,ReadBufferAndDrawBuffersSync)592 TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
593 {
594 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
595
596 // Initialize two FBO attachments
597 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
598 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
599 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
600 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
601 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
602 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
603
604 // Clear first attachment to red
605 GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
606 glDrawBuffers(2, bufs1);
607 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
608 glClear(GL_COLOR_BUFFER_BIT);
609
610 // Clear second texture to green
611 GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
612 glDrawBuffers(2, bufs2);
613 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
614 glClear(GL_COLOR_BUFFER_BIT);
615
616 // Verify first attachment is red and second is green
617 glReadBuffer(GL_COLOR_ATTACHMENT1);
618 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
619
620 glReadBuffer(GL_COLOR_ATTACHMENT0);
621 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
622
623 ASSERT_GL_NO_ERROR();
624 }
625
626 // Tests calling invalidate on incomplete framebuffers after switching attachments.
627 // Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
TEST_P(StateChangeTestES3,IncompleteRenderbufferAttachmentInvalidateSync)628 TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
629 {
630 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
631 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
632 GLint samples = 0;
633 glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
634 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
635 ASSERT_GL_NO_ERROR();
636
637 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
638 // attached renderbuffer
639 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
640 glCheckFramebufferStatus(GL_FRAMEBUFFER));
641 GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
642 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
643 ASSERT_GL_NO_ERROR();
644
645 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
646 getWindowWidth(), getWindowHeight());
647 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
648 glClear(GL_COLOR_BUFFER_BIT);
649 ASSERT_GL_NO_ERROR();
650
651 GLRenderbuffer renderbuf;
652
653 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
654 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuf);
655 ASSERT_GL_NO_ERROR();
656
657 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
658 // attached renderbuffer
659 // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
660 GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
661 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
662
663 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
664 GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
665 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
666 glClear(GL_DEPTH_BUFFER_BIT);
667 ASSERT_GL_NO_ERROR();
668 }
669
670 class StateChangeRenderTest : public StateChangeTest
671 {
672 protected:
StateChangeRenderTest()673 StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
674
testSetUp()675 void testSetUp() override
676 {
677 StateChangeTest::testSetUp();
678
679 constexpr char kVS[] =
680 "attribute vec2 position;\n"
681 "void main() {\n"
682 " gl_Position = vec4(position, 0, 1);\n"
683 "}";
684 constexpr char kFS[] =
685 "uniform highp vec4 uniformColor;\n"
686 "void main() {\n"
687 " gl_FragColor = uniformColor;\n"
688 "}";
689
690 mProgram = CompileProgram(kVS, kFS);
691 ASSERT_NE(0u, mProgram);
692
693 glGenRenderbuffers(1, &mRenderbuffer);
694 }
695
testTearDown()696 void testTearDown() override
697 {
698 glDeleteProgram(mProgram);
699 glDeleteRenderbuffers(1, &mRenderbuffer);
700
701 StateChangeTest::testTearDown();
702 }
703
setUniformColor(const GLColor & color)704 void setUniformColor(const GLColor &color)
705 {
706 glUseProgram(mProgram);
707 const Vector4 &normalizedColor = color.toNormalizedVector();
708 GLint uniformLocation = glGetUniformLocation(mProgram, "uniformColor");
709 ASSERT_NE(-1, uniformLocation);
710 glUniform4fv(uniformLocation, 1, normalizedColor.data());
711 }
712
713 GLuint mProgram;
714 GLuint mRenderbuffer;
715 };
716
717 // Test that re-creating a currently attached texture works as expected.
TEST_P(StateChangeRenderTest,RecreateTexture)718 TEST_P(StateChangeRenderTest, RecreateTexture)
719 {
720 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
721
722 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
723 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
724 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
725
726 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
727 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
728
729 // Draw with red to the FBO.
730 GLColor red(255, 0, 0, 255);
731 setUniformColor(red);
732 drawQuad(mProgram, "position", 0.5f);
733 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
734
735 // Recreate the texture with green.
736 GLColor green(0, 255, 0, 255);
737 std::vector<GLColor> greenPixels(32 * 32, green);
738 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
739 greenPixels.data());
740 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
741
742 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
743 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
744
745 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
746 GLColor blue(0, 0, 255, 255);
747 setUniformColor(blue);
748 drawQuad(mProgram, "position", 0.5f);
749 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
750
751 EXPECT_GL_NO_ERROR();
752 }
753
754 // Test that re-creating a currently attached renderbuffer works as expected.
TEST_P(StateChangeRenderTest,RecreateRenderbuffer)755 TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
756 {
757 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
758
759 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
760 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
761 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
762
763 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
764 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
765
766 // Draw with red to the FBO.
767 setUniformColor(GLColor::red);
768 drawQuad(mProgram, "position", 0.5f);
769 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
770
771 // Recreate the renderbuffer and clear to green.
772 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
773 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
774 glClear(GL_COLOR_BUFFER_BIT);
775 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
776
777 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
778 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
779
780 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
781 setUniformColor(GLColor::blue);
782 drawQuad(mProgram, "position", 0.5f);
783 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
784
785 EXPECT_GL_NO_ERROR();
786 }
787
788 // Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
TEST_P(StateChangeRenderTest,GenerateMipmap)789 TEST_P(StateChangeRenderTest, GenerateMipmap)
790 {
791 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
792
793 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
794 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
795 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
796 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
797 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
798
799 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
800 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
801
802 // Draw once to set the RenderTarget in D3D11
803 GLColor red(255, 0, 0, 255);
804 setUniformColor(red);
805 drawQuad(mProgram, "position", 0.5f);
806 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
807
808 // This may trigger the texture to be re-created internally.
809 glGenerateMipmap(GL_TEXTURE_2D);
810
811 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
812 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
813
814 // Now ensure we don't have a stale render target.
815 GLColor blue(0, 0, 255, 255);
816 setUniformColor(blue);
817 drawQuad(mProgram, "position", 0.5f);
818 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
819
820 EXPECT_GL_NO_ERROR();
821 }
822
823 // Tests that gl_DepthRange syncs correctly after a change.
TEST_P(StateChangeRenderTest,DepthRangeUpdates)824 TEST_P(StateChangeRenderTest, DepthRangeUpdates)
825 {
826 constexpr char kFragCoordShader[] = R"(void main()
827 {
828 if (gl_DepthRange.near == 0.2)
829 {
830 gl_FragColor = vec4(1, 0, 0, 1);
831 }
832 else if (gl_DepthRange.near == 0.5)
833 {
834 gl_FragColor = vec4(0, 1, 0, 1);
835 }
836 else
837 {
838 gl_FragColor = vec4(0, 0, 1, 1);
839 }
840 })";
841
842 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
843 glUseProgram(program);
844
845 const auto &quadVertices = GetQuadVertices();
846
847 ASSERT_EQ(0, glGetAttribLocation(program, essl1_shaders::PositionAttrib()));
848
849 GLBuffer vertexBuffer;
850 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
851 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
852 quadVertices.data(), GL_STATIC_DRAW);
853 glVertexAttribPointer(0u, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
854 glEnableVertexAttribArray(0u);
855
856 // First, clear.
857 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
858 glClear(GL_COLOR_BUFFER_BIT);
859
860 // Draw to left half viewport with a first depth range.
861 glDepthRangef(0.2f, 1.0f);
862 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
863 glDrawArrays(GL_TRIANGLES, 0, 6);
864 ASSERT_GL_NO_ERROR();
865
866 // Draw to right half viewport with a second depth range.
867 glDepthRangef(0.5f, 1.0f);
868 glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
869 glDrawArrays(GL_TRIANGLES, 0, 6);
870 ASSERT_GL_NO_ERROR();
871
872 // Verify left half of the framebuffer is red and right half is green.
873 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() / 2, getWindowHeight(), GLColor::red);
874 EXPECT_PIXEL_RECT_EQ(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight(),
875 GLColor::green);
876 }
877
878 class StateChangeRenderTestES3 : public StateChangeRenderTest
879 {};
880
TEST_P(StateChangeRenderTestES3,InvalidateNonCurrentFramebuffer)881 TEST_P(StateChangeRenderTestES3, InvalidateNonCurrentFramebuffer)
882 {
883 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
884 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
886 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
887 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
888 glBindTexture(GL_TEXTURE_2D, 0);
889 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
890 ASSERT_GL_NO_ERROR();
891
892 // Draw with red to the FBO.
893 GLColor red(255, 0, 0, 255);
894 setUniformColor(red);
895 drawQuad(mProgram, "position", 0.5f);
896 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
897
898 // Go back to default framebuffer, draw green
899 glBindFramebuffer(GL_FRAMEBUFFER, 0);
900 GLColor green(0, 255, 0, 255);
901 setUniformColor(green);
902 drawQuad(mProgram, "position", 0.5f);
903 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
904
905 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
906
907 // Invalidate color buffer of FBO
908 GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
909 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
910 ASSERT_GL_NO_ERROR();
911
912 // Verify drawing blue gives blue.
913 GLColor blue(0, 0, 255, 255);
914 setUniformColor(blue);
915 drawQuad(mProgram, "position", 0.5f);
916 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
917 }
918
919 // Tests that D3D11 dirty bit updates don't forget about BufferSubData attrib updates.
TEST_P(StateChangeTest,VertexBufferUpdatedAfterDraw)920 TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
921 {
922 constexpr char kVS[] =
923 "attribute vec2 position;\n"
924 "attribute vec4 color;\n"
925 "varying vec4 outcolor;\n"
926 "void main()\n"
927 "{\n"
928 " gl_Position = vec4(position, 0, 1);\n"
929 " outcolor = color;\n"
930 "}";
931 constexpr char kFS[] =
932 "varying mediump vec4 outcolor;\n"
933 "void main()\n"
934 "{\n"
935 " gl_FragColor = outcolor;\n"
936 "}";
937
938 ANGLE_GL_PROGRAM(program, kVS, kFS);
939 glUseProgram(program);
940
941 GLint colorLoc = glGetAttribLocation(program, "color");
942 ASSERT_NE(-1, colorLoc);
943 GLint positionLoc = glGetAttribLocation(program, "position");
944 ASSERT_NE(-1, positionLoc);
945
946 setupQuadVertexBuffer(0.5f, 1.0f);
947 glEnableVertexAttribArray(positionLoc);
948 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
949
950 GLBuffer colorBuf;
951 glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
952 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
953 glEnableVertexAttribArray(colorLoc);
954
955 // Fill with green.
956 std::vector<GLColor> colorData(6, GLColor::green);
957 glBufferData(GL_ARRAY_BUFFER, colorData.size() * sizeof(GLColor), colorData.data(),
958 GL_STATIC_DRAW);
959
960 // Draw, expect green.
961 glDrawArrays(GL_TRIANGLES, 0, 6);
962 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
963 ASSERT_GL_NO_ERROR();
964
965 // Update buffer with red.
966 std::fill(colorData.begin(), colorData.end(), GLColor::red);
967 glBufferSubData(GL_ARRAY_BUFFER, 0, colorData.size() * sizeof(GLColor), colorData.data());
968
969 // Draw, expect red.
970 glDrawArrays(GL_TRIANGLES, 0, 6);
971 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
972 ASSERT_GL_NO_ERROR();
973 }
974
975 // Tests that drawing after flush without any state change works.
TEST_P(StateChangeTestES3,DrawAfterFlushWithNoStateChange)976 TEST_P(StateChangeTestES3, DrawAfterFlushWithNoStateChange)
977 {
978 // Draw (0.125, 0.25, 0.5, 0.5) once, using additive blend
979 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
980 glUseProgram(drawColor);
981
982 GLint colorUniformLocation =
983 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
984 ASSERT_NE(colorUniformLocation, -1);
985
986 GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
987 ASSERT_NE(-1, positionLocation);
988
989 // Setup VAO
990 const auto &quadVertices = GetQuadVertices();
991
992 GLBuffer vertexBuffer;
993 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
994 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
995
996 GLVertexArray vertexArray;
997 glBindVertexArray(vertexArray);
998 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
999 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1000 glEnableVertexAttribArray(positionLocation);
1001 ASSERT_GL_NO_ERROR();
1002
1003 // Clear and draw
1004 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1005 glClear(GL_COLOR_BUFFER_BIT);
1006
1007 glEnable(GL_BLEND);
1008 glBlendFunc(GL_ONE, GL_ONE);
1009
1010 glUniform4f(colorUniformLocation, 0.125f, 0.25f, 0.5f, 0.5f);
1011 glDrawArrays(GL_TRIANGLES, 0, 6);
1012 ASSERT_GL_NO_ERROR();
1013
1014 // Make sure the work is submitted.
1015 glFinish();
1016
1017 // Draw again with no state change
1018 glDrawArrays(GL_TRIANGLES, 0, 6);
1019 ASSERT_GL_NO_ERROR();
1020
1021 // Make sure the pixels have the correct colors.
1022 const int h = getWindowHeight() - 1;
1023 const int w = getWindowWidth() - 1;
1024 const GLColor kExpected(63, 127, 255, 255);
1025
1026 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1027 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, kExpected, 1);
1028 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, kExpected, 1);
1029 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, kExpected, 1);
1030 }
1031
1032 // Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
TEST_P(StateChangeTestES3,VertexArrayObjectAndDisabledAttributes)1033 TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes)
1034 {
1035 constexpr char kSingleVS[] = "attribute vec4 position; void main() { gl_Position = position; }";
1036 constexpr char kSingleFS[] = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
1037 ANGLE_GL_PROGRAM(singleProgram, kSingleVS, kSingleFS);
1038
1039 constexpr char kDualVS[] =
1040 "#version 300 es\n"
1041 "in vec4 position;\n"
1042 "in vec4 color;\n"
1043 "out vec4 varyColor;\n"
1044 "void main()\n"
1045 "{\n"
1046 " gl_Position = position;\n"
1047 " varyColor = color;\n"
1048 "}";
1049 constexpr char kDualFS[] =
1050 "#version 300 es\n"
1051 "precision mediump float;\n"
1052 "in vec4 varyColor;\n"
1053 "out vec4 colorOut;\n"
1054 "void main()\n"
1055 "{\n"
1056 " colorOut = varyColor;\n"
1057 "}";
1058
1059 ANGLE_GL_PROGRAM(dualProgram, kDualVS, kDualFS);
1060
1061 // Force consistent attribute locations
1062 constexpr GLint positionLocation = 0;
1063 constexpr GLint colorLocation = 1;
1064
1065 glBindAttribLocation(singleProgram, positionLocation, "position");
1066 glBindAttribLocation(dualProgram, positionLocation, "position");
1067 glBindAttribLocation(dualProgram, colorLocation, "color");
1068
1069 {
1070 glLinkProgram(singleProgram);
1071 GLint linkStatus;
1072 glGetProgramiv(singleProgram, GL_LINK_STATUS, &linkStatus);
1073 ASSERT_NE(linkStatus, 0);
1074 }
1075
1076 {
1077 glLinkProgram(dualProgram);
1078 GLint linkStatus;
1079 glGetProgramiv(dualProgram, GL_LINK_STATUS, &linkStatus);
1080 ASSERT_NE(linkStatus, 0);
1081 }
1082
1083 glUseProgram(singleProgram);
1084
1085 // Initialize position vertex buffer.
1086 const auto &quadVertices = GetQuadVertices();
1087
1088 GLBuffer vertexBuffer;
1089 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1090 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
1091
1092 // Initialize a VAO. Draw with single program.
1093 GLVertexArray vertexArray;
1094 glBindVertexArray(vertexArray);
1095 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1096 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1097 glEnableVertexAttribArray(positionLocation);
1098
1099 // Should draw red.
1100 glDrawArrays(GL_TRIANGLES, 0, 6);
1101 ASSERT_GL_NO_ERROR();
1102 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1103
1104 // Draw with a green buffer attribute, without the VAO.
1105 glBindVertexArray(0);
1106 glUseProgram(dualProgram);
1107 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1108 glEnableVertexAttribArray(positionLocation);
1109
1110 std::vector<GLColor> greenColors(6, GLColor::green);
1111 GLBuffer greenBuffer;
1112 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
1113 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, greenColors.data(), GL_STATIC_DRAW);
1114
1115 glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4, nullptr);
1116 glEnableVertexAttribArray(colorLocation);
1117
1118 glDrawArrays(GL_TRIANGLES, 0, 6);
1119 ASSERT_GL_NO_ERROR();
1120 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1121
1122 // Re-bind VAO and try to draw with different program, without changing state.
1123 // Should draw black since current value is not initialized.
1124 glBindVertexArray(vertexArray);
1125 glDrawArrays(GL_TRIANGLES, 0, 6);
1126 ASSERT_GL_NO_ERROR();
1127 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1128 }
1129
1130 const char kSamplerMetadataVertexShader0[] = R"(#version 300 es
1131 precision mediump float;
1132 out vec4 color;
1133 uniform sampler2D texture;
1134 void main()
1135 {
1136 vec2 size = vec2(textureSize(texture, 0));
1137 color = size.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1138 vec2 pos = vec2(0.0);
1139 switch (gl_VertexID) {
1140 case 0: pos = vec2(-1.0, -1.0); break;
1141 case 1: pos = vec2(3.0, -1.0); break;
1142 case 2: pos = vec2(-1.0, 3.0); break;
1143 };
1144 gl_Position = vec4(pos, 0.0, 1.0);
1145 })";
1146
1147 const char kSamplerMetadataVertexShader1[] = R"(#version 300 es
1148 precision mediump float;
1149 out vec4 color;
1150 uniform sampler2D texture1;
1151 uniform sampler2D texture2;
1152 void main()
1153 {
1154 vec2 size1 = vec2(textureSize(texture1, 0));
1155 vec2 size2 = vec2(textureSize(texture2, 0));
1156 color = size1.x * size2.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1157 vec2 pos = vec2(0.0);
1158 switch (gl_VertexID) {
1159 case 0: pos = vec2(-1.0, -1.0); break;
1160 case 1: pos = vec2(3.0, -1.0); break;
1161 case 2: pos = vec2(-1.0, 3.0); break;
1162 };
1163 gl_Position = vec4(pos, 0.0, 1.0);
1164 })";
1165
1166 const char kSamplerMetadataFragmentShader[] = R"(#version 300 es
1167 precision mediump float;
1168 in vec4 color;
1169 out vec4 result;
1170 void main()
1171 {
1172 result = color;
1173 })";
1174
1175 // Tests that changing an active program invalidates the sampler metadata properly.
TEST_P(StateChangeTestES3,SamplerMetadataUpdateOnSetProgram)1176 TEST_P(StateChangeTestES3, SamplerMetadataUpdateOnSetProgram)
1177 {
1178 // http://anglebug.com/40096654
1179 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1180 GLVertexArray vertexArray;
1181 glBindVertexArray(vertexArray);
1182
1183 // Create a simple framebuffer.
1184 GLTexture texture1, texture2;
1185 glActiveTexture(GL_TEXTURE0);
1186 glBindTexture(GL_TEXTURE_2D, texture1);
1187 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1188 glActiveTexture(GL_TEXTURE1);
1189 glBindTexture(GL_TEXTURE_2D, texture2);
1190 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1191
1192 // Create 2 shader programs differing only in the number of active samplers.
1193 ANGLE_GL_PROGRAM(program1, kSamplerMetadataVertexShader0, kSamplerMetadataFragmentShader);
1194 glUseProgram(program1);
1195 glUniform1i(glGetUniformLocation(program1, "texture"), 0);
1196 ANGLE_GL_PROGRAM(program2, kSamplerMetadataVertexShader1, kSamplerMetadataFragmentShader);
1197 glUseProgram(program2);
1198 glUniform1i(glGetUniformLocation(program2, "texture1"), 0);
1199 glUniform1i(glGetUniformLocation(program2, "texture2"), 0);
1200
1201 // Draw a solid green color to the framebuffer.
1202 glUseProgram(program1);
1203 glDrawArrays(GL_TRIANGLES, 0, 3);
1204 // Test that our first program is good.
1205 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1206
1207 // Bind a different program that uses more samplers.
1208 // Draw another quad that depends on the sampler metadata.
1209 glUseProgram(program2);
1210 glDrawArrays(GL_TRIANGLES, 0, 3);
1211 // Flush via ReadPixels and check that it's still green.
1212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1213
1214 ASSERT_GL_NO_ERROR();
1215 }
1216
1217 // Tests that redefining Buffer storage syncs with the Transform Feedback object.
TEST_P(StateChangeTestES3,RedefineTransformFeedbackBuffer)1218 TEST_P(StateChangeTestES3, RedefineTransformFeedbackBuffer)
1219 {
1220 // Create the most simple program possible - simple a passthrough for a float attribute.
1221 constexpr char kVertexShader[] = R"(#version 300 es
1222 in float valueIn;
1223 out float valueOut;
1224 void main()
1225 {
1226 gl_Position = vec4(0, 0, 0, 0);
1227 valueOut = valueIn;
1228 })";
1229
1230 constexpr char kFragmentShader[] = R"(#version 300 es
1231 out mediump float unused;
1232 void main()
1233 {
1234 unused = 1.0;
1235 })";
1236
1237 std::vector<std::string> tfVaryings = {"valueOut"};
1238 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, kVertexShader, kFragmentShader, tfVaryings,
1239 GL_SEPARATE_ATTRIBS);
1240 glUseProgram(program);
1241
1242 GLint attribLoc = glGetAttribLocation(program, "valueIn");
1243 ASSERT_NE(-1, attribLoc);
1244
1245 // Disable rasterization - we're not interested in the framebuffer.
1246 glEnable(GL_RASTERIZER_DISCARD);
1247
1248 // Initialize a float vertex buffer with 1.0.
1249 std::vector<GLfloat> data1(16, 1.0);
1250 GLsizei size1 = static_cast<GLsizei>(sizeof(GLfloat) * data1.size());
1251
1252 GLBuffer vertexBuffer;
1253 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1254 glBufferData(GL_ARRAY_BUFFER, size1, data1.data(), GL_STATIC_DRAW);
1255 glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1256 glEnableVertexAttribArray(attribLoc);
1257
1258 ASSERT_GL_NO_ERROR();
1259
1260 // Initialize a same-sized XFB buffer.
1261 GLBuffer xfbBuffer;
1262 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1263 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size1, nullptr, GL_STATIC_DRAW);
1264
1265 // Draw with XFB enabled.
1266 GLTransformFeedback xfb;
1267 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1268 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1269
1270 glBeginTransformFeedback(GL_POINTS);
1271 glDrawArrays(GL_POINTS, 0, 16);
1272 glEndTransformFeedback();
1273
1274 ASSERT_GL_NO_ERROR();
1275
1276 // Verify the XFB stage caught the 1.0 attribute values.
1277 void *mapped1 = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size1, GL_MAP_READ_BIT);
1278 GLfloat *asFloat1 = reinterpret_cast<GLfloat *>(mapped1);
1279 std::vector<GLfloat> actualData1(asFloat1, asFloat1 + data1.size());
1280 EXPECT_EQ(data1, actualData1);
1281 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1282
1283 // Now, reinitialize the XFB buffer to a larger size, and draw with 2.0.
1284 std::vector<GLfloat> data2(128, 2.0);
1285 const GLsizei size2 = static_cast<GLsizei>(sizeof(GLfloat) * data2.size());
1286 glBufferData(GL_ARRAY_BUFFER, size2, data2.data(), GL_STATIC_DRAW);
1287 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size2, nullptr, GL_STATIC_DRAW);
1288
1289 glBeginTransformFeedback(GL_POINTS);
1290 glDrawArrays(GL_POINTS, 0, 128);
1291 glEndTransformFeedback();
1292
1293 ASSERT_GL_NO_ERROR();
1294
1295 // Verify the XFB stage caught the 2.0 attribute values.
1296 void *mapped2 = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size2, GL_MAP_READ_BIT);
1297 GLfloat *asFloat2 = reinterpret_cast<GLfloat *>(mapped2);
1298 std::vector<GLfloat> actualData2(asFloat2, asFloat2 + data2.size());
1299 EXPECT_EQ(data2, actualData2);
1300 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1301 }
1302
1303 // Variations:
1304 //
1305 // - bool: whether to use WebGL compatibility mode.
1306 using StateChangeTestWebGL2Params = std::tuple<angle::PlatformParameters, bool>;
1307
StateChangeTestWebGL2Print(const::testing::TestParamInfo<StateChangeTestWebGL2Params> & paramsInfo)1308 std::string StateChangeTestWebGL2Print(
1309 const ::testing::TestParamInfo<StateChangeTestWebGL2Params> ¶msInfo)
1310 {
1311 const StateChangeTestWebGL2Params ¶ms = paramsInfo.param;
1312 std::ostringstream out;
1313
1314 out << std::get<0>(params);
1315
1316 if (std::get<1>(params))
1317 {
1318 out << "__WebGLCompatibility";
1319 }
1320
1321 return out.str();
1322 }
1323
1324 // State change test verifying both ES3 and WebGL2 specific behaviors.
1325 // Test is parameterized to allow execution with and without WebGL validation.
1326 // Note that this can not inherit from StateChangeTest due to the need to use ANGLETestWithParam.
1327 class StateChangeTestWebGL2 : public ANGLETest<StateChangeTestWebGL2Params>
1328 {
1329 protected:
StateChangeTestWebGL2()1330 StateChangeTestWebGL2()
1331 {
1332 setWindowWidth(kWidth);
1333 setWindowHeight(kHeight);
1334 setConfigRedBits(8);
1335 setConfigGreenBits(8);
1336 setConfigBlueBits(8);
1337 setConfigAlphaBits(8);
1338 if (testing::get<1>(GetParam()))
1339 setWebGLCompatibilityEnabled(true);
1340 }
1341
1342 struct TestResources
1343 {
1344 GLTexture colorTexture;
1345 GLFramebuffer framebuffer;
1346 };
1347
setupResources(TestResources & resources)1348 void setupResources(TestResources &resources)
1349 {
1350 glBindTexture(GL_TEXTURE_2D, resources.colorTexture);
1351 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
1352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1354 EXPECT_GL_NO_ERROR();
1355
1356 glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
1357 EXPECT_GL_NO_ERROR();
1358 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1359 resources.colorTexture, 0);
1360 EXPECT_GL_NO_ERROR();
1361 }
1362
1363 // Use a larger window/framebuffer size than 1x1 (though not much larger) to
1364 // increase the chances that random garbage will appear.
1365 static constexpr GLsizei kWidth = 4;
1366 static constexpr GLsizei kHeight = 4;
1367 };
1368
1369 // Note: tested multiple other combinations:
1370 //
1371 // - Clearing/drawing to the framebuffer after invalidating, without using a
1372 // secondary FBO
1373 // - Clearing the framebuffer after invalidating, using a secondary FBO
1374 // - Invalidating after clearing/drawing to the FBO, to verify WebGL's behavior
1375 // that after invalidation, the framebuffer is either unmodified, or cleared
1376 // to transparent black
1377 //
1378 // This combination, drawing after invalidating plus copying from the drawn-to
1379 // texture, was the only one which provoked the original bug in the Metal
1380 // backend with the following command line arguments:
1381 //
1382 // MTL_DEBUG_LAYER=1 MTL_DEBUG_LAYER_VALIDATE_LOAD_ACTIONS=1 \
1383 // MTL_DEBUG_LAYER_VALIDATE_STORE_ACTIONS=1 \
1384 // MTL_DEBUG_LAYER_VALIDATE_UNRETAINED_RESOURCES=4 \
1385 // angle_end2end_tests ...
1386 //
1387 // See anglebug.com/42265402.
1388
TEST_P(StateChangeTestWebGL2,InvalidateThenDrawFBO)1389 TEST_P(StateChangeTestWebGL2, InvalidateThenDrawFBO)
1390 {
1391 GLint origFramebuffer = 0;
1392 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &origFramebuffer);
1393
1394 TestResources resources;
1395 setupResources(resources);
1396
1397 ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
1398
1399 const GLenum attachment = GL_COLOR_ATTACHMENT0;
1400
1401 glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
1402 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1403
1404 // Clear to red to start.
1405 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1406 glClear(GL_COLOR_BUFFER_BIT);
1407
1408 // Invalidate framebuffer.
1409 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &attachment);
1410 EXPECT_GL_NO_ERROR();
1411
1412 // Draw green.
1413 // Important to use a vertex buffer because WebGL doesn't support client-side arrays.
1414 constexpr bool useVertexBuffer = true;
1415 drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, useVertexBuffer);
1416 EXPECT_GL_NO_ERROR();
1417
1418 // Bind original framebuffer.
1419 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, origFramebuffer);
1420 glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.framebuffer);
1421 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1422 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1423 EXPECT_GL_NO_ERROR();
1424
1425 // Blit from user's framebuffer to the window.
1426 //
1427 // This step is crucial to catch bugs in the Metal backend's use of no-op load/store actions.
1428 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1429 GL_NEAREST);
1430 EXPECT_GL_NO_ERROR();
1431
1432 // Verify results.
1433 glBindFramebuffer(GL_READ_FRAMEBUFFER, origFramebuffer);
1434 EXPECT_GL_NO_ERROR();
1435 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1436 }
1437
1438 // Simple state change tests for line loop drawing. There is some very specific handling of line
1439 // line loops in Vulkan and we need to test switching between drawElements and drawArrays calls to
1440 // validate every edge cases.
1441 class LineLoopStateChangeTest : public StateChangeTest
1442 {
1443 protected:
LineLoopStateChangeTest()1444 LineLoopStateChangeTest()
1445 {
1446 setWindowWidth(32);
1447 setWindowHeight(32);
1448 setConfigRedBits(8);
1449 setConfigGreenBits(8);
1450 setConfigBlueBits(8);
1451 setConfigAlphaBits(8);
1452 }
1453
validateSquareAndHourglass() const1454 void validateSquareAndHourglass() const
1455 {
1456 ASSERT_GL_NO_ERROR();
1457
1458 int quarterWidth = getWindowWidth() / 4;
1459 int quarterHeight = getWindowHeight() / 4;
1460
1461 // Bottom left
1462 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::blue);
1463
1464 // Top left
1465 EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::blue);
1466
1467 // Top right
1468 // The last pixel isn't filled on a line loop so we check the pixel right before.
1469 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::blue);
1470
1471 // dead center to validate the hourglass.
1472 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight * 2, GLColor::blue);
1473
1474 // Verify line is closed between the 2 last vertices
1475 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::blue);
1476 }
1477 };
1478
1479 // Draw an hourglass with a drawElements call followed by a square with drawArrays.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawArrays)1480 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
1481 {
1482 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1483 glUseProgram(program);
1484
1485 // We expect to draw a square with these 4 vertices with a drawArray call.
1486 std::vector<Vector3> vertices;
1487 CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1488 getWindowHeight(), &vertices);
1489
1490 // If we use these indices to draw however, we should be drawing an hourglass.
1491 auto indices = std::vector<GLushort>{0, 2, 1, 3};
1492
1493 GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1494 ASSERT_NE(-1, mPositionLocation);
1495
1496 GLBuffer vertexBuffer;
1497 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1498 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1499 GL_STATIC_DRAW);
1500
1501 GLBuffer indexBuffer;
1502 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1503 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1504 GL_STATIC_DRAW);
1505
1506 glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1507 glEnableVertexAttribArray(mPositionLocation);
1508 glClear(GL_COLOR_BUFFER_BIT);
1509 glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr); // hourglass
1510 glDrawArrays(GL_LINE_LOOP, 0, 4); // square
1511 glDisableVertexAttribArray(mPositionLocation);
1512
1513 validateSquareAndHourglass();
1514 }
1515
1516 // Draw line loop using a drawArrays followed by an hourglass with drawElements.
TEST_P(LineLoopStateChangeTest,DrawArraysThenDrawElements)1517 TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
1518 {
1519 // http://anglebug.com/40644657: Seems to fail on older drivers and pass on newer.
1520 // Tested failing on 18.3.3 and passing on 18.9.2.
1521 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
1522
1523 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1524 glUseProgram(program);
1525
1526 // We expect to draw a square with these 4 vertices with a drawArray call.
1527 std::vector<Vector3> vertices;
1528 CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1529 getWindowHeight(), &vertices);
1530
1531 // If we use these indices to draw however, we should be drawing an hourglass.
1532 auto indices = std::vector<GLushort>{0, 2, 1, 3};
1533
1534 GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1535 ASSERT_NE(-1, mPositionLocation);
1536
1537 GLBuffer vertexBuffer;
1538 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1539 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1540 GL_STATIC_DRAW);
1541
1542 GLBuffer indexBuffer;
1543 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1544 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1545 GL_STATIC_DRAW);
1546
1547 glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1548 glEnableVertexAttribArray(mPositionLocation);
1549 glClear(GL_COLOR_BUFFER_BIT);
1550 glDrawArrays(GL_LINE_LOOP, 0, 4); // square
1551 glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr); // hourglass
1552 glDisableVertexAttribArray(mPositionLocation);
1553
1554 validateSquareAndHourglass();
1555 }
1556
1557 // Draw a triangle with a drawElements call and a non-zero offset and draw the same
1558 // triangle with the same offset again followed by a line loop with drawElements.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawElements)1559 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawElements)
1560 {
1561 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1562
1563 glUseProgram(program);
1564
1565 // Background Red color
1566 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1567 glClear(GL_COLOR_BUFFER_BIT);
1568
1569 // We expect to draw a triangle with the last three points on the bottom right,
1570 // draw with LineLoop, and then draw a triangle with the same non-zero offset.
1571 auto vertices = std::vector<Vector3>{
1572 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1573
1574 auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1575
1576 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1577 ASSERT_NE(-1, positionLocation);
1578
1579 GLBuffer indexBuffer;
1580 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1581 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1582 GL_STATIC_DRAW);
1583
1584 GLBuffer vertexBuffer;
1585 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1586 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1587 GL_STATIC_DRAW);
1588
1589 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1590 glEnableVertexAttribArray(positionLocation);
1591
1592 // Draw a triangle with a non-zero offset on the bottom right.
1593 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1594
1595 // Draw with LineLoop.
1596 glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, nullptr);
1597
1598 // Draw the triangle again with the same offset.
1599 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1600
1601 glDisableVertexAttribArray(positionLocation);
1602
1603 ASSERT_GL_NO_ERROR();
1604
1605 int quarterWidth = getWindowWidth() / 4;
1606 int quarterHeight = getWindowHeight() / 4;
1607
1608 // Validate the top left point's color.
1609 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::blue);
1610
1611 // Validate the triangle is drawn on the bottom right.
1612 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1613
1614 // Validate the triangle is NOT on the top left part.
1615 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1616 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1617 }
1618
1619 // Simple state change tests, primarily focused on basic object lifetime and dependency management
1620 // with back-ends that don't support that automatically (i.e. Vulkan).
1621 class SimpleStateChangeTest : public ANGLETest<>
1622 {
1623 protected:
1624 static constexpr int kWindowSize = 64;
1625
SimpleStateChangeTest()1626 SimpleStateChangeTest()
1627 {
1628 setWindowWidth(kWindowSize);
1629 setWindowHeight(kWindowSize);
1630 setConfigRedBits(8);
1631 setConfigGreenBits(8);
1632 setConfigBlueBits(8);
1633 setConfigAlphaBits(8);
1634 }
1635
1636 void simpleDrawWithBuffer(GLBuffer *buffer);
1637 void simpleDrawWithColor(const GLColor &color);
1638
1639 using UpdateFunc = std::function<void(GLenum, GLTexture *, GLint, GLint, const GLColor &)>;
1640 void updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc);
1641 void bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture);
1642 void drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty);
1643 };
1644
1645 class SimpleStateChangeTestES3 : public SimpleStateChangeTest
1646 {
1647 protected:
blendAndVerifyColor(const GLColor32F blendColor,const GLColor expectedColor)1648 void blendAndVerifyColor(const GLColor32F blendColor, const GLColor expectedColor)
1649 {
1650 glEnable(GL_BLEND);
1651 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1652 EXPECT_GL_NO_ERROR();
1653
1654 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1655 glUseProgram(program);
1656
1657 GLint colorUniformLocation =
1658 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1659 ASSERT_NE(colorUniformLocation, -1);
1660
1661 glUniform4f(colorUniformLocation, blendColor.R, blendColor.G, blendColor.B, blendColor.A);
1662 EXPECT_GL_NO_ERROR();
1663
1664 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1665 EXPECT_GL_NO_ERROR();
1666 EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 1);
1667 }
1668 };
1669
1670 class SimpleStateChangeTestES31 : public SimpleStateChangeTestES3
1671 {};
1672
1673 class SimpleStateChangeTestComputeES31 : public SimpleStateChangeTest
1674 {
1675 protected:
testSetUp()1676 void testSetUp() override
1677 {
1678 glGenFramebuffers(1, &mFramebuffer);
1679 glGenTextures(1, &mTexture);
1680
1681 glBindTexture(GL_TEXTURE_2D, mTexture);
1682 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
1683 EXPECT_GL_NO_ERROR();
1684
1685 constexpr char kCS[] = R"(#version 310 es
1686 layout(local_size_x=2, local_size_y=2) in;
1687 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
1688 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
1689 void main()
1690 {
1691 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1692 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
1693 })";
1694
1695 mProgram = CompileComputeProgram(kCS);
1696 ASSERT_NE(mProgram, 0u);
1697
1698 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1699
1700 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
1701 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture,
1702 0);
1703
1704 ASSERT_GL_NO_ERROR();
1705 }
1706
testTearDown()1707 void testTearDown() override
1708 {
1709 if (mFramebuffer != 0)
1710 {
1711 glDeleteFramebuffers(1, &mFramebuffer);
1712 mFramebuffer = 0;
1713 }
1714
1715 if (mTexture != 0)
1716 {
1717 glDeleteTextures(1, &mTexture);
1718 mTexture = 0;
1719 }
1720 glDeleteProgram(mProgram);
1721 }
1722
1723 GLuint mProgram;
1724 GLuint mFramebuffer = 0;
1725 GLuint mTexture = 0;
1726 };
1727
1728 class ImageES31PPO
1729 {
1730 protected:
ImageES31PPO()1731 ImageES31PPO() : mComputeProg(0), mPipeline(0) {}
1732
bindProgramPipeline(const GLchar * computeString)1733 void bindProgramPipeline(const GLchar *computeString)
1734 {
1735 mComputeProg = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &computeString);
1736 ASSERT_NE(mComputeProg, 0u);
1737
1738 // Generate a program pipeline and attach the programs to their respective stages
1739 glGenProgramPipelines(1, &mPipeline);
1740 EXPECT_GL_NO_ERROR();
1741 glUseProgramStages(mPipeline, GL_COMPUTE_SHADER_BIT, mComputeProg);
1742 EXPECT_GL_NO_ERROR();
1743 glBindProgramPipeline(mPipeline);
1744 EXPECT_GL_NO_ERROR();
1745 glActiveShaderProgram(mPipeline, mComputeProg);
1746 EXPECT_GL_NO_ERROR();
1747 }
1748
1749 GLuint mComputeProg;
1750 GLuint mPipeline;
1751 };
1752
1753 class SimpleStateChangeTestComputeES31PPO : public ImageES31PPO, public SimpleStateChangeTest
1754 {
1755 protected:
SimpleStateChangeTestComputeES31PPO()1756 SimpleStateChangeTestComputeES31PPO() : ImageES31PPO(), SimpleStateChangeTest() {}
1757
testTearDown()1758 void testTearDown() override
1759 {
1760 if (mFramebuffer != 0)
1761 {
1762 glDeleteFramebuffers(1, &mFramebuffer);
1763 mFramebuffer = 0;
1764 }
1765
1766 if (mTexture != 0)
1767 {
1768 glDeleteTextures(1, &mTexture);
1769 mTexture = 0;
1770 }
1771 glDeleteProgramPipelines(1, &mPipeline);
1772 }
1773
1774 GLuint mFramebuffer = 0;
1775 GLuint mTexture = 0;
1776 };
1777
1778 constexpr char kSimpleVertexShader[] = R"(attribute vec2 position;
1779 attribute vec4 color;
1780 varying vec4 vColor;
1781 void main()
1782 {
1783 gl_Position = vec4(position, 0, 1);
1784 vColor = color;
1785 }
1786 )";
1787
1788 constexpr char kSimpleVertexShaderForPoints[] = R"(attribute vec2 position;
1789 attribute vec4 color;
1790 varying vec4 vColor;
1791 void main()
1792 {
1793 gl_Position = vec4(position, 0, 1);
1794 gl_PointSize = 1.0;
1795 vColor = color;
1796 }
1797 )";
1798
1799 constexpr char kZeroVertexShaderForPoints[] = R"(void main()
1800 {
1801 gl_Position = vec4(0);
1802 gl_PointSize = 1.0;
1803 }
1804 )";
1805
1806 constexpr char kSimpleFragmentShader[] = R"(precision mediump float;
1807 varying vec4 vColor;
1808 void main()
1809 {
1810 gl_FragColor = vColor;
1811 }
1812 )";
1813
simpleDrawWithBuffer(GLBuffer * buffer)1814 void SimpleStateChangeTest::simpleDrawWithBuffer(GLBuffer *buffer)
1815 {
1816 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
1817 glUseProgram(program);
1818
1819 GLint colorLoc = glGetAttribLocation(program, "color");
1820 ASSERT_NE(-1, colorLoc);
1821
1822 glBindBuffer(GL_ARRAY_BUFFER, *buffer);
1823 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1824 glEnableVertexAttribArray(colorLoc);
1825
1826 drawQuad(program, "position", 0.5f, 1.0f, true);
1827 ASSERT_GL_NO_ERROR();
1828 }
1829
simpleDrawWithColor(const GLColor & color)1830 void SimpleStateChangeTest::simpleDrawWithColor(const GLColor &color)
1831 {
1832 std::vector<GLColor> colors(6, color);
1833 GLBuffer colorBuffer;
1834 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
1835 glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLColor), colors.data(), GL_STATIC_DRAW);
1836 simpleDrawWithBuffer(&colorBuffer);
1837 }
1838
1839 // Test that we can do a drawElements call successfully after making a drawArrays call in the same
1840 // frame.
TEST_P(SimpleStateChangeTest,DrawArraysThenDrawElements)1841 TEST_P(SimpleStateChangeTest, DrawArraysThenDrawElements)
1842 {
1843 // http://anglebug.com/40644706
1844 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
1845
1846 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1847 glUseProgram(program);
1848
1849 // We expect to draw a triangle with the first 3 points to the left, then another triangle with
1850 // the last 3 vertices using a drawElements call.
1851 auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
1852 {-1.0f, 1.0f, 0.0f},
1853 {0.0f, 0.0f, 0.0f},
1854 {1.0f, 1.0f, 0.0f},
1855 {1.0f, -1.0f, 0.0f}};
1856
1857 // If we use these indices to draw we'll be using the last 2 vertex only to draw.
1858 auto indices = std::vector<GLushort>{2, 3, 4};
1859
1860 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1861 ASSERT_NE(-1, positionLocation);
1862
1863 GLBuffer vertexBuffer;
1864 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1865 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1866 GL_STATIC_DRAW);
1867
1868 GLBuffer indexBuffer;
1869 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1870 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1871 GL_STATIC_DRAW);
1872
1873 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1874 glEnableVertexAttribArray(positionLocation);
1875
1876 for (int i = 0; i < 10; i++)
1877 {
1878 glClear(GL_COLOR_BUFFER_BIT);
1879 glDrawArrays(GL_TRIANGLES, 0, 3); // triangle to the left
1880 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr); // triangle to the right
1881 glFinish();
1882 }
1883 glDisableVertexAttribArray(positionLocation);
1884
1885 ASSERT_GL_NO_ERROR();
1886
1887 int quarterWidth = getWindowWidth() / 4;
1888 int halfHeight = getWindowHeight() / 2;
1889
1890 // Validate triangle to the left
1891 EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::blue);
1892
1893 // Validate triangle to the right
1894 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::blue);
1895 }
1896
1897 // Draw a triangle with drawElements and a non-zero offset and draw the same
1898 // triangle with the same offset followed by binding the same element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElements)1899 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElements)
1900 {
1901 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1902
1903 glUseProgram(program);
1904
1905 // Background Red color
1906 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1907 glClear(GL_COLOR_BUFFER_BIT);
1908
1909 // We expect to draw the triangle with the last three points on the bottom right, and
1910 // rebind the same element buffer and draw with the same indices.
1911 auto vertices = std::vector<Vector3>{
1912 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1913
1914 auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1915
1916 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1917 ASSERT_NE(-1, positionLocation);
1918
1919 GLBuffer indexBuffer;
1920 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1921 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1922 GL_STATIC_DRAW);
1923
1924 GLBuffer vertexBuffer;
1925 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1926 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1927 GL_STATIC_DRAW);
1928
1929 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1930 glEnableVertexAttribArray(positionLocation);
1931
1932 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1933
1934 // Rebind the same element buffer.
1935 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1936
1937 // Draw the triangle again with the same offset.
1938 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1939
1940 glDisableVertexAttribArray(positionLocation);
1941
1942 ASSERT_GL_NO_ERROR();
1943
1944 int quarterWidth = getWindowWidth() / 4;
1945 int quarterHeight = getWindowHeight() / 4;
1946
1947 // Validate the triangle is drawn on the bottom right.
1948 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1949
1950 // Validate the triangle is NOT on the top left part.
1951 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1952 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1953 }
1954
1955 // Draw a triangle with drawElements then change the index buffer and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndexBuffer)1956 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndexBuffer)
1957 {
1958 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1959
1960 glUseProgram(program);
1961
1962 // Background Red color
1963 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1964 glClear(GL_COLOR_BUFFER_BIT);
1965
1966 // We expect to draw the triangle with the last three points on the bottom right, and
1967 // rebind the same element buffer and draw with the same indices.
1968 auto vertices = std::vector<Vector3>{
1969 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1970
1971 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
1972
1973 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1974 ASSERT_NE(-1, positionLocation);
1975
1976 GLint colorUniformLocation =
1977 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1978 ASSERT_NE(colorUniformLocation, -1);
1979
1980 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1981
1982 GLBuffer indexBuffer8;
1983 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1984 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1985 GL_STATIC_DRAW);
1986
1987 GLBuffer vertexBuffer;
1988 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1989 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1990 GL_STATIC_DRAW);
1991
1992 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1993 glEnableVertexAttribArray(positionLocation);
1994
1995 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1996
1997 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
1998
1999 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2000 GL_STATIC_DRAW);
2001
2002 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2003
2004 // Draw the triangle again with the same offset.
2005 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2006
2007 glDisableVertexAttribArray(positionLocation);
2008
2009 ASSERT_GL_NO_ERROR();
2010
2011 int quarterWidth = getWindowWidth() / 4;
2012 int quarterHeight = getWindowHeight() / 4;
2013
2014 // Validate the triangle is drawn on the bottom left.
2015 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2016 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2017
2018 // Validate the triangle is NOT on the top right part.
2019 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2020 }
2021
2022 // Draw a triangle with drawElements then change the indices and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndices)2023 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndices)
2024 {
2025 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2026
2027 glUseProgram(program);
2028
2029 // Background Red color
2030 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2031 glClear(GL_COLOR_BUFFER_BIT);
2032
2033 // We expect to draw the triangle with the last three points on the bottom right, and
2034 // rebind the same element buffer and draw with the same indices.
2035 std::vector<Vector3> vertices = {
2036 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2037
2038 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
2039
2040 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2041 ASSERT_NE(-1, positionLocation);
2042
2043 GLint colorUniformLocation =
2044 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2045 ASSERT_NE(colorUniformLocation, -1);
2046
2047 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2048
2049 GLBuffer indexBuffer8;
2050 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2051 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2052 GL_DYNAMIC_DRAW);
2053
2054 GLBuffer vertexBuffer;
2055 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2056 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2057 GL_STATIC_DRAW);
2058
2059 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2060 glEnableVertexAttribArray(positionLocation);
2061
2062 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2063
2064 std::vector<GLubyte> newIndices8 = {2, 3, 0};
2065
2066 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
2067 &newIndices8[0]);
2068
2069 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2070
2071 // Draw the triangle again with the same offset.
2072 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2073
2074 glDisableVertexAttribArray(positionLocation);
2075
2076 ASSERT_GL_NO_ERROR();
2077
2078 int quarterWidth = getWindowWidth() / 4;
2079 int quarterHeight = getWindowHeight() / 4;
2080
2081 // Validate the triangle is drawn on the bottom left.
2082 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2083 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2084
2085 // Validate the triangle is NOT on the top right part.
2086 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2087 }
2088
2089 // Draw a triangle with drawElements then change the indices and draw again. Similar to
2090 // DrawElementsThenDrawElementsNewIndices, but changes the whole index buffer (not just half). This
2091 // triggers a different path in the Vulkan backend based on the fact that the majority of the buffer
2092 // is being updated.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsWholeNewIndices)2093 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsWholeNewIndices)
2094 {
2095 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2096
2097 glUseProgram(program);
2098
2099 // Background Red color
2100 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2101 glClear(GL_COLOR_BUFFER_BIT);
2102
2103 // We expect to draw the triangle with the last three points on the bottom right, and
2104 // rebind the same element buffer and draw with the same indices.
2105 std::vector<Vector3> vertices = {
2106 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2107
2108 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
2109
2110 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2111 ASSERT_NE(-1, positionLocation);
2112
2113 GLint colorUniformLocation =
2114 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2115 ASSERT_NE(colorUniformLocation, -1);
2116
2117 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2118
2119 GLBuffer indexBuffer8;
2120 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2121 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2122 GL_DYNAMIC_DRAW);
2123
2124 GLBuffer vertexBuffer;
2125 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2126 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2127 GL_STATIC_DRAW);
2128
2129 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2130 glEnableVertexAttribArray(positionLocation);
2131
2132 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2133
2134 std::vector<GLubyte> newIndices8 = {2, 3, 0, 0, 0, 0};
2135
2136 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
2137 &newIndices8[0]);
2138
2139 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2140
2141 // Draw the triangle again with the same offset.
2142 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2143
2144 glDisableVertexAttribArray(positionLocation);
2145
2146 ASSERT_GL_NO_ERROR();
2147
2148 int quarterWidth = getWindowWidth() / 4;
2149 int quarterHeight = getWindowHeight() / 4;
2150
2151 // Validate the triangle is drawn on the bottom left.
2152 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2153 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2154
2155 // Validate the triangle is NOT on the top right part.
2156 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2157 }
2158
2159 // Draw a triangle with drawElements and a non-zero offset and draw the same
2160 // triangle with the same offset followed by binding a USHORT element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsUBYTEX2ThenDrawElementsUSHORT)2161 TEST_P(SimpleStateChangeTest, DrawElementsUBYTEX2ThenDrawElementsUSHORT)
2162 {
2163 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2164
2165 glUseProgram(program);
2166
2167 // Background Red color
2168 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2169 glClear(GL_COLOR_BUFFER_BIT);
2170
2171 // We expect to draw the triangle with the last three points on the bottom right, and
2172 // rebind the same element buffer and draw with the same indices.
2173 auto vertices = std::vector<Vector3>{
2174 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2175
2176 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
2177
2178 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2179 ASSERT_NE(-1, positionLocation);
2180
2181 GLint colorUniformLocation =
2182 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2183 ASSERT_NE(colorUniformLocation, -1);
2184
2185 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2186
2187 GLBuffer indexBuffer8;
2188 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2189 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2190 GL_STATIC_DRAW);
2191
2192 GLBuffer vertexBuffer;
2193 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2194 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2195 GL_STATIC_DRAW);
2196
2197 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2198 glEnableVertexAttribArray(positionLocation);
2199
2200 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2201
2202 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
2203 GLBuffer indexBuffer2nd8;
2204 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2nd8);
2205 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2206 GL_STATIC_DRAW);
2207 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2208
2209 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2210
2211 // Bind the 16bit element buffer.
2212 auto indices16 = std::vector<GLushort>{0, 1, 3, 1, 2, 3};
2213 GLBuffer indexBuffer16;
2214 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2215 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices16.size() * sizeof(GLushort), &indices16[0],
2216 GL_STATIC_DRAW);
2217
2218 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2219
2220 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2221
2222 // Draw the triangle again with the same offset.
2223 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(0 * sizeof(GLushort)));
2224
2225 glDisableVertexAttribArray(positionLocation);
2226
2227 ASSERT_GL_NO_ERROR();
2228
2229 int quarterWidth = getWindowWidth() / 4;
2230 int quarterHeight = getWindowHeight() / 4;
2231
2232 // Validate green triangle is drawn on the bottom.
2233 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::green);
2234
2235 // Validate white triangle is drawn on the right.
2236 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 3, quarterHeight * 2, GLColor::white);
2237
2238 // Validate blue triangle is on the top left part.
2239 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::blue);
2240 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2241 }
2242
2243 // Draw a points use multiple unaligned vertex buffer with same data,
2244 // verify all the rendering results are the same.
TEST_P(SimpleStateChangeTest,DrawRepeatUnalignedVboChange)2245 TEST_P(SimpleStateChangeTest, DrawRepeatUnalignedVboChange)
2246 {
2247 // http://anglebug.com/42263089
2248 ANGLE_SKIP_TEST_IF(isSwiftshader() && (IsWindows() || IsLinux()));
2249
2250 const int kRepeat = 2;
2251
2252 // set up VBO, colorVBO is unaligned
2253 GLBuffer positionBuffer;
2254 constexpr size_t posOffset = 0;
2255 const GLfloat posData[] = {0.5f, 0.5f};
2256 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2257 glBufferData(GL_ARRAY_BUFFER, sizeof(posData), posData, GL_STATIC_DRAW);
2258
2259 GLBuffer colorBuffers[kRepeat];
2260 constexpr size_t colorOffset = 1;
2261 const GLfloat colorData[] = {0.515f, 0.515f, 0.515f, 1.0f};
2262 constexpr size_t colorBufferSize = colorOffset + sizeof(colorData);
2263 uint8_t colorDataUnaligned[colorBufferSize] = {0};
2264 memcpy(reinterpret_cast<void *>(colorDataUnaligned + colorOffset), colorData,
2265 sizeof(colorData));
2266 for (uint32_t i = 0; i < kRepeat; i++)
2267 {
2268 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2269 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorDataUnaligned, GL_STATIC_DRAW);
2270 }
2271
2272 // set up frame buffer
2273 GLFramebuffer framebuffer;
2274 GLTexture framebufferTexture;
2275 bindTextureToFbo(framebuffer, framebufferTexture);
2276
2277 // set up program
2278 ANGLE_GL_PROGRAM(program, kSimpleVertexShaderForPoints, kSimpleFragmentShader);
2279 glUseProgram(program);
2280 GLuint colorAttrLocation = glGetAttribLocation(program, "color");
2281 glEnableVertexAttribArray(colorAttrLocation);
2282 GLuint posAttrLocation = glGetAttribLocation(program, "position");
2283 glEnableVertexAttribArray(posAttrLocation);
2284 EXPECT_GL_NO_ERROR();
2285
2286 // draw and get drawing results
2287 constexpr size_t kRenderSize = kWindowSize * kWindowSize;
2288 std::array<GLColor, kRenderSize> pixelBufs[kRepeat];
2289
2290 for (uint32_t i = 0; i < kRepeat; i++)
2291 {
2292 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2293 glClear(GL_COLOR_BUFFER_BIT);
2294
2295 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2296 glVertexAttribPointer(posAttrLocation, 2, GL_FLOAT, GL_FALSE, 0,
2297 reinterpret_cast<const void *>(posOffset));
2298 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2299 glVertexAttribPointer(colorAttrLocation, 4, GL_FLOAT, GL_FALSE, 0,
2300 reinterpret_cast<const void *>(colorOffset));
2301
2302 glDrawArrays(GL_POINTS, 0, 1);
2303
2304 // read drawing results
2305 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
2306 pixelBufs[i].data());
2307 EXPECT_GL_NO_ERROR();
2308 }
2309
2310 // verify something is drawn
2311 static_assert(kRepeat >= 2, "More than one repetition required");
2312 std::array<GLColor, kRenderSize> pixelAllBlack{0};
2313 EXPECT_NE(pixelBufs[0], pixelAllBlack);
2314 // verify drawing results are all identical
2315 for (uint32_t i = 1; i < kRepeat; i++)
2316 {
2317 EXPECT_EQ(pixelBufs[i - 1], pixelBufs[i]);
2318 }
2319 }
2320
2321 // Handles deleting a Buffer when it's being used.
TEST_P(SimpleStateChangeTest,DeleteBufferInUse)2322 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
2323 {
2324 std::vector<GLColor> colorData(6, GLColor::red);
2325
2326 GLBuffer buffer;
2327 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2328 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * colorData.size(), colorData.data(),
2329 GL_STATIC_DRAW);
2330
2331 simpleDrawWithBuffer(&buffer);
2332
2333 buffer.reset();
2334 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2335 }
2336
2337 // Tests that resizing a Buffer during a draw works as expected.
TEST_P(SimpleStateChangeTest,RedefineBufferInUse)2338 TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
2339 {
2340 std::vector<GLColor> redColorData(6, GLColor::red);
2341
2342 GLBuffer buffer;
2343 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2344 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2345 GL_STATIC_DRAW);
2346
2347 // Trigger a pull from the buffer.
2348 simpleDrawWithBuffer(&buffer);
2349
2350 // Redefine the buffer that's in-flight.
2351 std::vector<GLColor> greenColorData(1024, GLColor::green);
2352 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * greenColorData.size(), greenColorData.data(),
2353 GL_STATIC_DRAW);
2354
2355 // Trigger the flush and verify the first draw worked.
2356 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2357
2358 // Draw again and verify the new data is correct.
2359 simpleDrawWithBuffer(&buffer);
2360 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2361 }
2362
2363 // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest,UpdateBufferInUse)2364 TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
2365 {
2366 std::vector<GLColor> redColorData(6, GLColor::red);
2367
2368 GLBuffer buffer;
2369 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2370 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2371 GL_STATIC_DRAW);
2372
2373 // Trigger a pull from the buffer.
2374 simpleDrawWithBuffer(&buffer);
2375
2376 // Update the buffer that's in-flight.
2377 std::vector<GLColor> greenColorData(6, GLColor::green);
2378 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * greenColorData.size(),
2379 greenColorData.data());
2380
2381 // Trigger the flush and verify the first draw worked.
2382 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2383
2384 // Draw again and verify the new data is correct.
2385 simpleDrawWithBuffer(&buffer);
2386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2387 }
2388
2389 // Tests that deleting an in-flight Texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTest,DeleteTextureInUse)2390 TEST_P(SimpleStateChangeTest, DeleteTextureInUse)
2391 {
2392 std::array<GLColor, 4> colors = {
2393 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2394
2395 GLTexture tex;
2396 glBindTexture(GL_TEXTURE_2D, tex);
2397 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2400
2401 draw2DTexturedQuad(0.5f, 1.0f, true);
2402 tex.reset();
2403 EXPECT_GL_NO_ERROR();
2404
2405 int w = getWindowWidth() - 2;
2406 int h = getWindowHeight() - 2;
2407
2408 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2409 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2410 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2411 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2412 }
2413
2414 // Tests that modifying a texture parameter in-flight does not cause problems.
TEST_P(SimpleStateChangeTest,ChangeTextureFilterModeBetweenTwoDraws)2415 TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
2416 {
2417 std::array<GLColor, 4> colors = {
2418 {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
2419
2420 GLTexture tex;
2421 glBindTexture(GL_TEXTURE_2D, tex);
2422 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2423
2424 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2425 glClear(GL_COLOR_BUFFER_BIT);
2426
2427 // Draw to the left side of the window only with NEAREST.
2428 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2429 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2431 draw2DTexturedQuad(0.5f, 1.0f, true);
2432
2433 // Draw to the right side of the window only with LINEAR.
2434 glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2437 draw2DTexturedQuad(0.5f, 1.0f, true);
2438 EXPECT_GL_NO_ERROR();
2439
2440 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2441
2442 // The first half (left) should be only black followed by plain white.
2443 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2444 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
2445 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
2446 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
2447
2448 // The second half (right) should be a gradient so we shouldn't find plain black/white in the
2449 // middle.
2450 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
2451 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
2452 }
2453
2454 // Tests that bind the same texture all the time between different draw calls.
TEST_P(SimpleStateChangeTest,RebindTextureDrawAgain)2455 TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
2456 {
2457 GLuint program = get2DTexturedQuadProgram();
2458 glUseProgram(program);
2459
2460 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2461
2462 // Setup the texture
2463 GLTexture tex;
2464 glBindTexture(GL_TEXTURE_2D, tex);
2465 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2468
2469 // Setup the vertex array to draw a quad.
2470 GLint positionLocation = glGetAttribLocation(program, "position");
2471 setupQuadVertexBuffer(1.0f, 1.0f);
2472 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2473 glEnableVertexAttribArray(positionLocation);
2474
2475 // Draw quad
2476 glDrawArrays(GL_TRIANGLES, 0, 6);
2477 ASSERT_GL_NO_ERROR();
2478
2479 // Bind again
2480 glBindTexture(GL_TEXTURE_2D, tex);
2481 ASSERT_GL_NO_ERROR();
2482
2483 // Draw again, should still work.
2484 glDrawArrays(GL_TRIANGLES, 0, 6);
2485 ASSERT_GL_NO_ERROR();
2486
2487 // Validate whole surface is filled with cyan.
2488 int h = getWindowHeight() - 1;
2489 int w = getWindowWidth() - 1;
2490
2491 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2492 }
2493
2494 // Tests that we can draw with a texture, modify the texture with a texSubImage, and then draw again
2495 // correctly.
TEST_P(SimpleStateChangeTest,DrawWithTextureTexSubImageThenDrawAgain)2496 TEST_P(SimpleStateChangeTest, DrawWithTextureTexSubImageThenDrawAgain)
2497 {
2498 GLuint program = get2DTexturedQuadProgram();
2499 ASSERT_NE(0u, program);
2500 glUseProgram(program);
2501
2502 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
2503 std::array<GLColor, 4> subColors = {
2504 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
2505
2506 // Setup the texture
2507 GLTexture tex;
2508 glBindTexture(GL_TEXTURE_2D, tex);
2509 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2510 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2512
2513 // Setup the vertex array to draw a quad.
2514 GLint positionLocation = glGetAttribLocation(program, "position");
2515 setupQuadVertexBuffer(1.0f, 1.0f);
2516 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2517 glEnableVertexAttribArray(positionLocation);
2518
2519 // Draw quad
2520 glDrawArrays(GL_TRIANGLES, 0, 6);
2521 ASSERT_GL_NO_ERROR();
2522
2523 // Update bottom-half of texture with green.
2524 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
2525 ASSERT_GL_NO_ERROR();
2526
2527 // Draw again, should still work.
2528 glDrawArrays(GL_TRIANGLES, 0, 6);
2529 ASSERT_GL_NO_ERROR();
2530
2531 // Validate first half of the screen is red and the bottom is green.
2532 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2533 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4 * 3, GLColor::red);
2534 }
2535
2536 // Test that we can alternate between textures between different draws.
TEST_P(SimpleStateChangeTest,DrawTextureAThenTextureBThenTextureA)2537 TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
2538 {
2539 GLuint program = get2DTexturedQuadProgram();
2540 glUseProgram(program);
2541
2542 std::array<GLColor, 4> colorsTex1 = {
2543 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2544
2545 std::array<GLColor, 4> colorsTex2 = {
2546 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
2547
2548 // Setup the texture
2549 GLTexture tex1;
2550 glBindTexture(GL_TEXTURE_2D, tex1);
2551 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
2552 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2553 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2554
2555 GLTexture tex2;
2556 glBindTexture(GL_TEXTURE_2D, tex2);
2557 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
2558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2560
2561 // Setup the vertex array to draw a quad.
2562 GLint positionLocation = glGetAttribLocation(program, "position");
2563 setupQuadVertexBuffer(1.0f, 1.0f);
2564 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2565 glEnableVertexAttribArray(positionLocation);
2566
2567 // Draw quad
2568 glBindTexture(GL_TEXTURE_2D, tex1);
2569 glDrawArrays(GL_TRIANGLES, 0, 6);
2570 ASSERT_GL_NO_ERROR();
2571
2572 // Bind again, draw again
2573 glBindTexture(GL_TEXTURE_2D, tex2);
2574 glDrawArrays(GL_TRIANGLES, 0, 6);
2575 ASSERT_GL_NO_ERROR();
2576
2577 // Bind again, draw again
2578 glBindTexture(GL_TEXTURE_2D, tex1);
2579 glDrawArrays(GL_TRIANGLES, 0, 6);
2580
2581 // Validate whole surface is filled with cyan.
2582 int h = getWindowHeight() - 1;
2583 int w = getWindowWidth() - 1;
2584
2585 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2586 }
2587
2588 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
TEST_P(SimpleStateChangeTest,RedefineTextureInUse)2589 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
2590 {
2591 std::array<GLColor, 4> colors = {
2592 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2593
2594 GLTexture tex;
2595 glBindTexture(GL_TEXTURE_2D, tex);
2596 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2599
2600 // Draw with the first texture.
2601 draw2DTexturedQuad(0.5f, 1.0f, true);
2602
2603 // Redefine the in-flight texture.
2604 constexpr int kBigSize = 32;
2605 std::vector<GLColor> bigColors;
2606 for (int y = 0; y < kBigSize; ++y)
2607 {
2608 for (int x = 0; x < kBigSize; ++x)
2609 {
2610 bool xComp = x < kBigSize / 2;
2611 bool yComp = y < kBigSize / 2;
2612 if (yComp)
2613 {
2614 bigColors.push_back(xComp ? GLColor::cyan : GLColor::magenta);
2615 }
2616 else
2617 {
2618 bigColors.push_back(xComp ? GLColor::yellow : GLColor::white);
2619 }
2620 }
2621 }
2622
2623 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigColors.data());
2624 EXPECT_GL_NO_ERROR();
2625
2626 // Verify the first draw had the correct data via ReadPixels.
2627 int w = getWindowWidth() - 2;
2628 int h = getWindowHeight() - 2;
2629
2630 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2631 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2632 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2633 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2634
2635 // Draw and verify with the redefined data.
2636 draw2DTexturedQuad(0.5f, 1.0f, true);
2637 EXPECT_GL_NO_ERROR();
2638
2639 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2640 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::magenta);
2641 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::yellow);
2642 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::white);
2643 }
2644
2645 // Test updating a Texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTest,UpdateTextureInUse)2646 TEST_P(SimpleStateChangeTest, UpdateTextureInUse)
2647 {
2648 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2649
2650 // Set up 2D quad resources.
2651 GLuint program = get2DTexturedQuadProgram();
2652 glUseProgram(program);
2653 ASSERT_EQ(0, glGetAttribLocation(program, "position"));
2654
2655 const auto &quadVerts = GetQuadVertices();
2656
2657 GLBuffer vbo;
2658 glBindBuffer(GL_ARRAY_BUFFER, vbo);
2659 glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
2660 GL_STATIC_DRAW);
2661 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2662 glEnableVertexAttribArray(0);
2663
2664 GLTexture tex;
2665 glBindTexture(GL_TEXTURE_2D, tex);
2666 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
2667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2669
2670 // Draw RGBY to the Framebuffer. The texture is now in-use by GL.
2671 const int w = getWindowWidth() - 2;
2672 const int h = getWindowHeight() - 2;
2673 const int w2 = w >> 1;
2674
2675 glViewport(0, 0, w2, h);
2676 glDrawArrays(GL_TRIANGLES, 0, 6);
2677
2678 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the draw.
2679 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
2680 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
2681 ASSERT_GL_NO_ERROR();
2682
2683 // Draw again to the Framebuffer. The second draw call should use the updated YBGR data.
2684 glViewport(w2, 0, w2, h);
2685 glDrawArrays(GL_TRIANGLES, 0, 6);
2686
2687 // Check the Framebuffer. Both draws should have completed.
2688 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2689 EXPECT_PIXEL_COLOR_EQ(w2 - 1, 0, GLColor::green);
2690 EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::blue);
2691 EXPECT_PIXEL_COLOR_EQ(w2 - 1, h - 1, GLColor::yellow);
2692
2693 EXPECT_PIXEL_COLOR_EQ(w2 + 1, 0, GLColor::yellow);
2694 EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::blue);
2695 EXPECT_PIXEL_COLOR_EQ(w2 + 1, h - 1, GLColor::green);
2696 EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::red);
2697 ASSERT_GL_NO_ERROR();
2698 }
2699
updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)2700 void SimpleStateChangeTest::updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)
2701 {
2702 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2703
2704 std::vector<GLColor> red(4, GLColor::red);
2705 std::vector<GLColor> green(4, GLColor::green);
2706
2707 GLTexture renderTarget;
2708 glBindTexture(GL_TEXTURE_2D, renderTarget);
2709 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2710
2711 GLFramebuffer fbo;
2712 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2713 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2714 0);
2715 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2716 glViewport(0, 0, 2, 2);
2717 ASSERT_GL_NO_ERROR();
2718
2719 GLTexture tex;
2720 glBindTexture(GL_TEXTURE_2D, tex);
2721 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2722 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2723 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2724
2725 // Draw once to flush dirty state bits.
2726 draw2DTexturedQuad(0.5f, 1.0f, true);
2727
2728 ASSERT_GL_NO_ERROR();
2729
2730 // Update the (0, 1) pixel to be blue
2731 updateFunc(GL_TEXTURE_2D, &renderTarget, 0, 1, GLColor::blue);
2732
2733 // Draw green to the right half of the Framebuffer.
2734 glBindTexture(GL_TEXTURE_2D, tex);
2735 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, green.data());
2736 glViewport(1, 0, 1, 2);
2737 draw2DTexturedQuad(0.5f, 1.0f, true);
2738
2739 // Update the (1, 1) pixel to be yellow
2740 updateFunc(GL_TEXTURE_2D, &renderTarget, 1, 1, GLColor::yellow);
2741
2742 ASSERT_GL_NO_ERROR();
2743
2744 // Verify we have a quad with the right colors in the FBO.
2745 std::vector<GLColor> expected = {
2746 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2747 std::vector<GLColor> actual(4);
2748 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2749 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
2750 EXPECT_EQ(expected, actual);
2751 }
2752
2753 // Tests that TexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,TexSubImageOnTextureBoundToFrambuffer)2754 TEST_P(SimpleStateChangeTest, TexSubImageOnTextureBoundToFrambuffer)
2755 {
2756 // http://anglebug.com/40096654
2757 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2758 auto updateFunc = [](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2759 const GLColor &color) {
2760 glBindTexture(textureBinding, *tex);
2761 glTexSubImage2D(textureBinding, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2762 };
2763
2764 updateTextureBoundToFramebufferHelper(updateFunc);
2765 }
2766
2767 // Tests that CopyTexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,CopyTexSubImageOnTextureBoundToFrambuffer)2768 TEST_P(SimpleStateChangeTest, CopyTexSubImageOnTextureBoundToFrambuffer)
2769 {
2770 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2771
2772 GLTexture copySource;
2773 glBindTexture(GL_TEXTURE_2D, copySource);
2774 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2775
2776 GLFramebuffer copyFBO;
2777 glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFBO);
2778 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySource, 0);
2779
2780 ASSERT_GL_NO_ERROR();
2781 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2782
2783 auto updateFunc = [©Source](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2784 const GLColor &color) {
2785 glBindTexture(GL_TEXTURE_2D, copySource);
2786 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2787
2788 glBindTexture(textureBinding, *tex);
2789 glCopyTexSubImage2D(textureBinding, 0, x, y, 0, 0, 1, 1);
2790 };
2791
2792 updateTextureBoundToFramebufferHelper(updateFunc);
2793 }
2794
2795 // Tests that the read framebuffer doesn't affect what the draw call thinks the attachments are
2796 // (which is what the draw framebuffer dictates) when a command is issued with the GL_FRAMEBUFFER
2797 // target.
TEST_P(SimpleStateChangeTestES3,ReadFramebufferDrawFramebufferDifferentAttachments)2798 TEST_P(SimpleStateChangeTestES3, ReadFramebufferDrawFramebufferDifferentAttachments)
2799 {
2800 // http://anglebug.com/40096654
2801 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2802
2803 GLRenderbuffer drawColorBuffer;
2804 glBindRenderbuffer(GL_RENDERBUFFER, drawColorBuffer);
2805 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2806
2807 GLRenderbuffer drawDepthBuffer;
2808 glBindRenderbuffer(GL_RENDERBUFFER, drawDepthBuffer);
2809 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1);
2810
2811 GLRenderbuffer readColorBuffer;
2812 glBindRenderbuffer(GL_RENDERBUFFER, readColorBuffer);
2813 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2814
2815 GLFramebuffer drawFBO;
2816 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2817 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2818 drawColorBuffer);
2819 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2820 drawDepthBuffer);
2821 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2822
2823 GLFramebuffer readFBO;
2824 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2825 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2826 readColorBuffer);
2827 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2828
2829 EXPECT_GL_NO_ERROR();
2830
2831 glClearDepthf(1.0f);
2832 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2833
2834 // A handful of non-draw calls can sync framebuffer state, such as discard, invalidate,
2835 // invalidateSub and multisamplefv.
2836 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2837 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
2838 EXPECT_GL_NO_ERROR();
2839
2840 glEnable(GL_DEPTH_TEST);
2841 glDepthFunc(GL_EQUAL);
2842
2843 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
2844
2845 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
2846 EXPECT_GL_NO_ERROR();
2847
2848 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2849 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2850 }
2851
2852 // Tests that invalidate then copy then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenCopyThenBlend)2853 TEST_P(SimpleStateChangeTestES3, InvalidateThenCopyThenBlend)
2854 {
2855 // Create a framebuffer as the source of copy
2856 const GLColor kSrcData = GLColor::cyan;
2857 GLTexture copySrc;
2858 glBindTexture(GL_TEXTURE_2D, copySrc);
2859 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2860
2861 GLFramebuffer readFBO;
2862 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2863 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySrc, 0);
2864 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2865
2866 // Create the framebuffer that will be invalidated
2867 GLTexture renderTarget;
2868 glBindTexture(GL_TEXTURE_2D, renderTarget);
2869 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2870
2871 GLFramebuffer drawFBO;
2872 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2873 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2874 0);
2875 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2876
2877 EXPECT_GL_NO_ERROR();
2878
2879 // Clear the framebuffer and invalidate it.
2880 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2881 glClear(GL_COLOR_BUFFER_BIT);
2882
2883 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2884 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2885 EXPECT_GL_NO_ERROR();
2886
2887 // Copy into the framebuffer's texture. The framebuffer should now be cyan.
2888 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2889 EXPECT_GL_NO_ERROR();
2890
2891 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2892 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2893 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2894 }
2895
2896 // Tests that invalidate then blit then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenBlitThenBlend)2897 TEST_P(SimpleStateChangeTestES3, InvalidateThenBlitThenBlend)
2898 {
2899 // Create a framebuffer as the source of blit
2900 const GLColor kSrcData = GLColor::cyan;
2901 GLTexture blitSrc;
2902 glBindTexture(GL_TEXTURE_2D, blitSrc);
2903 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2904
2905 GLFramebuffer readFBO;
2906 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2907 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
2908 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2909
2910 // Create the framebuffer that will be invalidated
2911 GLTexture renderTarget;
2912 glBindTexture(GL_TEXTURE_2D, renderTarget);
2913 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2914
2915 GLFramebuffer drawFBO;
2916 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2917 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2918 0);
2919 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2920
2921 EXPECT_GL_NO_ERROR();
2922
2923 // Clear the framebuffer and invalidate it.
2924 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2925 glClear(GL_COLOR_BUFFER_BIT);
2926
2927 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2928 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2929 EXPECT_GL_NO_ERROR();
2930
2931 // Blit into the framebuffer. The framebuffer should now be cyan.
2932 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2933 EXPECT_GL_NO_ERROR();
2934
2935 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2936 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2937 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2938 }
2939
2940 // Tests that invalidate then generate mipmaps works
TEST_P(SimpleStateChangeTestES3,InvalidateThenGenerateMipmapsThenBlend)2941 TEST_P(SimpleStateChangeTestES3, InvalidateThenGenerateMipmapsThenBlend)
2942 {
2943 // Create a texture on which generate mipmaps would be called
2944 const GLColor kMip0Data[4] = {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan};
2945 const GLColor kMip1Data = GLColor::blue;
2946 GLTexture texture;
2947 glBindTexture(GL_TEXTURE_2D, texture);
2948 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data);
2949 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kMip1Data);
2950
2951 // Create the framebuffer that will be invalidated
2952 GLFramebuffer drawFBO;
2953 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2954 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
2955 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2956
2957 EXPECT_GL_NO_ERROR();
2958
2959 // Clear the framebuffer and invalidate it.
2960 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2961 glClear(GL_COLOR_BUFFER_BIT);
2962
2963 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2964 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2965 EXPECT_GL_NO_ERROR();
2966
2967 // Generate mipmaps
2968 glGenerateMipmap(GL_TEXTURE_2D);
2969
2970 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2971 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2972 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2973 }
2974
2975 // Tests that invalidate then upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenUploadThenBlend)2976 TEST_P(SimpleStateChangeTestES3, InvalidateThenUploadThenBlend)
2977 {
2978 // http://anglebug.com/42263445
2979 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2980
2981 // Create the framebuffer that will be invalidated
2982 GLTexture renderTarget;
2983 glBindTexture(GL_TEXTURE_2D, renderTarget);
2984 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2985
2986 GLFramebuffer drawFBO;
2987 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2988 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2989 0);
2990 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2991
2992 EXPECT_GL_NO_ERROR();
2993
2994 // Clear the framebuffer and invalidate it.
2995 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2996 glClear(GL_COLOR_BUFFER_BIT);
2997
2998 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2999 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3000 EXPECT_GL_NO_ERROR();
3001
3002 // Upload data to it
3003 const GLColor kUploadColor = GLColor::cyan;
3004 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
3005
3006 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3007 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3008 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3009 }
3010
3011 // Tests that invalidate then sub upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenSubUploadThenBlend)3012 TEST_P(SimpleStateChangeTestES3, InvalidateThenSubUploadThenBlend)
3013 {
3014 // http://anglebug.com/42263445
3015 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3016
3017 // Create the framebuffer that will be invalidated
3018 GLTexture renderTarget;
3019 glBindTexture(GL_TEXTURE_2D, renderTarget);
3020 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3021
3022 GLFramebuffer drawFBO;
3023 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3024 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3025 0);
3026 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3027
3028 EXPECT_GL_NO_ERROR();
3029
3030 // Clear the framebuffer and invalidate it.
3031 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3032 glClear(GL_COLOR_BUFFER_BIT);
3033
3034 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3035 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3036 EXPECT_GL_NO_ERROR();
3037
3038 // Upload data to it
3039 const GLColor kUploadColor = GLColor::cyan;
3040 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
3041
3042 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3043 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3044 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3045 }
3046
3047 // Tests that invalidate then compute write works
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlend)3048 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlend)
3049 {
3050 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3051 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3052 // http://anglebug.com/42263927
3053 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
3054
3055 constexpr char kCS[] = R"(#version 310 es
3056 layout(local_size_x=1, local_size_y=1) in;
3057 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
3058 void main()
3059 {
3060 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
3061 })";
3062
3063 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3064 glUseProgram(program);
3065 EXPECT_GL_NO_ERROR();
3066
3067 // Create the framebuffer texture
3068 GLTexture renderTarget;
3069 glBindTexture(GL_TEXTURE_2D, renderTarget);
3070 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
3071 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3072
3073 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
3074 // is already created with STORAGE usage and avoids recreate later.
3075 glDispatchCompute(1, 1, 1);
3076 EXPECT_GL_NO_ERROR();
3077
3078 // Needs explicit barrier between compute shader write to FBO access.
3079 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3080
3081 // Create the framebuffer that will be invalidated
3082 GLFramebuffer drawFBO;
3083 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3084 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3085 0);
3086 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3087
3088 EXPECT_GL_NO_ERROR();
3089
3090 // Clear the framebuffer and invalidate it.
3091 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3092 glClear(GL_COLOR_BUFFER_BIT);
3093
3094 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3095 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3096 EXPECT_GL_NO_ERROR();
3097
3098 // Issue a memory barrier before writing to the image again.
3099 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3100
3101 // Write to it with a compute shader
3102 glDispatchCompute(1, 1, 1);
3103 EXPECT_GL_NO_ERROR();
3104
3105 // Needs explicit barrier between compute shader write to FBO access.
3106 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3107
3108 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3109 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3110 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3111 }
3112
3113 // Tests that invalidate then compute write works inside PPO
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlendPpo)3114 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlendPpo)
3115 {
3116 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3117 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3118 // PPOs are only supported in the Vulkan backend
3119 ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
3120
3121 constexpr char kCS[] = R"(#version 310 es
3122 layout(local_size_x=1, local_size_y=1) in;
3123 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
3124 void main()
3125 {
3126 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
3127 })";
3128
3129 GLProgramPipeline pipeline;
3130 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3131 glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
3132 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, program);
3133 EXPECT_GL_NO_ERROR();
3134 glBindProgramPipeline(pipeline);
3135 EXPECT_GL_NO_ERROR();
3136 glUseProgram(0);
3137
3138 // Create the framebuffer texture
3139 GLTexture renderTarget;
3140 glBindTexture(GL_TEXTURE_2D, renderTarget);
3141 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
3142 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3143
3144 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
3145 // is already created with STORAGE usage and avoids recreate later.
3146 glDispatchCompute(1, 1, 1);
3147 EXPECT_GL_NO_ERROR();
3148
3149 // Needs explicit barrier between compute shader write to FBO access.
3150 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3151
3152 // Create the framebuffer that will be invalidated
3153 GLFramebuffer drawFBO;
3154 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3155 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3156 0);
3157 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3158
3159 EXPECT_GL_NO_ERROR();
3160
3161 // Clear the framebuffer and invalidate it.
3162 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3163 glClear(GL_COLOR_BUFFER_BIT);
3164
3165 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3166 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3167 EXPECT_GL_NO_ERROR();
3168
3169 // Issue a memory barrier before writing to the image again.
3170 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3171
3172 // Write to it with a compute shader
3173 glDispatchCompute(1, 1, 1);
3174 EXPECT_GL_NO_ERROR();
3175
3176 // Needs explicit barrier between compute shader write to FBO access.
3177 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3178
3179 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3180 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3181 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3182 }
3183
3184 // Tests that sub-invalidate then draw works.
TEST_P(SimpleStateChangeTestES3,SubInvalidateThenDraw)3185 TEST_P(SimpleStateChangeTestES3, SubInvalidateThenDraw)
3186 {
3187 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3188 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3189
3190 // Create the framebuffer that will be invalidated
3191 GLTexture renderTarget;
3192 glBindTexture(GL_TEXTURE_2D, renderTarget);
3193 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3194
3195 GLFramebuffer drawFBO;
3196 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3197 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3198 0);
3199 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3200
3201 EXPECT_GL_NO_ERROR();
3202
3203 // Clear the framebuffer.
3204 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3205 glClear(GL_COLOR_BUFFER_BIT);
3206
3207 // Draw into a quarter of the framebuffer, then invalidate that same region.
3208 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3209 glEnable(GL_SCISSOR_TEST);
3210 glScissor(1, 1, 1, 1);
3211 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3212
3213 // Only invalidate a quarter of the framebuffer.
3214 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3215 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment, 1, 1, 1, 1);
3216 EXPECT_GL_NO_ERROR();
3217
3218 glDisable(GL_SCISSOR_TEST);
3219
3220 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3221 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3222 blendAndVerifyColor(GLColor32F(0.0f, 0.0f, 1.0f, 0.5f), GLColor(127, 127, 127, 191));
3223 }
3224
3225 // Tests that mid-render-pass invalidate then clear works for color buffers. This test ensures that
3226 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,ColorInvalidateThenClear)3227 TEST_P(SimpleStateChangeTestES3, ColorInvalidateThenClear)
3228 {
3229 // Create the framebuffer that will be invalidated
3230 GLTexture color;
3231 glBindTexture(GL_TEXTURE_2D, color);
3232 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3233
3234 GLFramebuffer fbo;
3235 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3236 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3237 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3238
3239 EXPECT_GL_NO_ERROR();
3240
3241 // Initialize the framebuffer with a draw call.
3242 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3243 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3244
3245 // Invalidate it.
3246 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3247 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3248
3249 // Clear the framebuffer.
3250 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3251 glClear(GL_COLOR_BUFFER_BIT);
3252
3253 // Expect the clear color, ensuring that invalidate wasn't applied after clear.
3254 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3255 }
3256
3257 // Tests that mid-render-pass invalidate then clear works for depth buffers. This test ensures that
3258 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,DepthInvalidateThenClear)3259 TEST_P(SimpleStateChangeTestES3, DepthInvalidateThenClear)
3260 {
3261 // Create the framebuffer that will be invalidated
3262 GLTexture color;
3263 glBindTexture(GL_TEXTURE_2D, color);
3264 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3265
3266 GLRenderbuffer depth;
3267 glBindRenderbuffer(GL_RENDERBUFFER, depth);
3268 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
3269
3270 GLFramebuffer fbo;
3271 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3272 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3273 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
3274 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3275
3276 EXPECT_GL_NO_ERROR();
3277
3278 // Initialize the framebuffer with a draw call.
3279 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3280 glUseProgram(drawColor);
3281 GLint colorUniformLocation =
3282 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3283 ASSERT_NE(colorUniformLocation, -1);
3284
3285 glEnable(GL_DEPTH_TEST);
3286 glDepthFunc(GL_ALWAYS);
3287
3288 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3289 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
3290
3291 // Invalidate depth.
3292 GLenum invalidateAttachment = GL_DEPTH_ATTACHMENT;
3293 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3294
3295 // Clear the framebuffer.
3296 glClearDepthf(0.8f);
3297 glClear(GL_DEPTH_BUFFER_BIT);
3298
3299 // Expect the draw color. This breaks the render pass. Later, the test ensures that invalidate
3300 // of depth wasn't applied after clear.
3301 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3302
3303 // Blend with depth test and make sure depth is as expected.
3304 glEnable(GL_BLEND);
3305 glBlendFunc(GL_ONE, GL_ONE);
3306
3307 glDepthFunc(GL_LESS);
3308 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3309 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.59f);
3310
3311 glDepthFunc(GL_GREATER);
3312 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3313 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.61f);
3314
3315 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3316 }
3317
3318 // Invalidate an RGB framebuffer and verify that the alpha channel is not destroyed and remains
3319 // valid after a draw call.
TEST_P(SimpleStateChangeTestES3,InvalidateRGBThenDraw)3320 TEST_P(SimpleStateChangeTestES3, InvalidateRGBThenDraw)
3321 {
3322 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3323
3324 GLTexture texture;
3325 glBindTexture(GL_TEXTURE_2D, texture);
3326 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
3327 GL_UNSIGNED_BYTE, nullptr);
3328
3329 GLFramebuffer fbo;
3330 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3331 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3332 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3333 ASSERT_GL_NO_ERROR();
3334
3335 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3336 glClear(GL_COLOR_BUFFER_BIT);
3337 // Verify that clearing alpha is ineffective on an RGB format.
3338 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3339
3340 // Invalidate the framebuffer contents.
3341 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3342 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3343
3344 // Without an explicit clear, draw blue and make sure alpha is unaffected. If RGB is emulated
3345 // with RGBA, the previous invalidate shouldn't affect the alpha value.
3346 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
3347 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3348 }
3349
3350 // Draw and invalidate an RGB framebuffer and verify that the alpha channel is not destroyed and
3351 // remains valid after a draw call.
TEST_P(SimpleStateChangeTestES3,DrawInvalidateRGBThenDraw)3352 TEST_P(SimpleStateChangeTestES3, DrawInvalidateRGBThenDraw)
3353 {
3354 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3355 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3356
3357 GLTexture texture;
3358 glBindTexture(GL_TEXTURE_2D, texture);
3359 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
3360 GL_UNSIGNED_BYTE, nullptr);
3361
3362 GLFramebuffer fbo;
3363 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3364 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3365 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3366 ASSERT_GL_NO_ERROR();
3367
3368 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3369 glClear(GL_COLOR_BUFFER_BIT);
3370 // Verify that clearing alpha is ineffective on an RGB format.
3371 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3372
3373 // Draw before invalidating
3374 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
3375
3376 // Invalidate the framebuffer contents.
3377 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3378 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3379
3380 // Without an explicit clear, draw blue and make sure alpha is unaffected. If RGB is emulated
3381 // with RGBA, the previous invalidate shouldn't affect the alpha value.
3382 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
3383 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3384 }
3385
3386 // Invalidate an RGB framebuffer and verify that the alpha channel is not destroyed, even if the
3387 // color channels may be garbage.
TEST_P(SimpleStateChangeTestES3,DrawAndInvalidateRGBThenVerifyAlpha)3388 TEST_P(SimpleStateChangeTestES3, DrawAndInvalidateRGBThenVerifyAlpha)
3389 {
3390 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3391 glUseProgram(drawColor);
3392 GLint uniformLocation = glGetUniformLocation(drawColor, essl1_shaders::ColorUniform());
3393 ASSERT_NE(uniformLocation, -1);
3394
3395 const int w = getWindowWidth();
3396 const int h = getWindowHeight();
3397
3398 GLTexture texture;
3399 glBindTexture(GL_TEXTURE_2D, texture);
3400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
3401
3402 GLFramebuffer fbo;
3403 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3404 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3405 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3406 ASSERT_GL_NO_ERROR();
3407
3408 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3409 glClear(GL_COLOR_BUFFER_BIT);
3410
3411 glUniform4f(uniformLocation, 0.1f, 0.2f, 0.3f, 0.4f);
3412 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3413
3414 // Invalidate the framebuffer contents.
3415 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3416 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3417
3418 // Read back the contents of the framebuffer. The color channels are invalid, but as an RGB
3419 // format, readback should always return 1 in alpha.
3420 std::vector<GLColor> readback(w * h);
3421 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, readback.data());
3422 for (int y = 0; y < h; ++y)
3423 {
3424 for (int x = 0; x < w; ++x)
3425 {
3426 EXPECT_EQ(readback[y * w + x].A, 255) << x << " " << y;
3427 }
3428 }
3429 }
3430
3431 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3432 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
3433 {
3434 constexpr int kSize = 16;
3435
3436 // Create a simple framebuffer.
3437 GLTexture texture;
3438 glBindTexture(GL_TEXTURE_2D, texture);
3439 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3440
3441 GLFramebuffer framebuffer;
3442 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3443 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3444 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3445
3446 glViewport(0, 0, kSize, kSize);
3447
3448 // Draw a solid red color to the framebuffer.
3449 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3450 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3451
3452 // Delete the framebuffer while the call is in flight.
3453 framebuffer.reset();
3454
3455 // Make a new framebuffer so we can read back the texture.
3456 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3457 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3458 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3459
3460 // Flush via ReadPixels and check red was drawn.
3461 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3462 ASSERT_GL_NO_ERROR();
3463 }
3464
3465 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3466 // buffers too early. The test has 2 textures, we first create a texture and update it with
3467 // multiple updates, but we don't use it right away, we instead draw using another texture
3468 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3469 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3470 {
3471 constexpr int kSize = 64;
3472
3473 GLuint program = get2DTexturedQuadProgram();
3474 glUseProgram(program);
3475
3476 std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3477 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3478 GLTexture texture1;
3479 glBindTexture(GL_TEXTURE_2D, texture1);
3480 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3481
3482 for (int i = 0; i < 100; i++)
3483 {
3484 // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3485 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3486 greenPixels.data());
3487 }
3488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3490
3491 ASSERT_GL_NO_ERROR();
3492
3493 GLTexture texture2;
3494 glBindTexture(GL_TEXTURE_2D, texture2);
3495 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3496 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3498
3499 // Setup the vertex array to draw a quad.
3500 GLint positionLocation = glGetAttribLocation(program, "position");
3501 setupQuadVertexBuffer(1.0f, 1.0f);
3502 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3503 glEnableVertexAttribArray(positionLocation);
3504
3505 // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3506 glBindTexture(GL_TEXTURE_2D, texture2);
3507 glDrawArrays(GL_TRIANGLES, 0, 6);
3508 ASSERT_GL_NO_ERROR();
3509 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3510
3511 // If we now try to draw with texture1, we should trigger the issue.
3512 glBindTexture(GL_TEXTURE_2D, texture1);
3513 glDrawArrays(GL_TRIANGLES, 0, 6);
3514 ASSERT_GL_NO_ERROR();
3515
3516 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3517 }
3518
3519 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3520 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3521 {
3522 constexpr int kSize = 16;
3523
3524 // Create a simple framebuffer.
3525 GLTexture texture;
3526 glBindTexture(GL_TEXTURE_2D, texture);
3527 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3528
3529 GLFramebuffer framebuffer;
3530 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3531 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3532 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3533
3534 glViewport(0, 0, kSize, kSize);
3535
3536 // Draw red to the framebuffer.
3537 simpleDrawWithColor(GLColor::red);
3538
3539 // Change the framebuffer while the call is in flight to a new texture.
3540 GLTexture otherTexture;
3541 glBindTexture(GL_TEXTURE_2D, otherTexture);
3542 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3543
3544 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3545 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3546
3547 // Draw green to the framebuffer. Verify the color.
3548 simpleDrawWithColor(GLColor::green);
3549 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3550
3551 // Make a new framebuffer so we can read back the first texture and verify red.
3552 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3553 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3554 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3555
3556 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3557 ASSERT_GL_NO_ERROR();
3558 }
3559
3560 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3561 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3562 {
3563 GLFramebuffer framebuffer;
3564 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3565
3566 // Bind a simple 8x8 texture to the framebuffer, draw red.
3567 GLTexture texture;
3568 glBindTexture(GL_TEXTURE_2D, texture);
3569 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3570 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3571
3572 glViewport(0, 0, 8, 8);
3573 simpleDrawWithColor(GLColor::red);
3574 ASSERT_GL_NO_ERROR();
3575 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3576
3577 // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3578 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3579 glViewport(0, 0, 32, 32);
3580 simpleDrawWithColor(GLColor::green);
3581 ASSERT_GL_NO_ERROR();
3582 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3583 }
3584
3585 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3586 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3587 {
3588 // Fails on 431.02 driver. http://anglebug.com/40644697
3589 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3590
3591 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3592 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3593
3594 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3595
3596 GLTexture tex;
3597 glBindTexture(GL_TEXTURE_2D, tex);
3598 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3601 ASSERT_GL_NO_ERROR();
3602
3603 GLFramebuffer fbo;
3604 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3605 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3606 ASSERT_GL_NO_ERROR();
3607 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3608
3609 glUseProgram(program);
3610
3611 GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3612 ASSERT_NE(-1, uniLoc);
3613 glUniform1i(uniLoc, 0);
3614
3615 const int numRowsCols = 2;
3616 const int cellSize = getWindowWidth() / 2;
3617
3618 for (int cellY = 0; cellY < numRowsCols; cellY++)
3619 {
3620 for (int cellX = 0; cellX < numRowsCols; cellX++)
3621 {
3622 int seed = cellX + cellY * numRowsCols;
3623 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3624
3625 // Set the texture to a constant color using glClear and a user FBO.
3626 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3627 glClearColor(color[0], color[1], color[2], color[3]);
3628 glClear(GL_COLOR_BUFFER_BIT);
3629
3630 // Draw a small colored quad to the default FBO using the viewport.
3631 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3632 glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3633 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3634 }
3635 }
3636
3637 // Verify the colored quads were drawn correctly despite no flushing.
3638 std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3639 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3640 pixelData.data());
3641
3642 ASSERT_GL_NO_ERROR();
3643
3644 for (int cellY = 0; cellY < numRowsCols; cellY++)
3645 {
3646 for (int cellX = 0; cellX < numRowsCols; cellX++)
3647 {
3648 int seed = cellX + cellY * numRowsCols;
3649 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3650
3651 GLColor expectedColor(color);
3652
3653 int testN =
3654 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3655 GLColor actualColor = pixelData[testN];
3656 EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3657 }
3658 }
3659 }
3660
3661 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3662 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3663 {
3664 // Create a texture with red
3665 const GLColor kInitColor1 = GLColor::red;
3666 GLTexture texture1;
3667 glBindTexture(GL_TEXTURE_2D, texture1);
3668 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3669
3670 // Create a framebuffer to be cleared
3671 GLTexture texture2;
3672 glBindTexture(GL_TEXTURE_2D, texture2);
3673 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3674
3675 GLFramebuffer drawFBO;
3676 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3678 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3679
3680 EXPECT_GL_NO_ERROR();
3681
3682 // Clear the framebuffer to green
3683 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3684 glClear(GL_COLOR_BUFFER_BIT);
3685
3686 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3687 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3688 // a noop, the deferred clears will remain unflushed.
3689 glClear(0);
3690
3691 // Change framebuffer's attachment to the other texture.
3692 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3693 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3694
3695 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3696 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3697 glUseProgram(program);
3698
3699 glEnable(GL_BLEND);
3700 glBlendFunc(GL_ZERO, GL_ONE);
3701 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3702 EXPECT_GL_NO_ERROR();
3703
3704 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3705 // to the new attachment, green will be read back.
3706 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3707
3708 // Attach back to texture2. It should be cleared to green.
3709 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3711 }
3712
3713 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3714 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3715 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3716 {
3717 // Create a texture with red
3718 const GLColor kInitColor1 = GLColor::red;
3719 GLTexture texture1;
3720 glBindTexture(GL_TEXTURE_2D, texture1);
3721 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3722
3723 // Create a framebuffer to be cleared
3724 GLTexture texture2;
3725 glBindTexture(GL_TEXTURE_2D, texture2);
3726 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3727
3728 GLFramebuffer drawFBO;
3729 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3730 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3731 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3732
3733 EXPECT_GL_NO_ERROR();
3734
3735 // Clear the framebuffer to green
3736 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3737 glClear(GL_COLOR_BUFFER_BIT);
3738
3739 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3740 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3741 // a noop, the deferred clears will remain unflushed.
3742 glEnable(GL_SCISSOR_TEST);
3743 glScissor(0, 0, 0, 0);
3744 glClear(GL_COLOR_BUFFER_BIT);
3745 glDisable(GL_SCISSOR_TEST);
3746
3747 // Change framebuffer's attachment to the other texture.
3748 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3749 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3750
3751 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3752 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3753 glUseProgram(program);
3754
3755 glEnable(GL_BLEND);
3756 glBlendFunc(GL_ZERO, GL_ONE);
3757 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3758 EXPECT_GL_NO_ERROR();
3759
3760 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3761 // to the new attachment, green will be read back.
3762 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3763
3764 // Attach back to texture2. It should be cleared to green.
3765 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3767 }
3768
3769 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3770 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3771 {
3772 // Create a texture with red
3773 const GLColor kInitColor1 = GLColor::red;
3774 GLTexture texture1;
3775 glBindTexture(GL_TEXTURE_2D, texture1);
3776 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3777
3778 // Create a framebuffer to be cleared
3779 GLTexture texture2;
3780 glBindTexture(GL_TEXTURE_2D, texture2);
3781 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3782
3783 GLFramebuffer drawFBO;
3784 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3785 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3786 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3787
3788 EXPECT_GL_NO_ERROR();
3789
3790 // Clear the framebuffer to green
3791 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3792 glClear(GL_COLOR_BUFFER_BIT);
3793
3794 // Issue noop blit. In the Vulkan backend, this will result in a framebuffer sync state, which
3795 // extracts deferred clears. However, as the blit is actually a noop, the deferred clears will
3796 // remain unflushed.
3797 GLTexture blitSrc;
3798 glBindTexture(GL_TEXTURE_2D, blitSrc);
3799 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3800
3801 GLFramebuffer readFBO;
3802 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3803 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3804 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3805
3806 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3807 EXPECT_GL_NO_ERROR();
3808
3809 // Change framebuffer's attachment to the other texture.
3810 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3811 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3812
3813 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3814 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3815 glUseProgram(program);
3816
3817 glEnable(GL_BLEND);
3818 glBlendFunc(GL_ZERO, GL_ONE);
3819 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3820 EXPECT_GL_NO_ERROR();
3821
3822 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3823 // to the new attachment, green will be read back.
3824 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3825 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3826
3827 // Attach back to texture2. It should be cleared to green.
3828 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3829 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3830 }
3831
3832 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3833 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3834 {
3835 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3836 glUseProgram(program);
3837
3838 glClear(GL_COLOR_BUFFER_BIT);
3839 glEnable(GL_CULL_FACE);
3840
3841 glCullFace(GL_FRONT);
3842
3843 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3844
3845 ASSERT_GL_NO_ERROR();
3846
3847 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3848
3849 // Disable cull face and redraw, then make sure we have the quad drawn.
3850 glDisable(GL_CULL_FACE);
3851
3852 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3853
3854 ASSERT_GL_NO_ERROR();
3855
3856 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3857 }
3858
TEST_P(SimpleStateChangeTest,ScissorTest)3859 TEST_P(SimpleStateChangeTest, ScissorTest)
3860 {
3861 // This test validates this order of state changes:
3862 // 1- Set scissor but don't enable it, validate its not used.
3863 // 2- Enable it and validate its working.
3864 // 3- Disable the scissor validate its not used anymore.
3865
3866 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3867
3868 glClear(GL_COLOR_BUFFER_BIT);
3869
3870 // Set the scissor region, but don't enable it yet.
3871 glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3872 getWindowHeight() / 2);
3873
3874 // Fill the whole screen with a quad.
3875 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3876
3877 ASSERT_GL_NO_ERROR();
3878
3879 // Test outside, scissor isnt enabled so its red.
3880 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3881
3882 // Test inside, red of the fragment shader.
3883 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3884
3885 // Clear everything and start over with the test enabled.
3886 glClear(GL_COLOR_BUFFER_BIT);
3887 glEnable(GL_SCISSOR_TEST);
3888
3889 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3890
3891 ASSERT_GL_NO_ERROR();
3892
3893 // Test outside the scissor test, pitch black.
3894 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3895
3896 // Test inside, red of the fragment shader.
3897 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3898
3899 // Now disable the scissor test, do it again, and verify the region isn't used
3900 // for the scissor test.
3901 glDisable(GL_SCISSOR_TEST);
3902
3903 // Clear everything and start over with the test enabled.
3904 glClear(GL_COLOR_BUFFER_BIT);
3905
3906 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3907
3908 ASSERT_GL_NO_ERROR();
3909
3910 // Test outside, scissor isnt enabled so its red.
3911 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3912
3913 // Test inside, red of the fragment shader.
3914 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3915 }
3916
3917 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3918 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3919 {
3920 constexpr char kPositionUniformVertexShader[] = R"(
3921 precision mediump float;
3922 attribute vec2 position;
3923 uniform vec2 uniPosModifier;
3924 void main()
3925 {
3926 gl_Position = vec4(position + uniPosModifier, 0, 1);
3927 })";
3928
3929 ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3930 glUseProgram(program);
3931
3932 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3933 glClear(GL_COLOR_BUFFER_BIT);
3934
3935 GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3936 ASSERT_NE(posUniformLocation, -1);
3937 GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3938 ASSERT_NE(colorUniformLocation, -1);
3939
3940 // draw a red quad to the left side.
3941 glUniform2f(posUniformLocation, -0.5, 0.0);
3942 glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3943 drawQuad(program, "position", 0.0f, 0.5f, true);
3944
3945 // draw a green quad to the right side.
3946 glUniform2f(posUniformLocation, 0.5, 0.0);
3947 glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3948 drawQuad(program, "position", 0.0f, 0.5f, true);
3949
3950 ASSERT_GL_NO_ERROR();
3951
3952 // Test the center of the left quad. Should be red.
3953 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3954
3955 // Test the center of the right quad. Should be green.
3956 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3957 }
3958
3959 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3960 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3961 {
3962 GLRenderbuffer renderbuffer;
3963 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3964 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3965
3966 GLFramebuffer framebuffer;
3967 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3968 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3969
3970 ASSERT_GL_NO_ERROR();
3971 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3972
3973 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3974 GLint colorLoc = glGetAttribLocation(program, "color");
3975 ASSERT_NE(-1, colorLoc);
3976
3977 // Set up and draw red to the left half the screen.
3978 std::vector<GLColor> redData(6, GLColor::red);
3979 GLBuffer vertexBufferRed;
3980 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3981 glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3982 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3983 glEnableVertexAttribArray(colorLoc);
3984
3985 glViewport(0, 0, 16, 16);
3986 drawQuad(program, "position", 0.5f, 1.0f, true);
3987
3988 // Immediately redefine the Renderbuffer.
3989 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3990
3991 // Set up and draw green to the right half of the screen.
3992 std::vector<GLColor> greenData(6, GLColor::green);
3993 GLBuffer vertexBufferGreen;
3994 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3995 glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3996 GL_STATIC_DRAW);
3997 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3998 glEnableVertexAttribArray(colorLoc);
3999
4000 glViewport(0, 0, 64, 64);
4001 drawQuad(program, "position", 0.5f, 1.0f, true);
4002
4003 ASSERT_GL_NO_ERROR();
4004 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4005 }
4006
4007 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
4008 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)4009 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
4010 {
4011 constexpr size_t kSmallTextureSize = 2;
4012 constexpr size_t kBigTextureSize = 4;
4013
4014 // Create 2 textures, one of 2x2 and the other 4x4
4015 GLTexture texture1;
4016 glBindTexture(GL_TEXTURE_2D, texture1);
4017 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
4018 GL_UNSIGNED_BYTE, nullptr);
4019 ASSERT_GL_NO_ERROR();
4020
4021 GLTexture texture2;
4022 glBindTexture(GL_TEXTURE_2D, texture2);
4023 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
4024 GL_UNSIGNED_BYTE, nullptr);
4025 ASSERT_GL_NO_ERROR();
4026
4027 // A framebuffer for each texture to draw on.
4028 GLFramebuffer framebuffer1;
4029 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4030 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
4031 ASSERT_GL_NO_ERROR();
4032 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4033
4034 GLFramebuffer framebuffer2;
4035 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4036 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
4037 ASSERT_GL_NO_ERROR();
4038 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4039
4040 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4041 glUseProgram(program);
4042 GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4043 ASSERT_NE(uniformLocation, -1);
4044
4045 // Bind to the first framebuffer for drawing.
4046 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4047
4048 // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
4049 // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
4050 glScissor(0, 0, 16, 16);
4051 ASSERT_GL_NO_ERROR();
4052
4053 // Set color to red.
4054 glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4055 glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
4056
4057 // Draw a full sized red quad
4058 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4059 ASSERT_GL_NO_ERROR();
4060
4061 // Bind to the second (bigger) framebuffer
4062 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4063 glViewport(0, 0, kBigTextureSize, kBigTextureSize);
4064
4065 ASSERT_GL_NO_ERROR();
4066
4067 // Set color to green.
4068 glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4069
4070 // Draw again and we should fill everything with green and expect everything to be green.
4071 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4072 ASSERT_GL_NO_ERROR();
4073
4074 EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
4075 }
4076
4077 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)4078 TEST_P(SimpleStateChangeTest, RelinkProgram)
4079 {
4080 // http://anglebug.com/40644706
4081 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
4082 const GLuint program = glCreateProgram();
4083
4084 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
4085 GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
4086 GLuint redFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
4087
4088 glAttachShader(program, vs);
4089 glAttachShader(program, blueFs);
4090
4091 glLinkProgram(program);
4092 CheckLinkStatusAndReturnProgram(program, true);
4093
4094 glClear(GL_COLOR_BUFFER_BIT);
4095 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
4096 {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
4097 GLBuffer vertexBuffer;
4098 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4099 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4100 GL_STATIC_DRAW);
4101 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4102 ASSERT_NE(-1, positionLocation);
4103 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4104 glEnableVertexAttribArray(positionLocation);
4105
4106 // Draw a blue triangle to the right
4107 glUseProgram(program);
4108 glDrawArrays(GL_TRIANGLES, 0, 3);
4109
4110 // Relink to draw red to the left
4111 glDetachShader(program, blueFs);
4112 glAttachShader(program, redFs);
4113
4114 glLinkProgram(program);
4115 CheckLinkStatusAndReturnProgram(program, true);
4116
4117 glDrawArrays(GL_TRIANGLES, 3, 3);
4118
4119 ASSERT_GL_NO_ERROR();
4120
4121 glDisableVertexAttribArray(positionLocation);
4122
4123 // Verify we drew red and green in the right places.
4124 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
4125 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
4126
4127 glDeleteShader(vs);
4128 glDeleteShader(blueFs);
4129 glDeleteShader(redFs);
4130 glDeleteProgram(program);
4131 }
4132
4133 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
4134 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)4135 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
4136 {
4137 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4138 glUseProgram(program);
4139
4140 const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4141 EXPECT_NE(-1, uniformLoc);
4142
4143 // Set color to red.
4144 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4145
4146 glClear(GL_COLOR_BUFFER_BIT);
4147 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
4148 GLBuffer vertexBuffer;
4149 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4150 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4151 GL_STATIC_DRAW);
4152 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4153 ASSERT_NE(-1, positionLocation);
4154 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4155 glEnableVertexAttribArray(positionLocation);
4156
4157 // Release program while its in use.
4158 glDeleteProgram(program);
4159
4160 // Draw a red triangle
4161 glDrawArrays(GL_TRIANGLES, 0, 3);
4162
4163 // Set color to green
4164 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4165
4166 // Draw a green triangle
4167 glDrawArrays(GL_TRIANGLES, 0, 3);
4168
4169 ASSERT_GL_NO_ERROR();
4170
4171 glDisableVertexAttribArray(positionLocation);
4172
4173 glUseProgram(0);
4174
4175 // Verify we drew red in the end since thats the last draw.
4176 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
4177 }
4178
4179 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)4180 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
4181 {
4182 // Create a sampler with NEAREST filtering.
4183 GLSampler sampler;
4184 glBindSampler(0, sampler);
4185 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4186 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4187 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4188 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4189 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4190 ASSERT_GL_NO_ERROR();
4191
4192 // Draw with a program that uses no textures.
4193 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4194 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
4195 ASSERT_GL_NO_ERROR();
4196 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4197
4198 // Create a simple texture with four colors and linear filtering.
4199 constexpr GLsizei kSize = 2;
4200 std::array<GLColor, 4> pixels = {
4201 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4202 GLTexture redTex;
4203 glBindTexture(GL_TEXTURE_2D, redTex);
4204 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4205 pixels.data());
4206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4211
4212 // Create a program that uses the texture.
4213 constexpr char kVS[] = R"(attribute vec4 position;
4214 varying vec2 texCoord;
4215 void main()
4216 {
4217 gl_Position = position;
4218 texCoord = position.xy * 0.5 + vec2(0.5);
4219 })";
4220
4221 constexpr char kFS[] = R"(precision mediump float;
4222 varying vec2 texCoord;
4223 uniform sampler2D tex;
4224 void main()
4225 {
4226 gl_FragColor = texture2D(tex, texCoord);
4227 })";
4228
4229 // Draw. The sampler should override the clamp wrap mode with nearest.
4230 ANGLE_GL_PROGRAM(program2, kVS, kFS);
4231 ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
4232 drawQuad(program2, "position", 0.5f);
4233 ASSERT_GL_NO_ERROR();
4234
4235 constexpr int kHalfSize = kWindowSize / 2;
4236
4237 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4238 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4239 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4240 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4241 }
4242
4243 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)4244 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
4245 {
4246 // Test overview - Create two separate sampler objects, initially with the same
4247 // sampling args (NEAREST). Bind the same texture object to separate texture units.
4248 // FS samples from two samplers and blends result.
4249 // Bind separate sampler objects to the same texture units as the texture object.
4250 // Render & verify initial results
4251 // Next modify sampler0 to have LINEAR filtering instead of NEAREST
4252 // Render and save results
4253 // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
4254 // Render and verify results are the same as previous
4255
4256 // Create 2 samplers with NEAREST filtering.
4257 constexpr GLsizei kNumSamplers = 2;
4258 // We create/bind an extra sampler w/o bound tex object for testing purposes
4259 GLSampler samplers[kNumSamplers + 1];
4260 // Set samplers to initially have same state w/ NEAREST filter mode
4261 for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
4262 {
4263 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4264 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4265 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4266 glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4267 glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4268 glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
4269 glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
4270 glBindSampler(i, samplers[i]);
4271 ASSERT_GL_NO_ERROR();
4272 }
4273
4274 // Create a simple texture with four colors
4275 constexpr GLsizei kSize = 2;
4276 std::array<GLColor, 4> pixels = {
4277 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4278 GLTexture rgbyTex;
4279 // Bind same texture object to tex units 0 & 1
4280 glActiveTexture(GL_TEXTURE0);
4281 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4282 glActiveTexture(GL_TEXTURE1);
4283 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4284 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4285 pixels.data());
4286
4287 // Create a program that uses the texture with 2 separate samplers.
4288 constexpr char kFS[] = R"(precision mediump float;
4289 varying vec2 v_texCoord;
4290 uniform sampler2D samp1;
4291 uniform sampler2D samp2;
4292 void main()
4293 {
4294 gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
4295 })";
4296
4297 // Create program and bind samplers to tex units 0 & 1
4298 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
4299 GLint s1loc = glGetUniformLocation(program, "samp1");
4300 GLint s2loc = glGetUniformLocation(program, "samp2");
4301 glUseProgram(program);
4302 glUniform1i(s1loc, 0);
4303 glUniform1i(s2loc, 1);
4304 // Draw. This first draw is a confidence check and not really necessary for the test
4305 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4306 ASSERT_GL_NO_ERROR();
4307
4308 constexpr int kHalfSize = kWindowSize / 2;
4309
4310 // When rendering w/ NEAREST, colors are all maxed out so should still be solid
4311 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4312 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4313 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4314 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4315
4316 // Make first sampler use linear filtering
4317 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4318 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4319
4320 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4321 ASSERT_GL_NO_ERROR();
4322 // Capture rendered pixel color with s0 linear
4323 std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
4324 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
4325
4326 // Now restore first sampler & update second sampler
4327 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4328 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4329 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4330 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4331
4332 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4333 ASSERT_GL_NO_ERROR();
4334 // Capture rendered pixel color w/ s1 linear
4335 std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
4336 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
4337
4338 // Results should be the same regardless of if s0 or s1 is linear
4339 ASSERT(s0LinearColors.size() == s1LinearColors.size());
4340 for (size_t index = 0; index < s0LinearColors.size(); index++)
4341 {
4342 EXPECT_COLOR_NEAR(s0LinearColors[index], s1LinearColors[index], 1u);
4343 }
4344 }
4345
4346 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)4347 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
4348 {
4349 constexpr char kVertexShader[] = R"(attribute vec4 a_position;
4350 attribute vec4 a_color;
4351 varying vec4 v_color;
4352 void main()
4353 {
4354 gl_Position = a_position;
4355 v_color = a_color;
4356 })";
4357
4358 constexpr char kFragmentShader[] = R"(precision mediump float;
4359 varying vec4 v_color;
4360 void main()
4361 {
4362 gl_FragColor = v_color;
4363 })";
4364
4365 ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
4366 GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
4367 ASSERT_NE(-1, positionLoc);
4368 GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
4369 ASSERT_NE(-1, colorLoc);
4370
4371 GLVertexArray VAOS[2];
4372 GLBuffer positionBuffer;
4373 GLBuffer colorBuffer;
4374 const auto quadVertices = GetQuadVertices();
4375
4376 glBindVertexArray(VAOS[0]);
4377 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4378 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4379 GL_STATIC_DRAW);
4380 glEnableVertexAttribArray(positionLoc);
4381 glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4382
4383 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4384 std::vector<GLColor32F> blueColor(6, kFloatBlue);
4385 glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4386 GL_STATIC_DRAW);
4387 glEnableVertexAttribArray(colorLoc);
4388 glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4389
4390 glBindVertexArray(0);
4391 glBindBuffer(GL_ARRAY_BUFFER, 0);
4392
4393 glBindVertexArray(VAOS[1]);
4394 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4395 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4396 GL_STATIC_DRAW);
4397 glEnableVertexAttribArray(positionLoc);
4398 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4399
4400 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4401 std::vector<GLColor32F> greenColor(6, kFloatGreen);
4402 glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4403 GL_STATIC_DRAW);
4404 glEnableVertexAttribArray(colorLoc);
4405 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4406
4407 glBindVertexArray(0);
4408 glBindBuffer(GL_ARRAY_BUFFER, 0);
4409
4410 glUseProgram(mProgram);
4411 ASSERT_GL_NO_ERROR();
4412
4413 glBindVertexArray(VAOS[1]);
4414 glClear(GL_COLOR_BUFFER_BIT);
4415 glDrawArrays(GL_TRIANGLES, 0, 6);
4416
4417 // This drawing should not affect the next drawing.
4418 glBindVertexArray(VAOS[0]);
4419 glClear(GL_COLOR_BUFFER_BIT);
4420 glDrawArrays(GL_TRIANGLES, 0, 6);
4421
4422 glBindVertexArray(VAOS[1]);
4423 glClear(GL_COLOR_BUFFER_BIT);
4424 glDrawArrays(GL_TRIANGLES, 0, 6);
4425
4426 EXPECT_GL_NO_ERROR();
4427 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4428 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4429 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4430 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4431
4432 ASSERT_GL_NO_ERROR();
4433 }
4434
4435 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4436 // correctly. This requires a memory barrier in between the draw calls which should not be
4437 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4438 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4439 {
4440 // http://anglebug.com/42264124
4441 ANGLE_SKIP_TEST_IF(IsD3D11());
4442
4443 GLint maxFragmentImageUniforms;
4444 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4445
4446 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4447
4448 // The test uses a GL_R32F framebuffer.
4449 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4450
4451 constexpr GLsizei kSize = 1;
4452
4453 GLTexture color;
4454 glBindTexture(GL_TEXTURE_2D, color);
4455 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4456 EXPECT_GL_NO_ERROR();
4457
4458 GLFramebuffer fbo;
4459 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4460 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4461 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4462 EXPECT_GL_NO_ERROR();
4463
4464 const float kInitialValue = 0.125f;
4465
4466 GLTexture texture;
4467 glBindTexture(GL_TEXTURE_2D, texture);
4468 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4469 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4470 EXPECT_GL_NO_ERROR();
4471
4472 GLFramebuffer readbackFbo;
4473 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4474 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4475 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4476 EXPECT_GL_NO_ERROR();
4477
4478 // Create a program that outputs to the image in the fragment shader.
4479 constexpr char kFS[] = R"(#version 310 es
4480 precision mediump float;
4481 layout(r32f, binding = 0) uniform highp image2D dst;
4482 out vec4 colorOut;
4483 void main()
4484 {
4485 vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4486 colorOut = result;
4487
4488 result.x += 0.193;
4489 imageStore(dst, ivec2(gl_FragCoord.xy), result);
4490 })";
4491
4492 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4493 glUseProgram(program);
4494
4495 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4496 ASSERT_NE(-1, positionLoc);
4497
4498 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4499 EXPECT_GL_NO_ERROR();
4500
4501 // Setup the draw so that there's no state change between the draw calls.
4502 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4503 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4504
4505 GLBuffer posBuffer;
4506 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4507 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4508 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4509 glEnableVertexAttribArray(positionLoc);
4510 EXPECT_GL_NO_ERROR();
4511
4512 glDrawArrays(GL_TRIANGLES, 0, 6);
4513 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4514 glDrawArrays(GL_TRIANGLES, 0, 6);
4515 EXPECT_GL_NO_ERROR();
4516
4517 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4518 EXPECT_GL_NO_ERROR();
4519
4520 // Verify the output of the two draw calls through the image is correct
4521 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4522 0.001f);
4523
4524 // Verify the output of rendering as well
4525 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4526 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4527 }
4528
4529 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4530 // draw call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4531 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4532 {
4533 // http://anglebug.com/42264124
4534 ANGLE_SKIP_TEST_IF(IsD3D11());
4535 // http://anglebug.com/42264222
4536 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4537
4538 GLint maxFragmentImageUniforms;
4539 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4540
4541 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4542
4543 constexpr GLsizei kSize = 1;
4544
4545 GLTexture color;
4546 glBindTexture(GL_TEXTURE_2D, color);
4547 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4548 EXPECT_GL_NO_ERROR();
4549
4550 GLFramebuffer fbo;
4551 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4552 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4553 EXPECT_GL_NO_ERROR();
4554
4555 const GLColor kInitialColor = GLColor::red;
4556
4557 GLTexture texture;
4558 glBindTexture(GL_TEXTURE_2D, texture);
4559 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4560 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4561 &kInitialColor);
4562 EXPECT_GL_NO_ERROR();
4563
4564 GLFramebuffer readbackFbo;
4565 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4566 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4567 EXPECT_GL_NO_ERROR();
4568
4569 // Create a program that samples from the texture in the fragment shader.
4570 constexpr char kFSSample[] = R"(#version 310 es
4571 precision mediump float;
4572 uniform sampler2D tex;
4573 out vec4 colorOut;
4574 void main()
4575 {
4576 colorOut = texture(tex, vec2(0));
4577 })";
4578 ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4579
4580 // Create a program that outputs to the image in the fragment shader.
4581 constexpr char kFSWrite[] = R"(#version 310 es
4582 precision mediump float;
4583 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4584 out vec4 colorOut;
4585 void main()
4586 {
4587 colorOut = vec4(0, 0, 1.0, 0);
4588 imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4589 })";
4590
4591 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4592
4593 glUseProgram(sampleProgram);
4594 GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4595 ASSERT_NE(-1, positionLocSample);
4596
4597 glUseProgram(writeProgram);
4598 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4599 ASSERT_NE(-1, positionLocWrite);
4600
4601 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4602
4603 // Setup the draw so that there's no state change between the draw calls.
4604 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4605 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4606
4607 GLBuffer posBuffer;
4608 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4609 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4610 glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4611 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4612 glEnableVertexAttribArray(positionLocSample);
4613 glEnableVertexAttribArray(positionLocWrite);
4614
4615 glUseProgram(sampleProgram);
4616 glDrawArrays(GL_TRIANGLES, 0, 6);
4617
4618 glEnable(GL_BLEND);
4619 glBlendFunc(GL_ONE, GL_ONE);
4620 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4621
4622 glUseProgram(writeProgram);
4623 glDrawArrays(GL_TRIANGLES, 0, 6);
4624
4625 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4626 EXPECT_GL_NO_ERROR();
4627
4628 // Verify the output of the two draw calls through the image is correct
4629 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4630
4631 // Verify the output of rendering as well
4632 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4633 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4634 }
4635
4636 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4637 // call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4638 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4639 {
4640 GLint maxFragmentShaderStorageBlocks;
4641 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4642
4643 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4644
4645 constexpr GLsizei kSize = 1;
4646
4647 GLTexture color;
4648 glBindTexture(GL_TEXTURE_2D, color);
4649 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4650 EXPECT_GL_NO_ERROR();
4651
4652 GLFramebuffer fbo;
4653 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4654 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4655 EXPECT_GL_NO_ERROR();
4656
4657 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4658 GLBuffer buffer;
4659 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4660 glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4661 GL_STATIC_DRAW);
4662 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4663
4664 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4665 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4666
4667 // Create a program that reads from the ubo in the fragment shader.
4668 constexpr char kFSRead[] = R"(#version 310 es
4669 precision mediump float;
4670 uniform block { vec4 vec; } b;
4671 out vec4 colorOut;
4672 void main()
4673 {
4674 colorOut = b.vec;
4675 })";
4676 ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4677
4678 // Create a program that outputs to the image in the fragment shader.
4679 constexpr char kFSWrite[] = R"(#version 310 es
4680 precision mediump float;
4681 layout(binding = 0, std430) buffer Output {
4682 vec4 vec;
4683 } b;
4684 out vec4 colorOut;
4685 void main()
4686 {
4687 b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4688 colorOut = vec4(0.125, 0.125, 0.125, 0);
4689 })";
4690
4691 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4692
4693 glUseProgram(readProgram);
4694 GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4695 ASSERT_NE(-1, positionLocRead);
4696
4697 glUseProgram(writeProgram);
4698 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4699 ASSERT_NE(-1, positionLocWrite);
4700
4701 // Setup the draw so that there's no state change between the draw calls.
4702 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4703 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4704
4705 GLBuffer posBuffer;
4706 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4707 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4708 glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4709 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4710 glEnableVertexAttribArray(positionLocRead);
4711 glEnableVertexAttribArray(positionLocWrite);
4712
4713 glUseProgram(readProgram);
4714 glDrawArrays(GL_TRIANGLES, 0, 6);
4715
4716 glEnable(GL_BLEND);
4717 glBlendFunc(GL_ONE, GL_ONE);
4718 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4719
4720 glUseProgram(writeProgram);
4721 glDrawArrays(GL_TRIANGLES, 0, 6);
4722
4723 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4724 EXPECT_GL_NO_ERROR();
4725
4726 // Verify the output of rendering
4727 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4728
4729 // Verify the output from the second draw call
4730 const float *ptr = reinterpret_cast<const float *>(
4731 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4732
4733 EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4734 EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4735 EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4736 EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4737
4738 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4739 }
4740
4741 // Tests that writing to an SSBO in the fragment shader before and after a change to the drawbuffers
4742 // still works
TEST_P(SimpleStateChangeTestES31,FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4743 TEST_P(SimpleStateChangeTestES31, FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4744 {
4745 GLint maxFragmentShaderStorageBlocks;
4746 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4747
4748 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4749
4750 constexpr GLsizei kSize = 1;
4751
4752 GLTexture color;
4753 glBindTexture(GL_TEXTURE_2D, color);
4754 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4755 EXPECT_GL_NO_ERROR();
4756
4757 GLFramebuffer fbo;
4758 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4759 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4760 EXPECT_GL_NO_ERROR();
4761
4762 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4763 GLBuffer buffer;
4764 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4765 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4766 GL_STATIC_DRAW);
4767 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4768
4769 // Create a program that writes to the SSBO in the fragment shader.
4770 constexpr char kFS[] = R"(#version 310 es
4771 precision mediump float;
4772 layout(binding = 0, std430) buffer Output {
4773 vec4 value;
4774 } b;
4775 out vec4 colorOut;
4776 uniform vec4 value;
4777 void main()
4778 {
4779 b.value = value;
4780 colorOut = vec4(1, 1, 1, 0);
4781 })";
4782
4783 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
4784 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
4785
4786 const GLuint program = glCreateProgram();
4787 glAttachShader(program, vs);
4788 glAttachShader(program, fs);
4789 glLinkProgram(program);
4790 CheckLinkStatusAndReturnProgram(program, true);
4791
4792 // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4793 glDetachShader(program, vs);
4794 glDetachShader(program, fs);
4795
4796 glUseProgram(program);
4797 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4798 ASSERT_NE(-1, positionLoc);
4799 GLint valueLoc = glGetUniformLocation(program, "value");
4800 ASSERT_NE(-1, valueLoc);
4801
4802 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4803 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4804
4805 GLBuffer posBuffer;
4806 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4807 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4808 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4809 glEnableVertexAttribArray(positionLoc);
4810
4811 glUseProgram(program);
4812 constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4813
4814 glUniform4fv(valueLoc, 1, kValue1);
4815 glDrawArrays(GL_TRIANGLES, 0, 6);
4816 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4817 EXPECT_GL_NO_ERROR();
4818
4819 // Verify that the program wrote the SSBO correctly.
4820 const float *ptr = reinterpret_cast<const float *>(
4821 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4822
4823 for (int i = 0; i < 4; ++i)
4824 {
4825 EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4826 }
4827
4828 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4829
4830 GLenum drawBuffers[] = {GL_NONE};
4831 glDrawBuffers(1, drawBuffers);
4832
4833 constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4834 glUniform4fv(valueLoc, 1, kValue2);
4835 glDrawArrays(GL_TRIANGLES, 0, 6);
4836 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4837 EXPECT_GL_NO_ERROR();
4838 // Verify that the program wrote the SSBO correctly.
4839 ptr = reinterpret_cast<const float *>(
4840 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4841
4842 for (int i = 0; i < 4; ++i)
4843 {
4844 EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4845 }
4846
4847 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4848 }
4849
4850 // Tests that writing to an SSBO in the vertex shader before and after a change to the drawbuffers
4851 // still works
TEST_P(SimpleStateChangeTestES31,VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4852 TEST_P(SimpleStateChangeTestES31, VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4853 {
4854 GLint maxVertexShaderStorageBlocks;
4855 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
4856
4857 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks < 1);
4858
4859 constexpr GLsizei kSize = 1;
4860
4861 GLTexture color;
4862 glBindTexture(GL_TEXTURE_2D, color);
4863 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4864 EXPECT_GL_NO_ERROR();
4865
4866 GLFramebuffer fbo;
4867 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4868 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4869 EXPECT_GL_NO_ERROR();
4870
4871 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4872 GLBuffer buffer;
4873 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4874 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4875 GL_STATIC_DRAW);
4876 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4877
4878 // Create a program that writes to the SSBO in the vertex shader.
4879 constexpr char kVS[] = R"(#version 310 es
4880 in vec4 a_position;
4881 uniform vec4 value;
4882 layout(binding = 0, std430) buffer Output {
4883 vec4 value;
4884 } b;
4885 void main()
4886 {
4887 b.value = value;
4888 gl_Position = a_position;
4889 })";
4890
4891 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
4892 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, essl31_shaders::fs::Green());
4893
4894 const GLuint program = glCreateProgram();
4895 glAttachShader(program, vs);
4896 glAttachShader(program, fs);
4897 glLinkProgram(program);
4898 CheckLinkStatusAndReturnProgram(program, true);
4899
4900 // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4901 glDetachShader(program, vs);
4902 glDetachShader(program, fs);
4903
4904 glUseProgram(program);
4905 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4906 ASSERT_NE(-1, positionLoc);
4907 GLint valueLoc = glGetUniformLocation(program, "value");
4908 ASSERT_NE(-1, valueLoc);
4909
4910 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4911 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4912
4913 GLBuffer posBuffer;
4914 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4915 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4916 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4917 glEnableVertexAttribArray(positionLoc);
4918
4919 glUseProgram(program);
4920 constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4921
4922 glUniform4fv(valueLoc, 1, kValue1);
4923 glDrawArrays(GL_TRIANGLES, 0, 6);
4924 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4925 EXPECT_GL_NO_ERROR();
4926
4927 // Verify that the program wrote the SSBO correctly.
4928 const float *ptr = reinterpret_cast<const float *>(
4929 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4930
4931 for (int i = 0; i < 4; ++i)
4932 {
4933 EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4934 }
4935
4936 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4937
4938 GLenum drawBuffers[] = {GL_NONE};
4939 glDrawBuffers(1, drawBuffers);
4940
4941 constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4942 glUniform4fv(valueLoc, 1, kValue2);
4943 glDrawArrays(GL_TRIANGLES, 0, 6);
4944 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4945 EXPECT_GL_NO_ERROR();
4946 // Verify that the program wrote the SSBO correctly.
4947 ptr = reinterpret_cast<const float *>(
4948 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4949
4950 for (int i = 0; i < 4; ++i)
4951 {
4952 EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4953 }
4954
4955 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4956 }
4957
4958 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4959 // call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4960 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4961 {
4962 // TODO(anglebug.com/42264185): Test is failing since it was introduced on Linux AMD GLES
4963 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4964
4965 constexpr GLsizei kSize = 1;
4966 const GLColor kInitColor(111, 222, 33, 44);
4967
4968 GLTexture color;
4969 glBindTexture(GL_TEXTURE_2D, color);
4970 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4971 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4973 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4974 EXPECT_GL_NO_ERROR();
4975
4976 GLFramebuffer fbo;
4977 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4978 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4979 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4980 EXPECT_GL_NO_ERROR();
4981
4982 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4983 GLBuffer buffer;
4984 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4985 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4986 GL_STATIC_DRAW);
4987 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4988 EXPECT_GL_NO_ERROR();
4989
4990 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4991
4992 constexpr char kCS[] = R"(#version 310 es
4993 layout(local_size_x=1, local_size_y=1) in;
4994 uniform sampler2D tex;
4995 layout(binding = 0, std430) buffer Output {
4996 vec4 vec;
4997 } b;
4998 void main()
4999 {
5000 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
5001 })";
5002
5003 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5004 glUseProgram(readProgram);
5005
5006 glActiveTexture(GL_TEXTURE0);
5007 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
5008
5009 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
5010 EXPECT_GL_NO_ERROR();
5011
5012 glUseProgram(readProgram);
5013 glDispatchCompute(1, 1, 1);
5014
5015 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5016 EXPECT_GL_NO_ERROR();
5017
5018 // Verify the output of rendering
5019 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5020
5021 // Verify the output from the compute shader
5022 const float *ptr = reinterpret_cast<const float *>(
5023 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
5024
5025 EXPECT_EQ(ptr[0], 1.0f);
5026 EXPECT_EQ(ptr[1], 0.0f);
5027 EXPECT_EQ(ptr[2], 0.0f);
5028 EXPECT_EQ(ptr[3], 1.0f);
5029
5030 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5031 }
5032
5033 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
5034 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)5035 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
5036 {
5037 // http://anglebug.com/42264223
5038 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
5039
5040 constexpr GLsizei kSize = 1;
5041
5042 GLTexture color;
5043 glBindTexture(GL_TEXTURE_2D, color);
5044 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5046 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5047 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
5048 EXPECT_GL_NO_ERROR();
5049
5050 GLFramebuffer fbo;
5051 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5052 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5053 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5054 EXPECT_GL_NO_ERROR();
5055
5056 // Make sure the update to the texture is effective.
5057 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5058
5059 // Clear the texture through the framebuffer
5060 glClearColor(0, 1.0f, 0, 1.0f);
5061 glClear(GL_COLOR_BUFFER_BIT);
5062
5063 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
5064 GLBuffer buffer;
5065 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
5066 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
5067 GL_STATIC_DRAW);
5068 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
5069 EXPECT_GL_NO_ERROR();
5070
5071 constexpr char kCS[] = R"(#version 310 es
5072 layout(local_size_x=1, local_size_y=1) in;
5073 uniform sampler2D tex;
5074 layout(binding = 0, std430) buffer Output {
5075 vec4 vec;
5076 } b;
5077 void main()
5078 {
5079 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
5080 })";
5081
5082 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5083 glUseProgram(readProgram);
5084
5085 glActiveTexture(GL_TEXTURE0);
5086 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
5087
5088 glUseProgram(readProgram);
5089 glDispatchCompute(1, 1, 1);
5090
5091 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5092 EXPECT_GL_NO_ERROR();
5093
5094 // Verify the clear
5095 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5096
5097 // Verify the output from the compute shader
5098 const float *ptr = reinterpret_cast<const float *>(
5099 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
5100
5101 EXPECT_EQ(ptr[0], 0.0f);
5102 EXPECT_EQ(ptr[1], 1.0f);
5103 EXPECT_EQ(ptr[2], 0.0f);
5104 EXPECT_EQ(ptr[3], 1.0f);
5105
5106 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5107 }
5108
5109 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
5110 // it in a dispatch call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)5111 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
5112 {
5113 // http://anglebug.com/42264223
5114 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
5115
5116 constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
5117 GLBuffer buffer;
5118 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
5119 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
5120 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
5121
5122 std::vector<std::string> tfVaryings = {"gl_Position"};
5123 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5124 essl3_shaders::fs::Green(), tfVaryings,
5125 GL_INTERLEAVED_ATTRIBS);
5126 glUseProgram(program);
5127
5128 glBeginTransformFeedback(GL_TRIANGLES);
5129 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
5130 glEndTransformFeedback();
5131
5132 constexpr char kCS[] = R"(#version 310 es
5133 layout(local_size_x=1, local_size_y=1) in;
5134 layout(binding = 0) uniform Input
5135 {
5136 vec4 data[3];
5137 };
5138 layout(binding = 0, std430) buffer Output {
5139 bool pass;
5140 };
5141 void main()
5142 {
5143 pass = data[0] == vec4(-1, 1, 0, 1) &&
5144 data[1] == vec4(-1, -1, 0, 1) &&
5145 data[2] == vec4(1, -1, 0, 1);
5146 })";
5147
5148 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5149 glUseProgram(readProgram);
5150
5151 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
5152
5153 constexpr GLsizei kResultSize = sizeof(uint32_t);
5154 GLBuffer resultBuffer;
5155 glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5156 glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
5157 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
5158
5159 glDispatchCompute(1, 1, 1);
5160
5161 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5162 EXPECT_GL_NO_ERROR();
5163
5164 // Verify the output of rendering
5165 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5166
5167 // Verify the output from the compute shader
5168 const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
5169 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
5170
5171 EXPECT_EQ(ptr[0], 1u);
5172
5173 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5174 }
5175
5176 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)5177 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
5178 {
5179 std::array<GLColor, 4> colors = {
5180 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5181 GLTexture texRead;
5182 glBindTexture(GL_TEXTURE_2D, texRead);
5183 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5184 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5185 EXPECT_GL_NO_ERROR();
5186
5187 glUseProgram(mProgram);
5188
5189 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5190 glDispatchCompute(1, 1, 1);
5191 texRead.reset();
5192
5193 std::array<GLColor, 4> results;
5194 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5195 EXPECT_GL_NO_ERROR();
5196
5197 for (int i = 0; i < 4; i++)
5198 {
5199 EXPECT_EQ(colors[i], results[i]);
5200 }
5201 }
5202
5203 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)5204 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
5205 {
5206 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5207 GLTexture texRead;
5208 glBindTexture(GL_TEXTURE_2D, texRead);
5209 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5210 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5211
5212 glUseProgram(mProgram);
5213
5214 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5215 glDispatchCompute(1, 1, 1);
5216
5217 // Bind again
5218 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5219 glDispatchCompute(1, 1, 1);
5220 EXPECT_GL_NO_ERROR();
5221
5222 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5223 }
5224
5225 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
5226 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)5227 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
5228 {
5229 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
5230 std::array<GLColor, 4> subColors = {
5231 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
5232
5233 GLTexture texRead;
5234 glBindTexture(GL_TEXTURE_2D, texRead);
5235 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5236 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5237
5238 glUseProgram(mProgram);
5239
5240 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5241 glDispatchCompute(1, 1, 1);
5242
5243 // Update bottom-half of image texture with green.
5244 glBindTexture(GL_TEXTURE_2D, texRead);
5245 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
5246 ASSERT_GL_NO_ERROR();
5247
5248 // Dispatch again, should still work.
5249 glDispatchCompute(1, 1, 1);
5250 ASSERT_GL_NO_ERROR();
5251
5252 // Validate first half of the image is red and the bottom is green.
5253 std::array<GLColor, 4> results;
5254 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5255 EXPECT_GL_NO_ERROR();
5256
5257 EXPECT_EQ(GLColor::green, results[0]);
5258 EXPECT_EQ(GLColor::green, results[1]);
5259 EXPECT_EQ(GLColor::red, results[2]);
5260 EXPECT_EQ(GLColor::red, results[3]);
5261 }
5262
5263 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)5264 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
5265 {
5266 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5267
5268 GLTexture texRead;
5269 glBindTexture(GL_TEXTURE_2D, texRead);
5270 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5271 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
5272
5273 glUseProgram(mProgram);
5274
5275 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5276 glDispatchCompute(1, 1, 1);
5277
5278 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
5279 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
5280 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
5281 ASSERT_GL_NO_ERROR();
5282
5283 // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
5284 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5285 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
5286 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
5287 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
5288
5289 // Dispatch again. The second dispatch call should use the updated YBGR data.
5290 glDispatchCompute(1, 1, 1);
5291
5292 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5293 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
5294 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
5295 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
5296 ASSERT_GL_NO_ERROR();
5297 }
5298
5299 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)5300 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
5301 {
5302 std::array<GLColor, 4> colorsTexA = {
5303 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5304
5305 std::array<GLColor, 4> colorsTexB = {
5306 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
5307
5308 GLTexture texA;
5309 glBindTexture(GL_TEXTURE_2D, texA);
5310 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5311 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
5312 GLTexture texB;
5313 glBindTexture(GL_TEXTURE_2D, texB);
5314 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5315 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
5316
5317 glUseProgram(mProgram);
5318
5319 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5320 glDispatchCompute(1, 1, 1);
5321
5322 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5323 glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5324 glDispatchCompute(1, 1, 1);
5325
5326 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5327 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5328 glDispatchCompute(1, 1, 1);
5329
5330 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5331 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5332 ASSERT_GL_NO_ERROR();
5333 }
5334
5335 // Tests that glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) after draw works, where the render
5336 // pass is marked as closed.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenStorageWrite)5337 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenStorageWrite)
5338 {
5339 // Create a framebuffer for the purpose of switching FBOs
5340 GLTexture clearColor;
5341 glBindTexture(GL_TEXTURE_2D, clearColor);
5342 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5343
5344 GLFramebuffer clearFBO;
5345 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, clearFBO);
5346 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, clearColor, 0);
5347 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5348 EXPECT_GL_NO_ERROR();
5349
5350 constexpr char kCS[] = R"(#version 310 es
5351 layout(local_size_x=1, local_size_y=1) in;
5352 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5353 void main()
5354 {
5355 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
5356 })";
5357
5358 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
5359 glUseProgram(program);
5360 EXPECT_GL_NO_ERROR();
5361
5362 // Create the framebuffer texture
5363 GLTexture renderTarget;
5364 glBindTexture(GL_TEXTURE_2D, renderTarget);
5365 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5366 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5367
5368 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
5369 // is already created with STORAGE usage and avoids recreate later.
5370 glDispatchCompute(1, 1, 1);
5371 EXPECT_GL_NO_ERROR();
5372
5373 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5374
5375 // Create the framebuffer for this texture
5376 GLFramebuffer drawFBO;
5377 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
5378 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
5379 0);
5380 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5381 EXPECT_GL_NO_ERROR();
5382
5383 // Draw to this framebuffer to start a render pass
5384 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
5385 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
5386
5387 // Change framebuffers and do a clear, making sure the old render pass is marked as closed. In
5388 // the Vulkan backend, the clear is stashed, so the render pass is kept in the hopes of reviving
5389 // it later.
5390
5391 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
5392 glClear(GL_COLOR_BUFFER_BIT);
5393
5394 // Issue a memory barrier before writing to the original image again.
5395 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5396
5397 // Write to it with a compute shader
5398 glDispatchCompute(1, 1, 1);
5399 EXPECT_GL_NO_ERROR();
5400
5401 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5402
5403 // Bind the original framebuffer and verify that the compute shader wrote the correct value.
5404 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
5405 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5406 }
5407
5408 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
5409 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)5410 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
5411 {
5412 ANGLE_SKIP_TEST_IF(!IsVulkan());
5413
5414 glGenFramebuffers(1, &mFramebuffer);
5415 glGenTextures(1, &mTexture);
5416
5417 glBindTexture(GL_TEXTURE_2D, mTexture);
5418 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5419 EXPECT_GL_NO_ERROR();
5420
5421 constexpr char kCS[] = R"(#version 310 es
5422 layout(local_size_x=2, local_size_y=2) in;
5423 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
5424 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5425 void main()
5426 {
5427 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
5428 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
5429 })";
5430
5431 bindProgramPipeline(kCS);
5432
5433 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5434
5435 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
5436 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
5437
5438 ASSERT_GL_NO_ERROR();
5439
5440 std::array<GLColor, 4> colors = {
5441 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5442 GLTexture texRead;
5443 glBindTexture(GL_TEXTURE_2D, texRead);
5444 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5445 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5446 EXPECT_GL_NO_ERROR();
5447
5448 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5449 glDispatchCompute(1, 1, 1);
5450 texRead.reset();
5451
5452 std::array<GLColor, 4> results;
5453 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5454 EXPECT_GL_NO_ERROR();
5455
5456 for (int i = 0; i < 4; i++)
5457 {
5458 EXPECT_EQ(colors[i], results[i]);
5459 }
5460 }
5461
5462 static constexpr char kColorVS[] = R"(attribute vec2 position;
5463 attribute vec4 color;
5464 varying vec4 vColor;
5465 void main()
5466 {
5467 gl_Position = vec4(position, 0, 1);
5468 vColor = color;
5469 })";
5470
5471 static constexpr char kColorFS[] = R"(precision mediump float;
5472 varying vec4 vColor;
5473 void main()
5474 {
5475 gl_FragColor = vColor;
5476 })";
5477
5478 class ValidationStateChangeTest : public ANGLETest<>
5479 {
5480 protected:
ValidationStateChangeTest()5481 ValidationStateChangeTest()
5482 {
5483 setWindowWidth(64);
5484 setWindowHeight(64);
5485 setConfigRedBits(8);
5486 setConfigGreenBits(8);
5487 setConfigBlueBits(8);
5488 setConfigAlphaBits(8);
5489 }
5490 };
5491
5492 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
5493 {
5494 protected:
WebGL2ValidationStateChangeTest()5495 WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5496 };
5497
5498 class ValidationStateChangeTestES31 : public ANGLETest<>
5499 {};
5500
5501 class WebGLComputeValidationStateChangeTest : public ANGLETest<>
5502 {
5503 public:
WebGLComputeValidationStateChangeTest()5504 WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5505 };
5506
5507 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
5508 {
5509 protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()5510 RobustBufferAccessWebGL2ValidationStateChangeTest()
5511 {
5512 // SwS/OSX GL do not support robustness. Mali does not support it.
5513 if (!isSwiftshader() && !IsMac() && !IsIOS() && !IsARM())
5514 {
5515 setRobustAccess(true);
5516 }
5517 }
5518 };
5519
5520 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
5521 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)5522 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
5523 {
5524 // Initialize program and set up state.
5525 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5526
5527 glUseProgram(program);
5528 GLint positionLoc = glGetAttribLocation(program, "position");
5529 ASSERT_NE(-1, positionLoc);
5530 GLint colorLoc = glGetAttribLocation(program, "color");
5531 ASSERT_NE(-1, colorLoc);
5532
5533 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5534 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5535
5536 GLBuffer posBuffer;
5537 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5538 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5539
5540 // Start with position enabled.
5541 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5542 glEnableVertexAttribArray(positionLoc);
5543
5544 std::vector<GLColor> colorVertices(6, GLColor::blue);
5545 const size_t colorBufferSize = sizeof(GLColor) * 6;
5546
5547 GLBuffer colorBuffer;
5548 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5549 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
5550
5551 // Start with color disabled.
5552 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5553 glDisableVertexAttribArray(colorLoc);
5554
5555 ASSERT_GL_NO_ERROR();
5556
5557 // Draw without a mapped buffer. Should succeed.
5558 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5559 glDrawArrays(GL_TRIANGLES, 0, 6);
5560 ASSERT_GL_NO_ERROR();
5561 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5562
5563 // Map position buffer and draw. Should fail.
5564 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5565 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
5566 ASSERT_GL_NO_ERROR();
5567
5568 glDrawArrays(GL_TRIANGLES, 0, 6);
5569 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
5570 glUnmapBuffer(GL_ARRAY_BUFFER);
5571
5572 // Map then enable color buffer. Should fail.
5573 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5574 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
5575 glEnableVertexAttribArray(colorLoc);
5576 ASSERT_GL_NO_ERROR();
5577
5578 glDrawArrays(GL_TRIANGLES, 0, 6);
5579 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
5580
5581 // Unmap then draw. Should succeed.
5582 glUnmapBuffer(GL_ARRAY_BUFFER);
5583 ASSERT_GL_NO_ERROR();
5584
5585 glDrawArrays(GL_TRIANGLES, 0, 6);
5586 ASSERT_GL_NO_ERROR();
5587 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5588 }
5589
5590 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
5591 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)5592 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
5593 {
5594 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5595
5596 // Initialize program and set up state.
5597 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5598
5599 glUseProgram(program);
5600 GLint positionLoc = glGetAttribLocation(program, "position");
5601 ASSERT_NE(-1, positionLoc);
5602 GLint colorLoc = glGetAttribLocation(program, "color");
5603 ASSERT_NE(-1, colorLoc);
5604
5605 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5606 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5607
5608 GLBuffer posBuffer;
5609 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5610 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5611 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5612
5613 // Start with position enabled.
5614 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5615 glEnableVertexAttribArray(positionLoc);
5616
5617 std::vector<GLColor> colorVertices(6, GLColor::blue);
5618 const size_t colorBufferSize = sizeof(GLColor) * 6;
5619
5620 GLBuffer colorBuffer;
5621 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5622 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5623 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5624
5625 // Start with color disabled.
5626 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5627 glDisableVertexAttribArray(colorLoc);
5628
5629 ASSERT_GL_NO_ERROR();
5630
5631 // Draw without a mapped buffer. Should succeed.
5632 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5633 glDrawArrays(GL_TRIANGLES, 0, 6);
5634 ASSERT_GL_NO_ERROR();
5635 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5636
5637 // Map position buffer and draw. Should succeed.
5638 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5639 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5640 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5641 ASSERT_GL_NO_ERROR();
5642
5643 glDrawArrays(GL_TRIANGLES, 0, 6);
5644 ASSERT_GL_NO_ERROR();
5645 glUnmapBuffer(GL_ARRAY_BUFFER);
5646
5647 // Map then enable color buffer. Should succeed.
5648 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5649 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5650 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5651 glEnableVertexAttribArray(colorLoc);
5652 ASSERT_GL_NO_ERROR();
5653
5654 glDrawArrays(GL_TRIANGLES, 0, 6);
5655 ASSERT_GL_NO_ERROR();
5656
5657 // Unmap then draw. Should succeed.
5658 glUnmapBuffer(GL_ARRAY_BUFFER);
5659 ASSERT_GL_NO_ERROR();
5660
5661 glDrawArrays(GL_TRIANGLES, 0, 6);
5662 ASSERT_GL_NO_ERROR();
5663 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5664 }
5665
5666 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5667 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5668 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5669 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5670 {
5671 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5672
5673 // Initialize program and set up state.
5674 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5675
5676 glUseProgram(program);
5677 GLint positionLoc = glGetAttribLocation(program, "position");
5678 ASSERT_NE(-1, positionLoc);
5679 GLint colorLoc = glGetAttribLocation(program, "color");
5680 ASSERT_NE(-1, colorLoc);
5681
5682 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5683 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5684
5685 GLBuffer posBuffer;
5686 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5687 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5688 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5689
5690 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5691 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5692
5693 // Start with position enabled.
5694 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5695 glEnableVertexAttribArray(positionLoc);
5696
5697 std::vector<GLColor> colorVertices(6, GLColor::blue);
5698 const size_t colorBufferSize = sizeof(GLColor) * 6;
5699
5700 GLBuffer colorBuffer;
5701 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5702 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5703 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5704
5705 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5706 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5707 ASSERT_GL_NO_ERROR();
5708
5709 // Start with color disabled.
5710 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5711 glDisableVertexAttribArray(colorLoc);
5712
5713 ASSERT_GL_NO_ERROR();
5714
5715 // Draw without a mapped buffer. Should succeed.
5716 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5717 glDrawArrays(GL_TRIANGLES, 0, 6);
5718 ASSERT_GL_NO_ERROR();
5719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5720
5721 // Unmap then draw. Should succeed.
5722 glUnmapBuffer(GL_ARRAY_BUFFER);
5723 glEnableVertexAttribArray(colorLoc);
5724 ASSERT_GL_NO_ERROR();
5725 glDrawArrays(GL_TRIANGLES, 0, 6);
5726 ASSERT_GL_NO_ERROR();
5727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5728 }
5729
5730 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5731 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5732 {
5733 // Seems to trigger a GL error in some edge cases. http://anglebug.com/42261462
5734 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5735
5736 // Initialize program and set up state.
5737 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5738
5739 glUseProgram(program);
5740 GLint positionLoc = glGetAttribLocation(program, "position");
5741 ASSERT_NE(-1, positionLoc);
5742 GLint colorLoc = glGetAttribLocation(program, "color");
5743 ASSERT_NE(-1, colorLoc);
5744
5745 // Create a user vertex array.
5746 GLVertexArray vao;
5747 glBindVertexArray(vao);
5748
5749 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5750 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5751
5752 GLBuffer posBuffer;
5753 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5754 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5755
5756 // Start with position enabled.
5757 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5758 glEnableVertexAttribArray(positionLoc);
5759
5760 std::vector<GLColor> blueVertices(6, GLColor::blue);
5761 const size_t blueBufferSize = sizeof(GLColor) * 6;
5762
5763 GLBuffer blueBuffer;
5764 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5765 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5766
5767 // Start with color enabled at an unused binding.
5768 constexpr GLint kUnusedBinding = 3;
5769 ASSERT_NE(colorLoc, kUnusedBinding);
5770 ASSERT_NE(positionLoc, kUnusedBinding);
5771 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5772 glVertexAttribBinding(colorLoc, kUnusedBinding);
5773 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5774 glEnableVertexAttribArray(colorLoc);
5775
5776 // Make binding 'colorLoc' use a mapped buffer.
5777 std::vector<GLColor> greenVertices(6, GLColor::green);
5778 const size_t greenBufferSize = sizeof(GLColor) * 6;
5779 GLBuffer greenBuffer;
5780 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5781 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5782 glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5783 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5784
5785 ASSERT_GL_NO_ERROR();
5786
5787 // Draw without a mapped buffer. Should succeed.
5788 glDrawArrays(GL_TRIANGLES, 0, 6);
5789 ASSERT_GL_NO_ERROR();
5790 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5791
5792 // Change divisor with VertexAttribDivisor. Should fail.
5793 glVertexAttribDivisor(colorLoc, 0);
5794 ASSERT_GL_NO_ERROR();
5795 glDrawArrays(GL_TRIANGLES, 0, 6);
5796 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5797
5798 // Unmap the buffer. Should succeed.
5799 glUnmapBuffer(GL_ARRAY_BUFFER);
5800 glDrawArrays(GL_TRIANGLES, 0, 6);
5801 ASSERT_GL_NO_ERROR();
5802 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5803 }
5804
5805 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5806 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5807 {
5808 // Initialize program and set up state.
5809 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5810
5811 glUseProgram(program);
5812 GLint positionLoc = glGetAttribLocation(program, "position");
5813 ASSERT_NE(-1, positionLoc);
5814 GLint colorLoc = glGetAttribLocation(program, "color");
5815 ASSERT_NE(-1, colorLoc);
5816
5817 // Create a user vertex array.
5818 GLVertexArray vao;
5819 glBindVertexArray(vao);
5820
5821 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5822 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5823
5824 GLBuffer posBuffer;
5825 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5826 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5827
5828 // Start with position enabled.
5829 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5830 glEnableVertexAttribArray(positionLoc);
5831
5832 std::vector<GLColor> blueVertices(6, GLColor::blue);
5833 const size_t blueBufferSize = sizeof(GLColor) * 6;
5834
5835 GLBuffer blueBuffer;
5836 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5837 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5838
5839 // Start with color enabled at an unused binding.
5840 constexpr GLint kUnusedBinding = 3;
5841 ASSERT_NE(colorLoc, kUnusedBinding);
5842 ASSERT_NE(positionLoc, kUnusedBinding);
5843 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5844 glVertexAttribBinding(colorLoc, kUnusedBinding);
5845 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5846 glEnableVertexAttribArray(colorLoc);
5847
5848 // Make binding 'colorLoc' use a small buffer.
5849 std::vector<GLColor> greenVertices(6, GLColor::green);
5850 const size_t greenBufferSize = sizeof(GLColor) * 3;
5851 GLBuffer greenBuffer;
5852 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5853 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5854 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5855
5856 ASSERT_GL_NO_ERROR();
5857
5858 // Draw without a mapped buffer. Should succeed.
5859 glDrawArrays(GL_TRIANGLES, 0, 6);
5860 ASSERT_GL_NO_ERROR();
5861 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5862
5863 // Change divisor with VertexAttribDivisor. Should fail.
5864 glVertexAttribDivisor(colorLoc, 0);
5865 ASSERT_GL_NO_ERROR();
5866 glDrawArrays(GL_TRIANGLES, 0, 6);
5867 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5868
5869 // Do a small draw. Should succeed.
5870 glDrawArrays(GL_TRIANGLES, 0, 3);
5871 ASSERT_GL_NO_ERROR();
5872 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5873 }
5874
5875 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5876 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5877 {
5878 constexpr char kVS[] = R"(#version 300 es
5879 in vec2 position;
5880 void main()
5881 {
5882 gl_Position = vec4(position, 0, 1);
5883 })";
5884
5885 constexpr char kFS[] = R"(#version 300 es
5886 precision mediump float;
5887 uniform uni { vec4 vec; };
5888 out vec4 color;
5889 void main()
5890 {
5891 color = vec;
5892 })";
5893
5894 ANGLE_GL_PROGRAM(program, kVS, kFS);
5895 glUseProgram(program);
5896
5897 GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5898 ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5899
5900 glUniformBlockBinding(program, blockIndex, 0);
5901
5902 GLBuffer uniformBuffer;
5903 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5904 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5905 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5906
5907 const auto &quadVertices = GetQuadVertices();
5908
5909 GLBuffer positionBuffer;
5910 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5911 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5912 GL_STATIC_DRAW);
5913
5914 GLint positionLocation = glGetAttribLocation(program, "position");
5915 ASSERT_NE(-1, positionLocation);
5916
5917 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5918 glEnableVertexAttribArray(positionLocation);
5919 ASSERT_GL_NO_ERROR();
5920
5921 // First draw should succeed.
5922 glDrawArrays(GL_TRIANGLES, 0, 6);
5923 ASSERT_GL_NO_ERROR();
5924 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5925
5926 // Change the uniform block binding. Should fail.
5927 glUniformBlockBinding(program, blockIndex, 1);
5928 ASSERT_GL_NO_ERROR();
5929 glDrawArrays(GL_TRIANGLES, 0, 6);
5930 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5931
5932 // Reset to a correct state.
5933 glUniformBlockBinding(program, blockIndex, 0);
5934 glDrawArrays(GL_TRIANGLES, 0, 6);
5935 ASSERT_GL_NO_ERROR();
5936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5937
5938 // Change the buffer binding. Should fail.
5939 glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5940 ASSERT_GL_NO_ERROR();
5941 glDrawArrays(GL_TRIANGLES, 0, 6);
5942 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5943
5944 // Reset to a correct state.
5945 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5946 glDrawArrays(GL_TRIANGLES, 0, 6);
5947 ASSERT_GL_NO_ERROR();
5948 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5949
5950 // Resize the buffer to be too small. Should fail.
5951 glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5952 glDrawArrays(GL_TRIANGLES, 0, 6);
5953 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5954 }
5955
5956 // Tests that redefining attachment storage updates the component type mask
TEST_P(WebGL2ValidationStateChangeTest,AttachmentTypeRedefinition)5957 TEST_P(WebGL2ValidationStateChangeTest, AttachmentTypeRedefinition)
5958 {
5959 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
5960
5961 GLFramebuffer fb;
5962 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5963
5964 GLRenderbuffer rb;
5965 glBindRenderbuffer(GL_RENDERBUFFER, rb);
5966 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5967
5968 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 4, 4);
5969 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5970 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5971
5972 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 4, 4);
5973 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5974 EXPECT_GL_NO_ERROR();
5975 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
5976
5977 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 4, 4);
5978 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5979 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5980 }
5981
5982 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5983 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5984 {
5985 // Set up a simple draw from a Texture to a user Framebuffer.
5986 GLuint program = get2DTexturedQuadProgram();
5987 ASSERT_NE(0u, program);
5988 glUseProgram(program);
5989
5990 GLint posLoc = glGetAttribLocation(program, "position");
5991 ASSERT_NE(-1, posLoc);
5992
5993 const auto &quadVertices = GetQuadVertices();
5994
5995 GLBuffer positionBuffer;
5996 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5997 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5998 GL_STATIC_DRAW);
5999
6000 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6001 glEnableVertexAttribArray(posLoc);
6002
6003 constexpr size_t kSize = 2;
6004
6005 GLTexture colorBufferTexture;
6006 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
6007 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6008 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6009 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6010
6011 GLFramebuffer framebuffer;
6012 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6013 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
6014 0);
6015 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6016
6017 std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
6018
6019 GLTexture greenTexture;
6020 glBindTexture(GL_TEXTURE_2D, greenTexture);
6021 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6022 greenColor.data());
6023 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6024 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6025
6026 // Second framebuffer with a feedback loop. Initially unbound.
6027 GLFramebuffer loopedFramebuffer;
6028 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
6029 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
6030 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6031 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6032
6033 ASSERT_GL_NO_ERROR();
6034
6035 glDrawArrays(GL_TRIANGLES, 0, 6);
6036 ASSERT_GL_NO_ERROR();
6037 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6038
6039 // Create a rendering feedback loop. Should fail.
6040 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
6041 ASSERT_GL_NO_ERROR();
6042 glDrawArrays(GL_TRIANGLES, 0, 6);
6043 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6044
6045 // Reset to a valid state.
6046 glBindTexture(GL_TEXTURE_2D, greenTexture);
6047 glDrawArrays(GL_TRIANGLES, 0, 6);
6048 ASSERT_GL_NO_ERROR();
6049 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6050
6051 // Bind a second framebuffer with a feedback loop.
6052 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
6053 ASSERT_GL_NO_ERROR();
6054 glDrawArrays(GL_TRIANGLES, 0, 6);
6055 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6056
6057 // Update the framebuffer texture attachment. Should succeed.
6058 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
6059 0);
6060 glDrawArrays(GL_TRIANGLES, 0, 6);
6061 ASSERT_GL_NO_ERROR();
6062 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6063 }
6064
6065 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)6066 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
6067 {
6068 // Crashes on 64-bit Android. http://anglebug.com/42262522
6069 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
6070
6071 // Set up a program that writes to two outputs: one int and one float.
6072 constexpr char kVS[] = R"(#version 300 es
6073 layout(location = 0) in vec2 position;
6074 out vec2 texCoord;
6075 void main()
6076 {
6077 gl_Position = vec4(position, 0, 1);
6078 texCoord = position * 0.5 + vec2(0.5);
6079 })";
6080
6081 constexpr char kFS[] = R"(#version 300 es
6082 precision mediump float;
6083 in vec2 texCoord;
6084 layout(location = 0) out vec4 outFloat;
6085 layout(location = 1) out uvec4 outInt;
6086 void main()
6087 {
6088 outFloat = vec4(0, 1, 0, 1);
6089 outInt = uvec4(0, 1, 0, 1);
6090 })";
6091
6092 ANGLE_GL_PROGRAM(program, kVS, kFS);
6093 glUseProgram(program);
6094
6095 constexpr GLint kPosLoc = 0;
6096
6097 const auto &quadVertices = GetQuadVertices();
6098
6099 GLBuffer positionBuffer;
6100 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
6101 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
6102 GL_STATIC_DRAW);
6103
6104 glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6105 glEnableVertexAttribArray(kPosLoc);
6106
6107 constexpr size_t kSize = 2;
6108
6109 GLFramebuffer floatFramebuffer;
6110 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6111
6112 GLTexture floatTextures[2];
6113 for (int i = 0; i < 2; ++i)
6114 {
6115 glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
6116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6117 nullptr);
6118 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6119 floatTextures[i], 0);
6120 ASSERT_GL_NO_ERROR();
6121 }
6122
6123 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6124
6125 GLFramebuffer intFramebuffer;
6126 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6127
6128 GLTexture intTextures[2];
6129 for (int i = 0; i < 2; ++i)
6130 {
6131 glBindTexture(GL_TEXTURE_2D, intTextures[i]);
6132 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
6133 GL_UNSIGNED_BYTE, nullptr);
6134 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6135 intTextures[i], 0);
6136 ASSERT_GL_NO_ERROR();
6137 }
6138
6139 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6140
6141 ASSERT_GL_NO_ERROR();
6142
6143 constexpr GLenum kColor0Enabled[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
6144 constexpr GLenum kColor1Enabled[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
6145 constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6146
6147 // Draw float. Should work.
6148 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6149 glDrawBuffers(2, kColor0Enabled);
6150
6151 glDrawArrays(GL_TRIANGLES, 0, 6);
6152 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6153 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6154
6155 // Set an invalid component write.
6156 glDrawBuffers(2, kColor0And1Enabled);
6157 ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
6158 glDrawArrays(GL_TRIANGLES, 0, 6);
6159 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6160 // Set all 4 channels of color mask to false. Validate success.
6161 glColorMask(false, false, false, false);
6162 glDrawArrays(GL_TRIANGLES, 0, 6);
6163 EXPECT_GL_NO_ERROR();
6164 glColorMask(false, true, false, false);
6165 glDrawArrays(GL_TRIANGLES, 0, 6);
6166 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6167 glColorMask(true, true, true, true);
6168 glDrawArrays(GL_TRIANGLES, 0, 6);
6169 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6170
6171 // Restore state.
6172 glDrawBuffers(2, kColor0Enabled);
6173 glDrawArrays(GL_TRIANGLES, 0, 6);
6174 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6175 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6176
6177 // Bind an invalid framebuffer. Validate failure.
6178 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6179 ASSERT_GL_NO_ERROR();
6180 glDrawArrays(GL_TRIANGLES, 0, 6);
6181 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
6182
6183 // Set draw mask to a valid mask. Validate success.
6184 glDrawBuffers(2, kColor1Enabled);
6185 glDrawArrays(GL_TRIANGLES, 0, 6);
6186 ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
6187 }
6188
6189 // Tests that switching the program properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,IncompatibleDrawFramebufferProgramSwitch)6190 TEST_P(WebGL2ValidationStateChangeTest, IncompatibleDrawFramebufferProgramSwitch)
6191 {
6192 constexpr char kFS0[] = R"(#version 300 es
6193 precision mediump float;
6194 in vec2 texCoord;
6195 out ivec4 color;
6196 void main()
6197 {
6198 color = ivec4(1, 0, 1, 1);
6199 })";
6200 ANGLE_GL_PROGRAM(programInt, essl3_shaders::vs::Simple(), kFS0);
6201
6202 constexpr char kFS1[] = R"(#version 300 es
6203 precision mediump float;
6204 in vec2 texCoord;
6205 out vec4 color;
6206 void main()
6207 {
6208 color = vec4(0, 1, 0, 1);
6209 })";
6210 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS1);
6211
6212 constexpr size_t kSize = 2;
6213
6214 GLFramebuffer fb;
6215 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6216
6217 GLRenderbuffer rb;
6218 glBindRenderbuffer(GL_RENDERBUFFER, rb);
6219 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6220 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
6221
6222 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6223
6224 // Incompatible masked-out draw call
6225 // Implementations may internally disable render targets to avoid runtime failures
6226 glColorMask(false, false, false, false);
6227 drawQuad(programInt, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6228 ASSERT_GL_NO_ERROR();
6229
6230 // Clear must not be affected
6231 glColorMask(true, true, true, true);
6232 glClearColor(1.0, 0.0, 0.0, 1.0);
6233 glClear(GL_COLOR_BUFFER_BIT);
6234 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
6235
6236 // Compatible draw call
6237 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6238 ASSERT_GL_NO_ERROR();
6239 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6240 }
6241
6242 // Tests that updating the render target storage properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)6243 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)
6244 {
6245 constexpr char kFS[] = R"(#version 300 es
6246 precision mediump float;
6247 in vec2 texCoord;
6248 layout(location = 0) out ivec4 colorInt;
6249 layout(location = 1) out vec4 colorFloat;
6250 void main()
6251 {
6252 colorInt = ivec4(1, 0, 1, 1);
6253 colorFloat = vec4(0, 1, 0, 1);
6254 })";
6255
6256 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6257
6258 // Explicitly set the program here so that
6259 // drawQuad helpers do not switch it
6260 glUseProgram(program);
6261
6262 constexpr size_t kSize = 2;
6263
6264 GLFramebuffer fb;
6265 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6266
6267 GLRenderbuffer rb0;
6268 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6269 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6270 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
6271
6272 GLRenderbuffer rb1;
6273 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6274 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6275 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rb1);
6276
6277 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6278
6279 constexpr GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6280 glDrawBuffers(2, bufs);
6281
6282 // Incompatible masked-out draw call
6283 // Implementations may internally disable render targets to avoid runtime failures
6284 glColorMask(false, false, false, false);
6285 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6286 ASSERT_GL_NO_ERROR();
6287
6288 // Redefine storage, swapping numeric types
6289 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6290 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6291 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6292 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6293
6294 // The same draw call should be valid now
6295 glColorMask(true, true, true, true);
6296 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6297 ASSERT_GL_NO_ERROR();
6298
6299 glReadBuffer(GL_COLOR_ATTACHMENT0);
6300 EXPECT_PIXEL_RECT32I_EQ(0, 0, kSize, kSize, GLColor32I(1, 0, 1, 1));
6301
6302 glReadBuffer(GL_COLOR_ATTACHMENT1);
6303 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6304 }
6305
6306 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)6307 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
6308 {
6309 // TODO(anglebug.com/40096690) This fails after the upgrade to the 26.20.100.7870 driver.
6310 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
6311
6312 constexpr char kFS[] = R"(#version 300 es
6313 precision mediump float;
6314 uniform block { vec4 color; };
6315 out vec4 colorOut;
6316 void main()
6317 {
6318 colorOut = color;
6319 })";
6320
6321 std::vector<std::string> tfVaryings = {"gl_Position"};
6322 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
6323 GL_INTERLEAVED_ATTRIBS);
6324 glUseProgram(program);
6325
6326 std::vector<Vector4> positionData;
6327 for (const Vector3 &quadVertex : GetQuadVertices())
6328 {
6329 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6330 }
6331
6332 GLBuffer arrayBuffer;
6333 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6334 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6335 GL_STATIC_DRAW);
6336
6337 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6338 ASSERT_NE(-1, positionLoc);
6339
6340 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6341 glEnableVertexAttribArray(positionLoc);
6342
6343 EXPECT_GL_NO_ERROR();
6344
6345 // Set up transform feedback.
6346 GLTransformFeedback transformFeedback;
6347 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6348
6349 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6350
6351 GLBuffer transformFeedbackBuffer;
6352 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6353 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6354 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6355
6356 // Set up uniform buffer.
6357 GLBuffer uniformBuffer;
6358 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
6359 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
6360 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
6361
6362 ASSERT_GL_NO_ERROR();
6363
6364 // Do the draw operation. Should succeed.
6365 glBeginTransformFeedback(GL_TRIANGLES);
6366 glDrawArrays(GL_TRIANGLES, 0, 6);
6367 glEndTransformFeedback();
6368
6369 ASSERT_GL_NO_ERROR();
6370 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6371
6372 const GLvoid *mapPointer =
6373 glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
6374 ASSERT_GL_NO_ERROR();
6375 ASSERT_NE(nullptr, mapPointer);
6376 const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
6377 std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
6378 EXPECT_EQ(positionData, actualData);
6379 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
6380
6381 // Draw once to update validation cache.
6382 glBeginTransformFeedback(GL_TRIANGLES);
6383 glDrawArrays(GL_TRIANGLES, 0, 6);
6384
6385 // Bind transform feedback buffer to another binding point. Should cause a conflict.
6386 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
6387 ASSERT_GL_NO_ERROR();
6388 glDrawArrays(GL_TRIANGLES, 0, 6);
6389 glEndTransformFeedback();
6390 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
6391
6392 // Reset to valid state.
6393 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6394 glBeginTransformFeedback(GL_TRIANGLES);
6395 glDrawArrays(GL_TRIANGLES, 0, 6);
6396 glEndTransformFeedback();
6397 ASSERT_GL_NO_ERROR();
6398
6399 // Simultaneous non-vertex-array binding. Should fail.
6400 glBeginTransformFeedback(GL_TRIANGLES);
6401 glDrawArrays(GL_TRIANGLES, 0, 6);
6402 ASSERT_GL_NO_ERROR();
6403 glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
6404 ASSERT_GL_NO_ERROR();
6405 glDrawArrays(GL_TRIANGLES, 0, 6);
6406 glEndTransformFeedback();
6407 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
6408 }
6409
6410 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)6411 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
6412 {
6413 // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
6414 // DEPTH_COMPONENT24 is emulated with D32_S8X24. http://anglebug.com/42262525
6415 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
6416
6417 constexpr char kFS[] = R"(#version 300 es
6418 precision mediump float;
6419 uniform sampler2D sampler;
6420 out vec4 colorOut;
6421 void main()
6422 {
6423 colorOut = texture(sampler, vec2(0));
6424 })";
6425
6426 std::vector<std::string> tfVaryings = {"gl_Position"};
6427 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6428 glUseProgram(program);
6429
6430 std::array<GLColor, 4> colors = {
6431 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6432
6433 GLTexture tex;
6434 glBindTexture(GL_TEXTURE_2D, tex);
6435 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
6436
6437 const auto &quadVertices = GetQuadVertices();
6438
6439 GLBuffer arrayBuffer;
6440 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6441 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6442 GL_STATIC_DRAW);
6443
6444 GLint samplerLoc = glGetUniformLocation(program, "sampler");
6445 ASSERT_NE(-1, samplerLoc);
6446 glUniform1i(samplerLoc, 0);
6447
6448 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6449 ASSERT_NE(-1, positionLoc);
6450 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6451 glEnableVertexAttribArray(positionLoc);
6452
6453 ASSERT_GL_NO_ERROR();
6454
6455 glDrawArrays(GL_TRIANGLES, 0, 6);
6456 ASSERT_GL_NO_ERROR();
6457
6458 // TexImage2D should update the sampler format cache.
6459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
6460 colors.data());
6461 glDrawArrays(GL_TRIANGLES, 0, 6);
6462 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
6463
6464 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
6465 GL_UNSIGNED_INT, colors.data());
6466 glDrawArrays(GL_TRIANGLES, 0, 6);
6467 ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
6468
6469 // TexParameteri should update the sampler format cache.
6470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
6471 glDrawArrays(GL_TRIANGLES, 0, 6);
6472 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
6473 }
6474
6475 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)6476 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
6477 {
6478 std::vector<std::string> tfVaryings = {"gl_Position"};
6479 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
6480 essl3_shaders::fs::Red(), tfVaryings,
6481 GL_INTERLEAVED_ATTRIBS);
6482 glUseProgram(program);
6483
6484 std::vector<Vector4> positionData;
6485 for (const Vector3 &quadVertex : GetQuadVertices())
6486 {
6487 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6488 }
6489
6490 GLBuffer arrayBuffer;
6491 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6492 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6493 GL_STATIC_DRAW);
6494
6495 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6496 ASSERT_NE(-1, positionLoc);
6497
6498 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6499 glEnableVertexAttribArray(positionLoc);
6500
6501 // Set up transform feedback.
6502 GLTransformFeedback transformFeedback;
6503 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6504
6505 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6506
6507 GLBuffer transformFeedbackBuffer;
6508 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6509 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6510 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6511
6512 GLTransformFeedback pointsXFB;
6513 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6514 GLBuffer pointsXFBBuffer;
6515 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
6516 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
6517 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
6518
6519 // Begin TRIANGLES, switch to paused POINTS, should be valid.
6520 glBeginTransformFeedback(GL_POINTS);
6521 glPauseTransformFeedback();
6522 ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
6523
6524 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6525 glBeginTransformFeedback(GL_TRIANGLES);
6526 glDrawArrays(GL_TRIANGLES, 0, 6);
6527 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6528 glDrawArrays(GL_POINTS, 0, 6);
6529 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
6530 glDrawArrays(GL_LINES, 0, 6);
6531 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6532 glPauseTransformFeedback();
6533 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6534 glResumeTransformFeedback();
6535 glDrawArrays(GL_POINTS, 0, 6);
6536 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6537 glDrawArrays(GL_TRIANGLES, 0, 6);
6538 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
6539 glDrawArrays(GL_LINES, 0, 6);
6540 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6541
6542 glEndTransformFeedback();
6543 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6544 glEndTransformFeedback();
6545 ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
6546
6547 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
6548
6549 glDrawArrays(GL_POINTS, 0, 6);
6550 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6551 glDrawArrays(GL_TRIANGLES, 0, 6);
6552 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6553 glDrawArrays(GL_LINES, 0, 6);
6554 EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
6555 }
6556
6557 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)6558 TEST_P(ValidationStateChangeTest, TextureConflict)
6559 {
6560 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
6561
6562 GLint maxTextures = 0;
6563 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
6564 ANGLE_SKIP_TEST_IF(maxTextures < 2);
6565
6566 // Set up state.
6567 constexpr GLint kSize = 2;
6568
6569 std::vector<GLColor> greenData(4, GLColor::green);
6570
6571 GLTexture textureA;
6572 glBindTexture(GL_TEXTURE_2D, textureA);
6573 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6574 greenData.data());
6575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6576 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6577
6578 glActiveTexture(GL_TEXTURE1);
6579
6580 GLTexture textureB;
6581 glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
6582 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6583 GL_UNSIGNED_BYTE, greenData.data());
6584 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6585 GL_UNSIGNED_BYTE, greenData.data());
6586 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6587 GL_UNSIGNED_BYTE, greenData.data());
6588 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6589 GL_UNSIGNED_BYTE, greenData.data());
6590 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6591 GL_UNSIGNED_BYTE, greenData.data());
6592 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6593 GL_UNSIGNED_BYTE, greenData.data());
6594 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6595 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6596
6597 constexpr char kVS[] = R"(attribute vec2 position;
6598 varying mediump vec2 texCoord;
6599 void main()
6600 {
6601 gl_Position = vec4(position, 0, 1);
6602 texCoord = position * 0.5 + vec2(0.5);
6603 })";
6604
6605 constexpr char kFS[] = R"(varying mediump vec2 texCoord;
6606 uniform sampler2D texA;
6607 uniform samplerCube texB;
6608 void main()
6609 {
6610 gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
6611 })";
6612
6613 ANGLE_GL_PROGRAM(program, kVS, kFS);
6614 glUseProgram(program);
6615
6616 const auto &quadVertices = GetQuadVertices();
6617
6618 GLBuffer arrayBuffer;
6619 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6620 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6621 GL_STATIC_DRAW);
6622
6623 GLint positionLoc = glGetAttribLocation(program, "position");
6624 ASSERT_NE(-1, positionLoc);
6625
6626 GLint texALoc = glGetUniformLocation(program, "texA");
6627 ASSERT_NE(-1, texALoc);
6628
6629 GLint texBLoc = glGetUniformLocation(program, "texB");
6630 ASSERT_NE(-1, texBLoc);
6631
6632 glUniform1i(texALoc, 0);
6633 glUniform1i(texBLoc, 1);
6634
6635 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6636 glEnableVertexAttribArray(positionLoc);
6637
6638 ASSERT_GL_NO_ERROR();
6639
6640 // First draw. Should succeed.
6641 glDrawArrays(GL_TRIANGLES, 0, 6);
6642 ASSERT_GL_NO_ERROR();
6643 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6644
6645 // Second draw to ensure all state changes are flushed.
6646 glDrawArrays(GL_TRIANGLES, 0, 6);
6647 ASSERT_GL_NO_ERROR();
6648
6649 // Make the uniform use an invalid texture binding.
6650 glUniform1i(texBLoc, 0);
6651 glDrawArrays(GL_TRIANGLES, 0, 6);
6652 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6653 }
6654
6655 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)6656 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
6657 {
6658 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
6659 glUseProgram(program);
6660
6661 std::array<GLushort, 6> quadIndices = GetQuadIndices();
6662 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
6663
6664 GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
6665
6666 GLBuffer elementArrayBuffer;
6667 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6668 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
6669
6670 GLBuffer arrayBuffer;
6671 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6672 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
6673 quadVertices.data(), GL_STATIC_DRAW);
6674
6675 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6676 ASSERT_NE(-1, positionLoc);
6677 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6678 glEnableVertexAttribArray(positionLoc);
6679
6680 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6681 ASSERT_GL_NO_ERROR();
6682
6683 void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
6684 ASSERT_NE(nullptr, ptr);
6685
6686 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6687 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6688
6689 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
6690
6691 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6692 ASSERT_GL_NO_ERROR();
6693 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6694 }
6695
6696 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)6697 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
6698 {
6699 constexpr char kFS[] =
6700 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6701 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6702 glUseProgram(program);
6703 GLint loc = glGetUniformLocation(program, "us");
6704 ASSERT_EQ(0, loc);
6705
6706 auto quadVertices = GetQuadVertices();
6707 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6708 ASSERT_EQ(0, posLoc);
6709
6710 GLBuffer buffer;
6711 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6712 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6713 quadVertices.data(), GL_STATIC_DRAW);
6714 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6715 glEnableVertexAttribArray(posLoc);
6716
6717 constexpr size_t kSize = 2;
6718 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6719
6720 GLTexture tex;
6721 glBindTexture(GL_TEXTURE_2D, tex);
6722 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6723 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6724 glUniform1i(loc, 0);
6725
6726 glDrawArrays(GL_TRIANGLES, 0, 3);
6727 ASSERT_GL_NO_ERROR();
6728 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6729
6730 // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
6731 GLTexture tex2;
6732 glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
6733 tex2.reset();
6734
6735 glDrawArrays(GL_TRIANGLES, 0, 3);
6736 ASSERT_GL_NO_ERROR();
6737 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6738
6739 // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
6740 tex.reset();
6741
6742 glDrawArrays(GL_TRIANGLES, 0, 3);
6743 ASSERT_GL_NO_ERROR();
6744 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6745 }
6746
6747 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)6748 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
6749 {
6750 constexpr char kFS[] =
6751 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6752 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6753 glUseProgram(program);
6754 GLint loc = glGetUniformLocation(program, "us");
6755 ASSERT_EQ(0, loc);
6756
6757 auto quadVertices = GetQuadVertices();
6758 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6759 ASSERT_EQ(0, posLoc);
6760
6761 GLBuffer buffer;
6762 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6763 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6764 quadVertices.data(), GL_STATIC_DRAW);
6765 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6766 glEnableVertexAttribArray(posLoc);
6767
6768 constexpr size_t kSize = 2;
6769 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6770
6771 GLTexture tex;
6772 glBindTexture(GL_TEXTURE_2D, tex);
6773 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6774 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6775 glUniform1i(loc, 1);
6776 tex.reset();
6777
6778 glDrawArrays(GL_TRIANGLES, 0, 3);
6779 ASSERT_GL_NO_ERROR();
6780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6781 }
6782
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)6783 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
6784 {
6785 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6786 glBindTexture(GL_TEXTURE_2D, texture);
6787 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6788 GL_UNSIGNED_BYTE, nullptr);
6789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6791 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6792 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6793 }
6794
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6795 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6796 {
6797 // Render to an FBO
6798 GLFramebuffer fbo1;
6799 GLTexture texture1;
6800
6801 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6802 ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6803 essl1_shaders::fs::Texture2D());
6804
6805 bindTextureToFbo(fbo1, texture1);
6806
6807 // Clear the surface FBO to initialize it to a known value
6808 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6809 glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
6810 glClear(GL_COLOR_BUFFER_BIT);
6811 ASSERT_GL_NO_ERROR();
6812 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6813 glFlush();
6814
6815 // Draw to FBO 1 to initialize it to a known value
6816 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6817
6818 if (earlyFrontFaceDirty)
6819 {
6820 glEnable(GL_CULL_FACE);
6821 // Make sure we don't cull
6822 glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6823 glFrontFace(frontFace);
6824 }
6825 else
6826 {
6827 glDisable(GL_CULL_FACE);
6828 }
6829
6830 glUseProgram(greenProgram);
6831 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6832 ASSERT_GL_NO_ERROR();
6833 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6834
6835 // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6836 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6837 glBindTexture(GL_TEXTURE_2D, texture1);
6838
6839 glCullFace(GL_BACK);
6840 if (!earlyFrontFaceDirty)
6841 {
6842 // Set the culling we want to test
6843 glEnable(GL_CULL_FACE);
6844 glFrontFace(frontFace);
6845 }
6846
6847 glUseProgram(textureProgram);
6848 drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6849 ASSERT_GL_NO_ERROR();
6850
6851 if (frontFace == GL_CCW)
6852 {
6853 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6854 }
6855 else
6856 {
6857 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6858 }
6859
6860 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6861 glBindTexture(GL_TEXTURE_2D, 0);
6862 }
6863
6864 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6865 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6866 {
6867 drawToFboWithCulling(GL_CCW, true);
6868 }
6869
6870 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6871 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6872 {
6873 drawToFboWithCulling(GL_CW, true);
6874 }
6875
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6876 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6877 {
6878 drawToFboWithCulling(GL_CCW, false);
6879 }
6880
6881 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6882 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6883 {
6884 drawToFboWithCulling(GL_CW, false);
6885 }
6886
6887 // Test that vertex attribute translation is still kept after binding it to another buffer then
6888 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6889 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6890 {
6891 // http://anglebug.com/42263918
6892 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6893
6894 constexpr char kVS[] = R"(attribute vec4 a_position;
6895 attribute float a_attrib;
6896 varying float v_attrib;
6897 void main()
6898 {
6899 v_attrib = a_attrib;
6900 gl_Position = a_position;
6901 })";
6902
6903 constexpr char kFS[] = R"(precision mediump float;
6904 varying float v_attrib;
6905 void main()
6906 {
6907 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6908 })";
6909
6910 ANGLE_GL_PROGRAM(program, kVS, kFS);
6911 glBindAttribLocation(program, 0, "a_position");
6912 glBindAttribLocation(program, 1, "a_attrib");
6913 glLinkProgram(program);
6914 glUseProgram(program);
6915 ASSERT_GL_NO_ERROR();
6916
6917 // Set up color data so red is drawn
6918 std::vector<GLushort> data(1000, 0xffff);
6919
6920 GLBuffer redBuffer;
6921 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6922 glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6923 // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6924 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6925 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6926 glBindBuffer(GL_ARRAY_BUFFER, 0);
6927 glEnableVertexAttribArray(1);
6928
6929 drawQuad(program, "a_position", 0.5f);
6930 // Verify red was drawn
6931 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6932
6933 glClearColor(0, 1, 0, 1);
6934 glClear(GL_COLOR_BUFFER_BIT);
6935 // Verify that green was drawn
6936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6937
6938 // Bind black color buffer to the same attribute with zero offset
6939 std::vector<GLfloat> black(6, 0.0f);
6940 GLBuffer blackBuffer;
6941 glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6942 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6943 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6944
6945 drawQuad(program, "a_position", 0.5f);
6946 // Verify black was drawn
6947 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6948
6949 // Rebind the old buffer & offset
6950 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6951 // Use offset not multiple of 4 GLushorts
6952 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6953 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6954
6955 drawQuad(program, "a_position", 0.5f);
6956 // Verify red was drawn
6957 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6958 }
6959
6960 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6961 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6962 {
6963 constexpr char kVS[] = R"(attribute vec4 a_position;
6964 varying float v_attrib;
6965 uniform float u_value;
6966 void main()
6967 {
6968 v_attrib = u_value;
6969 gl_Position = a_position;
6970 })";
6971
6972 constexpr char kFS[] = R"(precision mediump float;
6973 varying float v_attrib;
6974 void main()
6975 {
6976 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6977 })";
6978
6979 ANGLE_GL_PROGRAM(program1, kVS, kFS);
6980 ANGLE_GL_PROGRAM(program2, kVS, kFS);
6981
6982 // Don't use drawQuad so there's no state changes between the draw calls other than the program
6983 // binding.
6984
6985 constexpr size_t kProgramCount = 2;
6986 GLuint programs[kProgramCount] = {program1, program2};
6987 for (size_t i = 0; i < kProgramCount; ++i)
6988 {
6989 glUseProgram(programs[i]);
6990 GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6991 ASSERT_NE(uniformLoc, -1);
6992
6993 glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6994
6995 // Ensure position is at location 0 in both programs.
6996 GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6997 ASSERT_EQ(positionLocation, 0);
6998 }
6999 ASSERT_GL_NO_ERROR();
7000
7001 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7002 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7003 glEnableVertexAttribArray(0);
7004
7005 // Draw once with each so their uniforms are updated.
7006 // The first draw will clear the screen to 255, 0, 0, 255
7007 glUseProgram(program2);
7008 glDrawArrays(GL_TRIANGLES, 0, 6);
7009 // The second draw will clear the screen to 127, 0, 0, 255
7010 glUseProgram(program1);
7011 glDrawArrays(GL_TRIANGLES, 0, 6);
7012
7013 // Draw with the previous program again, to make sure its default uniforms are bound again.
7014 glUseProgram(program2);
7015 glDrawArrays(GL_TRIANGLES, 0, 6);
7016
7017 // Verify red was drawn
7018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7019 }
7020
7021 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
7022 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)7023 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
7024 {
7025 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
7026
7027 GLBuffer indexBuffer;
7028 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7029 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
7030 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
7031 ASSERT_GL_NO_ERROR();
7032
7033 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7034 }
7035
7036 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)7037 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
7038 {
7039 glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
7040 glClear(GL_COLOR_BUFFER_BIT);
7041 ASSERT_GL_NO_ERROR();
7042 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7043
7044 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
7045 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7046
7047 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7048 glEnable(GL_RASTERIZER_DISCARD);
7049 glUseProgram(greenProgram);
7050 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7051 ASSERT_GL_NO_ERROR();
7052 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7053
7054 // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
7055 glDisable(GL_RASTERIZER_DISCARD);
7056 glUseProgram(greenProgram);
7057 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7058 ASSERT_GL_NO_ERROR();
7059 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7060
7061 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7062 glEnable(GL_RASTERIZER_DISCARD);
7063 glUseProgram(blueProgram);
7064 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7065 ASSERT_GL_NO_ERROR();
7066 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7067 }
7068
7069 // Test that early return on binding the same texture is functional
TEST_P(SimpleStateChangeTestES3,BindingSameTexture)7070 TEST_P(SimpleStateChangeTestES3, BindingSameTexture)
7071 {
7072 // Create two 1x1 textures
7073 constexpr GLsizei kSize = 2;
7074 std::array<GLColor, kSize> colors = {GLColor::yellow, GLColor::cyan};
7075
7076 GLTexture tex[kSize];
7077 // Bind texture 0 and 1 to active textures 0 and 1 and set data
7078 glActiveTexture(GL_TEXTURE0);
7079 glBindTexture(GL_TEXTURE_2D, tex[0]);
7080 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[0].data());
7081
7082 glActiveTexture(GL_TEXTURE1);
7083 glBindTexture(GL_TEXTURE_2D, tex[1]);
7084 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[1].data());
7085
7086 // Create simple program and query sampler location
7087 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7088 ASSERT(program.valid());
7089 glUseProgram(program);
7090 GLint textureLocation = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
7091 ASSERT_NE(-1, textureLocation);
7092
7093 // Draw using active texture 0.
7094 glActiveTexture(GL_TEXTURE0);
7095 glUniform1i(textureLocation, 0);
7096 glBindTexture(GL_TEXTURE_2D, tex[0]);
7097 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7098 ASSERT_GL_NO_ERROR();
7099 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7100
7101 // Draw using active texture 1.
7102 glActiveTexture(GL_TEXTURE1);
7103 glUniform1i(textureLocation, 1);
7104 glBindTexture(GL_TEXTURE_2D, tex[1]);
7105 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7106 ASSERT_GL_NO_ERROR();
7107 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7108
7109 // Rebind the same texture to texture unit 1 and expect same color
7110 glBindTexture(GL_TEXTURE_2D, tex[1]);
7111 glUniform1i(textureLocation, 1);
7112 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7113 ASSERT_GL_NO_ERROR();
7114 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7115
7116 // Rebind the same texture to texture unit 0 and expect same color
7117 glActiveTexture(GL_TEXTURE0);
7118 glUniform1i(textureLocation, 0);
7119 glBindTexture(GL_TEXTURE_2D, tex[0]);
7120 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7121 ASSERT_GL_NO_ERROR();
7122 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7123 }
7124
7125 // Test that early return on binding the same sampler is functional
TEST_P(SimpleStateChangeTestES3,BindingSameSampler)7126 TEST_P(SimpleStateChangeTestES3, BindingSameSampler)
7127 {
7128 // Create 2 samplers with different filtering.
7129 constexpr GLsizei kNumSamplers = 2;
7130 GLSampler samplers[kNumSamplers];
7131
7132 // Init sampler0
7133 glBindSampler(0, samplers[0]);
7134 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7135 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7136 ASSERT_GL_NO_ERROR();
7137
7138 // Init sampler1
7139 glBindSampler(1, samplers[1]);
7140 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7141 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7142 ASSERT_GL_NO_ERROR();
7143
7144 // Create a simple 2x1 texture with black and white colors
7145 std::array<GLColor, 2> colors = {{GLColor::black, GLColor::white}};
7146
7147 GLTexture tex;
7148 // Bind the same texture to texture units 0 and 1
7149 glActiveTexture(GL_TEXTURE0);
7150 glBindTexture(GL_TEXTURE_2D, tex);
7151 glActiveTexture(GL_TEXTURE1);
7152 glBindTexture(GL_TEXTURE_2D, tex);
7153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
7154
7155 // Create a program that uses 2 samplers.
7156 constexpr char kFS[] = R"(precision mediump float;
7157 varying vec2 v_texCoord;
7158 uniform sampler2D baseSampler;
7159 uniform sampler2D overrideSampler;
7160 void main()
7161 {
7162 gl_FragColor = texture2D(baseSampler, v_texCoord);
7163 gl_FragColor = texture2D(overrideSampler, v_texCoord);
7164 })";
7165 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
7166 glUseProgram(program);
7167 GLint baseSamplerLoc = glGetUniformLocation(program, "baseSampler");
7168 GLint overrideSamplerLoc = glGetUniformLocation(program, "overrideSampler");
7169
7170 // Bind samplers to texture units 0 and 1
7171 glBindSampler(0, samplers[0]);
7172 glBindSampler(1, samplers[1]);
7173 glUniform1i(baseSamplerLoc, 0);
7174 glUniform1i(overrideSamplerLoc, 1);
7175 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7176 ASSERT_GL_NO_ERROR();
7177 // A gradient should have been rendered since "overrideSampler" has linear filter,
7178 // we should not expect a solid black or white color.
7179 EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::black);
7180 EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::white);
7181
7182 // Switch sampler bindings
7183 glBindSampler(1, samplers[0]);
7184 glBindSampler(0, samplers[1]);
7185 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7186 ASSERT_GL_NO_ERROR();
7187 // Now that "overrideSampler" has nearest filter expect solid colors.
7188 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7189 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7190
7191 // Rebind the same samplers again and expect same output
7192 glBindSampler(1, samplers[0]);
7193 glBindSampler(0, samplers[1]);
7194 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7195 ASSERT_GL_NO_ERROR();
7196 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7197 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7198 }
7199
7200 // Test that early return on binding the same buffer is functional
TEST_P(SimpleStateChangeTestES3,BindingSameBuffer)7201 TEST_P(SimpleStateChangeTestES3, BindingSameBuffer)
7202 {
7203 GLushort indexData[] = {0, 1, 2, 3};
7204
7205 GLBuffer elementArrayBuffer;
7206 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7207 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7208
7209 ANGLE_GL_PROGRAM(program, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
7210 glUseProgram(program);
7211
7212 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7213
7214 std::vector<GLColor> colors0(kWindowSize * kWindowSize);
7215 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors0.data());
7216
7217 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7218 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7219 std::vector<GLColor> colors1(kWindowSize * kWindowSize);
7220 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors1.data());
7221
7222 EXPECT_EQ(colors0, colors1);
7223 }
7224
7225 class ImageRespecificationTest : public ANGLETest<>
7226 {
7227 protected:
ImageRespecificationTest()7228 ImageRespecificationTest()
7229 {
7230 setWindowWidth(128);
7231 setWindowHeight(128);
7232 setConfigRedBits(8);
7233 setConfigGreenBits(8);
7234 setConfigBlueBits(8);
7235 setConfigAlphaBits(8);
7236 setConfigDepthBits(24);
7237 }
7238
testSetUp()7239 void testSetUp() override
7240 {
7241 constexpr char kVS[] = R"(precision highp float;
7242 attribute vec4 position;
7243 varying vec2 texcoord;
7244
7245 void main()
7246 {
7247 gl_Position = position;
7248 texcoord = (position.xy * 0.5) + 0.5;
7249 })";
7250
7251 constexpr char kFS[] = R"(precision highp float;
7252 uniform sampler2D tex;
7253 varying vec2 texcoord;
7254
7255 void main()
7256 {
7257 gl_FragColor = texture2D(tex, texcoord);
7258 })";
7259
7260 mProgram = CompileProgram(kVS, kFS);
7261 ASSERT_NE(0u, mProgram);
7262
7263 mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
7264 ASSERT_NE(-1, mTextureUniformLocation);
7265
7266 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7267 ASSERT_GL_NO_ERROR();
7268 }
7269
testTearDown()7270 void testTearDown() override
7271 {
7272 if (mProgram != 0)
7273 {
7274 glDeleteProgram(mProgram);
7275 }
7276 }
7277
7278 template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)7279 void init2DSourceTexture(GLenum internalFormat,
7280 GLenum dataFormat,
7281 GLenum dataType,
7282 const T *data)
7283 {
7284 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7285 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7286
7287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7289
7290 glBindTexture(GL_TEXTURE_2D, 0);
7291 }
7292
attachTargetTextureToFramebuffer()7293 void attachTargetTextureToFramebuffer()
7294 {
7295 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7296 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
7297 0);
7298
7299 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
7300 ASSERT_GL_NO_ERROR();
7301
7302 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7303 }
7304
renderToTargetTexture()7305 void renderToTargetTexture()
7306 {
7307 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7308
7309 glActiveTexture(GL_TEXTURE0);
7310 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7311
7312 glUseProgram(mProgram);
7313 glUniform1i(mTextureUniformLocation, 0);
7314
7315 drawQuad(mProgram, "position", 0.5f);
7316 ASSERT_GL_NO_ERROR();
7317
7318 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7319 glBindTexture(GL_TEXTURE_2D, 0);
7320 glUseProgram(0);
7321 }
7322
renderToDefaultFramebuffer(GLColor * expectedData)7323 void renderToDefaultFramebuffer(GLColor *expectedData)
7324 {
7325 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7326 glUseProgram(mProgram);
7327 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7328 glUniform1i(mTextureUniformLocation, 0);
7329
7330 glClear(GL_COLOR_BUFFER_BIT);
7331 drawQuad(mProgram, "position", 0.5f);
7332 ASSERT_GL_NO_ERROR();
7333
7334 EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
7335
7336 glBindTexture(GL_TEXTURE_2D, 0);
7337 glUseProgram(0);
7338 }
7339
7340 GLuint mProgram;
7341 GLint mTextureUniformLocation;
7342
7343 GLTexture mSourceTexture;
7344 GLTexture mTargetTexture;
7345
7346 GLFramebuffer mFramebuffer;
7347 };
7348
7349 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)7350 TEST_P(ImageRespecificationTest, Swizzle)
7351 {
7352 GLubyte data[] = {1, 64, 128, 200};
7353 GLColor expectedData(data[0], data[1], data[2], data[3]);
7354
7355 // Create the source and target texture
7356 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7357
7358 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7359 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
7360
7361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7363
7364 glBindTexture(GL_TEXTURE_2D, 0);
7365
7366 // Create a framebuffer and the target texture is attached to the framebuffer.
7367 attachTargetTextureToFramebuffer();
7368
7369 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7370 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7371 glClear(GL_COLOR_BUFFER_BIT);
7372 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7373
7374 // Render content of source texture to target texture
7375 // This command triggers the creation of -
7376 // - draw imageviews of the texture
7377 // - VkFramebuffer object of the framebuffer
7378 renderToTargetTexture();
7379
7380 // This swizzle operation should cause the read imageviews of the texture to be released
7381 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7386 glBindTexture(GL_TEXTURE_2D, 0);
7387
7388 // Draw using the newly created read imageviews
7389 renderToDefaultFramebuffer(&expectedData);
7390
7391 // Render content of source texture to target texture, again
7392 renderToTargetTexture();
7393
7394 // Make sure the content rendered to target texture is correct
7395 renderToDefaultFramebuffer(&expectedData);
7396 }
7397
7398 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
7399 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)7400 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
7401 {
7402 // This is the specific problem on the Vulkan backend and needs some extensions
7403 ANGLE_SKIP_TEST_IF(
7404 !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
7405 !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
7406
7407 GLubyte data[] = {1, 64, 128, 200};
7408 GLColor expectedData(data[0], data[1], data[2], data[3]);
7409
7410 // Create the source texture
7411 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7412
7413 // Create the first EGL image to attach the framebuffer through the texture
7414 GLTexture firstTexture;
7415
7416 glBindTexture(GL_TEXTURE_2D, firstTexture);
7417 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7418
7419 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7421
7422 glBindTexture(GL_TEXTURE_2D, 0);
7423
7424 EGLWindow *window = getEGLWindow();
7425 EGLint attribs[] = {
7426 EGL_IMAGE_PRESERVED,
7427 EGL_TRUE,
7428 EGL_NONE,
7429 };
7430 EGLImageKHR firstEGLImage = eglCreateImageKHR(
7431 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7432 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(firstTexture)), attribs);
7433 ASSERT_EGL_SUCCESS();
7434
7435 // Create the target texture and attach it to the framebuffer
7436 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7437 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7438
7439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7441
7442 glBindTexture(GL_TEXTURE_2D, 0);
7443
7444 attachTargetTextureToFramebuffer();
7445
7446 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7447
7448 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7449 glClear(GL_COLOR_BUFFER_BIT);
7450
7451 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7452
7453 // Render content of source texture to target texture
7454 // This command triggers the creation of -
7455 // - draw imageviews of the texture
7456 // - VkFramebuffer object of the framebuffer
7457 renderToTargetTexture();
7458
7459 // Make sure the content rendered to target texture is correct
7460 renderToDefaultFramebuffer(&expectedData);
7461
7462 // Create the second EGL image
7463 GLTexture secondTexture;
7464
7465 glBindTexture(GL_TEXTURE_2D, secondTexture);
7466 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7467
7468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7470
7471 glBindTexture(GL_TEXTURE_2D, 0);
7472
7473 EGLImageKHR secondEGLImage = eglCreateImageKHR(
7474 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7475 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(secondTexture)), attribs);
7476 ASSERT_EGL_SUCCESS();
7477
7478 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7479 // This will release all the imageviews related to the first EGL image
7480 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
7481
7482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7484
7485 glBindTexture(GL_TEXTURE_2D, 0);
7486
7487 // Attach the first EGL image to the target texture again
7488 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7489 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7490
7491 // This is for checking this code can deal with the problem even if both ORPHAN and
7492 // COLOR_ATTACHMENT dirty bits are set.
7493 GLTexture tempTexture;
7494
7495 glBindTexture(GL_TEXTURE_2D, tempTexture);
7496 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7497
7498 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7500
7501 glBindTexture(GL_TEXTURE_2D, 0);
7502
7503 // This sets COLOR_ATTACHMENT dirty bit
7504 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7505 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
7506 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7507
7508 // The released imageviews related to "secondEGLImage" will be garbage collected
7509 renderToDefaultFramebuffer(&expectedData);
7510
7511 // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
7512 renderToTargetTexture();
7513
7514 // Make sure the content rendered to target texture is correct
7515 renderToDefaultFramebuffer(&expectedData);
7516
7517 // Render content of source texture to target texture
7518 attachTargetTextureToFramebuffer();
7519 renderToTargetTexture();
7520
7521 // Make sure the content rendered to target texture is correct
7522 renderToDefaultFramebuffer(&expectedData);
7523
7524 eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
7525 eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
7526 }
7527
7528 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)7529 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
7530 {
7531 GLushort indexData[] = {0, 1, 2, 3};
7532
7533 GLBuffer elementArrayBuffer;
7534 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7535 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7536
7537 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7538 glUseProgram(program);
7539
7540 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7541
7542 elementArrayBuffer.reset();
7543
7544 // Must use a non-0 offset and a multiple of the type size.
7545 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
7546 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7547 }
7548
7549 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)7550 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
7551 {
7552 // SwiftShader does not currently support robustness.
7553 ANGLE_SKIP_TEST_IF(isSwiftshader());
7554
7555 // http://anglebug.com/42263447
7556 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
7557
7558 // no intent to follow up on this failure.
7559 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7560
7561 // no intent to follow up on this failure.
7562 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
7563
7564 // no intent to follow up on this failure.
7565 ANGLE_SKIP_TEST_IF(IsMac());
7566
7567 // Mali does not support robustness now.
7568 ANGLE_SKIP_TEST_IF(IsARM());
7569
7570 std::vector<GLubyte> data(48, 1);
7571
7572 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7573 glUseProgram(program);
7574
7575 // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
7576 GLBuffer arrayBuffer;
7577 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
7578 glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
7579 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
7580 glEnableVertexAttribArray(0);
7581 glDrawArrays(GL_TRIANGLES, 0, 3);
7582
7583 // Then bind a zero size buffer and draw.
7584 GLBuffer secondBuffer;
7585 glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
7586 glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
7587 glDrawArrays(GL_TRIANGLES, 0, 3);
7588
7589 // Finally delete the original buffer. This triggers the bug.
7590 arrayBuffer.reset();
7591 glDrawArrays(GL_TRIANGLES, 0, 3);
7592 ASSERT_GL_NO_ERROR();
7593 }
7594
7595 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)7596 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
7597 {
7598 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7599
7600 glUseProgram(program);
7601
7602 // Draw with empty buffer. Out of range but valid.
7603 GLBuffer buffer;
7604 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7605 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
7606
7607 // Switch VAO. No buffer bound, should be an error.
7608 GLVertexArray vao;
7609 glBindVertexArray(vao);
7610 glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
7611 reinterpret_cast<const GLvoid *>(0x1000));
7612 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7613 }
7614
7615 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
7616 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)7617 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
7618 {
7619 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7620 // bit.
7621 GLBuffer indexBuffer;
7622 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7623
7624 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7625 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7626
7627 // Setup vertices.
7628 const std::array<GLfloat, 6> kVertices = {
7629 -1, -1, 3, -1, -1, 3,
7630 };
7631 GLBuffer vertexBuffer;
7632 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7633 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7634 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7635 glEnableVertexAttribArray(0);
7636
7637 // Create a uniform buffer that will get modified. This is used to break the render pass.
7638 const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
7639
7640 GLBuffer ubo;
7641 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
7642 glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
7643 glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
7644
7645 // Set up a program. The same program is used for all draw calls to avoid state change due to
7646 // program change.
7647 constexpr char kFS[] = R"(#version 300 es
7648 precision mediump float;
7649 uniform block { uint data; } ubo;
7650 uniform highp uint expect;
7651 uniform vec4 successColor;
7652 out vec4 colorOut;
7653 void main()
7654 {
7655 colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
7656 })";
7657
7658 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7659 glUseProgram(program);
7660
7661 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7662 const GLint expectLoc = glGetUniformLocation(program, "expect");
7663 const GLint successLoc = glGetUniformLocation(program, "successColor");
7664 ASSERT_NE(-1, positionLoc);
7665 ASSERT_NE(-1, expectLoc);
7666 ASSERT_NE(-1, successLoc);
7667
7668 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7669 glEnableVertexAttribArray(positionLoc);
7670
7671 glUniform1ui(expectLoc, kUboData1[0]);
7672 glUniform4f(successLoc, 0, 0, 0, 1);
7673 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7674 EXPECT_GL_NO_ERROR();
7675
7676 // Then upload data to the UBO so on next use the render pass has to break. This draw call is
7677 // not indexed.
7678 constexpr GLuint kUboData2 = 0x87654321u;
7679 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
7680
7681 glEnable(GL_BLEND);
7682 glBlendFunc(GL_ONE, GL_ONE);
7683 glUniform1ui(expectLoc, kUboData2);
7684 glUniform4f(successLoc, 0, 1, 0, 0);
7685 glDrawArrays(GL_TRIANGLES, 0, 3);
7686
7687 // Issue another draw call that is indexed. The index buffer should be bound correctly on the
7688 // new render pass.
7689 glUniform4f(successLoc, 0, 0, 1, 0);
7690 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7691 EXPECT_GL_NO_ERROR();
7692
7693 // Ensure correct rendering.
7694 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7695 }
7696
7697 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)7698 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
7699 {
7700 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7701 glClearColor(0, 0, 0, 1);
7702 glClear(GL_COLOR_BUFFER_BIT);
7703 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7704
7705 GLFramebuffer fbo;
7706 GLTexture texture;
7707
7708 glBindTexture(GL_TEXTURE_2D, texture);
7709 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7710 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7711 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7712
7713 glClear(GL_COLOR_BUFFER_BIT);
7714 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7715
7716 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7717
7718 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7719 // bit.
7720 GLBuffer indexBuffer;
7721 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7722
7723 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7724 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7725
7726 // Setup vertices.
7727 const std::array<GLfloat, 6> kVertices = {
7728 -1, -1, 3, -1, -1, 3,
7729 };
7730 GLBuffer vertexBuffer;
7731 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7732 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7733 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7734 glEnableVertexAttribArray(0);
7735
7736 // Set up a program. The same program is used for all draw calls to avoid state change due to
7737 // program change.
7738 constexpr char kFS[] = R"(#version 300 es
7739 precision mediump float;
7740 uniform vec4 colorIn;
7741 out vec4 colorOut;
7742 void main()
7743 {
7744 colorOut = colorIn;
7745 })";
7746
7747 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7748 glUseProgram(program);
7749
7750 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7751 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
7752 ASSERT_NE(-1, positionLoc);
7753 ASSERT_NE(-1, colorLoc);
7754
7755 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7756 glEnableVertexAttribArray(positionLoc);
7757
7758 glUniform4f(colorLoc, 1, 0, 0, 1);
7759 glEnable(GL_BLEND);
7760 glBlendFunc(GL_ONE, GL_ONE);
7761 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7762 EXPECT_GL_NO_ERROR();
7763
7764 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7765 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7766 glUniform4f(colorLoc, 0, 1, 0, 0);
7767 glDrawArrays(GL_TRIANGLES, 0, 3);
7768
7769 glUniform4f(colorLoc, 0, 0, 1, 0);
7770 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7771 EXPECT_GL_NO_ERROR();
7772
7773 // Ensure correct rendering.
7774 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7775
7776 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7777 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7778 }
7779
7780 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
7781 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)7782 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
7783 {
7784 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7785 glClearColor(0, 0, 0, 1);
7786 glClear(GL_COLOR_BUFFER_BIT);
7787 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7788
7789 GLFramebuffer fbo;
7790 GLTexture texture;
7791
7792 glBindTexture(GL_TEXTURE_2D, texture);
7793 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7794 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7795 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7796
7797 glClear(GL_COLOR_BUFFER_BIT);
7798 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7799
7800 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7801
7802 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7803 // bit.
7804 GLBuffer indexBuffer;
7805 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7806
7807 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7808 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7809
7810 // Setup vertices.
7811 const std::array<GLfloat, 6> kVertices = {
7812 -1, -1, 3, -1, -1, 3,
7813 };
7814 GLBuffer vertexBuffer;
7815 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7816 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7817 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7818 glEnableVertexAttribArray(0);
7819
7820 // Set up a program. The same program is used for all draw calls to avoid state change due to
7821 // program change.
7822 constexpr char kFS[] = R"(#version 300 es
7823 precision mediump float;
7824 uniform vec4 colorIn;
7825 out vec4 colorOut;
7826 void main()
7827 {
7828 colorOut = colorIn;
7829 })";
7830
7831 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7832 glUseProgram(program);
7833
7834 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7835 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
7836 ASSERT_NE(-1, positionLoc);
7837 ASSERT_NE(-1, colorLoc);
7838
7839 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7840 glEnableVertexAttribArray(positionLoc);
7841
7842 glUniform4f(colorLoc, 0, 0, 0, 1);
7843 glEnable(GL_BLEND);
7844 glBlendFunc(GL_ONE, GL_ONE);
7845 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7846 EXPECT_GL_NO_ERROR();
7847
7848 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7849 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7850 glUniform4f(colorLoc, 0, 1, 0, 0);
7851 glDrawArrays(GL_TRIANGLES, 0, 3);
7852
7853 // In between the two calls, make sure the first render pass is submitted, so the primary
7854 // command buffer is reset.
7855 {
7856 EGLWindow *window = getEGLWindow();
7857 EGLDisplay dpy = window->getDisplay();
7858 EGLConfig config = window->getConfig();
7859 EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
7860 EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
7861 EGLContext ctx = window->createContext(EGL_NO_CONTEXT, nullptr);
7862 EXPECT_EGL_SUCCESS();
7863 std::thread flushThread = std::thread([&]() {
7864 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
7865 EXPECT_EGL_SUCCESS();
7866
7867 glClearColor(1, 0, 0, 1);
7868 glClear(GL_COLOR_BUFFER_BIT);
7869 EXPECT_GL_NO_ERROR();
7870
7871 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7872 });
7873 flushThread.join();
7874
7875 eglDestroySurface(dpy, surface);
7876 eglDestroyContext(dpy, ctx);
7877 }
7878
7879 glUniform4f(colorLoc, 0, 0, 1, 0);
7880 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7881 EXPECT_GL_NO_ERROR();
7882
7883 // Ensure correct rendering.
7884 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7885 }
7886
7887 // Negative test for EXT_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxEXTNegativeTest)7888 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxEXTNegativeTest)
7889 {
7890 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_primitive_bounding_box"));
7891
7892 glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7893 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7894
7895 GLfloat boundingBox[8] = {0};
7896 glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, boundingBox);
7897 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7898 }
7899
7900 // Negative test for OES_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxOESNegativeTest)7901 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxOESNegativeTest)
7902 {
7903 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_OES_primitive_bounding_box"));
7904
7905 glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7906 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7907
7908 GLfloat boundingBox[8] = {0};
7909 glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_OES, boundingBox);
7910 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7911 }
7912
7913 // Update an element array buffer that is already in use.
TEST_P(SimpleStateChangeTest,UpdateBoundElementArrayBuffer)7914 TEST_P(SimpleStateChangeTest, UpdateBoundElementArrayBuffer)
7915 {
7916 constexpr char kVS[] = R"(attribute vec4 position;
7917 attribute float color;
7918 varying float colorVarying;
7919 void main()
7920 {
7921 gl_Position = position;
7922 colorVarying = color;
7923 })";
7924
7925 constexpr char kFS[] = R"(precision mediump float;
7926 varying float colorVarying;
7927 void main()
7928 {
7929 if (colorVarying == 1.0)
7930 {
7931 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
7932 }
7933 else
7934 {
7935 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
7936 }
7937 })";
7938
7939 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
7940 glUseProgram(testProgram);
7941
7942 GLint posLoc = glGetAttribLocation(testProgram, "position");
7943 ASSERT_NE(-1, posLoc);
7944 GLint colorLoc = glGetAttribLocation(testProgram, "color");
7945 ASSERT_NE(-1, colorLoc);
7946
7947 std::array<GLushort, 6> quadIndices = GetQuadIndices();
7948
7949 std::vector<GLubyte> indices;
7950 for (GLushort index : quadIndices)
7951 {
7952 indices.push_back(static_cast<GLubyte>(index));
7953 }
7954
7955 GLBuffer indexBuffer;
7956 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7957 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), indices.data(),
7958 GL_STATIC_DRAW);
7959
7960 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
7961
7962 std::vector<Vector3> positionVertices;
7963 for (Vector3 vertex : quadVertices)
7964 {
7965 positionVertices.push_back(vertex);
7966 }
7967 for (Vector3 vertex : quadVertices)
7968 {
7969 positionVertices.push_back(vertex);
7970 }
7971
7972 GLBuffer positionVertexBuffer;
7973 glBindBuffer(GL_ARRAY_BUFFER, positionVertexBuffer);
7974 glBufferData(GL_ARRAY_BUFFER, positionVertices.size() * sizeof(positionVertices[0]),
7975 positionVertices.data(), GL_STATIC_DRAW);
7976 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
7977 glEnableVertexAttribArray(posLoc);
7978
7979 std::vector<float> colorVertices = {1, 1, 1, 1, 0, 0, 0, 0};
7980
7981 GLBuffer colorVertexBuffer;
7982 glBindBuffer(GL_ARRAY_BUFFER, colorVertexBuffer);
7983 glBufferData(GL_ARRAY_BUFFER, colorVertices.size() * sizeof(colorVertices[0]),
7984 colorVertices.data(), GL_STATIC_DRAW);
7985 glVertexAttribPointer(colorLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
7986 glEnableVertexAttribArray(colorLoc);
7987
7988 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7989 ASSERT_GL_NO_ERROR();
7990 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7991
7992 indices.clear();
7993 for (GLushort index : quadIndices)
7994 {
7995 indices.push_back(static_cast<GLubyte>(index + 4));
7996 }
7997 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(indices[0]),
7998 indices.data());
7999
8000 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
8001 ASSERT_GL_NO_ERROR();
8002 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8003 }
8004
8005 // Covers a bug where we would use a stale cache variable in the Vulkan back-end.
TEST_P(SimpleStateChangeTestES3,DeleteFramebufferBeforeQuery)8006 TEST_P(SimpleStateChangeTestES3, DeleteFramebufferBeforeQuery)
8007 {
8008 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
8009 glUseProgram(testProgram);
8010
8011 GLFramebuffer fbo;
8012 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8013
8014 GLRenderbuffer rbo;
8015 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
8016
8017 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, 16, 16);
8018 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
8019
8020 GLfloat floatArray[] = {1, 2, 3, 4};
8021
8022 GLBuffer buffer;
8023 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8024 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLfloat) * 4, floatArray, GL_DYNAMIC_COPY);
8025 glDrawElements(GL_TRIANGLE_FAN, 5, GL_UNSIGNED_SHORT, 0);
8026
8027 fbo.reset();
8028
8029 GLQuery query2;
8030 glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, query2);
8031
8032 ASSERT_GL_NO_ERROR();
8033 }
8034
8035 // Covers an edge case
TEST_P(SimpleStateChangeTestES3,TextureTypeConflictAfterDraw)8036 TEST_P(SimpleStateChangeTestES3, TextureTypeConflictAfterDraw)
8037 {
8038 constexpr char kVS[] = R"(precision highp float;
8039 attribute vec4 a_position;
8040 void main()
8041 {
8042 gl_Position = a_position;
8043 }
8044 )";
8045
8046 constexpr char kFS[] = R"(precision highp float;
8047 uniform sampler2D u_2d1;
8048 uniform samplerCube u_Cube1;
8049 void main()
8050 {
8051 gl_FragColor = texture2D(u_2d1, vec2(0.0, 0.0)) + textureCube(u_Cube1, vec3(0.0, 0.0, 0.0));
8052 }
8053 )";
8054
8055 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
8056 glUseProgram(testProgram);
8057
8058 GLTexture texture;
8059 glBindTexture(GL_TEXTURE_2D, texture);
8060 glTexStorage2D(GL_TEXTURE_2D, 4, GL_SRGB8, 1268, 614);
8061
8062 GLint uniformloc = glGetUniformLocation(testProgram, "u_Cube1");
8063 ASSERT_NE(-1, uniformloc);
8064 glUniform1i(uniformloc, 1);
8065
8066 glDrawArrays(GL_POINTS, 0, 1);
8067 ASSERT_GL_NO_ERROR();
8068
8069 // Trigger the state update.
8070 glLinkProgram(testProgram);
8071 texture.reset();
8072
8073 // The texture types are now conflicting, and draws should fail.
8074 glDrawArrays(GL_POINTS, 0, 1);
8075 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8076 }
8077
8078 // Regression test for a bug where a mutable texture is used with non-zero base level then rebased
8079 // to zero but made incomplete and attached to the framebuffer. The texture's image is not
8080 // recreated with level 0, leading to errors when drawing to the framebuffer.
TEST_P(SimpleStateChangeTestES3,NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)8081 TEST_P(SimpleStateChangeTestES3, NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)
8082 {
8083 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8084 glUseProgram(program);
8085
8086 const std::array<GLColor, 4> kMip0Data = {GLColor::red, GLColor::red, GLColor::red,
8087 GLColor::red};
8088 const std::array<GLColor, 2> kMip1Data = {GLColor::green, GLColor::green};
8089
8090 // Create two textures.
8091 GLTexture immutableTex;
8092 glBindTexture(GL_TEXTURE_2D, immutableTex);
8093 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
8094 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data.data());
8095
8096 GLTexture mutableTex;
8097 glBindTexture(GL_TEXTURE_2D, mutableTex);
8098 for (uint32_t mip = 0; mip < 2; ++mip)
8099 {
8100 const uint32_t size = 4 >> mip;
8101 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8102 mip == 0 ? kMip0Data.data() : kMip1Data.data());
8103 }
8104
8105 GLFramebuffer fbo;
8106 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8107
8108 // Sample from the mutable texture at non-zero base level.
8109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
8110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8111
8112 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, immutableTex, 0);
8113 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8114 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[0]);
8115
8116 // Rebase the mutable texture to zero, but enable mipmapping which makes it incomplete.
8117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
8119
8120 // Remove feedback loop for good measure.
8121 glBindTexture(GL_TEXTURE_2D, immutableTex);
8122
8123 // Draw into base zero of the texture.
8124 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutableTex, 0);
8125 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8126
8127 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[1]);
8128 ASSERT_GL_NO_ERROR();
8129 }
8130
8131 // Regression test for a bug where the framebuffer binding was not synced during invalidate when a
8132 // clear operation was deferred.
TEST_P(SimpleStateChangeTestES3,ChangeFramebufferThenInvalidateWithClear)8133 TEST_P(SimpleStateChangeTestES3, ChangeFramebufferThenInvalidateWithClear)
8134 {
8135 // Clear the default framebuffer.
8136 glClear(GL_COLOR_BUFFER_BIT);
8137
8138 // Start rendering to another framebuffer
8139 GLFramebuffer fbo;
8140 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8141
8142 GLRenderbuffer rbo;
8143 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
8144 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
8145 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
8146
8147 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
8148 glUseProgram(program);
8149 glDrawArrays(GL_TRIANGLES, 0, 3);
8150
8151 // Switch back to the default framebuffer
8152 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8153
8154 // Invalidate it. Don't invalidate color, as that's the one being cleared.
8155 constexpr GLenum kAttachment = GL_DEPTH;
8156 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8157 EXPECT_GL_NO_ERROR();
8158 }
8159
8160 // Test that clear / invalidate / clear works. The invalidate is for a target that's not cleared.
8161 // Regression test for a bug where invalidate() would start a render pass to perform the first
8162 // clear, while the second clear didn't expect a render pass opened without any draw calls in it.
TEST_P(SimpleStateChangeTestES3,ClearColorInvalidateDepthClearColor)8163 TEST_P(SimpleStateChangeTestES3, ClearColorInvalidateDepthClearColor)
8164 {
8165 // Clear color.
8166 glClear(GL_COLOR_BUFFER_BIT);
8167
8168 // Invalidate depth.
8169 constexpr GLenum kAttachment = GL_DEPTH;
8170 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8171 EXPECT_GL_NO_ERROR();
8172
8173 // Clear color again.
8174 glClear(GL_COLOR_BUFFER_BIT);
8175 ASSERT_GL_NO_ERROR();
8176 }
8177
8178 // Regression test for a bug where glInvalidateFramebuffer(GL_FRAMEBUFFER, ...) was invalidating
8179 // both the draw and read framebuffers.
TEST_P(SimpleStateChangeTestES3,InvalidateFramebufferShouldntInvalidateReadFramebuffer)8180 TEST_P(SimpleStateChangeTestES3, InvalidateFramebufferShouldntInvalidateReadFramebuffer)
8181 {
8182 // Create an invalid read framebuffer.
8183 GLFramebuffer fbo;
8184 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8185
8186 GLTexture tex;
8187 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
8188 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, 1, 1, 1);
8189 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, tex, 0, 5);
8190
8191 // Invalidate using GL_FRAMEBUFFER. If GL_READ_FRAMEBUFFER was used, validation would fail due
8192 // to the framebuffer not being complete. A bug here was attempting to invalidate the read
8193 // framebuffer given GL_FRAMEBUFFER anyway.
8194 constexpr std::array<GLenum, 2> kAttachments = {GL_DEPTH, GL_STENCIL};
8195 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, kAttachments.data());
8196 EXPECT_GL_NO_ERROR();
8197 }
8198
8199 // Test that respecifies a buffer after we start XFB.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedback)8200 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback)
8201 {
8202 std::vector<std::string> tfVaryings = {"gl_Position"};
8203 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8204 essl3_shaders::fs::Green(), tfVaryings,
8205 GL_INTERLEAVED_ATTRIBS);
8206
8207 glUseProgram(testProgram);
8208 GLBuffer buffer;
8209 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8210 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8211 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8212 glBeginTransformFeedback(GL_TRIANGLES);
8213 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8214 glDrawArrays(GL_TRIANGLES, 0, 6);
8215 glEndTransformFeedback();
8216 }
8217
8218 // Test a bug angleproject:6998 in TransformFeedback code path by allocating paddingBuffer first and
8219 // then allocate another buffer and then deallocate paddingBuffer and then allocate buffer again.
8220 // This new buffer will be allocated in the space where paddingBuffer was allocated which causing
8221 // XFB generate VVL error.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)8222 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)
8223 {
8224 std::vector<std::string> tfVaryings = {"gl_Position"};
8225 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8226 essl3_shaders::fs::Green(), tfVaryings,
8227 GL_INTERLEAVED_ATTRIBS);
8228 glUseProgram(testProgram);
8229
8230 GLuint paddingBuffer;
8231 glGenBuffers(1, &paddingBuffer);
8232 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, paddingBuffer);
8233 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 256, nullptr, GL_STREAM_DRAW);
8234
8235 GLBuffer buffer;
8236 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8237 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8238 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8239 // Delete padding buffer, expecting the next bufferData call will reuse the space of
8240 // paddingBuffer whose offset is smaller than buffer's offset, which triggers the bug.
8241 glDeleteBuffers(1, &paddingBuffer);
8242 glBeginTransformFeedback(GL_TRIANGLES);
8243 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8244 glDrawArrays(GL_TRIANGLES, 0, 6);
8245 glEndTransformFeedback();
8246 }
8247
8248 // Regression test for a bug in the Vulkan backend where a draw-based copy after a deferred flush
8249 // would lead to an image view being destroyed too early.
TEST_P(SimpleStateChangeTestES3,DrawFlushThenCopyTexImage)8250 TEST_P(SimpleStateChangeTestES3, DrawFlushThenCopyTexImage)
8251 {
8252 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8253
8254 // Issue a cheap draw call and a flush
8255 glEnable(GL_SCISSOR_TEST);
8256 glScissor(0, 0, 1, 1);
8257 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8258 glDisable(GL_SCISSOR_TEST);
8259 glFlush();
8260
8261 constexpr GLsizei kSize = 32;
8262
8263 // Then an expensive copy tex image
8264 GLTexture texture;
8265 glBindTexture(GL_TEXTURE_3D, texture);
8266 glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGB8, kSize, kSize, kSize);
8267 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, kSize, kSize);
8268 glFlush();
8269 ASSERT_GL_NO_ERROR();
8270 }
8271
TEST_P(SimpleStateChangeTestES3,DrawFlushThenBlit)8272 TEST_P(SimpleStateChangeTestES3, DrawFlushThenBlit)
8273 {
8274 constexpr GLsizei kSize = 256;
8275 const std::vector<GLColor> data(kSize * kSize, GLColor::red);
8276
8277 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8278
8279 GLFramebuffer fbo;
8280 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8281
8282 GLTexture readColor;
8283 glBindTexture(GL_TEXTURE_2D, readColor);
8284 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8285 data.data());
8286 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readColor, 0);
8287
8288 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8289
8290 // Issue a cheap draw call and a flush
8291 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8292 glEnable(GL_SCISSOR_TEST);
8293 glScissor(0, 0, 1, 1);
8294 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8295 glDisable(GL_SCISSOR_TEST);
8296 glFlush();
8297
8298 // Then an expensive blit
8299 glBlitFramebuffer(0, 0, kSize, kSize, kSize + 2, kSize, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
8300 glFlush();
8301 ASSERT_GL_NO_ERROR();
8302 }
8303
8304 class VertexAttribArrayStateChangeTest : public ANGLETest<>
8305 {
8306 protected:
VertexAttribArrayStateChangeTest()8307 VertexAttribArrayStateChangeTest()
8308 {
8309 setWindowWidth(128);
8310 setWindowHeight(128);
8311 setConfigRedBits(8);
8312 setConfigGreenBits(8);
8313 setConfigBlueBits(8);
8314 setConfigAlphaBits(8);
8315 setConfigDepthBits(24);
8316 }
8317
testSetUp()8318 void testSetUp() override
8319 {
8320 constexpr char kVS[] = R"(precision highp float;
8321 attribute vec4 position;
8322 attribute vec4 color;
8323 varying vec4 colorOut;
8324
8325 void main()
8326 {
8327 gl_Position = position;
8328 colorOut = color;
8329 })";
8330
8331 constexpr char kFS[] = R"(precision highp float;
8332 varying vec4 colorOut;
8333
8334 void main()
8335 {
8336 gl_FragColor = colorOut;
8337 })";
8338
8339 mProgram = CompileProgram(kVS, kFS);
8340 ASSERT_NE(0u, mProgram);
8341
8342 mPosAttribLocation = glGetAttribLocation(mProgram, "position");
8343 ASSERT_NE(-1, mPosAttribLocation);
8344 mColorAttribLocation = glGetAttribLocation(mProgram, "color");
8345 ASSERT_NE(-1, mColorAttribLocation);
8346
8347 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
8348 ASSERT_GL_NO_ERROR();
8349
8350 glGenBuffers(1, &mVertexBuffer);
8351 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8352
8353 const float posAttribData[] = {
8354 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8355 };
8356 glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8357
8358 glBindBuffer(GL_ARRAY_BUFFER, 0);
8359 }
8360
testTearDown()8361 void testTearDown() override
8362 {
8363 if (mVertexBuffer != 0)
8364 {
8365 glDeleteBuffers(1, &mVertexBuffer);
8366 }
8367
8368 if (mProgram != 0)
8369 {
8370 glDeleteProgram(mProgram);
8371 }
8372 }
8373
8374 GLuint mProgram;
8375 GLint mPosAttribLocation;
8376 GLint mColorAttribLocation;
8377 GLuint mVertexBuffer;
8378 };
8379
TEST_P(VertexAttribArrayStateChangeTest,Basic)8380 TEST_P(VertexAttribArrayStateChangeTest, Basic)
8381 {
8382 glUseProgram(mProgram);
8383 glClear(GL_COLOR_BUFFER_BIT);
8384 glDisable(GL_DEPTH_TEST);
8385 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8386
8387 glVertexAttribPointer(mPosAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8388 glEnableVertexAttribArray(mPosAttribLocation);
8389 glDisableVertexAttribArray(mColorAttribLocation);
8390 glVertexAttrib4f(mColorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8391 // Don't try to verify the color of this draw as red here because it might
8392 // hide the bug
8393 glDrawArrays(GL_TRIANGLES, 0, 6);
8394 glVertexAttrib4f(mColorAttribLocation, 0.0f, 1.0f, 0.0f, 1.0f);
8395 glDrawArrays(GL_TRIANGLES, 0, 6);
8396 ASSERT_GL_NO_ERROR();
8397 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8398
8399 glUseProgram(0);
8400 glBindBuffer(GL_ARRAY_BUFFER, 0);
8401 }
8402
TEST_P(SimpleStateChangeTestES3,DepthOnlyToColorAttachmentPreservesBlendState)8403 TEST_P(SimpleStateChangeTestES3, DepthOnlyToColorAttachmentPreservesBlendState)
8404 {
8405
8406 constexpr char kVS[] = R"(precision highp float;
8407 attribute vec4 position;
8408 attribute vec4 color;
8409 varying vec4 colorOut;
8410
8411 void main()
8412 {
8413 gl_Position = position;
8414 colorOut = color;
8415 })";
8416
8417 constexpr char kFS[] = R"(precision highp float;
8418 varying vec4 colorOut;
8419
8420 void main()
8421 {
8422 gl_FragColor = colorOut;
8423 })";
8424
8425 ANGLE_GL_PROGRAM(program, kVS, kFS);
8426
8427 GLint posAttribLocation = glGetAttribLocation(program, "position");
8428 ASSERT_NE(-1, posAttribLocation);
8429 GLint colorAttribLocation = glGetAttribLocation(program, "color");
8430 ASSERT_NE(-1, colorAttribLocation);
8431
8432 GLBuffer vertexBuffer;
8433 GLTexture texture;
8434 GLFramebuffer framebuffer;
8435 GLRenderbuffer depthRenderbuffer;
8436 GLFramebuffer depthFramebuffer;
8437
8438 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8439
8440 const float posAttribData[] = {
8441 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8442 };
8443 glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8444
8445 glBindBuffer(GL_ARRAY_BUFFER, 0);
8446
8447 constexpr int kWidth = 1;
8448 constexpr int kHeight = 1;
8449
8450 glBindTexture(GL_TEXTURE_2D, texture);
8451 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
8452 glBindTexture(GL_TEXTURE_2D, 0);
8453
8454 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8455 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8456 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8457
8458 glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
8459 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
8460 glBindRenderbuffer(GL_RENDERBUFFER, 0);
8461
8462 glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8463 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
8464 depthRenderbuffer);
8465 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8466
8467 glDisable(GL_DEPTH_TEST);
8468 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8469 glVertexAttribPointer(posAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8470 glEnableVertexAttribArray(posAttribLocation);
8471 glDisableVertexAttribArray(colorAttribLocation);
8472 glVertexAttrib4f(colorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8473
8474 glUseProgram(program);
8475 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8476 glEnable(GL_BLEND);
8477 glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
8478 glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
8479 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8480 glClear(GL_COLOR_BUFFER_BIT);
8481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8482
8483 glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8484 glDrawArrays(GL_TRIANGLES, 0, 6);
8485
8486 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8487 glDrawArrays(GL_TRIANGLES, 0, 6);
8488 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
8489
8490 glBindBuffer(GL_ARRAY_BUFFER, 0);
8491 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8492 glUseProgram(0);
8493 }
8494
8495 // Tests a bug where we wouldn't update our cached base/max levels in Vulkan.
TEST_P(SimpleStateChangeTestES3,MaxLevelChange)8496 TEST_P(SimpleStateChangeTestES3, MaxLevelChange)
8497 {
8498 // Initialize an immutable texture with 2 levels.
8499 std::vector<GLColor> bluePixels(4, GLColor::blue);
8500
8501 GLTexture tex;
8502 glBindTexture(GL_TEXTURE_2D, tex);
8503 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8506 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2);
8507 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, bluePixels.data());
8508 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::yellow);
8509
8510 // Set up draw resources.
8511 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8512 glUseProgram(testProgram);
8513
8514 GLint posLoc = glGetAttribLocation(testProgram, essl1_shaders::PositionAttrib());
8515 ASSERT_NE(-1, posLoc);
8516
8517 std::array<Vector3, 6> quadVerts = GetQuadVertices();
8518
8519 GLBuffer vao;
8520 glBindBuffer(GL_ARRAY_BUFFER, vao);
8521 glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
8522 GL_STATIC_DRAW);
8523 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
8524 glEnableVertexAttribArray(posLoc);
8525
8526 ASSERT_GL_NO_ERROR();
8527
8528 // Draw with the 2x2 mip / max level 1.
8529 glViewport(0, 0, 2, 2);
8530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8531 glDrawArrays(GL_TRIANGLES, 0, 6);
8532
8533 // Draw with the 1x1 mip / max level 2.
8534 glViewport(2, 0, 1, 1);
8535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8536 glDrawArrays(GL_TRIANGLES, 0, 6);
8537
8538 // Draw with the 2x2 mip / max level 1.
8539 glViewport(0, 2, 2, 2);
8540 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8541 glDrawArrays(GL_TRIANGLES, 0, 6);
8542
8543 // Draw with the 1x1 mip / max level 2.
8544 glViewport(2, 2, 1, 1);
8545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8546 glDrawArrays(GL_TRIANGLES, 0, 6);
8547
8548 ASSERT_GL_NO_ERROR();
8549
8550 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8551 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::yellow);
8552 EXPECT_PIXEL_COLOR_EQ(0, 2, GLColor::blue);
8553 EXPECT_PIXEL_COLOR_EQ(2, 2, GLColor::yellow);
8554 }
8555
8556 // Tests a bug when removing an element array buffer bound to two vertex arrays.
TEST_P(SimpleStateChangeTestES3,DeleteDoubleBoundBufferAndVertexArray)8557 TEST_P(SimpleStateChangeTestES3, DeleteDoubleBoundBufferAndVertexArray)
8558 {
8559 std::vector<uint8_t> bufData(100, 0);
8560 GLBuffer buffer;
8561 GLVertexArray vao;
8562
8563 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8564 glBindVertexArray(vao);
8565 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8566 buffer.reset();
8567 vao.reset();
8568
8569 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8570 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8571 ASSERT_GL_NO_ERROR();
8572 }
8573
8574 // Tests state change for glLineWidth.
TEST_P(StateChangeTestES3,LineWidth)8575 TEST_P(StateChangeTestES3, LineWidth)
8576 {
8577 // According to the spec, the minimum value for the line width range limits is one.
8578 GLfloat range[2] = {1};
8579 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8580 EXPECT_GL_NO_ERROR();
8581 EXPECT_GE(range[0], 1.0f);
8582 EXPECT_GE(range[1], 1.0f);
8583
8584 ANGLE_SKIP_TEST_IF(range[1] < 5.0);
8585
8586 constexpr char kVS[] = R"(#version 300 es
8587 precision highp float;
8588 uniform float height;
8589 void main()
8590 {
8591 gl_Position = vec4(gl_VertexID == 0 ? -1 : 1, height * 2. - 1., 0, 1);
8592 })";
8593
8594 constexpr char kFS[] = R"(#version 300 es
8595 precision highp float;
8596 out vec4 colorOut;
8597 uniform vec4 color;
8598 void main()
8599 {
8600 colorOut = color;
8601 })";
8602
8603 ANGLE_GL_PROGRAM(program, kVS, kFS);
8604 glUseProgram(program);
8605
8606 GLint heightLoc = glGetUniformLocation(program, "height");
8607 GLint colorLoc = glGetUniformLocation(program, "color");
8608 ASSERT_NE(-1, heightLoc);
8609 ASSERT_NE(-1, colorLoc);
8610
8611 glClearColor(0, 0, 0, 1);
8612 glClear(GL_COLOR_BUFFER_BIT);
8613
8614 const int w = getWindowWidth();
8615 const int h = getWindowHeight();
8616 const float halfPixelHeight = 0.5 / h;
8617
8618 glUniform1f(heightLoc, 0.25f + halfPixelHeight);
8619 glUniform4f(colorLoc, 1, 0, 0, 1);
8620 glLineWidth(3);
8621 glDrawArrays(GL_LINES, 0, 2);
8622
8623 glUniform1f(heightLoc, 0.5f + halfPixelHeight);
8624 glUniform4f(colorLoc, 0, 1, 0, 1);
8625 glLineWidth(5);
8626 glDrawArrays(GL_LINES, 0, 2);
8627
8628 glUniform1f(heightLoc, 0.75f + halfPixelHeight);
8629 glUniform4f(colorLoc, 0, 0, 1, 1);
8630 glLineWidth(1);
8631 glDrawArrays(GL_LINES, 0, 2);
8632
8633 EXPECT_PIXEL_RECT_EQ(0, h / 4 - 2, w, 1, GLColor::black);
8634 EXPECT_PIXEL_RECT_EQ(0, h / 4 - 1, w, 3, GLColor::red);
8635 EXPECT_PIXEL_RECT_EQ(0, h / 4 + 2, w, 1, GLColor::black);
8636
8637 EXPECT_PIXEL_RECT_EQ(0, h / 2 - 3, w, 1, GLColor::black);
8638 EXPECT_PIXEL_RECT_EQ(0, h / 2 - 2, w, 5, GLColor::green);
8639 EXPECT_PIXEL_RECT_EQ(0, h / 2 + 3, w, 1, GLColor::black);
8640
8641 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 - 1, w, 1, GLColor::black);
8642 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4, w, 1, GLColor::blue);
8643 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 + 1, w, 1, GLColor::black);
8644
8645 ASSERT_GL_NO_ERROR();
8646 }
8647
8648 // Tests state change for out-of-range value for glLineWidth. The expectation
8649 // here is primarily that rendering backends do not crash with invalid line
8650 // width values.
TEST_P(StateChangeTestES3,LineWidthOutOfRangeDoesntCrash)8651 TEST_P(StateChangeTestES3, LineWidthOutOfRangeDoesntCrash)
8652 {
8653 GLfloat range[2] = {1};
8654 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8655 EXPECT_GL_NO_ERROR();
8656
8657 constexpr char kVS[] = R"(#version 300 es
8658 precision highp float;
8659 void main()
8660 {
8661 gl_Position = vec4(gl_VertexID == 0 ? -1.0 : 1.0, -1.0, 0.0, 1.0);
8662 })";
8663
8664 constexpr char kFS[] = R"(#version 300 es
8665 precision highp float;
8666 out vec4 colorOut;
8667 void main()
8668 {
8669 colorOut = vec4(1.0);
8670 })";
8671
8672 ANGLE_GL_PROGRAM(program, kVS, kFS);
8673 glUseProgram(program);
8674
8675 glClearColor(0, 0, 0, 1);
8676 glClear(GL_COLOR_BUFFER_BIT);
8677
8678 glLineWidth(range[1] + 1.0f);
8679 glDrawArrays(GL_LINES, 0, 2);
8680
8681 glFinish();
8682
8683 ASSERT_GL_NO_ERROR();
8684 }
8685
8686 // Tests state change for glPolygonOffset.
TEST_P(StateChangeTestES3,PolygonOffset)8687 TEST_P(StateChangeTestES3, PolygonOffset)
8688 {
8689 constexpr char kVS[] = R"(#version 300 es
8690 precision highp float;
8691 void main()
8692 {
8693 // gl_VertexID x y
8694 // 0 -1 -1
8695 // 1 1 -1
8696 // 2 -1 1
8697 // 3 1 1
8698 int bit0 = gl_VertexID & 1;
8699 int bit1 = gl_VertexID >> 1;
8700 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8701 })";
8702
8703 constexpr char kFS[] = R"(#version 300 es
8704 precision highp float;
8705 out vec4 colorOut;
8706 uniform vec4 color;
8707 void main()
8708 {
8709 colorOut = color;
8710 })";
8711
8712 glEnable(GL_POLYGON_OFFSET_FILL);
8713
8714 ANGLE_GL_PROGRAM(program, kVS, kFS);
8715 glUseProgram(program);
8716
8717 GLint colorLoc = glGetUniformLocation(program, "color");
8718 ASSERT_NE(-1, colorLoc);
8719
8720 glClearColor(0, 0, 0, 1);
8721 glClearDepthf(0);
8722 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8723
8724 glEnable(GL_DEPTH_TEST);
8725 glDepthFunc(GL_ALWAYS);
8726
8727 // The shader creates a depth slope from left (0) to right (1).
8728 //
8729 // This test issues three draw calls:
8730 //
8731 // Draw 2 (green): factor width/2, offset 0, depth test: Greater
8732 // ^ | __________________
8733 // | | __/__/ __/
8734 // | V __/__/ __/ <--- Draw 1 (red): factor width/4, offset 0
8735 // | __/__/ ^ __/
8736 // | __/__/ _|/
8737 // |/__/ __/ |
8738 // |/ __/ |
8739 // | __/ Draw 3 (blue): factor width/2, offset -2, depth test: Less
8740 // |/
8741 // |
8742 // |
8743 // +------------------------------->
8744 //
8745 // Result: <----blue-----><-green-><--red-->
8746
8747 const int w = getWindowWidth();
8748 const int h = getWindowHeight();
8749
8750 glUniform4f(colorLoc, 1, 0, 0, 1);
8751 glPolygonOffset(getWindowWidth() / 4, 0);
8752 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8753
8754 glUniform4f(colorLoc, 0, 1, 0, 1);
8755 glPolygonOffset(getWindowWidth() / 2, 0);
8756 glDepthFunc(GL_GREATER);
8757 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8758
8759 glUniform4f(colorLoc, 0, 0, 1, 1);
8760 glPolygonOffset(getWindowWidth() / 2, -2);
8761 glDepthFunc(GL_LESS);
8762 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8763
8764 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::blue);
8765 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 4 - 1, h, GLColor::green);
8766 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8767
8768 ASSERT_GL_NO_ERROR();
8769 }
8770
8771 // Tests state change for glPolygonOffsetClampEXT.
TEST_P(StateChangeTestES3,PolygonOffsetClamp)8772 TEST_P(StateChangeTestES3, PolygonOffsetClamp)
8773 {
8774 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_polygon_offset_clamp"));
8775
8776 constexpr char kVS[] = R"(#version 300 es
8777 precision highp float;
8778 void main()
8779 {
8780 // gl_VertexID x y
8781 // 0 -1 -1
8782 // 1 1 -1
8783 // 2 -1 1
8784 // 3 1 1
8785 int bit0 = gl_VertexID & 1;
8786 int bit1 = gl_VertexID >> 1;
8787 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8788 })";
8789
8790 constexpr char kFS[] = R"(#version 300 es
8791 precision highp float;
8792 out vec4 colorOut;
8793 uniform vec4 color;
8794 void main()
8795 {
8796 colorOut = color;
8797 })";
8798
8799 glEnable(GL_POLYGON_OFFSET_FILL);
8800
8801 ANGLE_GL_PROGRAM(program, kVS, kFS);
8802 glUseProgram(program);
8803
8804 GLint colorLoc = glGetUniformLocation(program, "color");
8805 ASSERT_NE(-1, colorLoc);
8806
8807 glClearColor(0, 0, 0, 1);
8808 glClearDepthf(0);
8809 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8810
8811 glEnable(GL_DEPTH_TEST);
8812 glDepthFunc(GL_ALWAYS);
8813
8814 // The shader creates a depth slope from left (0) to right (1).
8815 //
8816 // This test issues two draw calls:
8817 //
8818 // Draw 2 (green): factor width, offset 0, clamp 0.5, depth test: Greater
8819 // ^ | __________________
8820 // | | __/ __/
8821 // | V __/ __/ <--- Draw 1 (red): factor width, offset 0, clamp 0.25
8822 // | __/ __/
8823 // | __/ __/
8824 // |/ __/
8825 // | __/
8826 // | __/
8827 // |/
8828 // |
8829 // |
8830 // +------------------------------->
8831 //
8832 // Result: <---------green--------><--red-->
8833
8834 const int w = getWindowWidth();
8835 const int h = getWindowHeight();
8836
8837 glUniform4f(colorLoc, 1, 0, 0, 1);
8838 glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.25);
8839 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8840
8841 glUniform4f(colorLoc, 0, 1, 0, 1);
8842 glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.5);
8843 glDepthFunc(GL_GREATER);
8844 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8845
8846 EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::green);
8847 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8848
8849 ASSERT_GL_NO_ERROR();
8850 }
8851
8852 // Tests state change for glBlendColor.
TEST_P(StateChangeTestES3,BlendColor)8853 TEST_P(StateChangeTestES3, BlendColor)
8854 {
8855 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8856 glUseProgram(program);
8857
8858 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8859 ASSERT_NE(colorLoc, -1);
8860
8861 glEnable(GL_BLEND);
8862 glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);
8863 glBlendColor(0.498, 0.498, 0, 1);
8864 glUniform4f(colorLoc, 1, 1, 1, 1);
8865 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8866
8867 const int w = getWindowWidth();
8868 const int h = getWindowHeight();
8869
8870 glEnable(GL_SCISSOR_TEST);
8871 glScissor(0, 0, w / 2, h);
8872 glBlendColor(0, 1, 0.498, 1);
8873 glUniform4f(colorLoc, 1, 0.247, 1, 1);
8874 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8875
8876 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor(0, 63, 127, 255));
8877 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor(127, 127, 0, 255));
8878
8879 ASSERT_GL_NO_ERROR();
8880 }
8881
8882 // Tests state change for ref and mask in glStencilFuncSeparate.
TEST_P(StateChangeTestES3,StencilReferenceAndCompareMask)8883 TEST_P(StateChangeTestES3, StencilReferenceAndCompareMask)
8884 {
8885 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8886 glUseProgram(program);
8887
8888 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8889 ASSERT_NE(colorLoc, -1);
8890
8891 glClearColor(0, 0, 0, 1);
8892 glClearStencil(0x3A);
8893 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8894
8895 glEnable(GL_STENCIL_TEST);
8896
8897 glStencilMaskSeparate(GL_FRONT, 0xF0);
8898 glStencilMaskSeparate(GL_BACK, 0x0F);
8899
8900 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0xB9, 0x7C);
8901 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8902
8903 glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x99, 0xAC);
8904 glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_KEEP);
8905
8906 const int w = getWindowWidth();
8907 const int h = getWindowHeight();
8908
8909 // Draw front-facing. Front stencil test should pass, replacing the top bits with 0xB:
8910 //
8911 // Current value of stencil buffer: 0x3A, mask: 0x7C, writing 0xB9
8912 //
8913 // B9 & 7C == 38 == 3A & 7C
8914 glUniform4f(colorLoc, 1, 0, 0, 1);
8915 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8916
8917 // Draw back-facing. Back stencil test should fail, replacing the bottom bits with 0x9:
8918 //
8919 // Current value of stencil buffer: 0xBA, mask: 0xAC, writing 0x99
8920 //
8921 // 99 & AC == 88 != A8 == BA & AC
8922 glFrontFace(GL_CW);
8923 glDisable(GL_CULL_FACE);
8924 glEnable(GL_SCISSOR_TEST);
8925 glScissor(0, 0, w / 2, h);
8926 glUniform4f(colorLoc, 0, 1, 0, 1);
8927 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8928
8929 // The left half of image should now have a value of B9, the right half should have BA
8930 //
8931 // Change the masks such that if the old masks are used, stencil test would fail, but if the new
8932 // mask is used it would pass.
8933 //
8934 // Left: B9 & 7C == 38 != 3C == 3D & 7C
8935 // B9 & 33 == 31 == 3D & 33
8936 //
8937 // Right: BA & AC == A8 != 28 == 3A & AC
8938 // BA & 59 == 18 == 3A & 59
8939 //
8940 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x3D, 0x33);
8941 glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x3A, 0x59);
8942 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
8943 glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
8944
8945 glScissor(0, 0, w, h / 2);
8946
8947 // Draw front-facing, coloring the top-left
8948 glUniform4f(colorLoc, 1, 1, 0, 1);
8949 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8950 glFrontFace(GL_CCW);
8951 glUniform4f(colorLoc, 0, 0, 1, 1);
8952 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8953
8954 // Verify results
8955 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
8956 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
8957 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
8958 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::red);
8959
8960 // Verify stencil exactly
8961 glDisable(GL_SCISSOR_TEST);
8962 glStencilFunc(GL_EQUAL, 0xB9, 0xFF);
8963 glUniform4f(colorLoc, 0, 1, 1, 1);
8964 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8965
8966 glStencilFunc(GL_EQUAL, 0xBA, 0xFF);
8967 glUniform4f(colorLoc, 1, 0, 1, 1);
8968 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8969
8970 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::cyan);
8971 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
8972
8973 ASSERT_GL_NO_ERROR();
8974 }
8975
8976 // Tests state change for mask in glStencilMaskSeparate.
TEST_P(StateChangeTestES3,StencilWriteMask)8977 TEST_P(StateChangeTestES3, StencilWriteMask)
8978 {
8979 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8980 glUseProgram(program);
8981
8982 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8983 ASSERT_NE(colorLoc, -1);
8984
8985 glClearColor(0, 0, 0, 1);
8986 glClearStencil(0x00);
8987 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8988
8989 glEnable(GL_STENCIL_TEST);
8990
8991 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8992 glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_REPLACE);
8993
8994 const int w = getWindowWidth();
8995 const int h = getWindowHeight();
8996
8997 // Draw front-facing to the left half, replacing the top four bits, and back-facing to the right
8998 // half, replacing the bottom four bits.
8999 glStencilMaskSeparate(GL_FRONT, 0xF0);
9000 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x39, 0xFF);
9001 glStencilMaskSeparate(GL_BACK, 0x0F);
9002 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x2A, 0xFF);
9003
9004 glEnable(GL_SCISSOR_TEST);
9005 glScissor(0, 0, w / 2, h);
9006 glUniform4f(colorLoc, 1, 0, 0, 1);
9007 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9008
9009 glDisable(GL_CULL_FACE);
9010 glFrontFace(GL_CW);
9011 glScissor(w / 2, 0, w / 2, h);
9012 glUniform4f(colorLoc, 0, 1, 0, 1);
9013 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9014
9015 // Draw back-facing to the top-left quarter, replacing the top two bits, and front-facing to the
9016 // top-right quarter, replacing the bottom two bits.
9017 glStencilMaskSeparate(GL_FRONT, 0xC0);
9018 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x81, 0xFF);
9019 glStencilMaskSeparate(GL_BACK, 0x03);
9020 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x53, 0xFF);
9021
9022 glScissor(0, 0, w / 2, h / 2);
9023 glUniform4f(colorLoc, 0, 0, 1, 1);
9024 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9025
9026 glFrontFace(GL_CCW);
9027 glScissor(w / 2, 0, w / 2, h / 2);
9028 glUniform4f(colorLoc, 1, 1, 0, 1);
9029 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9030
9031 // Verify results
9032 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
9033 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9034 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
9035 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
9036
9037 // Verify stencil exactly. Stencil has the following values:
9038 //
9039 // +------+------+
9040 // | | |
9041 // | 33 | 8A |
9042 // | | |
9043 // +------+------+
9044 // | | |
9045 // | 30 | 0A |
9046 // | | |
9047 // +------+------+
9048 //
9049 glDisable(GL_SCISSOR_TEST);
9050 glStencilFunc(GL_EQUAL, 0x33, 0xFF);
9051 glUniform4f(colorLoc, 0, 1, 1, 1);
9052 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9053
9054 glStencilFunc(GL_EQUAL, 0x8A, 0xFF);
9055 glUniform4f(colorLoc, 1, 0, 1, 1);
9056 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9057
9058 glStencilFunc(GL_EQUAL, 0x30, 0xFF);
9059 glUniform4f(colorLoc, 1, 1, 1, 1);
9060 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9061
9062 glStencilFunc(GL_EQUAL, 0x0A, 0xFF);
9063 glUniform4f(colorLoc, 0, 0, 0, 1);
9064 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9065
9066 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9067 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9068 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9069 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9070
9071 ASSERT_GL_NO_ERROR();
9072 }
9073
9074 // Tests that |discard| works with stencil write mask
TEST_P(StateChangeTestES3,StencilWriteMaskVsDiscard)9075 TEST_P(StateChangeTestES3, StencilWriteMaskVsDiscard)
9076 {
9077 constexpr char kVS[] = R"(#version 300 es
9078 precision highp float;
9079 void main()
9080 {
9081 // gl_VertexID x y
9082 // 0 -1 -1
9083 // 1 1 -1
9084 // 2 -1 1
9085 // 3 1 1
9086 int bit0 = gl_VertexID & 1;
9087 int bit1 = gl_VertexID >> 1;
9088 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
9089 })";
9090
9091 constexpr char kFS[] = R"(#version 300 es
9092 precision highp float;
9093 out vec4 colorOut;
9094 uniform vec4 color;
9095 uniform int flag;
9096 void main()
9097 {
9098 if (flag > 0)
9099 {
9100 discard;
9101 }
9102 colorOut = color;
9103 })";
9104
9105 ANGLE_GL_PROGRAM(program, kVS, kFS);
9106 glUseProgram(program);
9107
9108 GLint colorLoc = glGetUniformLocation(program, "color");
9109 ASSERT_NE(colorLoc, -1);
9110
9111 GLint flagLoc = glGetUniformLocation(program, "flag");
9112 ASSERT_NE(flagLoc, -1);
9113
9114 glEnable(GL_DEPTH_TEST);
9115
9116 glClearColor(0, 0, 0, 1);
9117 glClearDepthf(1);
9118 glClearStencil(0x00);
9119 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9120
9121 glDepthFunc(GL_LEQUAL);
9122 glDepthMask(GL_FALSE);
9123 glEnable(GL_STENCIL_TEST);
9124
9125 // Enable stencil write, but issue a draw call where all fragments are discarded.
9126 glStencilFunc(GL_ALWAYS, 128, 128);
9127 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
9128 glStencilMask(128);
9129
9130 glUniform4f(colorLoc, 1, 0, 0, 1);
9131 glUniform1i(flagLoc, 1);
9132 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9133
9134 // At this point, the stencil buffer should be unmodified. Verify it with another draw call.
9135 glStencilFunc(GL_NOTEQUAL, 128, 128);
9136 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9137 glStencilMask(128);
9138
9139 glUniform4f(colorLoc, 0, 1, 0, 1);
9140 glUniform1i(flagLoc, 0);
9141 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9142
9143 const int w = getWindowWidth();
9144 const int h = getWindowHeight();
9145
9146 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9147
9148 ASSERT_GL_NO_ERROR();
9149 }
9150
9151 // Tests state change for glCullFace and glEnable(GL_CULL_FACE) as well as glFrontFace
TEST_P(StateChangeTestES3,CullFaceAndFrontFace)9152 TEST_P(StateChangeTestES3, CullFaceAndFrontFace)
9153 {
9154 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9155 glUseProgram(program);
9156
9157 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9158 ASSERT_NE(colorLoc, -1);
9159
9160 glClearColor(0, 0, 0, 1);
9161 glClear(GL_COLOR_BUFFER_BIT);
9162
9163 const int w = getWindowWidth();
9164 const int h = getWindowHeight();
9165
9166 // Draw red back-facing. Face culling is initially disabled
9167 glFrontFace(GL_CW);
9168 glUniform4f(colorLoc, 1, 0, 0, 1);
9169 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9170
9171 // Draw green back-facing, but enable face culling. Default cull face is back.
9172 glEnable(GL_CULL_FACE);
9173 glEnable(GL_SCISSOR_TEST);
9174 glScissor(0, 0, w / 2, h / 2);
9175 glUniform4f(colorLoc, 0, 1, 0, 1);
9176 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9177
9178 // Draw blue front-facing.
9179 glFrontFace(GL_CCW);
9180 glScissor(w / 2, 0, w / 2, h / 2);
9181 glUniform4f(colorLoc, 0, 0, 1, 1);
9182 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9183
9184 // Draw magenta front-facing, but change cull face to front
9185 glCullFace(GL_FRONT);
9186 glScissor(0, h / 2, w / 2, h / 2);
9187 glUniform4f(colorLoc, 1, 0, 1, 1);
9188 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9189
9190 // Draw cyan front-facing, with face culling disabled
9191 glDisable(GL_CULL_FACE);
9192 glScissor(w / 2, h / 2, w / 2, h / 2);
9193 glUniform4f(colorLoc, 0, 1, 1, 1);
9194 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9195
9196 // Draw yellow front-facing, with cull face set to front and back
9197 glEnable(GL_CULL_FACE);
9198 glCullFace(GL_FRONT_AND_BACK);
9199 glDisable(GL_SCISSOR_TEST);
9200 glUniform4f(colorLoc, 1, 1, 0, 1);
9201 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9202
9203 // Verify results
9204 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9205 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9206 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
9207 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9208
9209 ASSERT_GL_NO_ERROR();
9210 }
9211
9212 // Tests state change for draw primitive mode
TEST_P(StateChangeTestES3,PrimitiveMode)9213 TEST_P(StateChangeTestES3, PrimitiveMode)
9214 {
9215 constexpr char kVS[] = R"(#version 300 es
9216 precision highp float;
9217
9218 // Hardcoded positions for a number of draw modes, using different vertex offsets.
9219 const vec2 kVertices[35] = vec2[35](
9220 // Two triangle
9221 vec2(-1, -1), vec2(1, -1), vec2(-1, 1),
9222 vec2(-1, 1), vec2(1, -1), vec2( 1, 1),
9223 // A triangle strip with 8 triangles
9224 vec2( -1, -0.5), vec2( -1, 0.5),
9225 vec2(-0.75, -0.5), vec2(-0.75, 0.5),
9226 vec2( -0.5, -0.5), vec2( -0.5, 0.5),
9227 vec2(-0.25, -0.5), vec2(-0.25, 0.5),
9228 vec2( 0, -0.5), vec2( 0, 0.5),
9229 // A triangle fan with 4 triangles
9230 vec2(0.5, 0), vec2(1, -0.5), vec2(1, 0.5), vec2(0, 0.5), vec2(0, -0.5), vec2(1, -0.5),
9231 // One line
9232 vec2(-1, -0.49), vec2(1, -0.49),
9233 // One line strip
9234 vec2(-1, 0.51), vec2(0, 0.51), vec2(1, 0.51),
9235 // One line loop
9236 vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99),
9237 // Four points
9238 vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99)
9239 );
9240
9241 void main()
9242 {
9243 gl_Position = vec4(kVertices[gl_VertexID], 0, 1);
9244 gl_PointSize = 1.;
9245 })";
9246
9247 constexpr char kFS[] = R"(#version 300 es
9248 precision highp float;
9249 out vec4 colorOut;
9250 uniform vec4 color;
9251 void main()
9252 {
9253 colorOut = color;
9254 })";
9255
9256 ANGLE_GL_PROGRAM(program, kVS, kFS);
9257 glUseProgram(program);
9258
9259 GLint colorLoc = glGetUniformLocation(program, "color");
9260 ASSERT_NE(colorLoc, -1);
9261
9262 glClearColor(0, 0, 0, 1);
9263 glClear(GL_COLOR_BUFFER_BIT);
9264
9265 // Draw the following:
9266 //
9267 // 1. Red with two triangles
9268 // 2. Green with a triangle strip
9269 // 3. Blue with a triangle fan
9270 // 4. Yellow with a line
9271 // 5. Cyan with a line strip
9272 // 6. Magenta with a line loop
9273 // 7. White with four points
9274 //
9275 //
9276 // +---------------------------+ <-- 7: corners
9277 // | |
9278 // | 1 |
9279 // | |
9280 // +-------------+-------------+ <-- 5: horizontal line
9281 // | | |
9282 // | | |
9283 // | | |
9284 // | 2 | 3 | <-- 6: border around image
9285 // | | |
9286 // | | |
9287 // | | |
9288 // +-------------+-------------+ <-- 4: horizontal line
9289 // | |
9290 // | 1 |
9291 // | |
9292 // +---------------------------+
9293
9294 glUniform4f(colorLoc, 1, 0, 0, 1);
9295 glDrawArrays(GL_TRIANGLES, 0, 6);
9296
9297 glUniform4f(colorLoc, 0, 1, 0, 1);
9298 glDrawArrays(GL_TRIANGLE_STRIP, 6, 10);
9299
9300 glUniform4f(colorLoc, 0, 0, 1, 1);
9301 glDrawArrays(GL_TRIANGLE_FAN, 16, 6);
9302
9303 glUniform4f(colorLoc, 1, 1, 0, 1);
9304 glDrawArrays(GL_LINES, 22, 2);
9305
9306 glUniform4f(colorLoc, 0, 1, 1, 1);
9307 glDrawArrays(GL_LINE_STRIP, 24, 3);
9308
9309 glUniform4f(colorLoc, 1, 0, 1, 1);
9310 glDrawArrays(GL_LINE_LOOP, 27, 4);
9311
9312 glUniform4f(colorLoc, 1, 1, 1, 1);
9313 glDrawArrays(GL_POINTS, 31, 4);
9314
9315 const int w = getWindowWidth();
9316 const int h = getWindowHeight();
9317
9318 // Verify results
9319 EXPECT_PIXEL_RECT_EQ(1, 1, w - 2, h / 4 - 2, GLColor::red);
9320 EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4 + 1, w - 2, h / 4 - 2, GLColor::red);
9321
9322 EXPECT_PIXEL_RECT_EQ(1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::green);
9323
9324 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::blue);
9325
9326 EXPECT_PIXEL_RECT_EQ(1, h / 4, w / 2 - 2, 1, GLColor::yellow);
9327
9328 EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4, w / 2 - 2, 1, GLColor::cyan);
9329
9330 EXPECT_PIXEL_RECT_EQ(1, 0, w - 2, 1, GLColor::magenta);
9331 EXPECT_PIXEL_RECT_EQ(0, 1, 1, h - 2, GLColor::magenta);
9332 EXPECT_PIXEL_RECT_EQ(w - 1, 1, 1, h - 2, GLColor::magenta);
9333 EXPECT_PIXEL_RECT_EQ(1, h - 1, w - 2, 1, GLColor::magenta);
9334
9335 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
9336 EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::white);
9337 EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::white);
9338 EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::white);
9339
9340 ASSERT_GL_NO_ERROR();
9341 }
9342
9343 // Tests that vertex attributes are correctly bound after a masked clear. In the Vulkan backend,
9344 // the masked clear is done with an internal shader that doesn't use vertex attributes.
TEST_P(StateChangeTestES3,DrawMaskedClearDraw)9345 TEST_P(StateChangeTestES3, DrawMaskedClearDraw)
9346 {
9347 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9348 glUseProgram(program);
9349
9350 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9351 ASSERT_NE(colorLoc, -1);
9352
9353 GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
9354 ASSERT_EQ(0, posAttrib);
9355
9356 std::array<GLfloat, 3 * 4> positionData = {
9357 -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9358 };
9359
9360 GLBuffer posBuffer;
9361 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9362 glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9363 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9364 glEnableVertexAttribArray(posAttrib);
9365
9366 const int w = getWindowWidth();
9367 const int h = getWindowHeight();
9368
9369 glClearColor(0, 0, 0, 1);
9370 glClear(GL_COLOR_BUFFER_BIT);
9371
9372 glEnable(GL_BLEND);
9373 glBlendFunc(GL_ONE, GL_ONE);
9374
9375 // Draw to red and alpha channels, with garbage in green and blue
9376 glUniform4f(colorLoc, 1, 0.123f, 0.456f, 0.5f);
9377 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9378
9379 // Clear the green and blue channels
9380 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
9381 glClearColor(0.333f, 0.5, 0, 0.888f);
9382 glClear(GL_COLOR_BUFFER_BIT);
9383
9384 // Blend in to saturate green and alpha
9385 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9386 glUniform4f(colorLoc, 0, 0.6f, 0, 0.6f);
9387 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9388
9389 // Verify results
9390 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::yellow);
9391
9392 ASSERT_GL_NO_ERROR();
9393 }
9394
9395 // Tests state change for vertex attribute stride
TEST_P(StateChangeTestES3,VertexStride)9396 TEST_P(StateChangeTestES3, VertexStride)
9397 {
9398 constexpr char kVS[] =
9399 R"(#version 300 es
9400 precision mediump float;
9401 in vec4 position;
9402 layout(location = 1) in vec4 test;
9403 layout(location = 5) in vec4 expected;
9404 out vec4 result;
9405 void main(void)
9406 {
9407 gl_Position = position;
9408 if (any(equal(test, vec4(0))) || any(equal(expected, vec4(0))))
9409 {
9410 result = vec4(0);
9411 }
9412 else
9413 {
9414 vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
9415 result = vec4(lessThanEqual(abs(test - expected), threshold));
9416 }
9417 })";
9418
9419 constexpr char kFS[] =
9420 R"(#version 300 es
9421 precision mediump float;
9422 in vec4 result;
9423 out vec4 colorOut;
9424 void main()
9425 {
9426 colorOut = vec4(greaterThanEqual(result, vec4(0.999)));
9427 })";
9428
9429 ANGLE_GL_PROGRAM(program, kVS, kFS);
9430 glUseProgram(program);
9431
9432 // Every draw call consists of 4 vertices. The vertex attributes are laid out as follows:
9433 //
9434 // Position: No gaps
9435 // test: 4 unorm vertices with stride 20, simultaneously 4 vertices with stride 16
9436 // expected: 4 float vertices with stride 80, simultaneously 4 vertices with stride 48
9437
9438 const std::array<GLubyte, 7 * 4> kData = {{1, 2, 3, 4, 5, 6, 7, 8, 125, 126,
9439 127, 128, 129, 250, 251, 252, 78, 79, 80, 81,
9440 155, 156, 157, 158, 20, 21, 22, 23}};
9441
9442 constexpr size_t kTestStride1 = 20;
9443 constexpr size_t kTestStride2 = 16;
9444 constexpr size_t kExpectedStride1 = 20;
9445 constexpr size_t kExpectedStride2 = 12;
9446
9447 std::array<GLubyte, kTestStride1 * 3 + 4> testInitData = {};
9448 std::array<GLfloat, kExpectedStride1 * 3 + 4> expectedInitData = {};
9449
9450 for (uint32_t vertex = 0; vertex < 7; ++vertex)
9451 {
9452 size_t testOffset = vertex * kTestStride1;
9453 size_t expectedOffset = vertex * kExpectedStride1;
9454 if (vertex >= 4)
9455 {
9456 testOffset = (vertex - 3) * kTestStride2;
9457 expectedOffset = (vertex - 3) * kExpectedStride2;
9458 }
9459
9460 for (uint32_t channel = 0; channel < 4; ++channel)
9461 {
9462 // The strides are chosen such that the two streams don't collide
9463 ASSERT_EQ(testInitData[testOffset + channel], 0);
9464 ASSERT_EQ(expectedInitData[expectedOffset + channel], 0);
9465
9466 GLubyte data = kData[vertex * 4 + channel];
9467 testInitData[testOffset + channel] = data;
9468 expectedInitData[expectedOffset + channel] = data;
9469 }
9470
9471 // For the first 4 vertices, expect perfect match (i.e. get white). For the last 3
9472 // vertices, expect the green channel test to fail (i.e. get magenta).
9473 if (vertex >= 4)
9474 {
9475 expectedInitData[expectedOffset + 1] += 2;
9476 }
9477 }
9478
9479 std::array<GLfloat, 3 * 4> positionData = {
9480 -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9481 };
9482
9483 GLBuffer posBuffer;
9484 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9485 glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9486
9487 GLBuffer testBuffer;
9488 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9489 glBufferData(GL_ARRAY_BUFFER, sizeof(testInitData), testInitData.data(), GL_STATIC_DRAW);
9490
9491 GLBuffer expectedBuffer;
9492 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9493 glBufferData(GL_ARRAY_BUFFER, sizeof(expectedInitData), expectedInitData.data(),
9494 GL_STATIC_DRAW);
9495
9496 GLint posAttrib = glGetAttribLocation(program, "position");
9497 ASSERT_EQ(0, posAttrib);
9498 GLint testAttrib = glGetAttribLocation(program, "test");
9499 ASSERT_EQ(1, testAttrib);
9500 GLint expectedAttrib = glGetAttribLocation(program, "expected");
9501 ASSERT_EQ(5, expectedAttrib);
9502
9503 const int w = getWindowWidth();
9504 const int h = getWindowHeight();
9505
9506 glClearColor(0, 0, 0, 1);
9507 glClear(GL_COLOR_BUFFER_BIT);
9508
9509 glEnableVertexAttribArray(posAttrib);
9510 glEnableVertexAttribArray(testAttrib);
9511 glEnableVertexAttribArray(expectedAttrib);
9512
9513 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9514 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9515 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9516 glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride1 * sizeof(GLubyte),
9517 nullptr);
9518 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9519 glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride1 * sizeof(GLfloat),
9520 nullptr);
9521
9522 glEnable(GL_SCISSOR_TEST);
9523 glScissor(0, 0, w / 2, h);
9524 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9525
9526 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9527 glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride2 * sizeof(GLubyte),
9528 nullptr);
9529 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9530 glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride2 * sizeof(GLfloat),
9531 nullptr);
9532
9533 glScissor(w / 2, 0, w / 2, h);
9534 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9535
9536 // Verify results
9537 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::white);
9538 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
9539
9540 ASSERT_GL_NO_ERROR();
9541 }
9542
9543 // Tests state change for vertex attribute format
TEST_P(StateChangeTestES3,VertexFormat)9544 TEST_P(StateChangeTestES3, VertexFormat)
9545 {
9546 constexpr char kVS[] = R"(precision highp float;
9547 attribute vec3 position;
9548 attribute vec4 color;
9549 varying vec4 colorOut;
9550
9551 void main()
9552 {
9553 gl_Position = vec4(position, 1.0);
9554 colorOut = color;
9555 })";
9556
9557 constexpr char kFS[] = R"(precision highp float;
9558 varying vec4 colorOut;
9559
9560 void main()
9561 {
9562 gl_FragColor = colorOut;
9563 })";
9564
9565 ANGLE_GL_PROGRAM(program, kVS, kFS);
9566 glUseProgram(program);
9567
9568 GLint positionLoc = glGetAttribLocation(program, "position");
9569 ASSERT_NE(positionLoc, -1);
9570 GLint colorLoc = glGetAttribLocation(program, "color");
9571 ASSERT_NE(colorLoc, -1);
9572
9573 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
9574 glClear(GL_COLOR_BUFFER_BIT);
9575
9576 std::vector<Vector4> colorAttribDataFloat(6, Vector4(255.0f, 0.0f, 0.0f, 255.0f));
9577 std::vector<GLColor> colorAttribDataUnsignedByte(6, GLColor::green);
9578
9579 // Setup position attribute
9580 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9581 GLBuffer vertexLocationBuffer;
9582 glBindBuffer(GL_ARRAY_BUFFER, vertexLocationBuffer);
9583 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
9584 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
9585 glEnableVertexAttribArray(positionLoc);
9586
9587 // Setup color attribute with float data
9588 GLBuffer floatBuffer;
9589 glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
9590 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector4) * 6, colorAttribDataFloat.data(), GL_STATIC_DRAW);
9591 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
9592 glEnableVertexAttribArray(colorLoc);
9593
9594 // Draw red using float attribute
9595 glDrawArrays(GL_TRIANGLES, 0, 6);
9596 ASSERT_GL_NO_ERROR();
9597 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9598
9599 // Setup color attribute with unsigned byte data
9600 GLBuffer unsignedByteBuffer;
9601 glBindBuffer(GL_ARRAY_BUFFER, unsignedByteBuffer);
9602 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, colorAttribDataUnsignedByte.data(),
9603 GL_STATIC_DRAW);
9604 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
9605 glEnableVertexAttribArray(colorLoc);
9606
9607 // Draw green using unsigned byte attribute
9608 glDrawArrays(GL_TRIANGLES, 0, 6);
9609 ASSERT_GL_NO_ERROR();
9610 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9611
9612 glUseProgram(0);
9613 glBindBuffer(GL_ARRAY_BUFFER, 0);
9614 }
9615
9616 // Tests state change for depth test, write and function
TEST_P(StateChangeTestES3,DepthTestWriteAndFunc)9617 TEST_P(StateChangeTestES3, DepthTestWriteAndFunc)
9618 {
9619 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9620 glUseProgram(program);
9621
9622 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9623 ASSERT_NE(colorLoc, -1);
9624
9625 const int w = getWindowWidth();
9626 const int h = getWindowHeight();
9627
9628 glClearColor(0, 0, 0, 1);
9629 glClearDepthf(0.5);
9630 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9631
9632 // Initialize the depth buffer:
9633 glEnable(GL_DEPTH_TEST);
9634 glDepthMask(GL_TRUE);
9635 glDepthFunc(GL_ALWAYS);
9636
9637 glEnable(GL_SCISSOR_TEST);
9638 glScissor(0, 0, w / 2, h / 2);
9639 glUniform4f(colorLoc, 0, 0, 0, 1);
9640 drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9641 glScissor(w / 2, 0, w / 2, h / 2);
9642 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9643 glScissor(0, h / 2, w / 2, h / 2);
9644 drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9645 glScissor(w / 2, h / 2, w / 2, h / 2);
9646 drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9647
9648 glDisable(GL_SCISSOR_TEST);
9649 glDisable(GL_DEPTH_TEST);
9650 glDepthMask(GL_FALSE);
9651 glUniform4f(colorLoc, 1, 0, 0, 1);
9652 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9653
9654 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9655
9656 // Make draw calls that test depth or not, write depth or not, and use different functions
9657
9658 // Write green to one half
9659 glEnable(GL_DEPTH_TEST);
9660 glDepthFunc(GL_LESS);
9661 glUniform4f(colorLoc, 0, 1, 0, 1);
9662 drawQuad(program, essl1_shaders::PositionAttrib(), 0.35f);
9663
9664 // Write blue to another half
9665 glDepthFunc(GL_GREATER);
9666 glUniform4f(colorLoc, 0, 0, 1, 1);
9667 drawQuad(program, essl1_shaders::PositionAttrib(), -0.15f);
9668
9669 // Write yellow to a corner, overriding depth
9670 glDepthMask(GL_TRUE);
9671 glUniform4f(colorLoc, 1, 1, 0, 1);
9672 drawQuad(program, essl1_shaders::PositionAttrib(), -0.6f);
9673
9674 // Write magenta to another corner, overriding depth
9675 glDepthFunc(GL_LESS);
9676 glUniform4f(colorLoc, 1, 0, 1, 1);
9677 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9678
9679 // No-op write
9680 glDepthFunc(GL_NEVER);
9681 glUniform4f(colorLoc, 0, 1, 1, 1);
9682 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9683
9684 // Verify results
9685 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::yellow);
9686 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9687 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9688 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::magenta);
9689
9690 // Verify the depth buffer
9691 glDepthMask(GL_FALSE);
9692 glDepthFunc(GL_LESS);
9693 glUniform4f(colorLoc, 1, 0, 0, 1);
9694 drawQuad(program, essl1_shaders::PositionAttrib(), -0.61f);
9695 glUniform4f(colorLoc, 0, 0, 0, 1);
9696 drawQuad(program, essl1_shaders::PositionAttrib(), -0.59f);
9697
9698 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9699 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9700 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9701 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9702
9703 glDepthFunc(GL_GREATER);
9704 glUniform4f(colorLoc, 0, 1, 1, 1);
9705 drawQuad(program, essl1_shaders::PositionAttrib(), 0.51f);
9706 glUniform4f(colorLoc, 0, 0, 0, 1);
9707 drawQuad(program, essl1_shaders::PositionAttrib(), 0.49f);
9708
9709 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9710 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9711 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9712 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9713
9714 glDepthFunc(GL_LESS);
9715 glUniform4f(colorLoc, 0, 1, 0, 1);
9716 drawQuad(program, essl1_shaders::PositionAttrib(), -0.21f);
9717 glUniform4f(colorLoc, 1, 1, 1, 1);
9718 drawQuad(program, essl1_shaders::PositionAttrib(), -0.19f);
9719
9720 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9721 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::green);
9722 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9723 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9724
9725 glDepthFunc(GL_GREATER);
9726 glUniform4f(colorLoc, 0, 0, 1, 1);
9727 drawQuad(program, essl1_shaders::PositionAttrib(), 0.41f);
9728 glUniform4f(colorLoc, 1, 0, 1, 1);
9729 drawQuad(program, essl1_shaders::PositionAttrib(), 0.39f);
9730
9731 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::magenta);
9732 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9733 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::blue);
9734 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9735
9736 ASSERT_GL_NO_ERROR();
9737 }
9738
9739 // Tests state change for depth test while depth write is enabled
TEST_P(StateChangeTestES3,DepthTestToggleWithDepthWrite)9740 TEST_P(StateChangeTestES3, DepthTestToggleWithDepthWrite)
9741 {
9742 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9743 glUseProgram(program);
9744
9745 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9746 ASSERT_NE(colorLoc, -1);
9747
9748 const int w = getWindowWidth();
9749 const int h = getWindowHeight();
9750
9751 glClearColor(0, 0, 0, 1);
9752 glClearDepthf(0.5);
9753 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9754
9755 // Enable depth write, but keep depth test disabled. Internally, depth write may be disabled
9756 // because of the depth test.
9757 glDisable(GL_DEPTH_TEST);
9758 glDepthMask(GL_TRUE);
9759 glDepthFunc(GL_LESS);
9760
9761 // Draw with a different depth, but because depth test is disabled, depth is not actually
9762 // changed.
9763 glUniform4f(colorLoc, 1, 0, 0, 1);
9764 drawQuad(program, essl1_shaders::PositionAttrib(), -0.3f);
9765
9766 // Enable depth test, but don't change state otherwise. The following draw must change depth.
9767 glEnable(GL_DEPTH_TEST);
9768
9769 glUniform4f(colorLoc, 0, 1, 0, 1);
9770 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9771
9772 // Verify that depth was changed in the last draw call.
9773 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9774
9775 glDepthFunc(GL_GREATER);
9776 glUniform4f(colorLoc, 0, 0, 1, 1);
9777 drawQuad(program, essl1_shaders::PositionAttrib(), -0.1f);
9778 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
9779 ASSERT_GL_NO_ERROR();
9780 }
9781
9782 // Tests state change for stencil test and function
TEST_P(StateChangeTestES3,StencilTestAndFunc)9783 TEST_P(StateChangeTestES3, StencilTestAndFunc)
9784 {
9785 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9786 glUseProgram(program);
9787
9788 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9789 ASSERT_NE(colorLoc, -1);
9790
9791 const int w = getWindowWidth();
9792 const int h = getWindowHeight();
9793
9794 glClearColor(0, 0, 0, 1);
9795 glClearDepthf(0.5);
9796 glClearStencil(0x55);
9797 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9798
9799 // Initialize the depth and stencil buffers
9800 glEnable(GL_DEPTH_TEST);
9801 glDepthMask(GL_TRUE);
9802 glDepthFunc(GL_ALWAYS);
9803
9804 glEnable(GL_STENCIL_TEST);
9805 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
9806
9807 glEnable(GL_SCISSOR_TEST);
9808 glScissor(0, 0, w / 2, h / 2);
9809 glUniform4f(colorLoc, 0, 0, 0, 1);
9810 glStencilFunc(GL_ALWAYS, 0x3E, 0xFF);
9811 drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9812 glScissor(w / 2, 0, w / 2, h / 2);
9813 glStencilFunc(GL_ALWAYS, 0xA7, 0xFF);
9814 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9815 glScissor(0, h / 2, w / 2, h / 2);
9816 glStencilFunc(GL_ALWAYS, 0x6C, 0xFF);
9817 drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9818 glScissor(w / 2, h / 2, w / 2, h / 2);
9819 glStencilFunc(GL_ALWAYS, 0x5B, 0xFF);
9820 drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9821
9822 glDisable(GL_SCISSOR_TEST);
9823 glDisable(GL_DEPTH_TEST);
9824 glDisable(GL_STENCIL_TEST);
9825 glDepthMask(GL_FALSE);
9826 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9827 glUniform4f(colorLoc, 1, 0, 0, 1);
9828 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9829
9830 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9831
9832 // Make draw calls that manipulate stencil and use different functions and ops.
9833
9834 // Current color/depth/stencil in the four sections of the image:
9835 //
9836 // red/-0.8/3E red/-0.2/A7
9837 // red/ 0.4/6C red/0.6/5B
9838 //
9839 glEnable(GL_DEPTH_TEST);
9840 glDepthFunc(GL_LESS);
9841 glEnable(GL_STENCIL_TEST);
9842 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x2C, 0x2C);
9843 glStencilOpSeparate(GL_FRONT, GL_INCR, GL_DECR, GL_INVERT);
9844 glStencilFuncSeparate(GL_BACK, GL_GREATER, 0x7B, 0xFF);
9845 glStencilOpSeparate(GL_BACK, GL_INCR, GL_ZERO, GL_REPLACE);
9846
9847 // Draw green front-facing to get:
9848 //
9849 // red/-0.8/3D red/-0.2/A8
9850 // green/ 0.4/93 red/ 0.6/5C
9851 //
9852 glUniform4f(colorLoc, 0, 1, 0, 1);
9853 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9854
9855 // Draw blue back-facing to get:
9856 //
9857 // red/-0.8/00 red/-0.2/A9
9858 // green/ 0.4/94 blue/ 0.6/7B
9859 //
9860 glFrontFace(GL_CW);
9861 glUniform4f(colorLoc, 0, 0, 1, 1);
9862 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9863
9864 glStencilFuncSeparate(GL_FRONT, GL_LEQUAL, 0x42, 0x42);
9865 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_INCR_WRAP);
9866 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x00, 0x00);
9867 glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_INVERT);
9868
9869 // Draw yellow back-facing to get:
9870 //
9871 // yellow/-0.8/FF yellow/-0.2/56
9872 // green/ 0.4/95 blue/ 0.6/7C
9873 //
9874 glDepthFunc(GL_GREATER);
9875 glUniform4f(colorLoc, 1, 1, 0, 1);
9876 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9877
9878 // Draw cyan front-facing to get:
9879 //
9880 // cyan/-0.8/00 yellow/-0.2/55
9881 // green/ 0.4/95 blue/ 0.6/7C
9882 //
9883 glFrontFace(GL_CCW);
9884 glUniform4f(colorLoc, 0, 1, 1, 1);
9885 drawQuad(program, essl1_shaders::PositionAttrib(), -0.5);
9886
9887 // No-op draw
9888 glStencilFuncSeparate(GL_FRONT, GL_NEVER, 0x00, 0x00);
9889 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INVERT, GL_INVERT);
9890 glUniform4f(colorLoc, 1, 0, 1, 1);
9891 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9892
9893 // Verify results
9894 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9895 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9896 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9897 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9898
9899 // Verify the stencil buffer
9900 glDisable(GL_DEPTH_TEST);
9901 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
9902 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x00, 0xFF);
9903 glUniform4f(colorLoc, 1, 0, 0, 1);
9904 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9905
9906 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9907 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9908 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9909 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9910
9911 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x55, 0xFF);
9912 glUniform4f(colorLoc, 1, 0, 1, 1);
9913 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9914
9915 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9916 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9917 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9918 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9919
9920 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x95, 0xFF);
9921 glUniform4f(colorLoc, 1, 1, 1, 1);
9922 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9923
9924 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9925 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9926 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9927 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9928
9929 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x7C, 0xFF);
9930 glUniform4f(colorLoc, 0, 0, 0, 1);
9931 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9932
9933 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9934 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9935 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9936 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9937
9938 ASSERT_GL_NO_ERROR();
9939 }
9940
9941 // Tests state change for rasterizer discard
TEST_P(StateChangeTestES3,RasterizerDiscard)9942 TEST_P(StateChangeTestES3, RasterizerDiscard)
9943 {
9944 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9945 glUseProgram(program);
9946
9947 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9948 ASSERT_NE(colorLoc, -1);
9949
9950 const int w = getWindowWidth();
9951 const int h = getWindowHeight();
9952
9953 glClearColor(0, 0, 0, 0);
9954 glClear(GL_COLOR_BUFFER_BIT);
9955
9956 glEnable(GL_BLEND);
9957 glBlendFunc(GL_ONE, GL_ONE);
9958
9959 // Start a render pass and issue three draw calls with the middle one having rasterizer discard
9960 // enabled.
9961 glUniform4f(colorLoc, 1, 0, 0, 0);
9962 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9963
9964 glEnable(GL_RASTERIZER_DISCARD);
9965
9966 glUniform4f(colorLoc, 0, 1, 1, 0);
9967 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9968
9969 glDisable(GL_RASTERIZER_DISCARD);
9970
9971 glUniform4f(colorLoc, 0, 0, 0, 1);
9972 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9973
9974 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9975
9976 // Enable rasterizer discard and make sure the state is effective.
9977 glEnable(GL_RASTERIZER_DISCARD);
9978
9979 glUniform4f(colorLoc, 0, 1, 0, 1);
9980 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9981
9982 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9983
9984 // Start a render pass and issue three draw calls with the first and last ones having rasterizer
9985 // discard enabled.
9986 glUniform4f(colorLoc, 0, 1, 0, 0);
9987 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9988
9989 glDisable(GL_RASTERIZER_DISCARD);
9990
9991 glUniform4f(colorLoc, 0, 0, 1, 0);
9992 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9993
9994 glEnable(GL_RASTERIZER_DISCARD);
9995
9996 glUniform4f(colorLoc, 0, 1, 0, 1);
9997 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9998
9999 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::magenta);
10000
10001 ASSERT_GL_NO_ERROR();
10002 }
10003
10004 // Tests state change for GL_POLYGON_OFFSET_FILL.
TEST_P(StateChangeTestES3,PolygonOffsetFill)10005 TEST_P(StateChangeTestES3, PolygonOffsetFill)
10006 {
10007 constexpr char kVS[] = R"(#version 300 es
10008 precision highp float;
10009 void main()
10010 {
10011 // gl_VertexID x y
10012 // 0 -1 -1
10013 // 1 1 -1
10014 // 2 -1 1
10015 // 3 1 1
10016 int bit0 = gl_VertexID & 1;
10017 int bit1 = gl_VertexID >> 1;
10018 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10019 })";
10020
10021 constexpr char kFS[] = R"(#version 300 es
10022 precision highp float;
10023 out vec4 colorOut;
10024 uniform vec4 color;
10025 void main()
10026 {
10027 colorOut = color;
10028 })";
10029
10030 ANGLE_GL_PROGRAM(program, kVS, kFS);
10031 glUseProgram(program);
10032
10033 GLint colorLoc = glGetUniformLocation(program, "color");
10034 ASSERT_NE(-1, colorLoc);
10035
10036 glClearColor(0, 0, 0, 1);
10037 glClearDepthf(0);
10038 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10039
10040 // The shader creates a depth slope from left (0) to right (1).
10041 //
10042 // This test issues three draw calls:
10043 //
10044 //
10045 // Draw 3 (blue): factor width/2, enabled, depth test: Greater
10046 // ^ | __________________
10047 // | | __/ __/ __/
10048 // | V __/ __/ __/
10049 // | __/ __/ __/
10050 // | __/ __/ __/
10051 // |/ __/^ __/
10052 // | __/ | __/ <--- Draw 2: factor width/2, disabled, depth test: Greater
10053 // | __/ _\/
10054 // |/ __/ \
10055 // | __/ Draw 1 (red): factor width/4, enabled
10056 // | __/
10057 // +/------------------------------>
10058 //
10059 // Result: <-------magenta-------><--red-->
10060
10061 glEnable(GL_BLEND);
10062 glBlendFunc(GL_ONE, GL_ONE);
10063
10064 glEnable(GL_DEPTH_TEST);
10065 glDepthFunc(GL_ALWAYS);
10066
10067 glEnable(GL_POLYGON_OFFSET_FILL);
10068
10069 const int w = getWindowWidth();
10070 const int h = getWindowHeight();
10071
10072 glUniform4f(colorLoc, 1, 0, 0, 1);
10073 glPolygonOffset(getWindowWidth() / 4, 0);
10074 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10075
10076 glUniform4f(colorLoc, 0, 1, 0, 1);
10077 glPolygonOffset(getWindowWidth() / 2, 0);
10078 glDepthFunc(GL_GREATER);
10079 glDisable(GL_POLYGON_OFFSET_FILL);
10080 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10081
10082 glUniform4f(colorLoc, 0, 0, 1, 1);
10083 glEnable(GL_POLYGON_OFFSET_FILL);
10084 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10085
10086 EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::magenta);
10087 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
10088
10089 ASSERT_GL_NO_ERROR();
10090 }
10091
10092 // Tests state change for GL_PRIMITIVE_RESTART.
TEST_P(StateChangeTestES3,PrimitiveRestart)10093 TEST_P(StateChangeTestES3, PrimitiveRestart)
10094 {
10095 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10096 glUseProgram(program);
10097
10098 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
10099 ASSERT_NE(colorLoc, -1);
10100
10101 GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
10102 ASSERT_EQ(0, posAttrib);
10103
10104 // Arrange the vertices as such:
10105 //
10106 // 1 3 4
10107 // +-----+-----+
10108 // | | |
10109 // | | |
10110 // | | |
10111 // | | |
10112 // | | |
10113 // | | |
10114 // +-----+-----+
10115 // 0 2 FF
10116 //
10117 // Drawing a triangle strip, without primitive restart, the whole framebuffer is rendered, while
10118 // with primitive restart only the left half is.
10119 std::vector<Vector3> positionData(256, {0, 0, 0});
10120
10121 positionData[0] = Vector3(-1, -1, 0);
10122 positionData[1] = Vector3(-1, 1, 0);
10123 positionData[2] = Vector3(0, -1, 0);
10124 positionData[3] = Vector3(0, 1, 0);
10125 positionData[0xFF] = Vector3(1, -1, 0);
10126 positionData[4] = Vector3(1, 1, 0);
10127
10128 constexpr std::array<GLubyte, 6> indices = {0, 1, 2, 3, 0xFF, 4};
10129
10130 GLBuffer posBuffer;
10131 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
10132 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(positionData[0]),
10133 positionData.data(), GL_STATIC_DRAW);
10134 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
10135 glEnableVertexAttribArray(posAttrib);
10136
10137 GLBuffer indexBuffer;
10138 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
10139 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
10140
10141 const int w = getWindowWidth();
10142 const int h = getWindowHeight();
10143
10144 glClearColor(0, 0, 0, 1);
10145 glClear(GL_COLOR_BUFFER_BIT);
10146
10147 glEnable(GL_BLEND);
10148 glBlendFunc(GL_ONE, GL_ONE);
10149
10150 // Draw red with primitive restart enabled
10151 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10152 glUniform4f(colorLoc, 1, 0, 0, 0);
10153 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10154
10155 // Draw green with primitive restart disabled
10156 glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10157 glUniform4f(colorLoc, 0, 1, 0, 1);
10158 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10159
10160 // Draw blue with primitive restart enabled again
10161 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10162 glUniform4f(colorLoc, 0, 0, 1, 0);
10163 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10164
10165 // Verify results
10166 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::white);
10167 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 2 - 1, h, GLColor::green);
10168
10169 ASSERT_GL_NO_ERROR();
10170 }
10171
10172 // Tests that primitive restart for patches can be queried when tessellation shaders are available,
10173 // and that its value is independent of whether primitive restart is enabled.
TEST_P(StateChangeTestES31,PrimitiveRestartForPatchQuery)10174 TEST_P(StateChangeTestES31, PrimitiveRestartForPatchQuery)
10175 {
10176 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
10177
10178 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10179 GLint primitiveRestartForPatchesWhenEnabled = -1;
10180 glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10181 &primitiveRestartForPatchesWhenEnabled);
10182 ASSERT_GL_NO_ERROR();
10183 EXPECT_GE(primitiveRestartForPatchesWhenEnabled, 0);
10184
10185 glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10186 GLint primitiveRestartForPatchesWhenDisabled = -1;
10187 glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10188 &primitiveRestartForPatchesWhenDisabled);
10189 ASSERT_GL_NO_ERROR();
10190 EXPECT_GE(primitiveRestartForPatchesWhenDisabled, 0);
10191
10192 EXPECT_EQ(primitiveRestartForPatchesWhenEnabled, primitiveRestartForPatchesWhenDisabled);
10193 }
10194
10195 // Tests state change for GL_COLOR_LOGIC_OP and glLogicOp.
TEST_P(StateChangeTestES3,LogicOp)10196 TEST_P(StateChangeTestES3, LogicOp)
10197 {
10198 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_logic_op"));
10199
10200 constexpr char kVS[] = R"(#version 300 es
10201 precision highp float;
10202 void main()
10203 {
10204 // gl_VertexID x y
10205 // 0 -1 -1
10206 // 1 1 -1
10207 // 2 -1 1
10208 // 3 1 1
10209 int bit0 = gl_VertexID & 1;
10210 int bit1 = gl_VertexID >> 1;
10211 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10212 })";
10213
10214 constexpr char kFS[] = R"(#version 300 es
10215 precision highp float;
10216 out vec4 colorOut;
10217 uniform vec4 color;
10218 void main()
10219 {
10220 colorOut = color;
10221 })";
10222
10223 ANGLE_GL_PROGRAM(program, kVS, kFS);
10224 glUseProgram(program);
10225
10226 GLint colorLoc = glGetUniformLocation(program, "color");
10227 ASSERT_NE(-1, colorLoc);
10228
10229 glClearColor(0, 0, 0, 1);
10230 glClearDepthf(0);
10231 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10232
10233 auto unorm8 = [](uint8_t value) { return (value + 0.1f) / 255.0f; };
10234
10235 constexpr uint8_t kInitRed = 0xA4;
10236 constexpr uint8_t kInitGreen = 0x1E;
10237 constexpr uint8_t kInitBlue = 0x97;
10238 constexpr uint8_t kInitAlpha = 0x65;
10239
10240 // Initialize with logic op enabled, but using the default GL_COPY op.
10241 glEnable(GL_COLOR_LOGIC_OP_ANGLE);
10242
10243 glUniform4f(colorLoc, unorm8(kInitRed), unorm8(kInitGreen), unorm8(kInitBlue),
10244 unorm8(kInitAlpha));
10245 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10246
10247 // Set logic op to GL_XOR and draw again.
10248 glLogicOpANGLE(GL_LOGIC_OP_XOR_ANGLE);
10249
10250 constexpr uint8_t kXorRed = 0x4C;
10251 constexpr uint8_t kXorGreen = 0x7D;
10252 constexpr uint8_t kXorBlue = 0xB3;
10253 constexpr uint8_t kXorAlpha = 0x0F;
10254
10255 glUniform4f(colorLoc, unorm8(kXorRed), unorm8(kXorGreen), unorm8(kXorBlue), unorm8(kXorAlpha));
10256 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10257
10258 // Set logic op to GL_INVERT and draw again.
10259 glLogicOpANGLE(GL_LOGIC_OP_INVERT_ANGLE);
10260 glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10261 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10262
10263 const int w = getWindowWidth();
10264 const int h = getWindowHeight();
10265
10266 // Verify results
10267 const GLColor kExpect(static_cast<uint8_t>(~(kInitRed ^ kXorRed)),
10268 static_cast<uint8_t>(~(kInitGreen ^ kXorGreen)),
10269 static_cast<uint8_t>(~(kInitBlue ^ kXorBlue)),
10270 static_cast<uint8_t>(~(kInitAlpha ^ kXorAlpha)));
10271 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, kExpect);
10272
10273 // Render again with logic op enabled, this time with GL_COPY_INVERTED
10274 glLogicOpANGLE(GL_LOGIC_OP_COPY_INVERTED_ANGLE);
10275 glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10276 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10277
10278 // Disable logic op and render again
10279 glDisable(GL_COLOR_LOGIC_OP_ANGLE);
10280 glUniform4f(colorLoc, 0, 1, 0, 1);
10281 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10282
10283 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
10284 ASSERT_GL_NO_ERROR();
10285 }
10286
10287 // Test for a bug with the VK_EXT_graphics_pipeline_library implementation in a scenario such as
10288 // this:
10289 //
10290 // - Use blend function A, draw <-- a new pipeline is created
10291 // - Use blend function B, draw <-- a new pipeline is created,
10292 // new transition from A to B
10293 // - Switch to program 2
10294 // - Use blend function A, draw <-- a new pipeline is created
10295 // - Switch to program 1
10296 // - draw <-- the first pipeline is retrieved from cache,
10297 // new transition from B to A
10298 // - Use blend function B, draw <-- the second pipeline is retrieved from transition
10299 // - Switch to program 3
10300 // - draw <-- a new pipeline is created
10301 //
10302 // With graphics pipeline library, the fragment output partial pipeline changes as follows:
10303 //
10304 // - Use blend function A, draw <-- a new fragment output pipeline is created
10305 // - Use blend function B, draw <-- a new fragment output pipeline is created,
10306 // new transition from A to B
10307 // - Switch to program 2
10308 // - Use blend function A, draw <-- the first fragment output pipeline is retrieved from cache
10309 // - Switch to program 1
10310 // - draw <-- the first monolithic pipeline is retrieved from cache
10311 // - Use blend function B, draw <-- the second monolithic pipeline is retrieved from transition
10312 // - Switch to program 3
10313 // - draw <-- the second fragment output pipeline is retrieved from cache
10314 //
10315 // The bug was that the dirty blend state was discarded when the monolithic pipeline was retrieved
10316 // through the transition graph, and the last draw call used a stale fragment output pipeline (from
10317 // the last draw call with function A)
10318 //
TEST_P(StateChangeTestES3,FragmentOutputStateChangeAfterCachedPipelineTransition)10319 TEST_P(StateChangeTestES3, FragmentOutputStateChangeAfterCachedPipelineTransition)
10320 {
10321 // Program 1
10322 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10323 // Program 2
10324 ANGLE_GL_PROGRAM(drawColor2, essl3_shaders::vs::Simple(), R"(#version 300 es
10325 precision mediump float;
10326 out vec4 colorOut;
10327 uniform vec4 colorIn;
10328 void main()
10329 {
10330 colorOut = colorIn;
10331 }
10332 )");
10333 // Program 3
10334 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10335
10336 glUseProgram(drawColor2);
10337 GLint color2UniformLocation = glGetUniformLocation(drawColor2, "colorIn");
10338 ASSERT_NE(color2UniformLocation, -1);
10339
10340 glUseProgram(drawColor);
10341 GLint colorUniformLocation =
10342 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
10343 ASSERT_NE(colorUniformLocation, -1);
10344
10345 glEnable(GL_BLEND);
10346 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10347 glClearColor(0, 0, 0, 0);
10348 glClear(GL_COLOR_BUFFER_BIT);
10349 // Framebuffer color is now (0, 0, 0, 0)
10350
10351 glUniform4f(colorUniformLocation, 0, 0, 1, 0.25f);
10352 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10353 // Framebuffer color is now (0, 0, 0.25, 0.25*0.25)
10354
10355 glBlendFunc(GL_ONE, GL_ONE);
10356 glUniform4f(colorUniformLocation, 0, 0, 0.25, 0.5 - 0.0625);
10357 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10358 // Framebuffer color is now (0, 0, 0.5, 0.5)
10359
10360 // Draw with a different program, but same fragment output state. The fragment output pipeline
10361 // is retrieved from cache.
10362 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10363 glUseProgram(drawColor2);
10364 glUniform4f(color2UniformLocation, 1, 0, 0, 0.5);
10365 drawQuad(drawColor2, essl1_shaders::PositionAttrib(), 0.5f);
10366 // Framebuffer color is now (0.5, 0, 0.25, 0.5)
10367
10368 // Draw with the original program and the first fragment output state, so it's retrieved from
10369 // cache.
10370 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10371 glUseProgram(drawColor);
10372 glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25);
10373 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10374 // Framebuffer color is now (0.25, 0, 0.25, 0.25+0.25*0.25)
10375
10376 // Change to the second fragment output state, so it's retrieved through the transition graph.
10377 glBlendFunc(GL_ONE, GL_ONE);
10378 glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25 - 0.25 * 0.25);
10379 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10380 // Framebuffer color is now (0.25, 0, 0.75, 0.5)
10381
10382 // Draw with the third program, not changing the fragment output state.
10383 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
10384 // Framebuffer color is now (0.25, 1, 0.75, 1)
10385
10386 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 255, 192, 255), 1);
10387 ASSERT_GL_NO_ERROR();
10388 }
10389
10390 // Tests a specific case for multiview and queries.
TEST_P(SimpleStateChangeTestES3,MultiviewAndQueries)10391 TEST_P(SimpleStateChangeTestES3, MultiviewAndQueries)
10392 {
10393 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OVR_multiview"));
10394
10395 ANGLE_GL_PROGRAM(prog, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
10396 glUseProgram(prog);
10397
10398 const int PRE_QUERY_CNT = 63;
10399
10400 GLQuery qry;
10401 GLTexture tex;
10402 GLFramebuffer fb;
10403 GLFramebuffer fb2;
10404 glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10405 for (int i = 0; i < PRE_QUERY_CNT; i++)
10406 {
10407 glDrawArrays(GL_POINTS, 0, 1);
10408
10409 GLColor color;
10410 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
10411 }
10412 glEndQuery(GL_ANY_SAMPLES_PASSED);
10413 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
10414 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
10415 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2);
10416 glBindFramebuffer(GL_FRAMEBUFFER, fb);
10417 glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
10418 glClear(GL_COLOR_BUFFER_BIT);
10419 glBindFramebuffer(GL_FRAMEBUFFER, fb2);
10420 glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10421 }
10422
10423 // Tests a bug related to an ordering of certain commands.
TEST_P(SimpleStateChangeTestES3,ClearQuerySwapClear)10424 TEST_P(SimpleStateChangeTestES3, ClearQuerySwapClear)
10425 {
10426 glClear(GL_COLOR_BUFFER_BIT);
10427 {
10428 GLQuery query;
10429 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
10430 glEndQuery(GL_ANY_SAMPLES_PASSED);
10431 }
10432 swapBuffers();
10433 glClear(GL_COLOR_BUFFER_BIT);
10434 }
10435
10436 // Tests a bug around sampler2D swap and uniform locations.
TEST_P(StateChangeTestES3,SamplerSwap)10437 TEST_P(StateChangeTestES3, SamplerSwap)
10438 {
10439 constexpr char kVS[] = R"(#version 300 es
10440 precision highp float;
10441 void main()
10442 {
10443 // gl_VertexID x y
10444 // 0 -1 -1
10445 // 1 1 -1
10446 // 2 -1 1
10447 // 3 1 1
10448 int bit0 = gl_VertexID & 1;
10449 int bit1 = gl_VertexID >> 1;
10450 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10451 })";
10452
10453 constexpr char kFS1[] = R"(#version 300 es
10454 precision highp float;
10455 uniform sampler2D A;
10456 uniform sampler2D B;
10457 out vec4 colorOut;
10458 void main()
10459 {
10460 float a = texture(A, vec2(0)).x;
10461 float b = texture(B, vec2(0)).x;
10462 colorOut = vec4(a, b, 0, 1);
10463 })";
10464
10465 constexpr char kFS2[] = R"(#version 300 es
10466 precision highp float;
10467 uniform sampler2D B;
10468 uniform sampler2D A;
10469 const vec2 multiplier = vec2(0.5, 0.5);
10470 out vec4 colorOut;
10471 void main()
10472 {
10473 float a = texture(A, vec2(0)).x;
10474 float b = texture(B, vec2(0)).x;
10475 colorOut = vec4(a, b, 0, 1);
10476 })";
10477
10478 ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10479 ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10480
10481 const GLColor kColorA(123, 0, 0, 0);
10482 const GLColor kColorB(157, 0, 0, 0);
10483
10484 GLTexture texA;
10485 glActiveTexture(GL_TEXTURE0);
10486 glBindTexture(GL_TEXTURE_2D, texA);
10487 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10488 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10489
10490 GLTexture texB;
10491 glActiveTexture(GL_TEXTURE1);
10492 glBindTexture(GL_TEXTURE_2D, texB);
10493 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10494 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10495 EXPECT_GL_NO_ERROR();
10496
10497 glUseProgram(prog1);
10498 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10499 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10500
10501 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10502
10503 const GLColor kExpect(kColorA.R, kColorB.R, 0, 255);
10504
10505 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10506 ASSERT_GL_NO_ERROR();
10507
10508 // The same with the second program that has sampler2D (definitions) swapped which should have
10509 // no effect on the result.
10510 glUseProgram(prog2);
10511 glUniform1i(glGetUniformLocation(prog2, "A"), 0);
10512 glUniform1i(glGetUniformLocation(prog2, "B"), 1);
10513
10514 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10515
10516 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10517 ASSERT_GL_NO_ERROR();
10518 }
10519
10520 // Tests a bug around sampler2D reordering and uniform locations.
TEST_P(StateChangeTestES3,SamplerReordering)10521 TEST_P(StateChangeTestES3, SamplerReordering)
10522 {
10523 constexpr char kVS[] = R"(#version 300 es
10524 precision highp float;
10525 void main()
10526 {
10527 // gl_VertexID x y
10528 // 0 -1 -1
10529 // 1 1 -1
10530 // 2 -1 1
10531 // 3 1 1
10532 int bit0 = gl_VertexID & 1;
10533 int bit1 = gl_VertexID >> 1;
10534 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10535 })";
10536
10537 constexpr char kFS1[] = R"(#version 300 es
10538 precision highp float;
10539 uniform sampler2D A;
10540 uniform sampler2D B;
10541 //uniform vec2 multiplier;
10542 const vec2 multiplier = vec2(0.5, 0.5);
10543 out vec4 colorOut;
10544 void main()
10545 {
10546 float a = texture(A, vec2(0)).x;
10547 float b = texture(B, vec2(0)).x;
10548 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10549 })";
10550
10551 constexpr char kFS2[] = R"(#version 300 es
10552 precision highp float;
10553 uniform sampler2D S;
10554 uniform sampler2D P;
10555 //uniform vec2 multiplier;
10556 const vec2 multiplier = vec2(0.5, 0.5);
10557 out vec4 colorOut;
10558 void main()
10559 {
10560 float a = texture(P, vec2(0)).x;
10561 float b = texture(S, vec2(0)).x;
10562 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10563 })";
10564
10565 constexpr char kFS3[] = R"(#version 300 es
10566 precision highp float;
10567 uniform sampler2D R;
10568 uniform sampler2D S;
10569 //uniform vec2 multiplier;
10570 const vec2 multiplier = vec2(0.5, 0.5);
10571 out vec4 colorOut;
10572 void main()
10573 {
10574 float a = texture(R, vec2(0)).x;
10575 float b = texture(S, vec2(0)).x;
10576 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10577 })";
10578
10579 ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10580 ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10581 ANGLE_GL_PROGRAM(prog3, kVS, kFS3);
10582
10583 const GLColor kColorA(123, 0, 0, 0);
10584 const GLColor kColorB(157, 0, 0, 0);
10585
10586 GLTexture texA;
10587 glActiveTexture(GL_TEXTURE0);
10588 glBindTexture(GL_TEXTURE_2D, texA);
10589 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10590 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10591
10592 GLTexture texB;
10593 glActiveTexture(GL_TEXTURE1);
10594 glBindTexture(GL_TEXTURE_2D, texB);
10595 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10596 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10597 EXPECT_GL_NO_ERROR();
10598
10599 glUseProgram(prog1);
10600 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10601 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10602
10603 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10604
10605 glUseProgram(prog2);
10606 glUniform1i(glGetUniformLocation(prog2, "S"), 0);
10607 glUniform1i(glGetUniformLocation(prog2, "P"), 1);
10608
10609 glEnable(GL_BLEND);
10610 glBlendFunc(GL_ONE, GL_ONE);
10611 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10612
10613 constexpr float kXMultiplier = 0.5;
10614 constexpr float kYMultiplier = 0.5;
10615
10616 const GLColor kExpect(static_cast<uint8_t>((kColorA.R + kColorB.R) * kXMultiplier),
10617 static_cast<uint8_t>((kColorA.R + kColorB.R) * kYMultiplier), 0, 255);
10618
10619 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10620 ASSERT_GL_NO_ERROR();
10621
10622 // Do the same thing again, but with the second shader having its samplers specified in the
10623 // opposite order. The difference between kFS2 and kFS3 is that S is now the second
10624 // declaration, and P is renamed to R. The reason for the rename is that even if the samplers
10625 // get sorted by name, they would still result in the two shaders declaring them in different
10626 // orders.
10627 glDisable(GL_BLEND);
10628
10629 glUseProgram(prog1);
10630 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10631 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10632
10633 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10634
10635 glUseProgram(prog3);
10636 glUniform1i(glGetUniformLocation(prog3, "S"), 0);
10637 glUniform1i(glGetUniformLocation(prog3, "R"), 1);
10638
10639 glEnable(GL_BLEND);
10640 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10641
10642 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10643 ASSERT_GL_NO_ERROR();
10644 }
10645
10646 // Test that switching FBO attachments affects sample coverage
TEST_P(StateChangeTestES3,SampleCoverageFramebufferAttachmentSwitch)10647 TEST_P(StateChangeTestES3, SampleCoverageFramebufferAttachmentSwitch)
10648 {
10649 // Keep this state unchanged during the test
10650 glEnable(GL_SAMPLE_COVERAGE);
10651 glSampleCoverage(0.0f, false);
10652
10653 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10654
10655 GLFramebuffer fbo;
10656 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10657
10658 GLRenderbuffer rbo;
10659 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10660 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10661
10662 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10663 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10664
10665 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10666 ASSERT_GL_NO_ERROR();
10667
10668 // Sample coverage must have no effect
10669 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10670
10671 GLRenderbuffer rboMS;
10672 glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10673 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10674
10675 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10676 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10677
10678 glClearColor(1, 0, 0, 1);
10679 glClear(GL_COLOR_BUFFER_BIT);
10680 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10681 ASSERT_GL_NO_ERROR();
10682
10683 // Use a temporary FBO to resolve
10684 {
10685 GLFramebuffer fboResolve;
10686 glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10687
10688 GLRenderbuffer rboResolve;
10689 glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10690 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10691
10692 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10693 rboResolve);
10694 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10695
10696 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10697 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10698 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10699 ASSERT_GL_NO_ERROR();
10700
10701 // Nothing was drawn because of zero coverage
10702 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10703 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10704 }
10705
10706 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10707
10708 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10709 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10710
10711 glClearColor(0, 0, 1, 1);
10712 glClear(GL_COLOR_BUFFER_BIT);
10713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10714
10715 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10716 ASSERT_GL_NO_ERROR();
10717
10718 // Sample coverage must have no effect
10719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10720 }
10721
10722 // Test that switching FBO attachments affects alpha-to-coverage
TEST_P(StateChangeTestES3,AlphaToCoverageFramebufferAttachmentSwitch)10723 TEST_P(StateChangeTestES3, AlphaToCoverageFramebufferAttachmentSwitch)
10724 {
10725 // Keep this state unchanged during the test
10726 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
10727
10728 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10729 glUseProgram(program);
10730 glUniform4f(glGetUniformLocation(program, essl1_shaders::ColorUniform()), 0, 1, 0, 0);
10731
10732 GLFramebuffer fbo;
10733 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10734
10735 GLRenderbuffer rbo;
10736 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10737 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10738
10739 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10740 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10741
10742 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10743 ASSERT_GL_NO_ERROR();
10744
10745 // A2C must have no effect
10746 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10747
10748 GLRenderbuffer rboMS;
10749 glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10750 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10751
10752 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10753 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10754
10755 glClearColor(1, 0, 0, 1);
10756 glClear(GL_COLOR_BUFFER_BIT);
10757 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10758 ASSERT_GL_NO_ERROR();
10759
10760 // Use a temporary FBO to resolve
10761 {
10762 GLFramebuffer fboResolve;
10763 glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10764
10765 GLRenderbuffer rboResolve;
10766 glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10767 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10768
10769 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10770 rboResolve);
10771 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10772
10773 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10774 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10775 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10776 ASSERT_GL_NO_ERROR();
10777
10778 // Nothing was drawn because of zero alpha
10779 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10781 }
10782
10783 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10784
10785 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10786 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10787
10788 glClearColor(0, 0, 1, 1);
10789 glClear(GL_COLOR_BUFFER_BIT);
10790 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10791
10792 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10793 ASSERT_GL_NO_ERROR();
10794
10795 // A2C must have no effect
10796 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10797 }
10798
10799 // Test that switching FBO attachments affects depth test
TEST_P(StateChangeTestES3,DepthTestFramebufferAttachmentSwitch)10800 TEST_P(StateChangeTestES3, DepthTestFramebufferAttachmentSwitch)
10801 {
10802 // Keep this state unchanged during the test
10803 glEnable(GL_DEPTH_TEST);
10804 glDepthMask(GL_TRUE);
10805 glDepthFunc(GL_GREATER);
10806
10807 constexpr char kVS[] = R"(#version 300 es
10808 precision highp float;
10809 uniform float u_depth;
10810 void main()
10811 {
10812 // gl_VertexID x y
10813 // 0 -1 -1
10814 // 1 1 -1
10815 // 2 -1 1
10816 // 3 1 1
10817 int bit0 = gl_VertexID & 1;
10818 int bit1 = gl_VertexID >> 1;
10819 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, u_depth * 2. - 1., 1);
10820 })";
10821
10822 constexpr char kFS[] = R"(#version 300 es
10823 uniform mediump vec4 u_color;
10824 out mediump vec4 color;
10825 void main(void)
10826 {
10827 color = u_color;
10828 })";
10829
10830 ANGLE_GL_PROGRAM(program, kVS, kFS);
10831 glUseProgram(program);
10832 GLint depthUni = glGetUniformLocation(program, "u_depth");
10833 GLint colorUni = glGetUniformLocation(program, "u_color");
10834
10835 constexpr uint32_t kWidth = 17;
10836 constexpr uint32_t kHeight = 23;
10837
10838 GLRenderbuffer rbo;
10839 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10840 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10841
10842 GLRenderbuffer depthStencil;
10843 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
10844 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight);
10845
10846 GLFramebuffer fbo;
10847 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10848 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10849 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10850 depthStencil);
10851 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10852
10853 glEnable(GL_BLEND);
10854 glBlendFunc(GL_ONE, GL_ONE);
10855
10856 glClearColor(0, 0, 0, 0);
10857 glClearDepthf(0);
10858 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10859 ASSERT_GL_NO_ERROR();
10860
10861 // Draw with the depth buffer attached, set depth to 0.5. Should succeed and the color buffer
10862 // becomes red.
10863 glUniform4f(colorUni, 1, 0, 0, 0);
10864 glUniform1f(depthUni, 0.5);
10865 glDrawArrays(GL_TRIANGLES, 0, 6);
10866
10867 // Detach the depth buffer and draw with a smaller depth. Should still succeed because there is
10868 // no depth buffer test against. Green should be added.
10869 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
10870 glUniform4f(colorUni, 0, 0.2, 0, 0.6);
10871 glUniform1f(depthUni, 0.3);
10872 glDrawArrays(GL_TRIANGLES, 0, 6);
10873 // Higher depth should also pass
10874 glUniform1f(depthUni, 0.9);
10875 glDrawArrays(GL_TRIANGLES, 0, 6);
10876
10877 // Reattach the depth buffer and draw with a depth in between. Should fail the depth. Blue
10878 // should not be added.
10879 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10880 depthStencil);
10881 glUniform4f(colorUni, 0, 0, 1, 1);
10882 glUniform1f(depthUni, 0.4);
10883 glDrawArrays(GL_TRIANGLES, 0, 6);
10884
10885 // Reattach the depth buffer and draw with a depth larger than 0.5. Should pass the depth test.
10886 // Blue should be added.
10887 glUniform4f(colorUni, 0, 0.8, 0, 0);
10888 glUniform1f(depthUni, 0.6);
10889 glDrawArrays(GL_TRIANGLES, 0, 6);
10890
10891 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10892 ASSERT_GL_NO_ERROR();
10893 }
10894
10895 // Test that switching FBO attachments affects blend state
TEST_P(StateChangeTestES3,BlendFramebufferAttachmentSwitch)10896 TEST_P(StateChangeTestES3, BlendFramebufferAttachmentSwitch)
10897 {
10898 // Keep this state unchanged during the test
10899 glEnable(GL_BLEND);
10900 glBlendFunc(GL_ONE, GL_ONE);
10901
10902 constexpr char kVS[] = R"(#version 300 es
10903 precision highp float;
10904 void main()
10905 {
10906 // gl_VertexID x y
10907 // 0 -1 -1
10908 // 1 1 -1
10909 // 2 -1 1
10910 // 3 1 1
10911 int bit0 = gl_VertexID & 1;
10912 int bit1 = gl_VertexID >> 1;
10913 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1);
10914 })";
10915
10916 constexpr char kFS[] = R"(#version 300 es
10917 uniform mediump vec4 u_color;
10918 layout(location=0) out mediump vec4 color0;
10919 layout(location=1) out mediump vec4 color1;
10920 void main(void)
10921 {
10922 color0 = u_color;
10923 color1 = u_color;
10924 })";
10925
10926 ANGLE_GL_PROGRAM(program, kVS, kFS);
10927 glUseProgram(program);
10928 GLint colorUni = glGetUniformLocation(program, "u_color");
10929
10930 constexpr uint32_t kWidth = 17;
10931 constexpr uint32_t kHeight = 23;
10932
10933 GLRenderbuffer color0;
10934 glBindRenderbuffer(GL_RENDERBUFFER, color0);
10935 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10936
10937 GLRenderbuffer color1;
10938 glBindRenderbuffer(GL_RENDERBUFFER, color1);
10939 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10940
10941 GLFramebuffer fbo;
10942 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10943 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10944 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10945
10946 constexpr GLenum kDrawBuffers[2] = {
10947 GL_COLOR_ATTACHMENT0,
10948 GL_COLOR_ATTACHMENT1,
10949 };
10950 glDrawBuffers(2, kDrawBuffers);
10951
10952 // Clear the first attachment to transparent green
10953 glClearColor(0, 1, 0, 0);
10954 glClear(GL_COLOR_BUFFER_BIT);
10955
10956 // Clear the second attachment to transparent blue
10957 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10958 glClearColor(0, 0, 1, 0);
10959 glClear(GL_COLOR_BUFFER_BIT);
10960 ASSERT_GL_NO_ERROR();
10961
10962 // Draw with only one attachment. Attachment 0 is now transparent yellow-ish.
10963 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10964 glUniform4f(colorUni, 0.6, 0, 0, 0);
10965 glDrawArrays(GL_TRIANGLES, 0, 6);
10966
10967 // Attach the second renderbuffer and draw to both. Attachment 0 is now yellow-ish, while
10968 // attachment 1 is blue.
10969 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, color1);
10970 glUniform4f(colorUni, 0, 0, 0, 1);
10971 glDrawArrays(GL_TRIANGLES, 0, 6);
10972
10973 // Detach the second renderbuffer again and draw. Attachment 0 is now yellow.
10974 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, 0);
10975 glUniform4f(colorUni, 0.6, 0, 0, 0);
10976 glDrawArrays(GL_TRIANGLES, 0, 6);
10977
10978 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10979 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10980 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
10981 ASSERT_GL_NO_ERROR();
10982 }
10983
10984 // Tests state change for sample shading.
TEST_P(StateChangeTestES31,SampleShading)10985 TEST_P(StateChangeTestES31, SampleShading)
10986 {
10987 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
10988 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
10989
10990 constexpr GLsizei kSize = 1;
10991 constexpr GLsizei kSampleCount = 4;
10992
10993 // Create a single sampled texture and framebuffer for verifying results
10994 GLFramebuffer fbo;
10995 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10996
10997 GLTexture texture;
10998 glBindTexture(GL_TEXTURE_2D, texture);
10999 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
11000 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11001 ASSERT_GL_NO_ERROR();
11002 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11003
11004 // Create a multisampled texture and framebuffer.
11005 GLFramebuffer msaaFBO;
11006 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
11007
11008 GLTexture msaaTexture;
11009 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
11010 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
11011 false);
11012 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
11013 msaaTexture, 0);
11014 ASSERT_GL_NO_ERROR();
11015 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11016
11017 // Create a fragment shader whose _resolved_ output is different based on whether sample shading
11018 // is enabled or not, but which doesn't use gl_SampleID (which implicitly enables sample
11019 // shading).
11020 //
11021 // This is done by non-linearly transforming a varying, resulting in a different color average
11022 // based on the location in which the varying is sampled. The framebuffer is 1x1 and the vertex
11023 // shader outputs the following triangle:
11024 //
11025 // (-3, 3)
11026 // |\
11027 // | \
11028 // | \
11029 // | \
11030 // | \
11031 // | \
11032 // +-----------+ <----- position evaluates as (1, 1)
11033 // | X | \
11034 // | W | \
11035 // | C | \
11036 // | Z | \
11037 // | Y | \
11038 // +-----------+-----------\
11039 // (-1, -1) (3, -1)
11040 //
11041 // The varying |gradient| is output as position. This means that:
11042 //
11043 // - At the center of the pixel (C), the |gradient| value is (0,0)
11044 // - At sample positions W, X, Y and Z, the |gradient| has 0.75 and 0.25 (positive or negative)
11045 // in its components. Most importantly, its length^2 (i.e. gradient.gradient) is:
11046 //
11047 // 0.25^2 + 0.75^2 = 0.625
11048 //
11049 // The fragment shader outputs gradient.gradient + (0.1, 0) as color. Without sample shading,
11050 // this outputs (0.1, 0, 0, 1) in the color. With sample shading, it outputs
11051 // (0.725, 0.625, 0, 1) (for all samples). By using additive blending, we can verify that when
11052 // only sample shading state is modified, that sample shading is indeed toggled.
11053 //
11054 constexpr char kVS[] = R"(#version 300 es
11055
11056 out mediump vec2 gradient;
11057
11058 void main()
11059 {
11060 vec2 position = vec2(-1, -1);
11061 if (gl_VertexID == 1)
11062 position = vec2(3, -1);
11063 else if (gl_VertexID == 2)
11064 position = vec2(-1, 3);
11065
11066 gradient = position;
11067 gl_Position = vec4(position, 0, 1);
11068 })";
11069
11070 constexpr char kFS[] = R"(#version 300 es
11071
11072 in mediump vec2 gradient;
11073 out mediump vec4 color;
11074
11075 uniform mediump vec2 offset;
11076
11077 void main()
11078 {
11079 mediump float len = dot(gradient, gradient);
11080 color = vec4(vec2(len, len) + offset, 0, 1);
11081 })";
11082
11083 ANGLE_GL_PROGRAM(program, kVS, kFS);
11084 glUseProgram(program);
11085 GLint offsetLoc = glGetUniformLocation(program, "offset");
11086 ASSERT_NE(offsetLoc, -1);
11087
11088 glClearColor(0, 0, 0, 0);
11089 glClear(GL_COLOR_BUFFER_BIT);
11090
11091 glEnable(GL_BLEND);
11092 glBlendFunc(GL_ONE, GL_ONE);
11093
11094 glViewport(0, 0, kSize, kSize);
11095
11096 // Issue 2 draw calls, with sample shading enabled then disabled.
11097 glUniform2f(offsetLoc, 0.1f, 0);
11098
11099 glEnable(GL_SAMPLE_SHADING_OES);
11100 glMinSampleShadingOES(1.0f);
11101 glDrawArrays(GL_TRIANGLES, 0, 3);
11102 glDisable(GL_SAMPLE_SHADING_OES);
11103 glDrawArrays(GL_TRIANGLES, 0, 3);
11104
11105 // Verify results
11106 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11107 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11108 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11109 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(210, 159, 0, 255), 1);
11110
11111 // Do the same test in opposite order (sample shading disabled first, then enabled).
11112 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
11113
11114 glUniform2f(offsetLoc, 0, 0.1f);
11115
11116 glClear(GL_COLOR_BUFFER_BIT);
11117 glDrawArrays(GL_TRIANGLES, 0, 3);
11118 glEnable(GL_SAMPLE_SHADING_OES);
11119 glDrawArrays(GL_TRIANGLES, 0, 3);
11120
11121 // Verify results
11122 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11123 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11124 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11125 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(159, 210, 0, 255), 1);
11126
11127 ASSERT_GL_NO_ERROR();
11128 }
11129
11130 // Tests value change for MinSampleShadingOES.
TEST_P(StateChangeTestES31,MinSampleShadingOES)11131 TEST_P(StateChangeTestES31, MinSampleShadingOES)
11132 {
11133 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
11134 ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_sample_variables"));
11135
11136 GLfloat value = 0.0f;
11137 glEnable(GL_SAMPLE_SHADING_OES);
11138 EXPECT_GL_TRUE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11139 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11140 ASSERT_EQ(value, 0); // initial value should be 0.
11141
11142 glDisable(GL_SAMPLE_SHADING_OES);
11143 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11144 ASSERT_EQ(value, 0);
11145
11146 glMinSampleShadingOES(0.5);
11147 EXPECT_GL_FALSE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11148 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11149 ASSERT_EQ(value, 0.5);
11150
11151 glMinSampleShadingOES(1.5);
11152 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11153 ASSERT_EQ(value, 1); // clamped to 1.
11154
11155 glMinSampleShadingOES(-0.5);
11156 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11157 ASSERT_EQ(value, 0); // clamped to 0.
11158 }
11159
11160 // Tests state changes with uniform block binding.
TEST_P(StateChangeTestES3,UniformBlockBinding)11161 TEST_P(StateChangeTestES3, UniformBlockBinding)
11162 {
11163 constexpr char kVS[] = R"(#version 300 es
11164 void main()
11165 {
11166 vec2 pos = vec2(0.0);
11167 switch (gl_VertexID) {
11168 case 0: pos = vec2(-1.0, -1.0); break;
11169 case 1: pos = vec2(3.0, -1.0); break;
11170 case 2: pos = vec2(-1.0, 3.0); break;
11171 };
11172 gl_Position = vec4(pos, 0.0, 1.0);
11173 })";
11174 constexpr char kFS[] = R"(#version 300 es
11175 out mediump vec4 colorOut;
11176
11177 layout(std140) uniform buffer { mediump vec4 color; };
11178
11179 void main()
11180 {
11181 colorOut = color;
11182 })";
11183
11184 ANGLE_GL_PROGRAM(program, kVS, kFS);
11185 glUseProgram(program);
11186 const GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
11187
11188 // Create buffers bound to bindings 1 and 2
11189 constexpr std::array<float, 4> kRed = {1, 0, 0, 1};
11190 constexpr std::array<float, 4> kTransparentGreen = {0, 1, 0, 0};
11191 GLBuffer red, transparentGreen;
11192 glBindBuffer(GL_UNIFORM_BUFFER, red);
11193 glBufferData(GL_UNIFORM_BUFFER, sizeof(kRed), kRed.data(), GL_STATIC_DRAW);
11194 glBindBuffer(GL_UNIFORM_BUFFER, transparentGreen);
11195 glBufferData(GL_UNIFORM_BUFFER, sizeof(kTransparentGreen), kTransparentGreen.data(),
11196 GL_STATIC_DRAW);
11197
11198 glBindBufferBase(GL_UNIFORM_BUFFER, 1, transparentGreen);
11199 glBindBufferBase(GL_UNIFORM_BUFFER, 2, red);
11200 glUniformBlockBinding(program, uniformBufferIndex, 2);
11201
11202 // Issue a draw call. The buffer should be transparent green now
11203 glClearColor(0, 0, 0, 0);
11204 glClear(GL_COLOR_BUFFER_BIT);
11205 glEnable(GL_BLEND);
11206 glBlendFunc(GL_ONE, GL_ONE);
11207
11208 glUseProgram(program);
11209 glDrawArrays(GL_TRIANGLES, 0, 3);
11210
11211 // Change the binding
11212 glUniformBlockBinding(program, uniformBufferIndex, 1);
11213 ASSERT_GL_NO_ERROR();
11214
11215 // Draw again, it should accumulate blue and the buffer should become magenta.
11216 glDrawArrays(GL_TRIANGLES, 0, 3);
11217
11218 // Verify results
11219 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
11220 ASSERT_GL_NO_ERROR();
11221 }
11222
11223 // Tests that viewport changes within a render pass are correct. WebGPU sets a default viewport,
11224 // cover the omission of setViewport in the backend.
TEST_P(StateChangeTest,ViewportChangeWithinRenderPass)11225 TEST_P(StateChangeTest, ViewportChangeWithinRenderPass)
11226 {
11227 glClearColor(0, 0, 0, 0);
11228 glClear(GL_COLOR_BUFFER_BIT);
11229
11230 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11231 glUseProgram(program);
11232 GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11233
11234 glViewport(0, 0, 10, 10);
11235 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11236 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11237
11238 glViewport(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11239 glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11240 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11241
11242 // Verify that the first draw is covered by the second "full" draw
11243 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11244 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11245
11246 // Go the other way, start with a full size viewport and change it to 10x10 for the second draw
11247 glViewport(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11248 glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11249 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11250
11251 glViewport(0, 0, 10, 10);
11252 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11253 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11254
11255 // Verify that the first draw is covered by the second "full" draw
11256 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11257 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11258 }
11259
11260 // Tests that scissor changes within a render pass are correct. WebGPU sets a default scissor, cover
11261 // the omission of setScissorRect in the backend.
TEST_P(StateChangeTest,ScissortChangeWithinRenderPass)11262 TEST_P(StateChangeTest, ScissortChangeWithinRenderPass)
11263 {
11264 glClearColor(0, 0, 0, 0);
11265 glClear(GL_COLOR_BUFFER_BIT);
11266 glEnable(GL_SCISSOR_TEST);
11267
11268 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11269 glUseProgram(program);
11270 GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11271
11272 glScissor(0, 0, 10, 10);
11273 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11274 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11275
11276 glScissor(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11277 glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11278 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11279
11280 // Verify that the first draw is covered by the second "full" draw
11281 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11282 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11283
11284 // Go the other way, start with a full size scissor and change it to 10x10 for the second draw
11285 glScissor(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11286 glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11287 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11288
11289 glScissor(0, 0, 10, 10);
11290 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11291 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11292
11293 // Verify that the first draw is covered by the second "full" draw
11294 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11295 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11296 }
11297
11298 } // anonymous namespace
11299
11300 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
11301 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
11302 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
11303
11304 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
11305 ANGLE_INSTANTIATE_TEST_ES3_AND(
11306 StateChangeTestES3,
11307 ES3_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11308 ES3_VULKAN().disable(Feature::UseDepthWriteEnableDynamicState),
11309 ES3_VULKAN()
11310 .disable(Feature::SupportsExtendedDynamicState)
11311 .disable(Feature::SupportsExtendedDynamicState2),
11312 ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11313 ES3_VULKAN()
11314 .disable(Feature::SupportsExtendedDynamicState2)
11315 .disable(Feature::SupportsGraphicsPipelineLibrary),
11316 ES3_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11317 ES3_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11318
11319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES31);
11320 ANGLE_INSTANTIATE_TEST_ES31_AND(
11321 StateChangeTestES31,
11322 ES31_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11323 ES31_VULKAN()
11324 .disable(Feature::SupportsExtendedDynamicState)
11325 .disable(Feature::SupportsExtendedDynamicState2),
11326 ES31_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11327 ES31_VULKAN()
11328 .disable(Feature::SupportsExtendedDynamicState2)
11329 .disable(Feature::SupportsGraphicsPipelineLibrary),
11330 ES31_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11331 ES31_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11332
11333 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestWebGL2);
11334 ANGLE_INSTANTIATE_TEST_COMBINE_1(StateChangeTestWebGL2,
11335 StateChangeTestWebGL2Print,
11336 testing::Bool(),
11337 ANGLE_ALL_TEST_PLATFORMS_ES3);
11338
11339 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
11340 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
11341
11342 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
11343
11344 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
11345 ANGLE_INSTANTIATE_TEST_ES3_AND(
11346 SimpleStateChangeTestES3,
11347 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory),
11348 ES3_VULKAN().disable(Feature::PreferSkippingInvalidateForEmulatedFormats));
11349
11350 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
11351 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
11352
11353 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
11354 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
11355
11356 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
11357 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
11358
11359 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
11360 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
11361
11362 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
11363 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
11364
11365 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
11366 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
11367
11368 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
11369 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
11370
11371 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
11372 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
11373
11374 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
11375 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
11376
11377 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttribArrayStateChangeTest);
11378 ANGLE_INSTANTIATE_TEST_ES3(VertexAttribArrayStateChangeTest);
11379