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 // Invalidate an RGB framebuffer and verify that the alpha channel is not destroyed, even if the
3351 // color channels may be garbage.
TEST_P(SimpleStateChangeTestES3,DrawAndInvalidateRGBThenVerifyAlpha)3352 TEST_P(SimpleStateChangeTestES3, DrawAndInvalidateRGBThenVerifyAlpha)
3353 {
3354 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3355 glUseProgram(drawColor);
3356 GLint uniformLocation = glGetUniformLocation(drawColor, essl1_shaders::ColorUniform());
3357 ASSERT_NE(uniformLocation, -1);
3358
3359 const int w = getWindowWidth();
3360 const int h = getWindowHeight();
3361
3362 GLTexture texture;
3363 glBindTexture(GL_TEXTURE_2D, texture);
3364 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
3365
3366 GLFramebuffer fbo;
3367 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3368 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3369 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3370 ASSERT_GL_NO_ERROR();
3371
3372 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3373 glClear(GL_COLOR_BUFFER_BIT);
3374
3375 glUniform4f(uniformLocation, 0.1f, 0.2f, 0.3f, 0.4f);
3376 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3377
3378 // Invalidate the framebuffer contents.
3379 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3380 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3381
3382 // Read back the contents of the framebuffer. The color channels are invalid, but as an RGB
3383 // format, readback should always return 1 in alpha.
3384 std::vector<GLColor> readback(w * h);
3385 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, readback.data());
3386 for (int y = 0; y < h; ++y)
3387 {
3388 for (int x = 0; x < w; ++x)
3389 {
3390 EXPECT_EQ(readback[y * w + x].A, 255) << x << " " << y;
3391 }
3392 }
3393 }
3394
3395 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3396 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
3397 {
3398 constexpr int kSize = 16;
3399
3400 // Create a simple framebuffer.
3401 GLTexture texture;
3402 glBindTexture(GL_TEXTURE_2D, texture);
3403 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3404
3405 GLFramebuffer framebuffer;
3406 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3407 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3408 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3409
3410 glViewport(0, 0, kSize, kSize);
3411
3412 // Draw a solid red color to the framebuffer.
3413 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3414 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3415
3416 // Delete the framebuffer while the call is in flight.
3417 framebuffer.reset();
3418
3419 // Make a new framebuffer so we can read back the texture.
3420 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3421 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3422 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3423
3424 // Flush via ReadPixels and check red was drawn.
3425 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3426 ASSERT_GL_NO_ERROR();
3427 }
3428
3429 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3430 // buffers too early. The test has 2 textures, we first create a texture and update it with
3431 // multiple updates, but we don't use it right away, we instead draw using another texture
3432 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3433 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3434 {
3435 constexpr int kSize = 64;
3436
3437 GLuint program = get2DTexturedQuadProgram();
3438 glUseProgram(program);
3439
3440 std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3441 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3442 GLTexture texture1;
3443 glBindTexture(GL_TEXTURE_2D, texture1);
3444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3445
3446 for (int i = 0; i < 100; i++)
3447 {
3448 // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3449 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3450 greenPixels.data());
3451 }
3452 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3454
3455 ASSERT_GL_NO_ERROR();
3456
3457 GLTexture texture2;
3458 glBindTexture(GL_TEXTURE_2D, texture2);
3459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3462
3463 // Setup the vertex array to draw a quad.
3464 GLint positionLocation = glGetAttribLocation(program, "position");
3465 setupQuadVertexBuffer(1.0f, 1.0f);
3466 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3467 glEnableVertexAttribArray(positionLocation);
3468
3469 // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3470 glBindTexture(GL_TEXTURE_2D, texture2);
3471 glDrawArrays(GL_TRIANGLES, 0, 6);
3472 ASSERT_GL_NO_ERROR();
3473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3474
3475 // If we now try to draw with texture1, we should trigger the issue.
3476 glBindTexture(GL_TEXTURE_2D, texture1);
3477 glDrawArrays(GL_TRIANGLES, 0, 6);
3478 ASSERT_GL_NO_ERROR();
3479
3480 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3481 }
3482
3483 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3484 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3485 {
3486 constexpr int kSize = 16;
3487
3488 // Create a simple framebuffer.
3489 GLTexture texture;
3490 glBindTexture(GL_TEXTURE_2D, texture);
3491 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3492
3493 GLFramebuffer framebuffer;
3494 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3495 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3496 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3497
3498 glViewport(0, 0, kSize, kSize);
3499
3500 // Draw red to the framebuffer.
3501 simpleDrawWithColor(GLColor::red);
3502
3503 // Change the framebuffer while the call is in flight to a new texture.
3504 GLTexture otherTexture;
3505 glBindTexture(GL_TEXTURE_2D, otherTexture);
3506 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3507
3508 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3509 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3510
3511 // Draw green to the framebuffer. Verify the color.
3512 simpleDrawWithColor(GLColor::green);
3513 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3514
3515 // Make a new framebuffer so we can read back the first texture and verify red.
3516 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3517 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3518 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3519
3520 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3521 ASSERT_GL_NO_ERROR();
3522 }
3523
3524 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3525 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3526 {
3527 GLFramebuffer framebuffer;
3528 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3529
3530 // Bind a simple 8x8 texture to the framebuffer, draw red.
3531 GLTexture texture;
3532 glBindTexture(GL_TEXTURE_2D, texture);
3533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3534 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3535
3536 glViewport(0, 0, 8, 8);
3537 simpleDrawWithColor(GLColor::red);
3538 ASSERT_GL_NO_ERROR();
3539 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3540
3541 // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3542 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3543 glViewport(0, 0, 32, 32);
3544 simpleDrawWithColor(GLColor::green);
3545 ASSERT_GL_NO_ERROR();
3546 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3547 }
3548
3549 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3550 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3551 {
3552 // Fails on 431.02 driver. http://anglebug.com/40644697
3553 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3554
3555 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3556 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3557
3558 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3559
3560 GLTexture tex;
3561 glBindTexture(GL_TEXTURE_2D, tex);
3562 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3564 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3565 ASSERT_GL_NO_ERROR();
3566
3567 GLFramebuffer fbo;
3568 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3569 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3570 ASSERT_GL_NO_ERROR();
3571 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3572
3573 glUseProgram(program);
3574
3575 GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3576 ASSERT_NE(-1, uniLoc);
3577 glUniform1i(uniLoc, 0);
3578
3579 const int numRowsCols = 2;
3580 const int cellSize = getWindowWidth() / 2;
3581
3582 for (int cellY = 0; cellY < numRowsCols; cellY++)
3583 {
3584 for (int cellX = 0; cellX < numRowsCols; cellX++)
3585 {
3586 int seed = cellX + cellY * numRowsCols;
3587 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3588
3589 // Set the texture to a constant color using glClear and a user FBO.
3590 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3591 glClearColor(color[0], color[1], color[2], color[3]);
3592 glClear(GL_COLOR_BUFFER_BIT);
3593
3594 // Draw a small colored quad to the default FBO using the viewport.
3595 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3596 glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3597 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3598 }
3599 }
3600
3601 // Verify the colored quads were drawn correctly despite no flushing.
3602 std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3603 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3604 pixelData.data());
3605
3606 ASSERT_GL_NO_ERROR();
3607
3608 for (int cellY = 0; cellY < numRowsCols; cellY++)
3609 {
3610 for (int cellX = 0; cellX < numRowsCols; cellX++)
3611 {
3612 int seed = cellX + cellY * numRowsCols;
3613 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3614
3615 GLColor expectedColor(color);
3616
3617 int testN =
3618 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3619 GLColor actualColor = pixelData[testN];
3620 EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3621 }
3622 }
3623 }
3624
3625 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3626 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3627 {
3628 // Create a texture with red
3629 const GLColor kInitColor1 = GLColor::red;
3630 GLTexture texture1;
3631 glBindTexture(GL_TEXTURE_2D, texture1);
3632 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3633
3634 // Create a framebuffer to be cleared
3635 GLTexture texture2;
3636 glBindTexture(GL_TEXTURE_2D, texture2);
3637 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3638
3639 GLFramebuffer drawFBO;
3640 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3641 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3642 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3643
3644 EXPECT_GL_NO_ERROR();
3645
3646 // Clear the framebuffer to green
3647 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3648 glClear(GL_COLOR_BUFFER_BIT);
3649
3650 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3651 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3652 // a noop, the deferred clears will remain unflushed.
3653 glClear(0);
3654
3655 // Change framebuffer's attachment to the other texture.
3656 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3657 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3658
3659 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3660 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3661 glUseProgram(program);
3662
3663 glEnable(GL_BLEND);
3664 glBlendFunc(GL_ZERO, GL_ONE);
3665 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3666 EXPECT_GL_NO_ERROR();
3667
3668 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3669 // to the new attachment, green will be read back.
3670 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3671
3672 // Attach back to texture2. It should be cleared to green.
3673 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3674 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3675 }
3676
3677 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3678 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3679 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3680 {
3681 // Create a texture with red
3682 const GLColor kInitColor1 = GLColor::red;
3683 GLTexture texture1;
3684 glBindTexture(GL_TEXTURE_2D, texture1);
3685 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3686
3687 // Create a framebuffer to be cleared
3688 GLTexture texture2;
3689 glBindTexture(GL_TEXTURE_2D, texture2);
3690 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3691
3692 GLFramebuffer drawFBO;
3693 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3694 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3695 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3696
3697 EXPECT_GL_NO_ERROR();
3698
3699 // Clear the framebuffer to green
3700 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3701 glClear(GL_COLOR_BUFFER_BIT);
3702
3703 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3704 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3705 // a noop, the deferred clears will remain unflushed.
3706 glEnable(GL_SCISSOR_TEST);
3707 glScissor(0, 0, 0, 0);
3708 glClear(GL_COLOR_BUFFER_BIT);
3709 glDisable(GL_SCISSOR_TEST);
3710
3711 // Change framebuffer's attachment to the other texture.
3712 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3713 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3714
3715 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3716 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3717 glUseProgram(program);
3718
3719 glEnable(GL_BLEND);
3720 glBlendFunc(GL_ZERO, GL_ONE);
3721 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3722 EXPECT_GL_NO_ERROR();
3723
3724 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3725 // to the new attachment, green will be read back.
3726 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3727
3728 // Attach back to texture2. It should be cleared to green.
3729 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3730 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3731 }
3732
3733 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3734 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3735 {
3736 // Create a texture with red
3737 const GLColor kInitColor1 = GLColor::red;
3738 GLTexture texture1;
3739 glBindTexture(GL_TEXTURE_2D, texture1);
3740 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3741
3742 // Create a framebuffer to be cleared
3743 GLTexture texture2;
3744 glBindTexture(GL_TEXTURE_2D, texture2);
3745 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3746
3747 GLFramebuffer drawFBO;
3748 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3749 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3750 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3751
3752 EXPECT_GL_NO_ERROR();
3753
3754 // Clear the framebuffer to green
3755 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3756 glClear(GL_COLOR_BUFFER_BIT);
3757
3758 // Issue noop blit. In the Vulkan backend, this will result in a framebuffer sync state, which
3759 // extracts deferred clears. However, as the blit is actually a noop, the deferred clears will
3760 // remain unflushed.
3761 GLTexture blitSrc;
3762 glBindTexture(GL_TEXTURE_2D, blitSrc);
3763 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3764
3765 GLFramebuffer readFBO;
3766 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3767 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3768 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3769
3770 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3771 EXPECT_GL_NO_ERROR();
3772
3773 // Change framebuffer's attachment to the other texture.
3774 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3775 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3776
3777 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3778 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3779 glUseProgram(program);
3780
3781 glEnable(GL_BLEND);
3782 glBlendFunc(GL_ZERO, GL_ONE);
3783 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3784 EXPECT_GL_NO_ERROR();
3785
3786 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3787 // to the new attachment, green will be read back.
3788 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3789 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3790
3791 // Attach back to texture2. It should be cleared to green.
3792 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3793 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3794 }
3795
3796 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3797 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3798 {
3799 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3800 glUseProgram(program);
3801
3802 glClear(GL_COLOR_BUFFER_BIT);
3803 glEnable(GL_CULL_FACE);
3804
3805 glCullFace(GL_FRONT);
3806
3807 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3808
3809 ASSERT_GL_NO_ERROR();
3810
3811 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3812
3813 // Disable cull face and redraw, then make sure we have the quad drawn.
3814 glDisable(GL_CULL_FACE);
3815
3816 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3817
3818 ASSERT_GL_NO_ERROR();
3819
3820 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3821 }
3822
TEST_P(SimpleStateChangeTest,ScissorTest)3823 TEST_P(SimpleStateChangeTest, ScissorTest)
3824 {
3825 // This test validates this order of state changes:
3826 // 1- Set scissor but don't enable it, validate its not used.
3827 // 2- Enable it and validate its working.
3828 // 3- Disable the scissor validate its not used anymore.
3829
3830 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3831
3832 glClear(GL_COLOR_BUFFER_BIT);
3833
3834 // Set the scissor region, but don't enable it yet.
3835 glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3836 getWindowHeight() / 2);
3837
3838 // Fill the whole screen with a quad.
3839 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3840
3841 ASSERT_GL_NO_ERROR();
3842
3843 // Test outside, scissor isnt enabled so its red.
3844 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3845
3846 // Test inside, red of the fragment shader.
3847 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3848
3849 // Clear everything and start over with the test enabled.
3850 glClear(GL_COLOR_BUFFER_BIT);
3851 glEnable(GL_SCISSOR_TEST);
3852
3853 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3854
3855 ASSERT_GL_NO_ERROR();
3856
3857 // Test outside the scissor test, pitch black.
3858 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3859
3860 // Test inside, red of the fragment shader.
3861 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3862
3863 // Now disable the scissor test, do it again, and verify the region isn't used
3864 // for the scissor test.
3865 glDisable(GL_SCISSOR_TEST);
3866
3867 // Clear everything and start over with the test enabled.
3868 glClear(GL_COLOR_BUFFER_BIT);
3869
3870 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3871
3872 ASSERT_GL_NO_ERROR();
3873
3874 // Test outside, scissor isnt enabled so its red.
3875 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3876
3877 // Test inside, red of the fragment shader.
3878 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3879 }
3880
3881 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3882 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3883 {
3884 constexpr char kPositionUniformVertexShader[] = R"(
3885 precision mediump float;
3886 attribute vec2 position;
3887 uniform vec2 uniPosModifier;
3888 void main()
3889 {
3890 gl_Position = vec4(position + uniPosModifier, 0, 1);
3891 })";
3892
3893 ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3894 glUseProgram(program);
3895
3896 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3897 glClear(GL_COLOR_BUFFER_BIT);
3898
3899 GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3900 ASSERT_NE(posUniformLocation, -1);
3901 GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3902 ASSERT_NE(colorUniformLocation, -1);
3903
3904 // draw a red quad to the left side.
3905 glUniform2f(posUniformLocation, -0.5, 0.0);
3906 glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3907 drawQuad(program, "position", 0.0f, 0.5f, true);
3908
3909 // draw a green quad to the right side.
3910 glUniform2f(posUniformLocation, 0.5, 0.0);
3911 glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3912 drawQuad(program, "position", 0.0f, 0.5f, true);
3913
3914 ASSERT_GL_NO_ERROR();
3915
3916 // Test the center of the left quad. Should be red.
3917 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3918
3919 // Test the center of the right quad. Should be green.
3920 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3921 }
3922
3923 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3924 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3925 {
3926 GLRenderbuffer renderbuffer;
3927 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3928 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3929
3930 GLFramebuffer framebuffer;
3931 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3932 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3933
3934 ASSERT_GL_NO_ERROR();
3935 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3936
3937 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3938 GLint colorLoc = glGetAttribLocation(program, "color");
3939 ASSERT_NE(-1, colorLoc);
3940
3941 // Set up and draw red to the left half the screen.
3942 std::vector<GLColor> redData(6, GLColor::red);
3943 GLBuffer vertexBufferRed;
3944 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3945 glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3946 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3947 glEnableVertexAttribArray(colorLoc);
3948
3949 glViewport(0, 0, 16, 16);
3950 drawQuad(program, "position", 0.5f, 1.0f, true);
3951
3952 // Immediately redefine the Renderbuffer.
3953 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3954
3955 // Set up and draw green to the right half of the screen.
3956 std::vector<GLColor> greenData(6, GLColor::green);
3957 GLBuffer vertexBufferGreen;
3958 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3959 glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3960 GL_STATIC_DRAW);
3961 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3962 glEnableVertexAttribArray(colorLoc);
3963
3964 glViewport(0, 0, 64, 64);
3965 drawQuad(program, "position", 0.5f, 1.0f, true);
3966
3967 ASSERT_GL_NO_ERROR();
3968 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3969 }
3970
3971 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
3972 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)3973 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
3974 {
3975 constexpr size_t kSmallTextureSize = 2;
3976 constexpr size_t kBigTextureSize = 4;
3977
3978 // Create 2 textures, one of 2x2 and the other 4x4
3979 GLTexture texture1;
3980 glBindTexture(GL_TEXTURE_2D, texture1);
3981 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
3982 GL_UNSIGNED_BYTE, nullptr);
3983 ASSERT_GL_NO_ERROR();
3984
3985 GLTexture texture2;
3986 glBindTexture(GL_TEXTURE_2D, texture2);
3987 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
3988 GL_UNSIGNED_BYTE, nullptr);
3989 ASSERT_GL_NO_ERROR();
3990
3991 // A framebuffer for each texture to draw on.
3992 GLFramebuffer framebuffer1;
3993 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3994 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3995 ASSERT_GL_NO_ERROR();
3996 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3997
3998 GLFramebuffer framebuffer2;
3999 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4000 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
4001 ASSERT_GL_NO_ERROR();
4002 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4003
4004 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4005 glUseProgram(program);
4006 GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4007 ASSERT_NE(uniformLocation, -1);
4008
4009 // Bind to the first framebuffer for drawing.
4010 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4011
4012 // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
4013 // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
4014 glScissor(0, 0, 16, 16);
4015 ASSERT_GL_NO_ERROR();
4016
4017 // Set color to red.
4018 glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4019 glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
4020
4021 // Draw a full sized red quad
4022 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4023 ASSERT_GL_NO_ERROR();
4024
4025 // Bind to the second (bigger) framebuffer
4026 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4027 glViewport(0, 0, kBigTextureSize, kBigTextureSize);
4028
4029 ASSERT_GL_NO_ERROR();
4030
4031 // Set color to green.
4032 glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4033
4034 // Draw again and we should fill everything with green and expect everything to be green.
4035 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4036 ASSERT_GL_NO_ERROR();
4037
4038 EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
4039 }
4040
4041 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)4042 TEST_P(SimpleStateChangeTest, RelinkProgram)
4043 {
4044 // http://anglebug.com/40644706
4045 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
4046 const GLuint program = glCreateProgram();
4047
4048 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
4049 GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
4050 GLuint redFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
4051
4052 glAttachShader(program, vs);
4053 glAttachShader(program, blueFs);
4054
4055 glLinkProgram(program);
4056 CheckLinkStatusAndReturnProgram(program, true);
4057
4058 glClear(GL_COLOR_BUFFER_BIT);
4059 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
4060 {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
4061 GLBuffer vertexBuffer;
4062 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4063 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4064 GL_STATIC_DRAW);
4065 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4066 ASSERT_NE(-1, positionLocation);
4067 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4068 glEnableVertexAttribArray(positionLocation);
4069
4070 // Draw a blue triangle to the right
4071 glUseProgram(program);
4072 glDrawArrays(GL_TRIANGLES, 0, 3);
4073
4074 // Relink to draw red to the left
4075 glDetachShader(program, blueFs);
4076 glAttachShader(program, redFs);
4077
4078 glLinkProgram(program);
4079 CheckLinkStatusAndReturnProgram(program, true);
4080
4081 glDrawArrays(GL_TRIANGLES, 3, 3);
4082
4083 ASSERT_GL_NO_ERROR();
4084
4085 glDisableVertexAttribArray(positionLocation);
4086
4087 // Verify we drew red and green in the right places.
4088 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
4089 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
4090
4091 glDeleteShader(vs);
4092 glDeleteShader(blueFs);
4093 glDeleteShader(redFs);
4094 glDeleteProgram(program);
4095 }
4096
4097 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
4098 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)4099 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
4100 {
4101 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4102 glUseProgram(program);
4103
4104 const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4105 EXPECT_NE(-1, uniformLoc);
4106
4107 // Set color to red.
4108 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4109
4110 glClear(GL_COLOR_BUFFER_BIT);
4111 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
4112 GLBuffer vertexBuffer;
4113 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4114 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4115 GL_STATIC_DRAW);
4116 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4117 ASSERT_NE(-1, positionLocation);
4118 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4119 glEnableVertexAttribArray(positionLocation);
4120
4121 // Release program while its in use.
4122 glDeleteProgram(program);
4123
4124 // Draw a red triangle
4125 glDrawArrays(GL_TRIANGLES, 0, 3);
4126
4127 // Set color to green
4128 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4129
4130 // Draw a green triangle
4131 glDrawArrays(GL_TRIANGLES, 0, 3);
4132
4133 ASSERT_GL_NO_ERROR();
4134
4135 glDisableVertexAttribArray(positionLocation);
4136
4137 glUseProgram(0);
4138
4139 // Verify we drew red in the end since thats the last draw.
4140 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
4141 }
4142
4143 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)4144 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
4145 {
4146 // Create a sampler with NEAREST filtering.
4147 GLSampler sampler;
4148 glBindSampler(0, sampler);
4149 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4150 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4151 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4152 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4153 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4154 ASSERT_GL_NO_ERROR();
4155
4156 // Draw with a program that uses no textures.
4157 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4158 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
4159 ASSERT_GL_NO_ERROR();
4160 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4161
4162 // Create a simple texture with four colors and linear filtering.
4163 constexpr GLsizei kSize = 2;
4164 std::array<GLColor, 4> pixels = {
4165 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4166 GLTexture redTex;
4167 glBindTexture(GL_TEXTURE_2D, redTex);
4168 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4169 pixels.data());
4170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4175
4176 // Create a program that uses the texture.
4177 constexpr char kVS[] = R"(attribute vec4 position;
4178 varying vec2 texCoord;
4179 void main()
4180 {
4181 gl_Position = position;
4182 texCoord = position.xy * 0.5 + vec2(0.5);
4183 })";
4184
4185 constexpr char kFS[] = R"(precision mediump float;
4186 varying vec2 texCoord;
4187 uniform sampler2D tex;
4188 void main()
4189 {
4190 gl_FragColor = texture2D(tex, texCoord);
4191 })";
4192
4193 // Draw. The sampler should override the clamp wrap mode with nearest.
4194 ANGLE_GL_PROGRAM(program2, kVS, kFS);
4195 ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
4196 drawQuad(program2, "position", 0.5f);
4197 ASSERT_GL_NO_ERROR();
4198
4199 constexpr int kHalfSize = kWindowSize / 2;
4200
4201 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4202 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4203 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4204 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4205 }
4206
4207 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)4208 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
4209 {
4210 // Test overview - Create two separate sampler objects, initially with the same
4211 // sampling args (NEAREST). Bind the same texture object to separate texture units.
4212 // FS samples from two samplers and blends result.
4213 // Bind separate sampler objects to the same texture units as the texture object.
4214 // Render & verify initial results
4215 // Next modify sampler0 to have LINEAR filtering instead of NEAREST
4216 // Render and save results
4217 // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
4218 // Render and verify results are the same as previous
4219
4220 // Create 2 samplers with NEAREST filtering.
4221 constexpr GLsizei kNumSamplers = 2;
4222 // We create/bind an extra sampler w/o bound tex object for testing purposes
4223 GLSampler samplers[kNumSamplers + 1];
4224 // Set samplers to initially have same state w/ NEAREST filter mode
4225 for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
4226 {
4227 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4228 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4229 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4230 glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4231 glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4232 glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
4233 glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
4234 glBindSampler(i, samplers[i]);
4235 ASSERT_GL_NO_ERROR();
4236 }
4237
4238 // Create a simple texture with four colors
4239 constexpr GLsizei kSize = 2;
4240 std::array<GLColor, 4> pixels = {
4241 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4242 GLTexture rgbyTex;
4243 // Bind same texture object to tex units 0 & 1
4244 glActiveTexture(GL_TEXTURE0);
4245 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4246 glActiveTexture(GL_TEXTURE1);
4247 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4248 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4249 pixels.data());
4250
4251 // Create a program that uses the texture with 2 separate samplers.
4252 constexpr char kFS[] = R"(precision mediump float;
4253 varying vec2 v_texCoord;
4254 uniform sampler2D samp1;
4255 uniform sampler2D samp2;
4256 void main()
4257 {
4258 gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
4259 })";
4260
4261 // Create program and bind samplers to tex units 0 & 1
4262 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
4263 GLint s1loc = glGetUniformLocation(program, "samp1");
4264 GLint s2loc = glGetUniformLocation(program, "samp2");
4265 glUseProgram(program);
4266 glUniform1i(s1loc, 0);
4267 glUniform1i(s2loc, 1);
4268 // Draw. This first draw is a confidence check and not really necessary for the test
4269 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4270 ASSERT_GL_NO_ERROR();
4271
4272 constexpr int kHalfSize = kWindowSize / 2;
4273
4274 // When rendering w/ NEAREST, colors are all maxed out so should still be solid
4275 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4276 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4277 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4278 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4279
4280 // Make first sampler use linear filtering
4281 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4282 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4283
4284 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4285 ASSERT_GL_NO_ERROR();
4286 // Capture rendered pixel color with s0 linear
4287 std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
4288 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
4289
4290 // Now restore first sampler & update second sampler
4291 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4292 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4293 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4294 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4295
4296 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4297 ASSERT_GL_NO_ERROR();
4298 // Capture rendered pixel color w/ s1 linear
4299 std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
4300 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
4301 // Results should be the same regardless of if s0 or s1 is linear
4302 EXPECT_EQ(s0LinearColors, s1LinearColors);
4303 }
4304
4305 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)4306 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
4307 {
4308 constexpr char kVertexShader[] = R"(attribute vec4 a_position;
4309 attribute vec4 a_color;
4310 varying vec4 v_color;
4311 void main()
4312 {
4313 gl_Position = a_position;
4314 v_color = a_color;
4315 })";
4316
4317 constexpr char kFragmentShader[] = R"(precision mediump float;
4318 varying vec4 v_color;
4319 void main()
4320 {
4321 gl_FragColor = v_color;
4322 })";
4323
4324 ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
4325 GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
4326 ASSERT_NE(-1, positionLoc);
4327 GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
4328 ASSERT_NE(-1, colorLoc);
4329
4330 GLVertexArray VAOS[2];
4331 GLBuffer positionBuffer;
4332 GLBuffer colorBuffer;
4333 const auto quadVertices = GetQuadVertices();
4334
4335 glBindVertexArray(VAOS[0]);
4336 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4337 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4338 GL_STATIC_DRAW);
4339 glEnableVertexAttribArray(positionLoc);
4340 glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4341
4342 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4343 std::vector<GLColor32F> blueColor(6, kFloatBlue);
4344 glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4345 GL_STATIC_DRAW);
4346 glEnableVertexAttribArray(colorLoc);
4347 glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4348
4349 glBindVertexArray(0);
4350 glBindBuffer(GL_ARRAY_BUFFER, 0);
4351
4352 glBindVertexArray(VAOS[1]);
4353 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4354 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4355 GL_STATIC_DRAW);
4356 glEnableVertexAttribArray(positionLoc);
4357 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4358
4359 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4360 std::vector<GLColor32F> greenColor(6, kFloatGreen);
4361 glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4362 GL_STATIC_DRAW);
4363 glEnableVertexAttribArray(colorLoc);
4364 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4365
4366 glBindVertexArray(0);
4367 glBindBuffer(GL_ARRAY_BUFFER, 0);
4368
4369 glUseProgram(mProgram);
4370 ASSERT_GL_NO_ERROR();
4371
4372 glBindVertexArray(VAOS[1]);
4373 glClear(GL_COLOR_BUFFER_BIT);
4374 glDrawArrays(GL_TRIANGLES, 0, 6);
4375
4376 // This drawing should not affect the next drawing.
4377 glBindVertexArray(VAOS[0]);
4378 glClear(GL_COLOR_BUFFER_BIT);
4379 glDrawArrays(GL_TRIANGLES, 0, 6);
4380
4381 glBindVertexArray(VAOS[1]);
4382 glClear(GL_COLOR_BUFFER_BIT);
4383 glDrawArrays(GL_TRIANGLES, 0, 6);
4384
4385 EXPECT_GL_NO_ERROR();
4386 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4387 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4388 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4389 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4390
4391 ASSERT_GL_NO_ERROR();
4392 }
4393
4394 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4395 // correctly. This requires a memory barrier in between the draw calls which should not be
4396 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4397 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4398 {
4399 // http://anglebug.com/42264124
4400 ANGLE_SKIP_TEST_IF(IsD3D11());
4401
4402 GLint maxFragmentImageUniforms;
4403 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4404
4405 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4406
4407 // The test uses a GL_R32F framebuffer.
4408 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4409
4410 constexpr GLsizei kSize = 1;
4411
4412 GLTexture color;
4413 glBindTexture(GL_TEXTURE_2D, color);
4414 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4415 EXPECT_GL_NO_ERROR();
4416
4417 GLFramebuffer fbo;
4418 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4419 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4420 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4421 EXPECT_GL_NO_ERROR();
4422
4423 const float kInitialValue = 0.125f;
4424
4425 GLTexture texture;
4426 glBindTexture(GL_TEXTURE_2D, texture);
4427 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4428 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4429 EXPECT_GL_NO_ERROR();
4430
4431 GLFramebuffer readbackFbo;
4432 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4433 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4434 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4435 EXPECT_GL_NO_ERROR();
4436
4437 // Create a program that outputs to the image in the fragment shader.
4438 constexpr char kFS[] = R"(#version 310 es
4439 precision mediump float;
4440 layout(r32f, binding = 0) uniform highp image2D dst;
4441 out vec4 colorOut;
4442 void main()
4443 {
4444 vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4445 colorOut = result;
4446
4447 result.x += 0.193;
4448 imageStore(dst, ivec2(gl_FragCoord.xy), result);
4449 })";
4450
4451 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4452 glUseProgram(program);
4453
4454 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4455 ASSERT_NE(-1, positionLoc);
4456
4457 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4458 EXPECT_GL_NO_ERROR();
4459
4460 // Setup the draw so that there's no state change between the draw calls.
4461 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4462 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4463
4464 GLBuffer posBuffer;
4465 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4466 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4467 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4468 glEnableVertexAttribArray(positionLoc);
4469 EXPECT_GL_NO_ERROR();
4470
4471 glDrawArrays(GL_TRIANGLES, 0, 6);
4472 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4473 glDrawArrays(GL_TRIANGLES, 0, 6);
4474 EXPECT_GL_NO_ERROR();
4475
4476 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4477 EXPECT_GL_NO_ERROR();
4478
4479 // Verify the output of the two draw calls through the image is correct
4480 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4481 0.001f);
4482
4483 // Verify the output of rendering as well
4484 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4485 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4486 }
4487
4488 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4489 // draw call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4490 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4491 {
4492 // http://anglebug.com/42264124
4493 ANGLE_SKIP_TEST_IF(IsD3D11());
4494 // http://anglebug.com/42264222
4495 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4496
4497 GLint maxFragmentImageUniforms;
4498 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4499
4500 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4501
4502 constexpr GLsizei kSize = 1;
4503
4504 GLTexture color;
4505 glBindTexture(GL_TEXTURE_2D, color);
4506 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4507 EXPECT_GL_NO_ERROR();
4508
4509 GLFramebuffer fbo;
4510 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4511 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4512 EXPECT_GL_NO_ERROR();
4513
4514 const GLColor kInitialColor = GLColor::red;
4515
4516 GLTexture texture;
4517 glBindTexture(GL_TEXTURE_2D, texture);
4518 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4519 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4520 &kInitialColor);
4521 EXPECT_GL_NO_ERROR();
4522
4523 GLFramebuffer readbackFbo;
4524 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4525 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4526 EXPECT_GL_NO_ERROR();
4527
4528 // Create a program that samples from the texture in the fragment shader.
4529 constexpr char kFSSample[] = R"(#version 310 es
4530 precision mediump float;
4531 uniform sampler2D tex;
4532 out vec4 colorOut;
4533 void main()
4534 {
4535 colorOut = texture(tex, vec2(0));
4536 })";
4537 ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4538
4539 // Create a program that outputs to the image in the fragment shader.
4540 constexpr char kFSWrite[] = R"(#version 310 es
4541 precision mediump float;
4542 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4543 out vec4 colorOut;
4544 void main()
4545 {
4546 colorOut = vec4(0, 0, 1.0, 0);
4547 imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4548 })";
4549
4550 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4551
4552 glUseProgram(sampleProgram);
4553 GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4554 ASSERT_NE(-1, positionLocSample);
4555
4556 glUseProgram(writeProgram);
4557 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4558 ASSERT_NE(-1, positionLocWrite);
4559
4560 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4561
4562 // Setup the draw so that there's no state change between the draw calls.
4563 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4564 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4565
4566 GLBuffer posBuffer;
4567 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4568 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4569 glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4570 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4571 glEnableVertexAttribArray(positionLocSample);
4572 glEnableVertexAttribArray(positionLocWrite);
4573
4574 glUseProgram(sampleProgram);
4575 glDrawArrays(GL_TRIANGLES, 0, 6);
4576
4577 glEnable(GL_BLEND);
4578 glBlendFunc(GL_ONE, GL_ONE);
4579 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4580
4581 glUseProgram(writeProgram);
4582 glDrawArrays(GL_TRIANGLES, 0, 6);
4583
4584 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4585 EXPECT_GL_NO_ERROR();
4586
4587 // Verify the output of the two draw calls through the image is correct
4588 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4589
4590 // Verify the output of rendering as well
4591 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4592 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4593 }
4594
4595 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4596 // call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4597 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4598 {
4599 GLint maxFragmentShaderStorageBlocks;
4600 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4601
4602 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4603
4604 constexpr GLsizei kSize = 1;
4605
4606 GLTexture color;
4607 glBindTexture(GL_TEXTURE_2D, color);
4608 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4609 EXPECT_GL_NO_ERROR();
4610
4611 GLFramebuffer fbo;
4612 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4613 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4614 EXPECT_GL_NO_ERROR();
4615
4616 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4617 GLBuffer buffer;
4618 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4619 glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4620 GL_STATIC_DRAW);
4621 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4622
4623 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4624 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4625
4626 // Create a program that reads from the ubo in the fragment shader.
4627 constexpr char kFSRead[] = R"(#version 310 es
4628 precision mediump float;
4629 uniform block { vec4 vec; } b;
4630 out vec4 colorOut;
4631 void main()
4632 {
4633 colorOut = b.vec;
4634 })";
4635 ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4636
4637 // Create a program that outputs to the image in the fragment shader.
4638 constexpr char kFSWrite[] = R"(#version 310 es
4639 precision mediump float;
4640 layout(binding = 0, std430) buffer Output {
4641 vec4 vec;
4642 } b;
4643 out vec4 colorOut;
4644 void main()
4645 {
4646 b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4647 colorOut = vec4(0.125, 0.125, 0.125, 0);
4648 })";
4649
4650 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4651
4652 glUseProgram(readProgram);
4653 GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4654 ASSERT_NE(-1, positionLocRead);
4655
4656 glUseProgram(writeProgram);
4657 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4658 ASSERT_NE(-1, positionLocWrite);
4659
4660 // Setup the draw so that there's no state change between the draw calls.
4661 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4662 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4663
4664 GLBuffer posBuffer;
4665 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4666 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4667 glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4668 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4669 glEnableVertexAttribArray(positionLocRead);
4670 glEnableVertexAttribArray(positionLocWrite);
4671
4672 glUseProgram(readProgram);
4673 glDrawArrays(GL_TRIANGLES, 0, 6);
4674
4675 glEnable(GL_BLEND);
4676 glBlendFunc(GL_ONE, GL_ONE);
4677 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4678
4679 glUseProgram(writeProgram);
4680 glDrawArrays(GL_TRIANGLES, 0, 6);
4681
4682 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4683 EXPECT_GL_NO_ERROR();
4684
4685 // Verify the output of rendering
4686 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4687
4688 // Verify the output from the second draw call
4689 const float *ptr = reinterpret_cast<const float *>(
4690 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4691
4692 EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4693 EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4694 EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4695 EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4696
4697 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4698 }
4699
4700 // Tests that writing to an SSBO in the fragment shader before and after a change to the drawbuffers
4701 // still works
TEST_P(SimpleStateChangeTestES31,FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4702 TEST_P(SimpleStateChangeTestES31, FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4703 {
4704 GLint maxFragmentShaderStorageBlocks;
4705 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4706
4707 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4708
4709 constexpr GLsizei kSize = 1;
4710
4711 GLTexture color;
4712 glBindTexture(GL_TEXTURE_2D, color);
4713 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4714 EXPECT_GL_NO_ERROR();
4715
4716 GLFramebuffer fbo;
4717 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4718 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4719 EXPECT_GL_NO_ERROR();
4720
4721 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4722 GLBuffer buffer;
4723 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4724 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4725 GL_STATIC_DRAW);
4726 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4727
4728 // Create a program that writes to the SSBO in the fragment shader.
4729 constexpr char kFS[] = R"(#version 310 es
4730 precision mediump float;
4731 layout(binding = 0, std430) buffer Output {
4732 vec4 value;
4733 } b;
4734 out vec4 colorOut;
4735 uniform vec4 value;
4736 void main()
4737 {
4738 b.value = value;
4739 colorOut = vec4(1, 1, 1, 0);
4740 })";
4741
4742 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
4743 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
4744
4745 const GLuint program = glCreateProgram();
4746 glAttachShader(program, vs);
4747 glAttachShader(program, fs);
4748 glLinkProgram(program);
4749 CheckLinkStatusAndReturnProgram(program, true);
4750
4751 // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4752 glDetachShader(program, vs);
4753 glDetachShader(program, fs);
4754
4755 glUseProgram(program);
4756 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4757 ASSERT_NE(-1, positionLoc);
4758 GLint valueLoc = glGetUniformLocation(program, "value");
4759 ASSERT_NE(-1, valueLoc);
4760
4761 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4762 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4763
4764 GLBuffer posBuffer;
4765 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4766 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4767 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4768 glEnableVertexAttribArray(positionLoc);
4769
4770 glUseProgram(program);
4771 constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4772
4773 glUniform4fv(valueLoc, 1, kValue1);
4774 glDrawArrays(GL_TRIANGLES, 0, 6);
4775 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4776 EXPECT_GL_NO_ERROR();
4777
4778 // Verify that the program wrote the SSBO correctly.
4779 const float *ptr = reinterpret_cast<const float *>(
4780 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4781
4782 for (int i = 0; i < 4; ++i)
4783 {
4784 EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4785 }
4786
4787 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4788
4789 GLenum drawBuffers[] = {GL_NONE};
4790 glDrawBuffers(1, drawBuffers);
4791
4792 constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4793 glUniform4fv(valueLoc, 1, kValue2);
4794 glDrawArrays(GL_TRIANGLES, 0, 6);
4795 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4796 EXPECT_GL_NO_ERROR();
4797 // Verify that the program wrote the SSBO correctly.
4798 ptr = reinterpret_cast<const float *>(
4799 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4800
4801 for (int i = 0; i < 4; ++i)
4802 {
4803 EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4804 }
4805
4806 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4807 }
4808
4809 // Tests that writing to an SSBO in the vertex shader before and after a change to the drawbuffers
4810 // still works
TEST_P(SimpleStateChangeTestES31,VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4811 TEST_P(SimpleStateChangeTestES31, VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4812 {
4813 GLint maxVertexShaderStorageBlocks;
4814 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
4815
4816 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks < 1);
4817
4818 constexpr GLsizei kSize = 1;
4819
4820 GLTexture color;
4821 glBindTexture(GL_TEXTURE_2D, color);
4822 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4823 EXPECT_GL_NO_ERROR();
4824
4825 GLFramebuffer fbo;
4826 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4827 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4828 EXPECT_GL_NO_ERROR();
4829
4830 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4831 GLBuffer buffer;
4832 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4833 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4834 GL_STATIC_DRAW);
4835 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4836
4837 // Create a program that writes to the SSBO in the vertex shader.
4838 constexpr char kVS[] = R"(#version 310 es
4839 in vec4 a_position;
4840 uniform vec4 value;
4841 layout(binding = 0, std430) buffer Output {
4842 vec4 value;
4843 } b;
4844 void main()
4845 {
4846 b.value = value;
4847 gl_Position = a_position;
4848 })";
4849
4850 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
4851 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, essl31_shaders::fs::Green());
4852
4853 const GLuint program = glCreateProgram();
4854 glAttachShader(program, vs);
4855 glAttachShader(program, fs);
4856 glLinkProgram(program);
4857 CheckLinkStatusAndReturnProgram(program, true);
4858
4859 // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4860 glDetachShader(program, vs);
4861 glDetachShader(program, fs);
4862
4863 glUseProgram(program);
4864 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4865 ASSERT_NE(-1, positionLoc);
4866 GLint valueLoc = glGetUniformLocation(program, "value");
4867 ASSERT_NE(-1, valueLoc);
4868
4869 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4870 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4871
4872 GLBuffer posBuffer;
4873 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4874 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4875 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4876 glEnableVertexAttribArray(positionLoc);
4877
4878 glUseProgram(program);
4879 constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4880
4881 glUniform4fv(valueLoc, 1, kValue1);
4882 glDrawArrays(GL_TRIANGLES, 0, 6);
4883 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4884 EXPECT_GL_NO_ERROR();
4885
4886 // Verify that the program wrote the SSBO correctly.
4887 const float *ptr = reinterpret_cast<const float *>(
4888 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4889
4890 for (int i = 0; i < 4; ++i)
4891 {
4892 EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4893 }
4894
4895 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4896
4897 GLenum drawBuffers[] = {GL_NONE};
4898 glDrawBuffers(1, drawBuffers);
4899
4900 constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4901 glUniform4fv(valueLoc, 1, kValue2);
4902 glDrawArrays(GL_TRIANGLES, 0, 6);
4903 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4904 EXPECT_GL_NO_ERROR();
4905 // Verify that the program wrote the SSBO correctly.
4906 ptr = reinterpret_cast<const float *>(
4907 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4908
4909 for (int i = 0; i < 4; ++i)
4910 {
4911 EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4912 }
4913
4914 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4915 }
4916
4917 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4918 // call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4919 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4920 {
4921 // TODO(anglebug.com/42264185): Test is failing since it was introduced on Linux AMD GLES
4922 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4923
4924 constexpr GLsizei kSize = 1;
4925 const GLColor kInitColor(111, 222, 33, 44);
4926
4927 GLTexture color;
4928 glBindTexture(GL_TEXTURE_2D, color);
4929 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4932 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4933 EXPECT_GL_NO_ERROR();
4934
4935 GLFramebuffer fbo;
4936 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4937 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4938 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4939 EXPECT_GL_NO_ERROR();
4940
4941 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4942 GLBuffer buffer;
4943 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4944 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4945 GL_STATIC_DRAW);
4946 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4947 EXPECT_GL_NO_ERROR();
4948
4949 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4950
4951 constexpr char kCS[] = R"(#version 310 es
4952 layout(local_size_x=1, local_size_y=1) in;
4953 uniform sampler2D tex;
4954 layout(binding = 0, std430) buffer Output {
4955 vec4 vec;
4956 } b;
4957 void main()
4958 {
4959 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4960 })";
4961
4962 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4963 glUseProgram(readProgram);
4964
4965 glActiveTexture(GL_TEXTURE0);
4966 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4967
4968 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
4969 EXPECT_GL_NO_ERROR();
4970
4971 glUseProgram(readProgram);
4972 glDispatchCompute(1, 1, 1);
4973
4974 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4975 EXPECT_GL_NO_ERROR();
4976
4977 // Verify the output of rendering
4978 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4979
4980 // Verify the output from the compute shader
4981 const float *ptr = reinterpret_cast<const float *>(
4982 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4983
4984 EXPECT_EQ(ptr[0], 1.0f);
4985 EXPECT_EQ(ptr[1], 0.0f);
4986 EXPECT_EQ(ptr[2], 0.0f);
4987 EXPECT_EQ(ptr[3], 1.0f);
4988
4989 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4990 }
4991
4992 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
4993 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)4994 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
4995 {
4996 // http://anglebug.com/42264223
4997 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
4998
4999 constexpr GLsizei kSize = 1;
5000
5001 GLTexture color;
5002 glBindTexture(GL_TEXTURE_2D, color);
5003 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5004 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5005 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5006 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
5007 EXPECT_GL_NO_ERROR();
5008
5009 GLFramebuffer fbo;
5010 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5011 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5012 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5013 EXPECT_GL_NO_ERROR();
5014
5015 // Make sure the update to the texture is effective.
5016 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5017
5018 // Clear the texture through the framebuffer
5019 glClearColor(0, 1.0f, 0, 1.0f);
5020 glClear(GL_COLOR_BUFFER_BIT);
5021
5022 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
5023 GLBuffer buffer;
5024 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
5025 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
5026 GL_STATIC_DRAW);
5027 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
5028 EXPECT_GL_NO_ERROR();
5029
5030 constexpr char kCS[] = R"(#version 310 es
5031 layout(local_size_x=1, local_size_y=1) in;
5032 uniform sampler2D tex;
5033 layout(binding = 0, std430) buffer Output {
5034 vec4 vec;
5035 } b;
5036 void main()
5037 {
5038 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
5039 })";
5040
5041 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5042 glUseProgram(readProgram);
5043
5044 glActiveTexture(GL_TEXTURE0);
5045 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
5046
5047 glUseProgram(readProgram);
5048 glDispatchCompute(1, 1, 1);
5049
5050 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5051 EXPECT_GL_NO_ERROR();
5052
5053 // Verify the clear
5054 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5055
5056 // Verify the output from the compute shader
5057 const float *ptr = reinterpret_cast<const float *>(
5058 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
5059
5060 EXPECT_EQ(ptr[0], 0.0f);
5061 EXPECT_EQ(ptr[1], 1.0f);
5062 EXPECT_EQ(ptr[2], 0.0f);
5063 EXPECT_EQ(ptr[3], 1.0f);
5064
5065 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5066 }
5067
5068 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
5069 // it in a dispatch call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)5070 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
5071 {
5072 // http://anglebug.com/42264223
5073 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
5074
5075 constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
5076 GLBuffer buffer;
5077 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
5078 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
5079 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
5080
5081 std::vector<std::string> tfVaryings = {"gl_Position"};
5082 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5083 essl3_shaders::fs::Green(), tfVaryings,
5084 GL_INTERLEAVED_ATTRIBS);
5085 glUseProgram(program);
5086
5087 glBeginTransformFeedback(GL_TRIANGLES);
5088 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
5089 glEndTransformFeedback();
5090
5091 constexpr char kCS[] = R"(#version 310 es
5092 layout(local_size_x=1, local_size_y=1) in;
5093 layout(binding = 0) uniform Input
5094 {
5095 vec4 data[3];
5096 };
5097 layout(binding = 0, std430) buffer Output {
5098 bool pass;
5099 };
5100 void main()
5101 {
5102 pass = data[0] == vec4(-1, 1, 0, 1) &&
5103 data[1] == vec4(-1, -1, 0, 1) &&
5104 data[2] == vec4(1, -1, 0, 1);
5105 })";
5106
5107 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5108 glUseProgram(readProgram);
5109
5110 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
5111
5112 constexpr GLsizei kResultSize = sizeof(uint32_t);
5113 GLBuffer resultBuffer;
5114 glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5115 glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
5116 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
5117
5118 glDispatchCompute(1, 1, 1);
5119
5120 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5121 EXPECT_GL_NO_ERROR();
5122
5123 // Verify the output of rendering
5124 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5125
5126 // Verify the output from the compute shader
5127 const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
5128 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
5129
5130 EXPECT_EQ(ptr[0], 1u);
5131
5132 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5133 }
5134
5135 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)5136 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
5137 {
5138 std::array<GLColor, 4> colors = {
5139 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5140 GLTexture texRead;
5141 glBindTexture(GL_TEXTURE_2D, texRead);
5142 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5143 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5144 EXPECT_GL_NO_ERROR();
5145
5146 glUseProgram(mProgram);
5147
5148 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5149 glDispatchCompute(1, 1, 1);
5150 texRead.reset();
5151
5152 std::array<GLColor, 4> results;
5153 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5154 EXPECT_GL_NO_ERROR();
5155
5156 for (int i = 0; i < 4; i++)
5157 {
5158 EXPECT_EQ(colors[i], results[i]);
5159 }
5160 }
5161
5162 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)5163 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
5164 {
5165 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5166 GLTexture texRead;
5167 glBindTexture(GL_TEXTURE_2D, texRead);
5168 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5169 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5170
5171 glUseProgram(mProgram);
5172
5173 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5174 glDispatchCompute(1, 1, 1);
5175
5176 // Bind again
5177 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5178 glDispatchCompute(1, 1, 1);
5179 EXPECT_GL_NO_ERROR();
5180
5181 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5182 }
5183
5184 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
5185 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)5186 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
5187 {
5188 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
5189 std::array<GLColor, 4> subColors = {
5190 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
5191
5192 GLTexture texRead;
5193 glBindTexture(GL_TEXTURE_2D, texRead);
5194 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5195 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5196
5197 glUseProgram(mProgram);
5198
5199 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5200 glDispatchCompute(1, 1, 1);
5201
5202 // Update bottom-half of image texture with green.
5203 glBindTexture(GL_TEXTURE_2D, texRead);
5204 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
5205 ASSERT_GL_NO_ERROR();
5206
5207 // Dispatch again, should still work.
5208 glDispatchCompute(1, 1, 1);
5209 ASSERT_GL_NO_ERROR();
5210
5211 // Validate first half of the image is red and the bottom is green.
5212 std::array<GLColor, 4> results;
5213 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5214 EXPECT_GL_NO_ERROR();
5215
5216 EXPECT_EQ(GLColor::green, results[0]);
5217 EXPECT_EQ(GLColor::green, results[1]);
5218 EXPECT_EQ(GLColor::red, results[2]);
5219 EXPECT_EQ(GLColor::red, results[3]);
5220 }
5221
5222 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)5223 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
5224 {
5225 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5226
5227 GLTexture texRead;
5228 glBindTexture(GL_TEXTURE_2D, texRead);
5229 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5230 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
5231
5232 glUseProgram(mProgram);
5233
5234 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5235 glDispatchCompute(1, 1, 1);
5236
5237 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
5238 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
5239 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
5240 ASSERT_GL_NO_ERROR();
5241
5242 // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
5243 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5244 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
5245 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
5246 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
5247
5248 // Dispatch again. The second dispatch call should use the updated YBGR data.
5249 glDispatchCompute(1, 1, 1);
5250
5251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5252 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
5253 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
5254 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
5255 ASSERT_GL_NO_ERROR();
5256 }
5257
5258 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)5259 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
5260 {
5261 std::array<GLColor, 4> colorsTexA = {
5262 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5263
5264 std::array<GLColor, 4> colorsTexB = {
5265 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
5266
5267 GLTexture texA;
5268 glBindTexture(GL_TEXTURE_2D, texA);
5269 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5270 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
5271 GLTexture texB;
5272 glBindTexture(GL_TEXTURE_2D, texB);
5273 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5274 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
5275
5276 glUseProgram(mProgram);
5277
5278 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5279 glDispatchCompute(1, 1, 1);
5280
5281 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5282 glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5283 glDispatchCompute(1, 1, 1);
5284
5285 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5286 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5287 glDispatchCompute(1, 1, 1);
5288
5289 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5290 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5291 ASSERT_GL_NO_ERROR();
5292 }
5293
5294 // Tests that glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) after draw works, where the render
5295 // pass is marked as closed.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenStorageWrite)5296 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenStorageWrite)
5297 {
5298 // Create a framebuffer for the purpose of switching FBOs
5299 GLTexture clearColor;
5300 glBindTexture(GL_TEXTURE_2D, clearColor);
5301 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5302
5303 GLFramebuffer clearFBO;
5304 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, clearFBO);
5305 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, clearColor, 0);
5306 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5307 EXPECT_GL_NO_ERROR();
5308
5309 constexpr char kCS[] = R"(#version 310 es
5310 layout(local_size_x=1, local_size_y=1) in;
5311 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5312 void main()
5313 {
5314 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
5315 })";
5316
5317 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
5318 glUseProgram(program);
5319 EXPECT_GL_NO_ERROR();
5320
5321 // Create the framebuffer texture
5322 GLTexture renderTarget;
5323 glBindTexture(GL_TEXTURE_2D, renderTarget);
5324 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5325 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5326
5327 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
5328 // is already created with STORAGE usage and avoids recreate later.
5329 glDispatchCompute(1, 1, 1);
5330 EXPECT_GL_NO_ERROR();
5331
5332 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5333
5334 // Create the framebuffer for this texture
5335 GLFramebuffer drawFBO;
5336 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
5337 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
5338 0);
5339 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5340 EXPECT_GL_NO_ERROR();
5341
5342 // Draw to this framebuffer to start a render pass
5343 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
5344 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
5345
5346 // Change framebuffers and do a clear, making sure the old render pass is marked as closed. In
5347 // the Vulkan backend, the clear is stashed, so the render pass is kept in the hopes of reviving
5348 // it later.
5349
5350 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
5351 glClear(GL_COLOR_BUFFER_BIT);
5352
5353 // Issue a memory barrier before writing to the original image again.
5354 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5355
5356 // Write to it with a compute shader
5357 glDispatchCompute(1, 1, 1);
5358 EXPECT_GL_NO_ERROR();
5359
5360 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5361
5362 // Bind the original framebuffer and verify that the compute shader wrote the correct value.
5363 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
5364 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5365 }
5366
5367 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
5368 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)5369 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
5370 {
5371 ANGLE_SKIP_TEST_IF(!IsVulkan());
5372
5373 glGenFramebuffers(1, &mFramebuffer);
5374 glGenTextures(1, &mTexture);
5375
5376 glBindTexture(GL_TEXTURE_2D, mTexture);
5377 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5378 EXPECT_GL_NO_ERROR();
5379
5380 constexpr char kCS[] = R"(#version 310 es
5381 layout(local_size_x=2, local_size_y=2) in;
5382 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
5383 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5384 void main()
5385 {
5386 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
5387 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
5388 })";
5389
5390 bindProgramPipeline(kCS);
5391
5392 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5393
5394 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
5395 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
5396
5397 ASSERT_GL_NO_ERROR();
5398
5399 std::array<GLColor, 4> colors = {
5400 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5401 GLTexture texRead;
5402 glBindTexture(GL_TEXTURE_2D, texRead);
5403 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5404 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5405 EXPECT_GL_NO_ERROR();
5406
5407 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5408 glDispatchCompute(1, 1, 1);
5409 texRead.reset();
5410
5411 std::array<GLColor, 4> results;
5412 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5413 EXPECT_GL_NO_ERROR();
5414
5415 for (int i = 0; i < 4; i++)
5416 {
5417 EXPECT_EQ(colors[i], results[i]);
5418 }
5419 }
5420
5421 static constexpr char kColorVS[] = R"(attribute vec2 position;
5422 attribute vec4 color;
5423 varying vec4 vColor;
5424 void main()
5425 {
5426 gl_Position = vec4(position, 0, 1);
5427 vColor = color;
5428 })";
5429
5430 static constexpr char kColorFS[] = R"(precision mediump float;
5431 varying vec4 vColor;
5432 void main()
5433 {
5434 gl_FragColor = vColor;
5435 })";
5436
5437 class ValidationStateChangeTest : public ANGLETest<>
5438 {
5439 protected:
ValidationStateChangeTest()5440 ValidationStateChangeTest()
5441 {
5442 setWindowWidth(64);
5443 setWindowHeight(64);
5444 setConfigRedBits(8);
5445 setConfigGreenBits(8);
5446 setConfigBlueBits(8);
5447 setConfigAlphaBits(8);
5448 }
5449 };
5450
5451 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
5452 {
5453 protected:
WebGL2ValidationStateChangeTest()5454 WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5455 };
5456
5457 class ValidationStateChangeTestES31 : public ANGLETest<>
5458 {};
5459
5460 class WebGLComputeValidationStateChangeTest : public ANGLETest<>
5461 {
5462 public:
WebGLComputeValidationStateChangeTest()5463 WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5464 };
5465
5466 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
5467 {
5468 protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()5469 RobustBufferAccessWebGL2ValidationStateChangeTest()
5470 {
5471 // SwS/OSX GL do not support robustness. Mali does not support it.
5472 if (!isSwiftshader() && !IsMac() && !IsIOS() && !IsARM())
5473 {
5474 setRobustAccess(true);
5475 }
5476 }
5477 };
5478
5479 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
5480 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)5481 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
5482 {
5483 // Initialize program and set up state.
5484 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5485
5486 glUseProgram(program);
5487 GLint positionLoc = glGetAttribLocation(program, "position");
5488 ASSERT_NE(-1, positionLoc);
5489 GLint colorLoc = glGetAttribLocation(program, "color");
5490 ASSERT_NE(-1, colorLoc);
5491
5492 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5493 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5494
5495 GLBuffer posBuffer;
5496 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5497 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5498
5499 // Start with position enabled.
5500 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5501 glEnableVertexAttribArray(positionLoc);
5502
5503 std::vector<GLColor> colorVertices(6, GLColor::blue);
5504 const size_t colorBufferSize = sizeof(GLColor) * 6;
5505
5506 GLBuffer colorBuffer;
5507 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5508 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
5509
5510 // Start with color disabled.
5511 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5512 glDisableVertexAttribArray(colorLoc);
5513
5514 ASSERT_GL_NO_ERROR();
5515
5516 // Draw without a mapped buffer. Should succeed.
5517 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5518 glDrawArrays(GL_TRIANGLES, 0, 6);
5519 ASSERT_GL_NO_ERROR();
5520 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5521
5522 // Map position buffer and draw. Should fail.
5523 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5524 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
5525 ASSERT_GL_NO_ERROR();
5526
5527 glDrawArrays(GL_TRIANGLES, 0, 6);
5528 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
5529 glUnmapBuffer(GL_ARRAY_BUFFER);
5530
5531 // Map then enable color buffer. Should fail.
5532 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5533 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
5534 glEnableVertexAttribArray(colorLoc);
5535 ASSERT_GL_NO_ERROR();
5536
5537 glDrawArrays(GL_TRIANGLES, 0, 6);
5538 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
5539
5540 // Unmap then draw. Should succeed.
5541 glUnmapBuffer(GL_ARRAY_BUFFER);
5542 ASSERT_GL_NO_ERROR();
5543
5544 glDrawArrays(GL_TRIANGLES, 0, 6);
5545 ASSERT_GL_NO_ERROR();
5546 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5547 }
5548
5549 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
5550 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)5551 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
5552 {
5553 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5554
5555 // Initialize program and set up state.
5556 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5557
5558 glUseProgram(program);
5559 GLint positionLoc = glGetAttribLocation(program, "position");
5560 ASSERT_NE(-1, positionLoc);
5561 GLint colorLoc = glGetAttribLocation(program, "color");
5562 ASSERT_NE(-1, colorLoc);
5563
5564 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5565 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5566
5567 GLBuffer posBuffer;
5568 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5569 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5570 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5571
5572 // Start with position enabled.
5573 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5574 glEnableVertexAttribArray(positionLoc);
5575
5576 std::vector<GLColor> colorVertices(6, GLColor::blue);
5577 const size_t colorBufferSize = sizeof(GLColor) * 6;
5578
5579 GLBuffer colorBuffer;
5580 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5581 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5582 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5583
5584 // Start with color disabled.
5585 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5586 glDisableVertexAttribArray(colorLoc);
5587
5588 ASSERT_GL_NO_ERROR();
5589
5590 // Draw without a mapped buffer. Should succeed.
5591 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5592 glDrawArrays(GL_TRIANGLES, 0, 6);
5593 ASSERT_GL_NO_ERROR();
5594 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5595
5596 // Map position buffer and draw. Should succeed.
5597 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5598 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5599 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5600 ASSERT_GL_NO_ERROR();
5601
5602 glDrawArrays(GL_TRIANGLES, 0, 6);
5603 ASSERT_GL_NO_ERROR();
5604 glUnmapBuffer(GL_ARRAY_BUFFER);
5605
5606 // Map then enable color buffer. Should succeed.
5607 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5608 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5609 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5610 glEnableVertexAttribArray(colorLoc);
5611 ASSERT_GL_NO_ERROR();
5612
5613 glDrawArrays(GL_TRIANGLES, 0, 6);
5614 ASSERT_GL_NO_ERROR();
5615
5616 // Unmap then draw. Should succeed.
5617 glUnmapBuffer(GL_ARRAY_BUFFER);
5618 ASSERT_GL_NO_ERROR();
5619
5620 glDrawArrays(GL_TRIANGLES, 0, 6);
5621 ASSERT_GL_NO_ERROR();
5622 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5623 }
5624
5625 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5626 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5627 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5628 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5629 {
5630 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5631
5632 // Initialize program and set up state.
5633 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5634
5635 glUseProgram(program);
5636 GLint positionLoc = glGetAttribLocation(program, "position");
5637 ASSERT_NE(-1, positionLoc);
5638 GLint colorLoc = glGetAttribLocation(program, "color");
5639 ASSERT_NE(-1, colorLoc);
5640
5641 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5642 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5643
5644 GLBuffer posBuffer;
5645 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5646 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5647 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5648
5649 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5650 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5651
5652 // Start with position enabled.
5653 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5654 glEnableVertexAttribArray(positionLoc);
5655
5656 std::vector<GLColor> colorVertices(6, GLColor::blue);
5657 const size_t colorBufferSize = sizeof(GLColor) * 6;
5658
5659 GLBuffer colorBuffer;
5660 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5661 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5662 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5663
5664 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5665 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5666 ASSERT_GL_NO_ERROR();
5667
5668 // Start with color disabled.
5669 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5670 glDisableVertexAttribArray(colorLoc);
5671
5672 ASSERT_GL_NO_ERROR();
5673
5674 // Draw without a mapped buffer. Should succeed.
5675 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5676 glDrawArrays(GL_TRIANGLES, 0, 6);
5677 ASSERT_GL_NO_ERROR();
5678 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5679
5680 // Unmap then draw. Should succeed.
5681 glUnmapBuffer(GL_ARRAY_BUFFER);
5682 glEnableVertexAttribArray(colorLoc);
5683 ASSERT_GL_NO_ERROR();
5684 glDrawArrays(GL_TRIANGLES, 0, 6);
5685 ASSERT_GL_NO_ERROR();
5686 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5687 }
5688
5689 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5690 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5691 {
5692 // Seems to trigger a GL error in some edge cases. http://anglebug.com/42261462
5693 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5694
5695 // Initialize program and set up state.
5696 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5697
5698 glUseProgram(program);
5699 GLint positionLoc = glGetAttribLocation(program, "position");
5700 ASSERT_NE(-1, positionLoc);
5701 GLint colorLoc = glGetAttribLocation(program, "color");
5702 ASSERT_NE(-1, colorLoc);
5703
5704 // Create a user vertex array.
5705 GLVertexArray vao;
5706 glBindVertexArray(vao);
5707
5708 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5709 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5710
5711 GLBuffer posBuffer;
5712 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5713 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5714
5715 // Start with position enabled.
5716 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5717 glEnableVertexAttribArray(positionLoc);
5718
5719 std::vector<GLColor> blueVertices(6, GLColor::blue);
5720 const size_t blueBufferSize = sizeof(GLColor) * 6;
5721
5722 GLBuffer blueBuffer;
5723 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5724 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5725
5726 // Start with color enabled at an unused binding.
5727 constexpr GLint kUnusedBinding = 3;
5728 ASSERT_NE(colorLoc, kUnusedBinding);
5729 ASSERT_NE(positionLoc, kUnusedBinding);
5730 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5731 glVertexAttribBinding(colorLoc, kUnusedBinding);
5732 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5733 glEnableVertexAttribArray(colorLoc);
5734
5735 // Make binding 'colorLoc' use a mapped buffer.
5736 std::vector<GLColor> greenVertices(6, GLColor::green);
5737 const size_t greenBufferSize = sizeof(GLColor) * 6;
5738 GLBuffer greenBuffer;
5739 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5740 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5741 glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5742 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5743
5744 ASSERT_GL_NO_ERROR();
5745
5746 // Draw without a mapped buffer. Should succeed.
5747 glDrawArrays(GL_TRIANGLES, 0, 6);
5748 ASSERT_GL_NO_ERROR();
5749 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5750
5751 // Change divisor with VertexAttribDivisor. Should fail.
5752 glVertexAttribDivisor(colorLoc, 0);
5753 ASSERT_GL_NO_ERROR();
5754 glDrawArrays(GL_TRIANGLES, 0, 6);
5755 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5756
5757 // Unmap the buffer. Should succeed.
5758 glUnmapBuffer(GL_ARRAY_BUFFER);
5759 glDrawArrays(GL_TRIANGLES, 0, 6);
5760 ASSERT_GL_NO_ERROR();
5761 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5762 }
5763
5764 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5765 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5766 {
5767 // Initialize program and set up state.
5768 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5769
5770 glUseProgram(program);
5771 GLint positionLoc = glGetAttribLocation(program, "position");
5772 ASSERT_NE(-1, positionLoc);
5773 GLint colorLoc = glGetAttribLocation(program, "color");
5774 ASSERT_NE(-1, colorLoc);
5775
5776 // Create a user vertex array.
5777 GLVertexArray vao;
5778 glBindVertexArray(vao);
5779
5780 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5781 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5782
5783 GLBuffer posBuffer;
5784 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5785 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5786
5787 // Start with position enabled.
5788 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5789 glEnableVertexAttribArray(positionLoc);
5790
5791 std::vector<GLColor> blueVertices(6, GLColor::blue);
5792 const size_t blueBufferSize = sizeof(GLColor) * 6;
5793
5794 GLBuffer blueBuffer;
5795 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5796 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5797
5798 // Start with color enabled at an unused binding.
5799 constexpr GLint kUnusedBinding = 3;
5800 ASSERT_NE(colorLoc, kUnusedBinding);
5801 ASSERT_NE(positionLoc, kUnusedBinding);
5802 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5803 glVertexAttribBinding(colorLoc, kUnusedBinding);
5804 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5805 glEnableVertexAttribArray(colorLoc);
5806
5807 // Make binding 'colorLoc' use a small buffer.
5808 std::vector<GLColor> greenVertices(6, GLColor::green);
5809 const size_t greenBufferSize = sizeof(GLColor) * 3;
5810 GLBuffer greenBuffer;
5811 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5812 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5813 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5814
5815 ASSERT_GL_NO_ERROR();
5816
5817 // Draw without a mapped buffer. Should succeed.
5818 glDrawArrays(GL_TRIANGLES, 0, 6);
5819 ASSERT_GL_NO_ERROR();
5820 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5821
5822 // Change divisor with VertexAttribDivisor. Should fail.
5823 glVertexAttribDivisor(colorLoc, 0);
5824 ASSERT_GL_NO_ERROR();
5825 glDrawArrays(GL_TRIANGLES, 0, 6);
5826 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5827
5828 // Do a small draw. Should succeed.
5829 glDrawArrays(GL_TRIANGLES, 0, 3);
5830 ASSERT_GL_NO_ERROR();
5831 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5832 }
5833
5834 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5835 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5836 {
5837 constexpr char kVS[] = R"(#version 300 es
5838 in vec2 position;
5839 void main()
5840 {
5841 gl_Position = vec4(position, 0, 1);
5842 })";
5843
5844 constexpr char kFS[] = R"(#version 300 es
5845 precision mediump float;
5846 uniform uni { vec4 vec; };
5847 out vec4 color;
5848 void main()
5849 {
5850 color = vec;
5851 })";
5852
5853 ANGLE_GL_PROGRAM(program, kVS, kFS);
5854 glUseProgram(program);
5855
5856 GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5857 ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5858
5859 glUniformBlockBinding(program, blockIndex, 0);
5860
5861 GLBuffer uniformBuffer;
5862 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5863 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5864 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5865
5866 const auto &quadVertices = GetQuadVertices();
5867
5868 GLBuffer positionBuffer;
5869 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5870 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5871 GL_STATIC_DRAW);
5872
5873 GLint positionLocation = glGetAttribLocation(program, "position");
5874 ASSERT_NE(-1, positionLocation);
5875
5876 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5877 glEnableVertexAttribArray(positionLocation);
5878 ASSERT_GL_NO_ERROR();
5879
5880 // First draw should succeed.
5881 glDrawArrays(GL_TRIANGLES, 0, 6);
5882 ASSERT_GL_NO_ERROR();
5883 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5884
5885 // Change the uniform block binding. Should fail.
5886 glUniformBlockBinding(program, blockIndex, 1);
5887 ASSERT_GL_NO_ERROR();
5888 glDrawArrays(GL_TRIANGLES, 0, 6);
5889 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5890
5891 // Reset to a correct state.
5892 glUniformBlockBinding(program, blockIndex, 0);
5893 glDrawArrays(GL_TRIANGLES, 0, 6);
5894 ASSERT_GL_NO_ERROR();
5895 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5896
5897 // Change the buffer binding. Should fail.
5898 glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5899 ASSERT_GL_NO_ERROR();
5900 glDrawArrays(GL_TRIANGLES, 0, 6);
5901 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5902
5903 // Reset to a correct state.
5904 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5905 glDrawArrays(GL_TRIANGLES, 0, 6);
5906 ASSERT_GL_NO_ERROR();
5907 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5908
5909 // Resize the buffer to be too small. Should fail.
5910 glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5911 glDrawArrays(GL_TRIANGLES, 0, 6);
5912 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5913 }
5914
5915 // Tests that redefining attachment storage updates the component type mask
TEST_P(WebGL2ValidationStateChangeTest,AttachmentTypeRedefinition)5916 TEST_P(WebGL2ValidationStateChangeTest, AttachmentTypeRedefinition)
5917 {
5918 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
5919
5920 GLFramebuffer fb;
5921 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5922
5923 GLRenderbuffer rb;
5924 glBindRenderbuffer(GL_RENDERBUFFER, rb);
5925 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5926
5927 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 4, 4);
5928 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5929 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5930
5931 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 4, 4);
5932 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5933 EXPECT_GL_NO_ERROR();
5934 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
5935
5936 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 4, 4);
5937 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5938 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5939 }
5940
5941 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5942 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5943 {
5944 // Set up a simple draw from a Texture to a user Framebuffer.
5945 GLuint program = get2DTexturedQuadProgram();
5946 ASSERT_NE(0u, program);
5947 glUseProgram(program);
5948
5949 GLint posLoc = glGetAttribLocation(program, "position");
5950 ASSERT_NE(-1, posLoc);
5951
5952 const auto &quadVertices = GetQuadVertices();
5953
5954 GLBuffer positionBuffer;
5955 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5956 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5957 GL_STATIC_DRAW);
5958
5959 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5960 glEnableVertexAttribArray(posLoc);
5961
5962 constexpr size_t kSize = 2;
5963
5964 GLTexture colorBufferTexture;
5965 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5966 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5968 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5969
5970 GLFramebuffer framebuffer;
5971 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5972 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5973 0);
5974 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5975
5976 std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
5977
5978 GLTexture greenTexture;
5979 glBindTexture(GL_TEXTURE_2D, greenTexture);
5980 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5981 greenColor.data());
5982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5984
5985 // Second framebuffer with a feedback loop. Initially unbound.
5986 GLFramebuffer loopedFramebuffer;
5987 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5988 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
5989 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5990 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5991
5992 ASSERT_GL_NO_ERROR();
5993
5994 glDrawArrays(GL_TRIANGLES, 0, 6);
5995 ASSERT_GL_NO_ERROR();
5996 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5997
5998 // Create a rendering feedback loop. Should fail.
5999 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
6000 ASSERT_GL_NO_ERROR();
6001 glDrawArrays(GL_TRIANGLES, 0, 6);
6002 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6003
6004 // Reset to a valid state.
6005 glBindTexture(GL_TEXTURE_2D, greenTexture);
6006 glDrawArrays(GL_TRIANGLES, 0, 6);
6007 ASSERT_GL_NO_ERROR();
6008 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6009
6010 // Bind a second framebuffer with a feedback loop.
6011 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
6012 ASSERT_GL_NO_ERROR();
6013 glDrawArrays(GL_TRIANGLES, 0, 6);
6014 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6015
6016 // Update the framebuffer texture attachment. Should succeed.
6017 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
6018 0);
6019 glDrawArrays(GL_TRIANGLES, 0, 6);
6020 ASSERT_GL_NO_ERROR();
6021 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6022 }
6023
6024 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)6025 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
6026 {
6027 // Crashes on 64-bit Android. http://anglebug.com/42262522
6028 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
6029
6030 // Set up a program that writes to two outputs: one int and one float.
6031 constexpr char kVS[] = R"(#version 300 es
6032 layout(location = 0) in vec2 position;
6033 out vec2 texCoord;
6034 void main()
6035 {
6036 gl_Position = vec4(position, 0, 1);
6037 texCoord = position * 0.5 + vec2(0.5);
6038 })";
6039
6040 constexpr char kFS[] = R"(#version 300 es
6041 precision mediump float;
6042 in vec2 texCoord;
6043 layout(location = 0) out vec4 outFloat;
6044 layout(location = 1) out uvec4 outInt;
6045 void main()
6046 {
6047 outFloat = vec4(0, 1, 0, 1);
6048 outInt = uvec4(0, 1, 0, 1);
6049 })";
6050
6051 ANGLE_GL_PROGRAM(program, kVS, kFS);
6052 glUseProgram(program);
6053
6054 constexpr GLint kPosLoc = 0;
6055
6056 const auto &quadVertices = GetQuadVertices();
6057
6058 GLBuffer positionBuffer;
6059 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
6060 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
6061 GL_STATIC_DRAW);
6062
6063 glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6064 glEnableVertexAttribArray(kPosLoc);
6065
6066 constexpr size_t kSize = 2;
6067
6068 GLFramebuffer floatFramebuffer;
6069 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6070
6071 GLTexture floatTextures[2];
6072 for (int i = 0; i < 2; ++i)
6073 {
6074 glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
6075 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6076 nullptr);
6077 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6078 floatTextures[i], 0);
6079 ASSERT_GL_NO_ERROR();
6080 }
6081
6082 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6083
6084 GLFramebuffer intFramebuffer;
6085 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6086
6087 GLTexture intTextures[2];
6088 for (int i = 0; i < 2; ++i)
6089 {
6090 glBindTexture(GL_TEXTURE_2D, intTextures[i]);
6091 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
6092 GL_UNSIGNED_BYTE, nullptr);
6093 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6094 intTextures[i], 0);
6095 ASSERT_GL_NO_ERROR();
6096 }
6097
6098 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6099
6100 ASSERT_GL_NO_ERROR();
6101
6102 constexpr GLenum kColor0Enabled[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
6103 constexpr GLenum kColor1Enabled[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
6104 constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6105
6106 // Draw float. Should work.
6107 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6108 glDrawBuffers(2, kColor0Enabled);
6109
6110 glDrawArrays(GL_TRIANGLES, 0, 6);
6111 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6112 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6113
6114 // Set an invalid component write.
6115 glDrawBuffers(2, kColor0And1Enabled);
6116 ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
6117 glDrawArrays(GL_TRIANGLES, 0, 6);
6118 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6119 // Set all 4 channels of color mask to false. Validate success.
6120 glColorMask(false, false, false, false);
6121 glDrawArrays(GL_TRIANGLES, 0, 6);
6122 EXPECT_GL_NO_ERROR();
6123 glColorMask(false, true, false, false);
6124 glDrawArrays(GL_TRIANGLES, 0, 6);
6125 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6126 glColorMask(true, true, true, true);
6127 glDrawArrays(GL_TRIANGLES, 0, 6);
6128 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6129
6130 // Restore state.
6131 glDrawBuffers(2, kColor0Enabled);
6132 glDrawArrays(GL_TRIANGLES, 0, 6);
6133 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6134 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6135
6136 // Bind an invalid framebuffer. Validate failure.
6137 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6138 ASSERT_GL_NO_ERROR();
6139 glDrawArrays(GL_TRIANGLES, 0, 6);
6140 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
6141
6142 // Set draw mask to a valid mask. Validate success.
6143 glDrawBuffers(2, kColor1Enabled);
6144 glDrawArrays(GL_TRIANGLES, 0, 6);
6145 ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
6146 }
6147
6148 // Tests that switching the program properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,IncompatibleDrawFramebufferProgramSwitch)6149 TEST_P(WebGL2ValidationStateChangeTest, IncompatibleDrawFramebufferProgramSwitch)
6150 {
6151 constexpr char kFS0[] = R"(#version 300 es
6152 precision mediump float;
6153 in vec2 texCoord;
6154 out ivec4 color;
6155 void main()
6156 {
6157 color = ivec4(1, 0, 1, 1);
6158 })";
6159 ANGLE_GL_PROGRAM(programInt, essl3_shaders::vs::Simple(), kFS0);
6160
6161 constexpr char kFS1[] = R"(#version 300 es
6162 precision mediump float;
6163 in vec2 texCoord;
6164 out vec4 color;
6165 void main()
6166 {
6167 color = vec4(0, 1, 0, 1);
6168 })";
6169 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS1);
6170
6171 constexpr size_t kSize = 2;
6172
6173 GLFramebuffer fb;
6174 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6175
6176 GLRenderbuffer rb;
6177 glBindRenderbuffer(GL_RENDERBUFFER, rb);
6178 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6179 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
6180
6181 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6182
6183 // Incompatible masked-out draw call
6184 // Implementations may internally disable render targets to avoid runtime failures
6185 glColorMask(false, false, false, false);
6186 drawQuad(programInt, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6187 ASSERT_GL_NO_ERROR();
6188
6189 // Clear must not be affected
6190 glColorMask(true, true, true, true);
6191 glClearColor(1.0, 0.0, 0.0, 1.0);
6192 glClear(GL_COLOR_BUFFER_BIT);
6193 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
6194
6195 // Compatible draw call
6196 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6197 ASSERT_GL_NO_ERROR();
6198 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6199 }
6200
6201 // Tests that updating the render target storage properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)6202 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)
6203 {
6204 constexpr char kFS[] = R"(#version 300 es
6205 precision mediump float;
6206 in vec2 texCoord;
6207 layout(location = 0) out ivec4 colorInt;
6208 layout(location = 1) out vec4 colorFloat;
6209 void main()
6210 {
6211 colorInt = ivec4(1, 0, 1, 1);
6212 colorFloat = vec4(0, 1, 0, 1);
6213 })";
6214
6215 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6216
6217 // Explicitly set the program here so that
6218 // drawQuad helpers do not switch it
6219 glUseProgram(program);
6220
6221 constexpr size_t kSize = 2;
6222
6223 GLFramebuffer fb;
6224 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6225
6226 GLRenderbuffer rb0;
6227 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6228 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6229 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
6230
6231 GLRenderbuffer rb1;
6232 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6233 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6234 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rb1);
6235
6236 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6237
6238 constexpr GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6239 glDrawBuffers(2, bufs);
6240
6241 // Incompatible masked-out draw call
6242 // Implementations may internally disable render targets to avoid runtime failures
6243 glColorMask(false, false, false, false);
6244 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6245 ASSERT_GL_NO_ERROR();
6246
6247 // Redefine storage, swapping numeric types
6248 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6249 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6250 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6251 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6252
6253 // The same draw call should be valid now
6254 glColorMask(true, true, true, true);
6255 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6256 ASSERT_GL_NO_ERROR();
6257
6258 glReadBuffer(GL_COLOR_ATTACHMENT0);
6259 EXPECT_PIXEL_RECT32I_EQ(0, 0, kSize, kSize, GLColor32I(1, 0, 1, 1));
6260
6261 glReadBuffer(GL_COLOR_ATTACHMENT1);
6262 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6263 }
6264
6265 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)6266 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
6267 {
6268 // TODO(anglebug.com/40096690) This fails after the upgrade to the 26.20.100.7870 driver.
6269 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
6270
6271 constexpr char kFS[] = R"(#version 300 es
6272 precision mediump float;
6273 uniform block { vec4 color; };
6274 out vec4 colorOut;
6275 void main()
6276 {
6277 colorOut = color;
6278 })";
6279
6280 std::vector<std::string> tfVaryings = {"gl_Position"};
6281 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
6282 GL_INTERLEAVED_ATTRIBS);
6283 glUseProgram(program);
6284
6285 std::vector<Vector4> positionData;
6286 for (const Vector3 &quadVertex : GetQuadVertices())
6287 {
6288 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6289 }
6290
6291 GLBuffer arrayBuffer;
6292 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6293 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6294 GL_STATIC_DRAW);
6295
6296 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6297 ASSERT_NE(-1, positionLoc);
6298
6299 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6300 glEnableVertexAttribArray(positionLoc);
6301
6302 EXPECT_GL_NO_ERROR();
6303
6304 // Set up transform feedback.
6305 GLTransformFeedback transformFeedback;
6306 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6307
6308 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6309
6310 GLBuffer transformFeedbackBuffer;
6311 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6312 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6313 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6314
6315 // Set up uniform buffer.
6316 GLBuffer uniformBuffer;
6317 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
6318 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
6319 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
6320
6321 ASSERT_GL_NO_ERROR();
6322
6323 // Do the draw operation. Should succeed.
6324 glBeginTransformFeedback(GL_TRIANGLES);
6325 glDrawArrays(GL_TRIANGLES, 0, 6);
6326 glEndTransformFeedback();
6327
6328 ASSERT_GL_NO_ERROR();
6329 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6330
6331 const GLvoid *mapPointer =
6332 glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
6333 ASSERT_GL_NO_ERROR();
6334 ASSERT_NE(nullptr, mapPointer);
6335 const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
6336 std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
6337 EXPECT_EQ(positionData, actualData);
6338 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
6339
6340 // Draw once to update validation cache.
6341 glBeginTransformFeedback(GL_TRIANGLES);
6342 glDrawArrays(GL_TRIANGLES, 0, 6);
6343
6344 // Bind transform feedback buffer to another binding point. Should cause a conflict.
6345 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
6346 ASSERT_GL_NO_ERROR();
6347 glDrawArrays(GL_TRIANGLES, 0, 6);
6348 glEndTransformFeedback();
6349 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
6350
6351 // Reset to valid state.
6352 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6353 glBeginTransformFeedback(GL_TRIANGLES);
6354 glDrawArrays(GL_TRIANGLES, 0, 6);
6355 glEndTransformFeedback();
6356 ASSERT_GL_NO_ERROR();
6357
6358 // Simultaneous non-vertex-array binding. Should fail.
6359 glBeginTransformFeedback(GL_TRIANGLES);
6360 glDrawArrays(GL_TRIANGLES, 0, 6);
6361 ASSERT_GL_NO_ERROR();
6362 glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
6363 ASSERT_GL_NO_ERROR();
6364 glDrawArrays(GL_TRIANGLES, 0, 6);
6365 glEndTransformFeedback();
6366 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
6367 }
6368
6369 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)6370 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
6371 {
6372 // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
6373 // DEPTH_COMPONENT24 is emulated with D32_S8X24. http://anglebug.com/42262525
6374 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
6375
6376 constexpr char kFS[] = R"(#version 300 es
6377 precision mediump float;
6378 uniform sampler2D sampler;
6379 out vec4 colorOut;
6380 void main()
6381 {
6382 colorOut = texture(sampler, vec2(0));
6383 })";
6384
6385 std::vector<std::string> tfVaryings = {"gl_Position"};
6386 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6387 glUseProgram(program);
6388
6389 std::array<GLColor, 4> colors = {
6390 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6391
6392 GLTexture tex;
6393 glBindTexture(GL_TEXTURE_2D, tex);
6394 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
6395
6396 const auto &quadVertices = GetQuadVertices();
6397
6398 GLBuffer arrayBuffer;
6399 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6400 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6401 GL_STATIC_DRAW);
6402
6403 GLint samplerLoc = glGetUniformLocation(program, "sampler");
6404 ASSERT_NE(-1, samplerLoc);
6405 glUniform1i(samplerLoc, 0);
6406
6407 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6408 ASSERT_NE(-1, positionLoc);
6409 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6410 glEnableVertexAttribArray(positionLoc);
6411
6412 ASSERT_GL_NO_ERROR();
6413
6414 glDrawArrays(GL_TRIANGLES, 0, 6);
6415 ASSERT_GL_NO_ERROR();
6416
6417 // TexImage2D should update the sampler format cache.
6418 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
6419 colors.data());
6420 glDrawArrays(GL_TRIANGLES, 0, 6);
6421 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
6422
6423 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
6424 GL_UNSIGNED_INT, colors.data());
6425 glDrawArrays(GL_TRIANGLES, 0, 6);
6426 ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
6427
6428 // TexParameteri should update the sampler format cache.
6429 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
6430 glDrawArrays(GL_TRIANGLES, 0, 6);
6431 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
6432 }
6433
6434 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)6435 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
6436 {
6437 std::vector<std::string> tfVaryings = {"gl_Position"};
6438 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
6439 essl3_shaders::fs::Red(), tfVaryings,
6440 GL_INTERLEAVED_ATTRIBS);
6441 glUseProgram(program);
6442
6443 std::vector<Vector4> positionData;
6444 for (const Vector3 &quadVertex : GetQuadVertices())
6445 {
6446 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6447 }
6448
6449 GLBuffer arrayBuffer;
6450 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6451 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6452 GL_STATIC_DRAW);
6453
6454 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6455 ASSERT_NE(-1, positionLoc);
6456
6457 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6458 glEnableVertexAttribArray(positionLoc);
6459
6460 // Set up transform feedback.
6461 GLTransformFeedback transformFeedback;
6462 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6463
6464 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6465
6466 GLBuffer transformFeedbackBuffer;
6467 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6468 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6469 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6470
6471 GLTransformFeedback pointsXFB;
6472 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6473 GLBuffer pointsXFBBuffer;
6474 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
6475 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
6476 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
6477
6478 // Begin TRIANGLES, switch to paused POINTS, should be valid.
6479 glBeginTransformFeedback(GL_POINTS);
6480 glPauseTransformFeedback();
6481 ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
6482
6483 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6484 glBeginTransformFeedback(GL_TRIANGLES);
6485 glDrawArrays(GL_TRIANGLES, 0, 6);
6486 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6487 glDrawArrays(GL_POINTS, 0, 6);
6488 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
6489 glDrawArrays(GL_LINES, 0, 6);
6490 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6491 glPauseTransformFeedback();
6492 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6493 glResumeTransformFeedback();
6494 glDrawArrays(GL_POINTS, 0, 6);
6495 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6496 glDrawArrays(GL_TRIANGLES, 0, 6);
6497 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
6498 glDrawArrays(GL_LINES, 0, 6);
6499 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6500
6501 glEndTransformFeedback();
6502 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6503 glEndTransformFeedback();
6504 ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
6505
6506 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
6507
6508 glDrawArrays(GL_POINTS, 0, 6);
6509 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6510 glDrawArrays(GL_TRIANGLES, 0, 6);
6511 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6512 glDrawArrays(GL_LINES, 0, 6);
6513 EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
6514 }
6515
6516 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)6517 TEST_P(ValidationStateChangeTest, TextureConflict)
6518 {
6519 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
6520
6521 GLint maxTextures = 0;
6522 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
6523 ANGLE_SKIP_TEST_IF(maxTextures < 2);
6524
6525 // Set up state.
6526 constexpr GLint kSize = 2;
6527
6528 std::vector<GLColor> greenData(4, GLColor::green);
6529
6530 GLTexture textureA;
6531 glBindTexture(GL_TEXTURE_2D, textureA);
6532 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6533 greenData.data());
6534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6536
6537 glActiveTexture(GL_TEXTURE1);
6538
6539 GLTexture textureB;
6540 glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
6541 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6542 GL_UNSIGNED_BYTE, greenData.data());
6543 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6544 GL_UNSIGNED_BYTE, greenData.data());
6545 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6546 GL_UNSIGNED_BYTE, greenData.data());
6547 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6548 GL_UNSIGNED_BYTE, greenData.data());
6549 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6550 GL_UNSIGNED_BYTE, greenData.data());
6551 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6552 GL_UNSIGNED_BYTE, greenData.data());
6553 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6554 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6555
6556 constexpr char kVS[] = R"(attribute vec2 position;
6557 varying mediump vec2 texCoord;
6558 void main()
6559 {
6560 gl_Position = vec4(position, 0, 1);
6561 texCoord = position * 0.5 + vec2(0.5);
6562 })";
6563
6564 constexpr char kFS[] = R"(varying mediump vec2 texCoord;
6565 uniform sampler2D texA;
6566 uniform samplerCube texB;
6567 void main()
6568 {
6569 gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
6570 })";
6571
6572 ANGLE_GL_PROGRAM(program, kVS, kFS);
6573 glUseProgram(program);
6574
6575 const auto &quadVertices = GetQuadVertices();
6576
6577 GLBuffer arrayBuffer;
6578 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6579 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6580 GL_STATIC_DRAW);
6581
6582 GLint positionLoc = glGetAttribLocation(program, "position");
6583 ASSERT_NE(-1, positionLoc);
6584
6585 GLint texALoc = glGetUniformLocation(program, "texA");
6586 ASSERT_NE(-1, texALoc);
6587
6588 GLint texBLoc = glGetUniformLocation(program, "texB");
6589 ASSERT_NE(-1, texBLoc);
6590
6591 glUniform1i(texALoc, 0);
6592 glUniform1i(texBLoc, 1);
6593
6594 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6595 glEnableVertexAttribArray(positionLoc);
6596
6597 ASSERT_GL_NO_ERROR();
6598
6599 // First draw. Should succeed.
6600 glDrawArrays(GL_TRIANGLES, 0, 6);
6601 ASSERT_GL_NO_ERROR();
6602 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6603
6604 // Second draw to ensure all state changes are flushed.
6605 glDrawArrays(GL_TRIANGLES, 0, 6);
6606 ASSERT_GL_NO_ERROR();
6607
6608 // Make the uniform use an invalid texture binding.
6609 glUniform1i(texBLoc, 0);
6610 glDrawArrays(GL_TRIANGLES, 0, 6);
6611 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6612 }
6613
6614 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)6615 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
6616 {
6617 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
6618 glUseProgram(program);
6619
6620 std::array<GLushort, 6> quadIndices = GetQuadIndices();
6621 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
6622
6623 GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
6624
6625 GLBuffer elementArrayBuffer;
6626 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6627 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
6628
6629 GLBuffer arrayBuffer;
6630 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6631 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
6632 quadVertices.data(), GL_STATIC_DRAW);
6633
6634 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6635 ASSERT_NE(-1, positionLoc);
6636 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6637 glEnableVertexAttribArray(positionLoc);
6638
6639 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6640 ASSERT_GL_NO_ERROR();
6641
6642 void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
6643 ASSERT_NE(nullptr, ptr);
6644
6645 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6646 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6647
6648 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
6649
6650 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6651 ASSERT_GL_NO_ERROR();
6652 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6653 }
6654
6655 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)6656 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
6657 {
6658 constexpr char kFS[] =
6659 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6660 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6661 glUseProgram(program);
6662 GLint loc = glGetUniformLocation(program, "us");
6663 ASSERT_EQ(0, loc);
6664
6665 auto quadVertices = GetQuadVertices();
6666 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6667 ASSERT_EQ(0, posLoc);
6668
6669 GLBuffer buffer;
6670 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6671 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6672 quadVertices.data(), GL_STATIC_DRAW);
6673 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6674 glEnableVertexAttribArray(posLoc);
6675
6676 constexpr size_t kSize = 2;
6677 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6678
6679 GLTexture tex;
6680 glBindTexture(GL_TEXTURE_2D, tex);
6681 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6683 glUniform1i(loc, 0);
6684
6685 glDrawArrays(GL_TRIANGLES, 0, 3);
6686 ASSERT_GL_NO_ERROR();
6687 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6688
6689 // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
6690 GLTexture tex2;
6691 glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
6692 tex2.reset();
6693
6694 glDrawArrays(GL_TRIANGLES, 0, 3);
6695 ASSERT_GL_NO_ERROR();
6696 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6697
6698 // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
6699 tex.reset();
6700
6701 glDrawArrays(GL_TRIANGLES, 0, 3);
6702 ASSERT_GL_NO_ERROR();
6703 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6704 }
6705
6706 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)6707 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
6708 {
6709 constexpr char kFS[] =
6710 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6711 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6712 glUseProgram(program);
6713 GLint loc = glGetUniformLocation(program, "us");
6714 ASSERT_EQ(0, loc);
6715
6716 auto quadVertices = GetQuadVertices();
6717 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6718 ASSERT_EQ(0, posLoc);
6719
6720 GLBuffer buffer;
6721 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6722 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6723 quadVertices.data(), GL_STATIC_DRAW);
6724 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6725 glEnableVertexAttribArray(posLoc);
6726
6727 constexpr size_t kSize = 2;
6728 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6729
6730 GLTexture tex;
6731 glBindTexture(GL_TEXTURE_2D, tex);
6732 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6734 glUniform1i(loc, 1);
6735 tex.reset();
6736
6737 glDrawArrays(GL_TRIANGLES, 0, 3);
6738 ASSERT_GL_NO_ERROR();
6739 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6740 }
6741
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)6742 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
6743 {
6744 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6745 glBindTexture(GL_TEXTURE_2D, texture);
6746 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6747 GL_UNSIGNED_BYTE, nullptr);
6748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6750 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6751 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6752 }
6753
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6754 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6755 {
6756 // Render to an FBO
6757 GLFramebuffer fbo1;
6758 GLTexture texture1;
6759
6760 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6761 ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6762 essl1_shaders::fs::Texture2D());
6763
6764 bindTextureToFbo(fbo1, texture1);
6765
6766 // Clear the surface FBO to initialize it to a known value
6767 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6768 glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
6769 glClear(GL_COLOR_BUFFER_BIT);
6770 ASSERT_GL_NO_ERROR();
6771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6772 glFlush();
6773
6774 // Draw to FBO 1 to initialize it to a known value
6775 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6776
6777 if (earlyFrontFaceDirty)
6778 {
6779 glEnable(GL_CULL_FACE);
6780 // Make sure we don't cull
6781 glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6782 glFrontFace(frontFace);
6783 }
6784 else
6785 {
6786 glDisable(GL_CULL_FACE);
6787 }
6788
6789 glUseProgram(greenProgram);
6790 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6791 ASSERT_GL_NO_ERROR();
6792 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6793
6794 // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6795 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6796 glBindTexture(GL_TEXTURE_2D, texture1);
6797
6798 glCullFace(GL_BACK);
6799 if (!earlyFrontFaceDirty)
6800 {
6801 // Set the culling we want to test
6802 glEnable(GL_CULL_FACE);
6803 glFrontFace(frontFace);
6804 }
6805
6806 glUseProgram(textureProgram);
6807 drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6808 ASSERT_GL_NO_ERROR();
6809
6810 if (frontFace == GL_CCW)
6811 {
6812 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6813 }
6814 else
6815 {
6816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6817 }
6818
6819 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6820 glBindTexture(GL_TEXTURE_2D, 0);
6821 }
6822
6823 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6824 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6825 {
6826 drawToFboWithCulling(GL_CCW, true);
6827 }
6828
6829 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6830 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6831 {
6832 drawToFboWithCulling(GL_CW, true);
6833 }
6834
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6835 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6836 {
6837 drawToFboWithCulling(GL_CCW, false);
6838 }
6839
6840 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6841 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6842 {
6843 drawToFboWithCulling(GL_CW, false);
6844 }
6845
6846 // Test that vertex attribute translation is still kept after binding it to another buffer then
6847 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6848 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6849 {
6850 // http://anglebug.com/42263918
6851 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6852
6853 constexpr char kVS[] = R"(attribute vec4 a_position;
6854 attribute float a_attrib;
6855 varying float v_attrib;
6856 void main()
6857 {
6858 v_attrib = a_attrib;
6859 gl_Position = a_position;
6860 })";
6861
6862 constexpr char kFS[] = R"(precision mediump float;
6863 varying float v_attrib;
6864 void main()
6865 {
6866 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6867 })";
6868
6869 ANGLE_GL_PROGRAM(program, kVS, kFS);
6870 glBindAttribLocation(program, 0, "a_position");
6871 glBindAttribLocation(program, 1, "a_attrib");
6872 glLinkProgram(program);
6873 glUseProgram(program);
6874 ASSERT_GL_NO_ERROR();
6875
6876 // Set up color data so red is drawn
6877 std::vector<GLushort> data(1000, 0xffff);
6878
6879 GLBuffer redBuffer;
6880 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6881 glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6882 // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6883 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6884 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6885 glBindBuffer(GL_ARRAY_BUFFER, 0);
6886 glEnableVertexAttribArray(1);
6887
6888 drawQuad(program, "a_position", 0.5f);
6889 // Verify red was drawn
6890 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6891
6892 glClearColor(0, 1, 0, 1);
6893 glClear(GL_COLOR_BUFFER_BIT);
6894 // Verify that green was drawn
6895 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6896
6897 // Bind black color buffer to the same attribute with zero offset
6898 std::vector<GLfloat> black(6, 0.0f);
6899 GLBuffer blackBuffer;
6900 glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6901 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6902 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6903
6904 drawQuad(program, "a_position", 0.5f);
6905 // Verify black was drawn
6906 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6907
6908 // Rebind the old buffer & offset
6909 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6910 // Use offset not multiple of 4 GLushorts
6911 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6912 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6913
6914 drawQuad(program, "a_position", 0.5f);
6915 // Verify red was drawn
6916 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6917 }
6918
6919 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6920 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6921 {
6922 constexpr char kVS[] = R"(attribute vec4 a_position;
6923 varying float v_attrib;
6924 uniform float u_value;
6925 void main()
6926 {
6927 v_attrib = u_value;
6928 gl_Position = a_position;
6929 })";
6930
6931 constexpr char kFS[] = R"(precision mediump float;
6932 varying float v_attrib;
6933 void main()
6934 {
6935 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6936 })";
6937
6938 ANGLE_GL_PROGRAM(program1, kVS, kFS);
6939 ANGLE_GL_PROGRAM(program2, kVS, kFS);
6940
6941 // Don't use drawQuad so there's no state changes between the draw calls other than the program
6942 // binding.
6943
6944 constexpr size_t kProgramCount = 2;
6945 GLuint programs[kProgramCount] = {program1, program2};
6946 for (size_t i = 0; i < kProgramCount; ++i)
6947 {
6948 glUseProgram(programs[i]);
6949 GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6950 ASSERT_NE(uniformLoc, -1);
6951
6952 glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6953
6954 // Ensure position is at location 0 in both programs.
6955 GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6956 ASSERT_EQ(positionLocation, 0);
6957 }
6958 ASSERT_GL_NO_ERROR();
6959
6960 std::array<Vector3, 6> quadVertices = GetQuadVertices();
6961 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6962 glEnableVertexAttribArray(0);
6963
6964 // Draw once with each so their uniforms are updated.
6965 // The first draw will clear the screen to 255, 0, 0, 255
6966 glUseProgram(program2);
6967 glDrawArrays(GL_TRIANGLES, 0, 6);
6968 // The second draw will clear the screen to 127, 0, 0, 255
6969 glUseProgram(program1);
6970 glDrawArrays(GL_TRIANGLES, 0, 6);
6971
6972 // Draw with the previous program again, to make sure its default uniforms are bound again.
6973 glUseProgram(program2);
6974 glDrawArrays(GL_TRIANGLES, 0, 6);
6975
6976 // Verify red was drawn
6977 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6978 }
6979
6980 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
6981 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)6982 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
6983 {
6984 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6985
6986 GLBuffer indexBuffer;
6987 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6988 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
6989 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
6990 ASSERT_GL_NO_ERROR();
6991
6992 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6993 }
6994
6995 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)6996 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
6997 {
6998 glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
6999 glClear(GL_COLOR_BUFFER_BIT);
7000 ASSERT_GL_NO_ERROR();
7001 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7002
7003 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
7004 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7005
7006 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7007 glEnable(GL_RASTERIZER_DISCARD);
7008 glUseProgram(greenProgram);
7009 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7010 ASSERT_GL_NO_ERROR();
7011 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7012
7013 // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
7014 glDisable(GL_RASTERIZER_DISCARD);
7015 glUseProgram(greenProgram);
7016 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7017 ASSERT_GL_NO_ERROR();
7018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7019
7020 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7021 glEnable(GL_RASTERIZER_DISCARD);
7022 glUseProgram(blueProgram);
7023 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7024 ASSERT_GL_NO_ERROR();
7025 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7026 }
7027
7028 // Test that early return on binding the same texture is functional
TEST_P(SimpleStateChangeTestES3,BindingSameTexture)7029 TEST_P(SimpleStateChangeTestES3, BindingSameTexture)
7030 {
7031 // Create two 1x1 textures
7032 constexpr GLsizei kSize = 2;
7033 std::array<GLColor, kSize> colors = {GLColor::yellow, GLColor::cyan};
7034
7035 GLTexture tex[kSize];
7036 // Bind texture 0 and 1 to active textures 0 and 1 and set data
7037 glActiveTexture(GL_TEXTURE0);
7038 glBindTexture(GL_TEXTURE_2D, tex[0]);
7039 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[0].data());
7040
7041 glActiveTexture(GL_TEXTURE1);
7042 glBindTexture(GL_TEXTURE_2D, tex[1]);
7043 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[1].data());
7044
7045 // Create simple program and query sampler location
7046 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7047 ASSERT(program.valid());
7048 glUseProgram(program);
7049 GLint textureLocation = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
7050 ASSERT_NE(-1, textureLocation);
7051
7052 // Draw using active texture 0.
7053 glActiveTexture(GL_TEXTURE0);
7054 glUniform1i(textureLocation, 0);
7055 glBindTexture(GL_TEXTURE_2D, tex[0]);
7056 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7057 ASSERT_GL_NO_ERROR();
7058 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7059
7060 // Draw using active texture 1.
7061 glActiveTexture(GL_TEXTURE1);
7062 glUniform1i(textureLocation, 1);
7063 glBindTexture(GL_TEXTURE_2D, tex[1]);
7064 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7065 ASSERT_GL_NO_ERROR();
7066 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7067
7068 // Rebind the same texture to texture unit 1 and expect same color
7069 glBindTexture(GL_TEXTURE_2D, tex[1]);
7070 glUniform1i(textureLocation, 1);
7071 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7072 ASSERT_GL_NO_ERROR();
7073 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7074
7075 // Rebind the same texture to texture unit 0 and expect same color
7076 glActiveTexture(GL_TEXTURE0);
7077 glUniform1i(textureLocation, 0);
7078 glBindTexture(GL_TEXTURE_2D, tex[0]);
7079 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7080 ASSERT_GL_NO_ERROR();
7081 EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7082 }
7083
7084 // Test that early return on binding the same sampler is functional
TEST_P(SimpleStateChangeTestES3,BindingSameSampler)7085 TEST_P(SimpleStateChangeTestES3, BindingSameSampler)
7086 {
7087 // Create 2 samplers with different filtering.
7088 constexpr GLsizei kNumSamplers = 2;
7089 GLSampler samplers[kNumSamplers];
7090
7091 // Init sampler0
7092 glBindSampler(0, samplers[0]);
7093 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7094 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7095 ASSERT_GL_NO_ERROR();
7096
7097 // Init sampler1
7098 glBindSampler(1, samplers[1]);
7099 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7100 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7101 ASSERT_GL_NO_ERROR();
7102
7103 // Create a simple 2x1 texture with black and white colors
7104 std::array<GLColor, 2> colors = {{GLColor::black, GLColor::white}};
7105
7106 GLTexture tex;
7107 // Bind the same texture to texture units 0 and 1
7108 glActiveTexture(GL_TEXTURE0);
7109 glBindTexture(GL_TEXTURE_2D, tex);
7110 glActiveTexture(GL_TEXTURE1);
7111 glBindTexture(GL_TEXTURE_2D, tex);
7112 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
7113
7114 // Create a program that uses 2 samplers.
7115 constexpr char kFS[] = R"(precision mediump float;
7116 varying vec2 v_texCoord;
7117 uniform sampler2D baseSampler;
7118 uniform sampler2D overrideSampler;
7119 void main()
7120 {
7121 gl_FragColor = texture2D(baseSampler, v_texCoord);
7122 gl_FragColor = texture2D(overrideSampler, v_texCoord);
7123 })";
7124 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
7125 glUseProgram(program);
7126 GLint baseSamplerLoc = glGetUniformLocation(program, "baseSampler");
7127 GLint overrideSamplerLoc = glGetUniformLocation(program, "overrideSampler");
7128
7129 // Bind samplers to texture units 0 and 1
7130 glBindSampler(0, samplers[0]);
7131 glBindSampler(1, samplers[1]);
7132 glUniform1i(baseSamplerLoc, 0);
7133 glUniform1i(overrideSamplerLoc, 1);
7134 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7135 ASSERT_GL_NO_ERROR();
7136 // A gradient should have been rendered since "overrideSampler" has linear filter,
7137 // we should not expect a solid black or white color.
7138 EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::black);
7139 EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::white);
7140
7141 // Switch sampler bindings
7142 glBindSampler(1, samplers[0]);
7143 glBindSampler(0, samplers[1]);
7144 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7145 ASSERT_GL_NO_ERROR();
7146 // Now that "overrideSampler" has nearest filter expect solid colors.
7147 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7148 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7149
7150 // Rebind the same samplers again and expect same output
7151 glBindSampler(1, samplers[0]);
7152 glBindSampler(0, samplers[1]);
7153 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7154 ASSERT_GL_NO_ERROR();
7155 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7156 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7157 }
7158
7159 // Test that early return on binding the same buffer is functional
TEST_P(SimpleStateChangeTestES3,BindingSameBuffer)7160 TEST_P(SimpleStateChangeTestES3, BindingSameBuffer)
7161 {
7162 GLushort indexData[] = {0, 1, 2, 3};
7163
7164 GLBuffer elementArrayBuffer;
7165 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7166 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7167
7168 ANGLE_GL_PROGRAM(program, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
7169 glUseProgram(program);
7170
7171 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7172
7173 std::vector<GLColor> colors0(kWindowSize * kWindowSize);
7174 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors0.data());
7175
7176 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7177 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7178 std::vector<GLColor> colors1(kWindowSize * kWindowSize);
7179 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors1.data());
7180
7181 EXPECT_EQ(colors0, colors1);
7182 }
7183
7184 class ImageRespecificationTest : public ANGLETest<>
7185 {
7186 protected:
ImageRespecificationTest()7187 ImageRespecificationTest()
7188 {
7189 setWindowWidth(128);
7190 setWindowHeight(128);
7191 setConfigRedBits(8);
7192 setConfigGreenBits(8);
7193 setConfigBlueBits(8);
7194 setConfigAlphaBits(8);
7195 setConfigDepthBits(24);
7196 }
7197
testSetUp()7198 void testSetUp() override
7199 {
7200 constexpr char kVS[] = R"(precision highp float;
7201 attribute vec4 position;
7202 varying vec2 texcoord;
7203
7204 void main()
7205 {
7206 gl_Position = position;
7207 texcoord = (position.xy * 0.5) + 0.5;
7208 })";
7209
7210 constexpr char kFS[] = R"(precision highp float;
7211 uniform sampler2D tex;
7212 varying vec2 texcoord;
7213
7214 void main()
7215 {
7216 gl_FragColor = texture2D(tex, texcoord);
7217 })";
7218
7219 mProgram = CompileProgram(kVS, kFS);
7220 ASSERT_NE(0u, mProgram);
7221
7222 mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
7223 ASSERT_NE(-1, mTextureUniformLocation);
7224
7225 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7226 ASSERT_GL_NO_ERROR();
7227 }
7228
testTearDown()7229 void testTearDown() override
7230 {
7231 if (mProgram != 0)
7232 {
7233 glDeleteProgram(mProgram);
7234 }
7235 }
7236
7237 template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)7238 void init2DSourceTexture(GLenum internalFormat,
7239 GLenum dataFormat,
7240 GLenum dataType,
7241 const T *data)
7242 {
7243 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7244 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7245
7246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7248
7249 glBindTexture(GL_TEXTURE_2D, 0);
7250 }
7251
attachTargetTextureToFramebuffer()7252 void attachTargetTextureToFramebuffer()
7253 {
7254 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7255 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
7256 0);
7257
7258 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
7259 ASSERT_GL_NO_ERROR();
7260
7261 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7262 }
7263
renderToTargetTexture()7264 void renderToTargetTexture()
7265 {
7266 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7267
7268 glActiveTexture(GL_TEXTURE0);
7269 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7270
7271 glUseProgram(mProgram);
7272 glUniform1i(mTextureUniformLocation, 0);
7273
7274 drawQuad(mProgram, "position", 0.5f);
7275 ASSERT_GL_NO_ERROR();
7276
7277 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7278 glBindTexture(GL_TEXTURE_2D, 0);
7279 glUseProgram(0);
7280 }
7281
renderToDefaultFramebuffer(GLColor * expectedData)7282 void renderToDefaultFramebuffer(GLColor *expectedData)
7283 {
7284 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7285 glUseProgram(mProgram);
7286 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7287 glUniform1i(mTextureUniformLocation, 0);
7288
7289 glClear(GL_COLOR_BUFFER_BIT);
7290 drawQuad(mProgram, "position", 0.5f);
7291 ASSERT_GL_NO_ERROR();
7292
7293 EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
7294
7295 glBindTexture(GL_TEXTURE_2D, 0);
7296 glUseProgram(0);
7297 }
7298
7299 GLuint mProgram;
7300 GLint mTextureUniformLocation;
7301
7302 GLTexture mSourceTexture;
7303 GLTexture mTargetTexture;
7304
7305 GLFramebuffer mFramebuffer;
7306 };
7307
7308 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)7309 TEST_P(ImageRespecificationTest, Swizzle)
7310 {
7311 GLubyte data[] = {1, 64, 128, 200};
7312 GLColor expectedData(data[0], data[1], data[2], data[3]);
7313
7314 // Create the source and target texture
7315 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7316
7317 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7318 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
7319
7320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7322
7323 glBindTexture(GL_TEXTURE_2D, 0);
7324
7325 // Create a framebuffer and the target texture is attached to the framebuffer.
7326 attachTargetTextureToFramebuffer();
7327
7328 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7329 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7330 glClear(GL_COLOR_BUFFER_BIT);
7331 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7332
7333 // Render content of source texture to target texture
7334 // This command triggers the creation of -
7335 // - draw imageviews of the texture
7336 // - VkFramebuffer object of the framebuffer
7337 renderToTargetTexture();
7338
7339 // This swizzle operation should cause the read imageviews of the texture to be released
7340 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7343 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7344 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7345 glBindTexture(GL_TEXTURE_2D, 0);
7346
7347 // Draw using the newly created read imageviews
7348 renderToDefaultFramebuffer(&expectedData);
7349
7350 // Render content of source texture to target texture, again
7351 renderToTargetTexture();
7352
7353 // Make sure the content rendered to target texture is correct
7354 renderToDefaultFramebuffer(&expectedData);
7355 }
7356
7357 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
7358 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)7359 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
7360 {
7361 // This is the specific problem on the Vulkan backend and needs some extensions
7362 ANGLE_SKIP_TEST_IF(
7363 !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
7364 !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
7365
7366 GLubyte data[] = {1, 64, 128, 200};
7367 GLColor expectedData(data[0], data[1], data[2], data[3]);
7368
7369 // Create the source texture
7370 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7371
7372 // Create the first EGL image to attach the framebuffer through the texture
7373 GLTexture firstTexture;
7374
7375 glBindTexture(GL_TEXTURE_2D, firstTexture);
7376 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7377
7378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7380
7381 glBindTexture(GL_TEXTURE_2D, 0);
7382
7383 EGLWindow *window = getEGLWindow();
7384 EGLint attribs[] = {
7385 EGL_IMAGE_PRESERVED,
7386 EGL_TRUE,
7387 EGL_NONE,
7388 };
7389 EGLImageKHR firstEGLImage = eglCreateImageKHR(
7390 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7391 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(firstTexture)), attribs);
7392 ASSERT_EGL_SUCCESS();
7393
7394 // Create the target texture and attach it to the framebuffer
7395 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7396 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7397
7398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7400
7401 glBindTexture(GL_TEXTURE_2D, 0);
7402
7403 attachTargetTextureToFramebuffer();
7404
7405 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7406
7407 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7408 glClear(GL_COLOR_BUFFER_BIT);
7409
7410 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7411
7412 // Render content of source texture to target texture
7413 // This command triggers the creation of -
7414 // - draw imageviews of the texture
7415 // - VkFramebuffer object of the framebuffer
7416 renderToTargetTexture();
7417
7418 // Make sure the content rendered to target texture is correct
7419 renderToDefaultFramebuffer(&expectedData);
7420
7421 // Create the second EGL image
7422 GLTexture secondTexture;
7423
7424 glBindTexture(GL_TEXTURE_2D, secondTexture);
7425 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7426
7427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7429
7430 glBindTexture(GL_TEXTURE_2D, 0);
7431
7432 EGLImageKHR secondEGLImage = eglCreateImageKHR(
7433 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7434 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(secondTexture)), attribs);
7435 ASSERT_EGL_SUCCESS();
7436
7437 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7438 // This will release all the imageviews related to the first EGL image
7439 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
7440
7441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7442 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7443
7444 glBindTexture(GL_TEXTURE_2D, 0);
7445
7446 // Attach the first EGL image to the target texture again
7447 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7448 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7449
7450 // This is for checking this code can deal with the problem even if both ORPHAN and
7451 // COLOR_ATTACHMENT dirty bits are set.
7452 GLTexture tempTexture;
7453
7454 glBindTexture(GL_TEXTURE_2D, tempTexture);
7455 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7456
7457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7458 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7459
7460 glBindTexture(GL_TEXTURE_2D, 0);
7461
7462 // This sets COLOR_ATTACHMENT dirty bit
7463 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7464 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
7465 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7466
7467 // The released imageviews related to "secondEGLImage" will be garbage collected
7468 renderToDefaultFramebuffer(&expectedData);
7469
7470 // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
7471 renderToTargetTexture();
7472
7473 // Make sure the content rendered to target texture is correct
7474 renderToDefaultFramebuffer(&expectedData);
7475
7476 // Render content of source texture to target texture
7477 attachTargetTextureToFramebuffer();
7478 renderToTargetTexture();
7479
7480 // Make sure the content rendered to target texture is correct
7481 renderToDefaultFramebuffer(&expectedData);
7482
7483 eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
7484 eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
7485 }
7486
7487 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)7488 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
7489 {
7490 GLushort indexData[] = {0, 1, 2, 3};
7491
7492 GLBuffer elementArrayBuffer;
7493 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7494 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7495
7496 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7497 glUseProgram(program);
7498
7499 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7500
7501 elementArrayBuffer.reset();
7502
7503 // Must use a non-0 offset and a multiple of the type size.
7504 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
7505 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7506 }
7507
7508 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)7509 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
7510 {
7511 // SwiftShader does not currently support robustness.
7512 ANGLE_SKIP_TEST_IF(isSwiftshader());
7513
7514 // http://anglebug.com/42263447
7515 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
7516
7517 // no intent to follow up on this failure.
7518 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7519
7520 // no intent to follow up on this failure.
7521 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
7522
7523 // no intent to follow up on this failure.
7524 ANGLE_SKIP_TEST_IF(IsMac());
7525
7526 // Mali does not support robustness now.
7527 ANGLE_SKIP_TEST_IF(IsARM());
7528
7529 std::vector<GLubyte> data(48, 1);
7530
7531 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7532 glUseProgram(program);
7533
7534 // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
7535 GLBuffer arrayBuffer;
7536 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
7537 glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
7538 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
7539 glEnableVertexAttribArray(0);
7540 glDrawArrays(GL_TRIANGLES, 0, 3);
7541
7542 // Then bind a zero size buffer and draw.
7543 GLBuffer secondBuffer;
7544 glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
7545 glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
7546 glDrawArrays(GL_TRIANGLES, 0, 3);
7547
7548 // Finally delete the original buffer. This triggers the bug.
7549 arrayBuffer.reset();
7550 glDrawArrays(GL_TRIANGLES, 0, 3);
7551 ASSERT_GL_NO_ERROR();
7552 }
7553
7554 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)7555 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
7556 {
7557 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7558
7559 glUseProgram(program);
7560
7561 // Draw with empty buffer. Out of range but valid.
7562 GLBuffer buffer;
7563 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7564 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
7565
7566 // Switch VAO. No buffer bound, should be an error.
7567 GLVertexArray vao;
7568 glBindVertexArray(vao);
7569 glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
7570 reinterpret_cast<const GLvoid *>(0x1000));
7571 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7572 }
7573
7574 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
7575 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)7576 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
7577 {
7578 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7579 // bit.
7580 GLBuffer indexBuffer;
7581 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7582
7583 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7584 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7585
7586 // Setup vertices.
7587 const std::array<GLfloat, 6> kVertices = {
7588 -1, -1, 3, -1, -1, 3,
7589 };
7590 GLBuffer vertexBuffer;
7591 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7592 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7593 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7594 glEnableVertexAttribArray(0);
7595
7596 // Create a uniform buffer that will get modified. This is used to break the render pass.
7597 const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
7598
7599 GLBuffer ubo;
7600 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
7601 glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
7602 glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
7603
7604 // Set up a program. The same program is used for all draw calls to avoid state change due to
7605 // program change.
7606 constexpr char kFS[] = R"(#version 300 es
7607 precision mediump float;
7608 uniform block { uint data; } ubo;
7609 uniform uint expect;
7610 uniform vec4 successColor;
7611 out vec4 colorOut;
7612 void main()
7613 {
7614 colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
7615 })";
7616
7617 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7618 glUseProgram(program);
7619
7620 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7621 const GLint expectLoc = glGetUniformLocation(program, "expect");
7622 const GLint successLoc = glGetUniformLocation(program, "successColor");
7623 ASSERT_NE(-1, positionLoc);
7624 ASSERT_NE(-1, expectLoc);
7625 ASSERT_NE(-1, successLoc);
7626
7627 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7628 glEnableVertexAttribArray(positionLoc);
7629
7630 glUniform1ui(expectLoc, kUboData1[0]);
7631 glUniform4f(successLoc, 0, 0, 0, 1);
7632 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7633 EXPECT_GL_NO_ERROR();
7634
7635 // Then upload data to the UBO so on next use the render pass has to break. This draw call is
7636 // not indexed.
7637 constexpr GLuint kUboData2 = 0x87654321u;
7638 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
7639
7640 glEnable(GL_BLEND);
7641 glBlendFunc(GL_ONE, GL_ONE);
7642 glUniform1ui(expectLoc, kUboData2);
7643 glUniform4f(successLoc, 0, 1, 0, 0);
7644 glDrawArrays(GL_TRIANGLES, 0, 3);
7645
7646 // Issue another draw call that is indexed. The index buffer should be bound correctly on the
7647 // new render pass.
7648 glUniform4f(successLoc, 0, 0, 1, 0);
7649 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7650 EXPECT_GL_NO_ERROR();
7651
7652 // Ensure correct rendering.
7653 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7654 }
7655
7656 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)7657 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
7658 {
7659 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7660 glClearColor(0, 0, 0, 1);
7661 glClear(GL_COLOR_BUFFER_BIT);
7662 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7663
7664 GLFramebuffer fbo;
7665 GLTexture texture;
7666
7667 glBindTexture(GL_TEXTURE_2D, texture);
7668 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7669 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7670 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7671
7672 glClear(GL_COLOR_BUFFER_BIT);
7673 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7674
7675 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7676
7677 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7678 // bit.
7679 GLBuffer indexBuffer;
7680 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7681
7682 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7683 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7684
7685 // Setup vertices.
7686 const std::array<GLfloat, 6> kVertices = {
7687 -1, -1, 3, -1, -1, 3,
7688 };
7689 GLBuffer vertexBuffer;
7690 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7691 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7692 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7693 glEnableVertexAttribArray(0);
7694
7695 // Set up a program. The same program is used for all draw calls to avoid state change due to
7696 // program change.
7697 constexpr char kFS[] = R"(#version 300 es
7698 precision mediump float;
7699 uniform vec4 colorIn;
7700 out vec4 colorOut;
7701 void main()
7702 {
7703 colorOut = colorIn;
7704 })";
7705
7706 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7707 glUseProgram(program);
7708
7709 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7710 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
7711 ASSERT_NE(-1, positionLoc);
7712 ASSERT_NE(-1, colorLoc);
7713
7714 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7715 glEnableVertexAttribArray(positionLoc);
7716
7717 glUniform4f(colorLoc, 1, 0, 0, 1);
7718 glEnable(GL_BLEND);
7719 glBlendFunc(GL_ONE, GL_ONE);
7720 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7721 EXPECT_GL_NO_ERROR();
7722
7723 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7724 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7725 glUniform4f(colorLoc, 0, 1, 0, 0);
7726 glDrawArrays(GL_TRIANGLES, 0, 3);
7727
7728 glUniform4f(colorLoc, 0, 0, 1, 0);
7729 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7730 EXPECT_GL_NO_ERROR();
7731
7732 // Ensure correct rendering.
7733 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7734
7735 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7736 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7737 }
7738
7739 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
7740 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)7741 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
7742 {
7743 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7744 glClearColor(0, 0, 0, 1);
7745 glClear(GL_COLOR_BUFFER_BIT);
7746 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7747
7748 GLFramebuffer fbo;
7749 GLTexture texture;
7750
7751 glBindTexture(GL_TEXTURE_2D, texture);
7752 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7753 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7754 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7755
7756 glClear(GL_COLOR_BUFFER_BIT);
7757 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7758
7759 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7760
7761 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
7762 // bit.
7763 GLBuffer indexBuffer;
7764 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7765
7766 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7767 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7768
7769 // Setup vertices.
7770 const std::array<GLfloat, 6> kVertices = {
7771 -1, -1, 3, -1, -1, 3,
7772 };
7773 GLBuffer vertexBuffer;
7774 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7775 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7776 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7777 glEnableVertexAttribArray(0);
7778
7779 // Set up a program. The same program is used for all draw calls to avoid state change due to
7780 // program change.
7781 constexpr char kFS[] = R"(#version 300 es
7782 precision mediump float;
7783 uniform vec4 colorIn;
7784 out vec4 colorOut;
7785 void main()
7786 {
7787 colorOut = colorIn;
7788 })";
7789
7790 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7791 glUseProgram(program);
7792
7793 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7794 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
7795 ASSERT_NE(-1, positionLoc);
7796 ASSERT_NE(-1, colorLoc);
7797
7798 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7799 glEnableVertexAttribArray(positionLoc);
7800
7801 glUniform4f(colorLoc, 0, 0, 0, 1);
7802 glEnable(GL_BLEND);
7803 glBlendFunc(GL_ONE, GL_ONE);
7804 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7805 EXPECT_GL_NO_ERROR();
7806
7807 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7808 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7809 glUniform4f(colorLoc, 0, 1, 0, 0);
7810 glDrawArrays(GL_TRIANGLES, 0, 3);
7811
7812 // In between the two calls, make sure the first render pass is submitted, so the primary
7813 // command buffer is reset.
7814 {
7815 EGLWindow *window = getEGLWindow();
7816 EGLDisplay dpy = window->getDisplay();
7817 EGLConfig config = window->getConfig();
7818 EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
7819 EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
7820 EGLContext ctx = window->createContext(EGL_NO_CONTEXT, nullptr);
7821 EXPECT_EGL_SUCCESS();
7822 std::thread flushThread = std::thread([&]() {
7823 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
7824 EXPECT_EGL_SUCCESS();
7825
7826 glClearColor(1, 0, 0, 1);
7827 glClear(GL_COLOR_BUFFER_BIT);
7828 EXPECT_GL_NO_ERROR();
7829
7830 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7831 });
7832 flushThread.join();
7833
7834 eglDestroySurface(dpy, surface);
7835 eglDestroyContext(dpy, ctx);
7836 }
7837
7838 glUniform4f(colorLoc, 0, 0, 1, 0);
7839 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7840 EXPECT_GL_NO_ERROR();
7841
7842 // Ensure correct rendering.
7843 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7844 }
7845
7846 // Negative test for EXT_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxEXTNegativeTest)7847 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxEXTNegativeTest)
7848 {
7849 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_primitive_bounding_box"));
7850
7851 glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7852 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7853
7854 GLfloat boundingBox[8] = {0};
7855 glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, boundingBox);
7856 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7857 }
7858
7859 // Negative test for OES_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxOESNegativeTest)7860 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxOESNegativeTest)
7861 {
7862 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_OES_primitive_bounding_box"));
7863
7864 glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7865 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7866
7867 GLfloat boundingBox[8] = {0};
7868 glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_OES, boundingBox);
7869 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7870 }
7871
7872 // Update an element array buffer that is already in use.
TEST_P(SimpleStateChangeTest,UpdateBoundElementArrayBuffer)7873 TEST_P(SimpleStateChangeTest, UpdateBoundElementArrayBuffer)
7874 {
7875 constexpr char kVS[] = R"(attribute vec4 position;
7876 attribute float color;
7877 varying float colorVarying;
7878 void main()
7879 {
7880 gl_Position = position;
7881 colorVarying = color;
7882 })";
7883
7884 constexpr char kFS[] = R"(precision mediump float;
7885 varying float colorVarying;
7886 void main()
7887 {
7888 if (colorVarying == 1.0)
7889 {
7890 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
7891 }
7892 else
7893 {
7894 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
7895 }
7896 })";
7897
7898 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
7899 glUseProgram(testProgram);
7900
7901 GLint posLoc = glGetAttribLocation(testProgram, "position");
7902 ASSERT_NE(-1, posLoc);
7903 GLint colorLoc = glGetAttribLocation(testProgram, "color");
7904 ASSERT_NE(-1, colorLoc);
7905
7906 std::array<GLushort, 6> quadIndices = GetQuadIndices();
7907
7908 std::vector<GLubyte> indices;
7909 for (GLushort index : quadIndices)
7910 {
7911 indices.push_back(static_cast<GLubyte>(index));
7912 }
7913
7914 GLBuffer indexBuffer;
7915 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7916 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), indices.data(),
7917 GL_STATIC_DRAW);
7918
7919 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
7920
7921 std::vector<Vector3> positionVertices;
7922 for (Vector3 vertex : quadVertices)
7923 {
7924 positionVertices.push_back(vertex);
7925 }
7926 for (Vector3 vertex : quadVertices)
7927 {
7928 positionVertices.push_back(vertex);
7929 }
7930
7931 GLBuffer positionVertexBuffer;
7932 glBindBuffer(GL_ARRAY_BUFFER, positionVertexBuffer);
7933 glBufferData(GL_ARRAY_BUFFER, positionVertices.size() * sizeof(positionVertices[0]),
7934 positionVertices.data(), GL_STATIC_DRAW);
7935 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
7936 glEnableVertexAttribArray(posLoc);
7937
7938 std::vector<float> colorVertices = {1, 1, 1, 1, 0, 0, 0, 0};
7939
7940 GLBuffer colorVertexBuffer;
7941 glBindBuffer(GL_ARRAY_BUFFER, colorVertexBuffer);
7942 glBufferData(GL_ARRAY_BUFFER, colorVertices.size() * sizeof(colorVertices[0]),
7943 colorVertices.data(), GL_STATIC_DRAW);
7944 glVertexAttribPointer(colorLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
7945 glEnableVertexAttribArray(colorLoc);
7946
7947 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7948 ASSERT_GL_NO_ERROR();
7949 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7950
7951 indices.clear();
7952 for (GLushort index : quadIndices)
7953 {
7954 indices.push_back(static_cast<GLubyte>(index + 4));
7955 }
7956 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(indices[0]),
7957 indices.data());
7958
7959 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7960 ASSERT_GL_NO_ERROR();
7961 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7962 }
7963
7964 // Covers a bug where we would use a stale cache variable in the Vulkan back-end.
TEST_P(SimpleStateChangeTestES3,DeleteFramebufferBeforeQuery)7965 TEST_P(SimpleStateChangeTestES3, DeleteFramebufferBeforeQuery)
7966 {
7967 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7968 glUseProgram(testProgram);
7969
7970 GLFramebuffer fbo;
7971 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
7972
7973 GLRenderbuffer rbo;
7974 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
7975
7976 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, 16, 16);
7977 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
7978
7979 GLfloat floatArray[] = {1, 2, 3, 4};
7980
7981 GLBuffer buffer;
7982 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7983 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLfloat) * 4, floatArray, GL_DYNAMIC_COPY);
7984 glDrawElements(GL_TRIANGLE_FAN, 5, GL_UNSIGNED_SHORT, 0);
7985
7986 fbo.reset();
7987
7988 GLQuery query2;
7989 glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, query2);
7990
7991 ASSERT_GL_NO_ERROR();
7992 }
7993
7994 // Covers an edge case
TEST_P(SimpleStateChangeTestES3,TextureTypeConflictAfterDraw)7995 TEST_P(SimpleStateChangeTestES3, TextureTypeConflictAfterDraw)
7996 {
7997 constexpr char kVS[] = R"(precision highp float;
7998 attribute vec4 a_position;
7999 void main()
8000 {
8001 gl_Position = a_position;
8002 }
8003 )";
8004
8005 constexpr char kFS[] = R"(precision highp float;
8006 uniform sampler2D u_2d1;
8007 uniform samplerCube u_Cube1;
8008 void main()
8009 {
8010 gl_FragColor = texture2D(u_2d1, vec2(0.0, 0.0)) + textureCube(u_Cube1, vec3(0.0, 0.0, 0.0));
8011 }
8012 )";
8013
8014 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
8015 glUseProgram(testProgram);
8016
8017 GLTexture texture;
8018 glBindTexture(GL_TEXTURE_2D, texture);
8019 glTexStorage2D(GL_TEXTURE_2D, 4, GL_SRGB8, 1268, 614);
8020
8021 GLint uniformloc = glGetUniformLocation(testProgram, "u_Cube1");
8022 ASSERT_NE(-1, uniformloc);
8023 glUniform1i(uniformloc, 1);
8024
8025 glDrawArrays(GL_POINTS, 0, 1);
8026 ASSERT_GL_NO_ERROR();
8027
8028 // Trigger the state update.
8029 glLinkProgram(testProgram);
8030 texture.reset();
8031
8032 // The texture types are now conflicting, and draws should fail.
8033 glDrawArrays(GL_POINTS, 0, 1);
8034 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8035 }
8036
8037 // Regression test for a bug where a mutable texture is used with non-zero base level then rebased
8038 // to zero but made incomplete and attached to the framebuffer. The texture's image is not
8039 // recreated with level 0, leading to errors when drawing to the framebuffer.
TEST_P(SimpleStateChangeTestES3,NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)8040 TEST_P(SimpleStateChangeTestES3, NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)
8041 {
8042 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8043 glUseProgram(program);
8044
8045 const std::array<GLColor, 4> kMip0Data = {GLColor::red, GLColor::red, GLColor::red,
8046 GLColor::red};
8047 const std::array<GLColor, 2> kMip1Data = {GLColor::green, GLColor::green};
8048
8049 // Create two textures.
8050 GLTexture immutableTex;
8051 glBindTexture(GL_TEXTURE_2D, immutableTex);
8052 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
8053 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data.data());
8054
8055 GLTexture mutableTex;
8056 glBindTexture(GL_TEXTURE_2D, mutableTex);
8057 for (uint32_t mip = 0; mip < 2; ++mip)
8058 {
8059 const uint32_t size = 4 >> mip;
8060 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8061 mip == 0 ? kMip0Data.data() : kMip1Data.data());
8062 }
8063
8064 GLFramebuffer fbo;
8065 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8066
8067 // Sample from the mutable texture at non-zero base level.
8068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
8069 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8070
8071 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, immutableTex, 0);
8072 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8073 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[0]);
8074
8075 // Rebase the mutable texture to zero, but enable mipmapping which makes it incomplete.
8076 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
8078
8079 // Remove feedback loop for good measure.
8080 glBindTexture(GL_TEXTURE_2D, immutableTex);
8081
8082 // Draw into base zero of the texture.
8083 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutableTex, 0);
8084 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8085
8086 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[1]);
8087 ASSERT_GL_NO_ERROR();
8088 }
8089
8090 // Regression test for a bug where the framebuffer binding was not synced during invalidate when a
8091 // clear operation was deferred.
TEST_P(SimpleStateChangeTestES3,ChangeFramebufferThenInvalidateWithClear)8092 TEST_P(SimpleStateChangeTestES3, ChangeFramebufferThenInvalidateWithClear)
8093 {
8094 // Clear the default framebuffer.
8095 glClear(GL_COLOR_BUFFER_BIT);
8096
8097 // Start rendering to another framebuffer
8098 GLFramebuffer fbo;
8099 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8100
8101 GLRenderbuffer rbo;
8102 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
8103 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
8104 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
8105
8106 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
8107 glUseProgram(program);
8108 glDrawArrays(GL_TRIANGLES, 0, 3);
8109
8110 // Switch back to the default framebuffer
8111 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8112
8113 // Invalidate it. Don't invalidate color, as that's the one being cleared.
8114 constexpr GLenum kAttachment = GL_DEPTH;
8115 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8116 EXPECT_GL_NO_ERROR();
8117 }
8118
8119 // Test that clear / invalidate / clear works. The invalidate is for a target that's not cleared.
8120 // Regression test for a bug where invalidate() would start a render pass to perform the first
8121 // clear, while the second clear didn't expect a render pass opened without any draw calls in it.
TEST_P(SimpleStateChangeTestES3,ClearColorInvalidateDepthClearColor)8122 TEST_P(SimpleStateChangeTestES3, ClearColorInvalidateDepthClearColor)
8123 {
8124 // Clear color.
8125 glClear(GL_COLOR_BUFFER_BIT);
8126
8127 // Invalidate depth.
8128 constexpr GLenum kAttachment = GL_DEPTH;
8129 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8130 EXPECT_GL_NO_ERROR();
8131
8132 // Clear color again.
8133 glClear(GL_COLOR_BUFFER_BIT);
8134 ASSERT_GL_NO_ERROR();
8135 }
8136
8137 // Regression test for a bug where glInvalidateFramebuffer(GL_FRAMEBUFFER, ...) was invalidating
8138 // both the draw and read framebuffers.
TEST_P(SimpleStateChangeTestES3,InvalidateFramebufferShouldntInvalidateReadFramebuffer)8139 TEST_P(SimpleStateChangeTestES3, InvalidateFramebufferShouldntInvalidateReadFramebuffer)
8140 {
8141 // Create an invalid read framebuffer.
8142 GLFramebuffer fbo;
8143 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8144
8145 GLTexture tex;
8146 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
8147 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, 1, 1, 1);
8148 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, tex, 0, 5);
8149
8150 // Invalidate using GL_FRAMEBUFFER. If GL_READ_FRAMEBUFFER was used, validation would fail due
8151 // to the framebuffer not being complete. A bug here was attempting to invalidate the read
8152 // framebuffer given GL_FRAMEBUFFER anyway.
8153 constexpr std::array<GLenum, 2> kAttachments = {GL_DEPTH, GL_STENCIL};
8154 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, kAttachments.data());
8155 EXPECT_GL_NO_ERROR();
8156 }
8157
8158 // Test that respecifies a buffer after we start XFB.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedback)8159 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback)
8160 {
8161 std::vector<std::string> tfVaryings = {"gl_Position"};
8162 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8163 essl3_shaders::fs::Green(), tfVaryings,
8164 GL_INTERLEAVED_ATTRIBS);
8165
8166 glUseProgram(testProgram);
8167 GLBuffer buffer;
8168 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8169 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8170 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8171 glBeginTransformFeedback(GL_TRIANGLES);
8172 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8173 glDrawArrays(GL_TRIANGLES, 0, 6);
8174 glEndTransformFeedback();
8175 }
8176
8177 // Test a bug angleproject:6998 in TransformFeedback code path by allocating paddingBuffer first and
8178 // then allocate another buffer and then deallocate paddingBuffer and then allocate buffer again.
8179 // This new buffer will be allocated in the space where paddingBuffer was allocated which causing
8180 // XFB generate VVL error.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)8181 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)
8182 {
8183 std::vector<std::string> tfVaryings = {"gl_Position"};
8184 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8185 essl3_shaders::fs::Green(), tfVaryings,
8186 GL_INTERLEAVED_ATTRIBS);
8187 glUseProgram(testProgram);
8188
8189 GLuint paddingBuffer;
8190 glGenBuffers(1, &paddingBuffer);
8191 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, paddingBuffer);
8192 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 256, nullptr, GL_STREAM_DRAW);
8193
8194 GLBuffer buffer;
8195 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8196 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8197 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8198 // Delete padding buffer, expecting the next bufferData call will reuse the space of
8199 // paddingBuffer whose offset is smaller than buffer's offset, which triggers the bug.
8200 glDeleteBuffers(1, &paddingBuffer);
8201 glBeginTransformFeedback(GL_TRIANGLES);
8202 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8203 glDrawArrays(GL_TRIANGLES, 0, 6);
8204 glEndTransformFeedback();
8205 }
8206
8207 // Regression test for a bug in the Vulkan backend where a draw-based copy after a deferred flush
8208 // would lead to an image view being destroyed too early.
TEST_P(SimpleStateChangeTestES3,DrawFlushThenCopyTexImage)8209 TEST_P(SimpleStateChangeTestES3, DrawFlushThenCopyTexImage)
8210 {
8211 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8212
8213 // Issue a cheap draw call and a flush
8214 glEnable(GL_SCISSOR_TEST);
8215 glScissor(0, 0, 1, 1);
8216 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8217 glDisable(GL_SCISSOR_TEST);
8218 glFlush();
8219
8220 constexpr GLsizei kSize = 32;
8221
8222 // Then an expensive copy tex image
8223 GLTexture texture;
8224 glBindTexture(GL_TEXTURE_3D, texture);
8225 glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGB8, kSize, kSize, kSize);
8226 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, kSize, kSize);
8227 glFlush();
8228 ASSERT_GL_NO_ERROR();
8229 }
8230
TEST_P(SimpleStateChangeTestES3,DrawFlushThenBlit)8231 TEST_P(SimpleStateChangeTestES3, DrawFlushThenBlit)
8232 {
8233 constexpr GLsizei kSize = 256;
8234 const std::vector<GLColor> data(kSize * kSize, GLColor::red);
8235
8236 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8237
8238 GLFramebuffer fbo;
8239 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8240
8241 GLTexture readColor;
8242 glBindTexture(GL_TEXTURE_2D, readColor);
8243 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8244 data.data());
8245 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readColor, 0);
8246
8247 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8248
8249 // Issue a cheap draw call and a flush
8250 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8251 glEnable(GL_SCISSOR_TEST);
8252 glScissor(0, 0, 1, 1);
8253 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8254 glDisable(GL_SCISSOR_TEST);
8255 glFlush();
8256
8257 // Then an expensive blit
8258 glBlitFramebuffer(0, 0, kSize, kSize, kSize + 2, kSize, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
8259 glFlush();
8260 ASSERT_GL_NO_ERROR();
8261 }
8262
8263 class VertexAttribArrayStateChangeTest : public ANGLETest<>
8264 {
8265 protected:
VertexAttribArrayStateChangeTest()8266 VertexAttribArrayStateChangeTest()
8267 {
8268 setWindowWidth(128);
8269 setWindowHeight(128);
8270 setConfigRedBits(8);
8271 setConfigGreenBits(8);
8272 setConfigBlueBits(8);
8273 setConfigAlphaBits(8);
8274 setConfigDepthBits(24);
8275 }
8276
testSetUp()8277 void testSetUp() override
8278 {
8279 constexpr char kVS[] = R"(precision highp float;
8280 attribute vec4 position;
8281 attribute vec4 color;
8282 varying vec4 colorOut;
8283
8284 void main()
8285 {
8286 gl_Position = position;
8287 colorOut = color;
8288 })";
8289
8290 constexpr char kFS[] = R"(precision highp float;
8291 varying vec4 colorOut;
8292
8293 void main()
8294 {
8295 gl_FragColor = colorOut;
8296 })";
8297
8298 mProgram = CompileProgram(kVS, kFS);
8299 ASSERT_NE(0u, mProgram);
8300
8301 mPosAttribLocation = glGetAttribLocation(mProgram, "position");
8302 ASSERT_NE(-1, mPosAttribLocation);
8303 mColorAttribLocation = glGetAttribLocation(mProgram, "color");
8304 ASSERT_NE(-1, mColorAttribLocation);
8305
8306 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
8307 ASSERT_GL_NO_ERROR();
8308
8309 glGenBuffers(1, &mVertexBuffer);
8310 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8311
8312 const float posAttribData[] = {
8313 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8314 };
8315 glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8316
8317 glBindBuffer(GL_ARRAY_BUFFER, 0);
8318 }
8319
testTearDown()8320 void testTearDown() override
8321 {
8322 if (mVertexBuffer != 0)
8323 {
8324 glDeleteBuffers(1, &mVertexBuffer);
8325 }
8326
8327 if (mProgram != 0)
8328 {
8329 glDeleteProgram(mProgram);
8330 }
8331 }
8332
8333 GLuint mProgram;
8334 GLint mPosAttribLocation;
8335 GLint mColorAttribLocation;
8336 GLuint mVertexBuffer;
8337 };
8338
TEST_P(VertexAttribArrayStateChangeTest,Basic)8339 TEST_P(VertexAttribArrayStateChangeTest, Basic)
8340 {
8341 glUseProgram(mProgram);
8342 glClear(GL_COLOR_BUFFER_BIT);
8343 glDisable(GL_DEPTH_TEST);
8344 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8345
8346 glVertexAttribPointer(mPosAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8347 glEnableVertexAttribArray(mPosAttribLocation);
8348 glDisableVertexAttribArray(mColorAttribLocation);
8349 glVertexAttrib4f(mColorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8350 // Don't try to verify the color of this draw as red here because it might
8351 // hide the bug
8352 glDrawArrays(GL_TRIANGLES, 0, 6);
8353 glVertexAttrib4f(mColorAttribLocation, 0.0f, 1.0f, 0.0f, 1.0f);
8354 glDrawArrays(GL_TRIANGLES, 0, 6);
8355 ASSERT_GL_NO_ERROR();
8356 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8357
8358 glUseProgram(0);
8359 glBindBuffer(GL_ARRAY_BUFFER, 0);
8360 }
8361
TEST_P(SimpleStateChangeTestES3,DepthOnlyToColorAttachmentPreservesBlendState)8362 TEST_P(SimpleStateChangeTestES3, DepthOnlyToColorAttachmentPreservesBlendState)
8363 {
8364
8365 constexpr char kVS[] = R"(precision highp float;
8366 attribute vec4 position;
8367 attribute vec4 color;
8368 varying vec4 colorOut;
8369
8370 void main()
8371 {
8372 gl_Position = position;
8373 colorOut = color;
8374 })";
8375
8376 constexpr char kFS[] = R"(precision highp float;
8377 varying vec4 colorOut;
8378
8379 void main()
8380 {
8381 gl_FragColor = colorOut;
8382 })";
8383
8384 ANGLE_GL_PROGRAM(program, kVS, kFS);
8385
8386 GLint posAttribLocation = glGetAttribLocation(program, "position");
8387 ASSERT_NE(-1, posAttribLocation);
8388 GLint colorAttribLocation = glGetAttribLocation(program, "color");
8389 ASSERT_NE(-1, colorAttribLocation);
8390
8391 GLBuffer vertexBuffer;
8392 GLTexture texture;
8393 GLFramebuffer framebuffer;
8394 GLRenderbuffer depthRenderbuffer;
8395 GLFramebuffer depthFramebuffer;
8396
8397 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8398
8399 const float posAttribData[] = {
8400 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8401 };
8402 glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8403
8404 glBindBuffer(GL_ARRAY_BUFFER, 0);
8405
8406 constexpr int kWidth = 1;
8407 constexpr int kHeight = 1;
8408
8409 glBindTexture(GL_TEXTURE_2D, texture);
8410 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
8411 glBindTexture(GL_TEXTURE_2D, 0);
8412
8413 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8414 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8415 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8416
8417 glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
8418 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
8419 glBindRenderbuffer(GL_RENDERBUFFER, 0);
8420
8421 glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8422 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
8423 depthRenderbuffer);
8424 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8425
8426 glDisable(GL_DEPTH_TEST);
8427 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8428 glVertexAttribPointer(posAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8429 glEnableVertexAttribArray(posAttribLocation);
8430 glDisableVertexAttribArray(colorAttribLocation);
8431 glVertexAttrib4f(colorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8432
8433 glUseProgram(program);
8434 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8435 glEnable(GL_BLEND);
8436 glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
8437 glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
8438 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8439 glClear(GL_COLOR_BUFFER_BIT);
8440 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8441
8442 glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8443 glDrawArrays(GL_TRIANGLES, 0, 6);
8444
8445 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8446 glDrawArrays(GL_TRIANGLES, 0, 6);
8447 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
8448
8449 glBindBuffer(GL_ARRAY_BUFFER, 0);
8450 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8451 glUseProgram(0);
8452 }
8453
8454 // Tests a bug where we wouldn't update our cached base/max levels in Vulkan.
TEST_P(SimpleStateChangeTestES3,MaxLevelChange)8455 TEST_P(SimpleStateChangeTestES3, MaxLevelChange)
8456 {
8457 // Initialize an immutable texture with 2 levels.
8458 std::vector<GLColor> bluePixels(4, GLColor::blue);
8459
8460 GLTexture tex;
8461 glBindTexture(GL_TEXTURE_2D, tex);
8462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8464 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8465 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2);
8466 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, bluePixels.data());
8467 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::yellow);
8468
8469 // Set up draw resources.
8470 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8471 glUseProgram(testProgram);
8472
8473 GLint posLoc = glGetAttribLocation(testProgram, essl1_shaders::PositionAttrib());
8474 ASSERT_NE(-1, posLoc);
8475
8476 std::array<Vector3, 6> quadVerts = GetQuadVertices();
8477
8478 GLBuffer vao;
8479 glBindBuffer(GL_ARRAY_BUFFER, vao);
8480 glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
8481 GL_STATIC_DRAW);
8482 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
8483 glEnableVertexAttribArray(posLoc);
8484
8485 ASSERT_GL_NO_ERROR();
8486
8487 // Draw with the 2x2 mip / max level 1.
8488 glViewport(0, 0, 2, 2);
8489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8490 glDrawArrays(GL_TRIANGLES, 0, 6);
8491
8492 // Draw with the 1x1 mip / max level 2.
8493 glViewport(2, 0, 1, 1);
8494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8495 glDrawArrays(GL_TRIANGLES, 0, 6);
8496
8497 // Draw with the 2x2 mip / max level 1.
8498 glViewport(0, 2, 2, 2);
8499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8500 glDrawArrays(GL_TRIANGLES, 0, 6);
8501
8502 // Draw with the 1x1 mip / max level 2.
8503 glViewport(2, 2, 1, 1);
8504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8505 glDrawArrays(GL_TRIANGLES, 0, 6);
8506
8507 ASSERT_GL_NO_ERROR();
8508
8509 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8510 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::yellow);
8511 EXPECT_PIXEL_COLOR_EQ(0, 2, GLColor::blue);
8512 EXPECT_PIXEL_COLOR_EQ(2, 2, GLColor::yellow);
8513 }
8514
8515 // Tests a bug when removing an element array buffer bound to two vertex arrays.
TEST_P(SimpleStateChangeTestES3,DeleteDoubleBoundBufferAndVertexArray)8516 TEST_P(SimpleStateChangeTestES3, DeleteDoubleBoundBufferAndVertexArray)
8517 {
8518 std::vector<uint8_t> bufData(100, 0);
8519 GLBuffer buffer;
8520 GLVertexArray vao;
8521
8522 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8523 glBindVertexArray(vao);
8524 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8525 buffer.reset();
8526 vao.reset();
8527
8528 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8529 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8530 ASSERT_GL_NO_ERROR();
8531 }
8532
8533 // Tests state change for glLineWidth.
TEST_P(StateChangeTestES3,LineWidth)8534 TEST_P(StateChangeTestES3, LineWidth)
8535 {
8536 // According to the spec, the minimum value for the line width range limits is one.
8537 GLfloat range[2] = {1};
8538 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8539 EXPECT_GL_NO_ERROR();
8540 EXPECT_GE(range[0], 1.0f);
8541 EXPECT_GE(range[1], 1.0f);
8542
8543 ANGLE_SKIP_TEST_IF(range[1] < 5.0);
8544
8545 constexpr char kVS[] = R"(#version 300 es
8546 precision highp float;
8547 uniform float height;
8548 void main()
8549 {
8550 gl_Position = vec4(gl_VertexID == 0 ? -1 : 1, height * 2. - 1., 0, 1);
8551 })";
8552
8553 constexpr char kFS[] = R"(#version 300 es
8554 precision highp float;
8555 out vec4 colorOut;
8556 uniform vec4 color;
8557 void main()
8558 {
8559 colorOut = color;
8560 })";
8561
8562 ANGLE_GL_PROGRAM(program, kVS, kFS);
8563 glUseProgram(program);
8564
8565 GLint heightLoc = glGetUniformLocation(program, "height");
8566 GLint colorLoc = glGetUniformLocation(program, "color");
8567 ASSERT_NE(-1, heightLoc);
8568 ASSERT_NE(-1, colorLoc);
8569
8570 glClearColor(0, 0, 0, 1);
8571 glClear(GL_COLOR_BUFFER_BIT);
8572
8573 const int w = getWindowWidth();
8574 const int h = getWindowHeight();
8575 const float halfPixelHeight = 0.5 / h;
8576
8577 glUniform1f(heightLoc, 0.25f + halfPixelHeight);
8578 glUniform4f(colorLoc, 1, 0, 0, 1);
8579 glLineWidth(3);
8580 glDrawArrays(GL_LINES, 0, 2);
8581
8582 glUniform1f(heightLoc, 0.5f + halfPixelHeight);
8583 glUniform4f(colorLoc, 0, 1, 0, 1);
8584 glLineWidth(5);
8585 glDrawArrays(GL_LINES, 0, 2);
8586
8587 glUniform1f(heightLoc, 0.75f + halfPixelHeight);
8588 glUniform4f(colorLoc, 0, 0, 1, 1);
8589 glLineWidth(1);
8590 glDrawArrays(GL_LINES, 0, 2);
8591
8592 EXPECT_PIXEL_RECT_EQ(0, h / 4 - 2, w, 1, GLColor::black);
8593 EXPECT_PIXEL_RECT_EQ(0, h / 4 - 1, w, 3, GLColor::red);
8594 EXPECT_PIXEL_RECT_EQ(0, h / 4 + 2, w, 1, GLColor::black);
8595
8596 EXPECT_PIXEL_RECT_EQ(0, h / 2 - 3, w, 1, GLColor::black);
8597 EXPECT_PIXEL_RECT_EQ(0, h / 2 - 2, w, 5, GLColor::green);
8598 EXPECT_PIXEL_RECT_EQ(0, h / 2 + 3, w, 1, GLColor::black);
8599
8600 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 - 1, w, 1, GLColor::black);
8601 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4, w, 1, GLColor::blue);
8602 EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 + 1, w, 1, GLColor::black);
8603
8604 ASSERT_GL_NO_ERROR();
8605 }
8606
8607 // Tests state change for out-of-range value for glLineWidth. The expectation
8608 // here is primarily that rendering backends do not crash with invalid line
8609 // width values.
TEST_P(StateChangeTestES3,LineWidthOutOfRangeDoesntCrash)8610 TEST_P(StateChangeTestES3, LineWidthOutOfRangeDoesntCrash)
8611 {
8612 GLfloat range[2] = {1};
8613 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8614 EXPECT_GL_NO_ERROR();
8615
8616 constexpr char kVS[] = R"(#version 300 es
8617 precision highp float;
8618 void main()
8619 {
8620 gl_Position = vec4(gl_VertexID == 0 ? -1.0 : 1.0, -1.0, 0.0, 1.0);
8621 })";
8622
8623 constexpr char kFS[] = R"(#version 300 es
8624 precision highp float;
8625 out vec4 colorOut;
8626 void main()
8627 {
8628 colorOut = vec4(1.0);
8629 })";
8630
8631 ANGLE_GL_PROGRAM(program, kVS, kFS);
8632 glUseProgram(program);
8633
8634 glClearColor(0, 0, 0, 1);
8635 glClear(GL_COLOR_BUFFER_BIT);
8636
8637 glLineWidth(range[1] + 1.0f);
8638 glDrawArrays(GL_LINES, 0, 2);
8639
8640 glFinish();
8641
8642 ASSERT_GL_NO_ERROR();
8643 }
8644
8645 // Tests state change for glPolygonOffset.
TEST_P(StateChangeTestES3,PolygonOffset)8646 TEST_P(StateChangeTestES3, PolygonOffset)
8647 {
8648 constexpr char kVS[] = R"(#version 300 es
8649 precision highp float;
8650 void main()
8651 {
8652 // gl_VertexID x y
8653 // 0 -1 -1
8654 // 1 1 -1
8655 // 2 -1 1
8656 // 3 1 1
8657 int bit0 = gl_VertexID & 1;
8658 int bit1 = gl_VertexID >> 1;
8659 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8660 })";
8661
8662 constexpr char kFS[] = R"(#version 300 es
8663 precision highp float;
8664 out vec4 colorOut;
8665 uniform vec4 color;
8666 void main()
8667 {
8668 colorOut = color;
8669 })";
8670
8671 glEnable(GL_POLYGON_OFFSET_FILL);
8672
8673 ANGLE_GL_PROGRAM(program, kVS, kFS);
8674 glUseProgram(program);
8675
8676 GLint colorLoc = glGetUniformLocation(program, "color");
8677 ASSERT_NE(-1, colorLoc);
8678
8679 glClearColor(0, 0, 0, 1);
8680 glClearDepthf(0);
8681 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8682
8683 glEnable(GL_DEPTH_TEST);
8684 glDepthFunc(GL_ALWAYS);
8685
8686 // The shader creates a depth slope from left (0) to right (1).
8687 //
8688 // This test issues three draw calls:
8689 //
8690 // Draw 2 (green): factor width/2, offset 0, depth test: Greater
8691 // ^ | __________________
8692 // | | __/__/ __/
8693 // | V __/__/ __/ <--- Draw 1 (red): factor width/4, offset 0
8694 // | __/__/ ^ __/
8695 // | __/__/ _|/
8696 // |/__/ __/ |
8697 // |/ __/ |
8698 // | __/ Draw 3 (blue): factor width/2, offset -2, depth test: Less
8699 // |/
8700 // |
8701 // |
8702 // +------------------------------->
8703 //
8704 // Result: <----blue-----><-green-><--red-->
8705
8706 const int w = getWindowWidth();
8707 const int h = getWindowHeight();
8708
8709 glUniform4f(colorLoc, 1, 0, 0, 1);
8710 glPolygonOffset(getWindowWidth() / 4, 0);
8711 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8712
8713 glUniform4f(colorLoc, 0, 1, 0, 1);
8714 glPolygonOffset(getWindowWidth() / 2, 0);
8715 glDepthFunc(GL_GREATER);
8716 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8717
8718 glUniform4f(colorLoc, 0, 0, 1, 1);
8719 glPolygonOffset(getWindowWidth() / 2, -2);
8720 glDepthFunc(GL_LESS);
8721 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8722
8723 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::blue);
8724 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 4 - 1, h, GLColor::green);
8725 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8726
8727 ASSERT_GL_NO_ERROR();
8728 }
8729
8730 // Tests state change for glPolygonOffsetClampEXT.
TEST_P(StateChangeTestES3,PolygonOffsetClamp)8731 TEST_P(StateChangeTestES3, PolygonOffsetClamp)
8732 {
8733 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_polygon_offset_clamp"));
8734
8735 constexpr char kVS[] = R"(#version 300 es
8736 precision highp float;
8737 void main()
8738 {
8739 // gl_VertexID x y
8740 // 0 -1 -1
8741 // 1 1 -1
8742 // 2 -1 1
8743 // 3 1 1
8744 int bit0 = gl_VertexID & 1;
8745 int bit1 = gl_VertexID >> 1;
8746 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8747 })";
8748
8749 constexpr char kFS[] = R"(#version 300 es
8750 precision highp float;
8751 out vec4 colorOut;
8752 uniform vec4 color;
8753 void main()
8754 {
8755 colorOut = color;
8756 })";
8757
8758 glEnable(GL_POLYGON_OFFSET_FILL);
8759
8760 ANGLE_GL_PROGRAM(program, kVS, kFS);
8761 glUseProgram(program);
8762
8763 GLint colorLoc = glGetUniformLocation(program, "color");
8764 ASSERT_NE(-1, colorLoc);
8765
8766 glClearColor(0, 0, 0, 1);
8767 glClearDepthf(0);
8768 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8769
8770 glEnable(GL_DEPTH_TEST);
8771 glDepthFunc(GL_ALWAYS);
8772
8773 // The shader creates a depth slope from left (0) to right (1).
8774 //
8775 // This test issues two draw calls:
8776 //
8777 // Draw 2 (green): factor width, offset 0, clamp 0.5, depth test: Greater
8778 // ^ | __________________
8779 // | | __/ __/
8780 // | V __/ __/ <--- Draw 1 (red): factor width, offset 0, clamp 0.25
8781 // | __/ __/
8782 // | __/ __/
8783 // |/ __/
8784 // | __/
8785 // | __/
8786 // |/
8787 // |
8788 // |
8789 // +------------------------------->
8790 //
8791 // Result: <---------green--------><--red-->
8792
8793 const int w = getWindowWidth();
8794 const int h = getWindowHeight();
8795
8796 glUniform4f(colorLoc, 1, 0, 0, 1);
8797 glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.25);
8798 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8799
8800 glUniform4f(colorLoc, 0, 1, 0, 1);
8801 glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.5);
8802 glDepthFunc(GL_GREATER);
8803 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8804
8805 EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::green);
8806 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8807
8808 ASSERT_GL_NO_ERROR();
8809 }
8810
8811 // Tests state change for glBlendColor.
TEST_P(StateChangeTestES3,BlendColor)8812 TEST_P(StateChangeTestES3, BlendColor)
8813 {
8814 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8815 glUseProgram(program);
8816
8817 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8818 ASSERT_NE(colorLoc, -1);
8819
8820 glEnable(GL_BLEND);
8821 glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);
8822 glBlendColor(0.498, 0.498, 0, 1);
8823 glUniform4f(colorLoc, 1, 1, 1, 1);
8824 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8825
8826 const int w = getWindowWidth();
8827 const int h = getWindowHeight();
8828
8829 glEnable(GL_SCISSOR_TEST);
8830 glScissor(0, 0, w / 2, h);
8831 glBlendColor(0, 1, 0.498, 1);
8832 glUniform4f(colorLoc, 1, 0.247, 1, 1);
8833 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8834
8835 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor(0, 63, 127, 255));
8836 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor(127, 127, 0, 255));
8837
8838 ASSERT_GL_NO_ERROR();
8839 }
8840
8841 // Tests state change for ref and mask in glStencilFuncSeparate.
TEST_P(StateChangeTestES3,StencilReferenceAndCompareMask)8842 TEST_P(StateChangeTestES3, StencilReferenceAndCompareMask)
8843 {
8844 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8845 glUseProgram(program);
8846
8847 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8848 ASSERT_NE(colorLoc, -1);
8849
8850 glClearColor(0, 0, 0, 1);
8851 glClearStencil(0x3A);
8852 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8853
8854 glEnable(GL_STENCIL_TEST);
8855
8856 glStencilMaskSeparate(GL_FRONT, 0xF0);
8857 glStencilMaskSeparate(GL_BACK, 0x0F);
8858
8859 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0xB9, 0x7C);
8860 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8861
8862 glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x99, 0xAC);
8863 glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_KEEP);
8864
8865 const int w = getWindowWidth();
8866 const int h = getWindowHeight();
8867
8868 // Draw front-facing. Front stencil test should pass, replacing the top bits with 0xB:
8869 //
8870 // Current value of stencil buffer: 0x3A, mask: 0x7C, writing 0xB9
8871 //
8872 // B9 & 7C == 38 == 3A & 7C
8873 glUniform4f(colorLoc, 1, 0, 0, 1);
8874 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8875
8876 // Draw back-facing. Back stencil test should fail, replacing the bottom bits with 0x9:
8877 //
8878 // Current value of stencil buffer: 0xBA, mask: 0xAC, writing 0x99
8879 //
8880 // 99 & AC == 88 != A8 == BA & AC
8881 glFrontFace(GL_CW);
8882 glDisable(GL_CULL_FACE);
8883 glEnable(GL_SCISSOR_TEST);
8884 glScissor(0, 0, w / 2, h);
8885 glUniform4f(colorLoc, 0, 1, 0, 1);
8886 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8887
8888 // The left half of image should now have a value of B9, the right half should have BA
8889 //
8890 // Change the masks such that if the old masks are used, stencil test would fail, but if the new
8891 // mask is used it would pass.
8892 //
8893 // Left: B9 & 7C == 38 != 3C == 3D & 7C
8894 // B9 & 33 == 31 == 3D & 33
8895 //
8896 // Right: BA & AC == A8 != 28 == 3A & AC
8897 // BA & 59 == 18 == 3A & 59
8898 //
8899 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x3D, 0x33);
8900 glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x3A, 0x59);
8901 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
8902 glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
8903
8904 glScissor(0, 0, w, h / 2);
8905
8906 // Draw front-facing, coloring the top-left
8907 glUniform4f(colorLoc, 1, 1, 0, 1);
8908 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8909 glFrontFace(GL_CCW);
8910 glUniform4f(colorLoc, 0, 0, 1, 1);
8911 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8912
8913 // Verify results
8914 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
8915 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
8916 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
8917 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::red);
8918
8919 // Verify stencil exactly
8920 glDisable(GL_SCISSOR_TEST);
8921 glStencilFunc(GL_EQUAL, 0xB9, 0xFF);
8922 glUniform4f(colorLoc, 0, 1, 1, 1);
8923 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8924
8925 glStencilFunc(GL_EQUAL, 0xBA, 0xFF);
8926 glUniform4f(colorLoc, 1, 0, 1, 1);
8927 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8928
8929 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::cyan);
8930 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
8931
8932 ASSERT_GL_NO_ERROR();
8933 }
8934
8935 // Tests state change for mask in glStencilMaskSeparate.
TEST_P(StateChangeTestES3,StencilWriteMask)8936 TEST_P(StateChangeTestES3, StencilWriteMask)
8937 {
8938 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8939 glUseProgram(program);
8940
8941 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8942 ASSERT_NE(colorLoc, -1);
8943
8944 glClearColor(0, 0, 0, 1);
8945 glClearStencil(0x00);
8946 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8947
8948 glEnable(GL_STENCIL_TEST);
8949
8950 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8951 glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_REPLACE);
8952
8953 const int w = getWindowWidth();
8954 const int h = getWindowHeight();
8955
8956 // Draw front-facing to the left half, replacing the top four bits, and back-facing to the right
8957 // half, replacing the bottom four bits.
8958 glStencilMaskSeparate(GL_FRONT, 0xF0);
8959 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x39, 0xFF);
8960 glStencilMaskSeparate(GL_BACK, 0x0F);
8961 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x2A, 0xFF);
8962
8963 glEnable(GL_SCISSOR_TEST);
8964 glScissor(0, 0, w / 2, h);
8965 glUniform4f(colorLoc, 1, 0, 0, 1);
8966 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8967
8968 glDisable(GL_CULL_FACE);
8969 glFrontFace(GL_CW);
8970 glScissor(w / 2, 0, w / 2, h);
8971 glUniform4f(colorLoc, 0, 1, 0, 1);
8972 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8973
8974 // Draw back-facing to the top-left quarter, replacing the top two bits, and front-facing to the
8975 // top-right quarter, replacing the bottom two bits.
8976 glStencilMaskSeparate(GL_FRONT, 0xC0);
8977 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x81, 0xFF);
8978 glStencilMaskSeparate(GL_BACK, 0x03);
8979 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x53, 0xFF);
8980
8981 glScissor(0, 0, w / 2, h / 2);
8982 glUniform4f(colorLoc, 0, 0, 1, 1);
8983 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8984
8985 glFrontFace(GL_CCW);
8986 glScissor(w / 2, 0, w / 2, h / 2);
8987 glUniform4f(colorLoc, 1, 1, 0, 1);
8988 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8989
8990 // Verify results
8991 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
8992 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
8993 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
8994 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
8995
8996 // Verify stencil exactly. Stencil has the following values:
8997 //
8998 // +------+------+
8999 // | | |
9000 // | 33 | 8A |
9001 // | | |
9002 // +------+------+
9003 // | | |
9004 // | 30 | 0A |
9005 // | | |
9006 // +------+------+
9007 //
9008 glDisable(GL_SCISSOR_TEST);
9009 glStencilFunc(GL_EQUAL, 0x33, 0xFF);
9010 glUniform4f(colorLoc, 0, 1, 1, 1);
9011 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9012
9013 glStencilFunc(GL_EQUAL, 0x8A, 0xFF);
9014 glUniform4f(colorLoc, 1, 0, 1, 1);
9015 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9016
9017 glStencilFunc(GL_EQUAL, 0x30, 0xFF);
9018 glUniform4f(colorLoc, 1, 1, 1, 1);
9019 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9020
9021 glStencilFunc(GL_EQUAL, 0x0A, 0xFF);
9022 glUniform4f(colorLoc, 0, 0, 0, 1);
9023 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9024
9025 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9026 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9027 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9028 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9029
9030 ASSERT_GL_NO_ERROR();
9031 }
9032
9033 // Tests that |discard| works with stencil write mask
TEST_P(StateChangeTestES3,StencilWriteMaskVsDiscard)9034 TEST_P(StateChangeTestES3, StencilWriteMaskVsDiscard)
9035 {
9036 constexpr char kVS[] = R"(#version 300 es
9037 precision highp float;
9038 void main()
9039 {
9040 // gl_VertexID x y
9041 // 0 -1 -1
9042 // 1 1 -1
9043 // 2 -1 1
9044 // 3 1 1
9045 int bit0 = gl_VertexID & 1;
9046 int bit1 = gl_VertexID >> 1;
9047 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
9048 })";
9049
9050 constexpr char kFS[] = R"(#version 300 es
9051 precision highp float;
9052 out vec4 colorOut;
9053 uniform vec4 color;
9054 uniform int flag;
9055 void main()
9056 {
9057 if (flag > 0)
9058 {
9059 discard;
9060 }
9061 colorOut = color;
9062 })";
9063
9064 ANGLE_GL_PROGRAM(program, kVS, kFS);
9065 glUseProgram(program);
9066
9067 GLint colorLoc = glGetUniformLocation(program, "color");
9068 ASSERT_NE(colorLoc, -1);
9069
9070 GLint flagLoc = glGetUniformLocation(program, "flag");
9071 ASSERT_NE(flagLoc, -1);
9072
9073 glEnable(GL_DEPTH_TEST);
9074
9075 glClearColor(0, 0, 0, 1);
9076 glClearDepthf(1);
9077 glClearStencil(0x00);
9078 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9079
9080 glDepthFunc(GL_LEQUAL);
9081 glDepthMask(GL_FALSE);
9082 glEnable(GL_STENCIL_TEST);
9083
9084 // Enable stencil write, but issue a draw call where all fragments are discarded.
9085 glStencilFunc(GL_ALWAYS, 128, 128);
9086 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
9087 glStencilMask(128);
9088
9089 glUniform4f(colorLoc, 1, 0, 0, 1);
9090 glUniform1i(flagLoc, 1);
9091 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9092
9093 // At this point, the stencil buffer should be unmodified. Verify it with another draw call.
9094 glStencilFunc(GL_NOTEQUAL, 128, 128);
9095 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9096 glStencilMask(128);
9097
9098 glUniform4f(colorLoc, 0, 1, 0, 1);
9099 glUniform1i(flagLoc, 0);
9100 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9101
9102 const int w = getWindowWidth();
9103 const int h = getWindowHeight();
9104
9105 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9106
9107 ASSERT_GL_NO_ERROR();
9108 }
9109
9110 // Tests state change for glCullFace and glEnable(GL_CULL_FACE) as well as glFrontFace
TEST_P(StateChangeTestES3,CullFaceAndFrontFace)9111 TEST_P(StateChangeTestES3, CullFaceAndFrontFace)
9112 {
9113 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9114 glUseProgram(program);
9115
9116 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9117 ASSERT_NE(colorLoc, -1);
9118
9119 glClearColor(0, 0, 0, 1);
9120 glClear(GL_COLOR_BUFFER_BIT);
9121
9122 const int w = getWindowWidth();
9123 const int h = getWindowHeight();
9124
9125 // Draw red back-facing. Face culling is initially disabled
9126 glFrontFace(GL_CW);
9127 glUniform4f(colorLoc, 1, 0, 0, 1);
9128 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9129
9130 // Draw green back-facing, but enable face culling. Default cull face is back.
9131 glEnable(GL_CULL_FACE);
9132 glEnable(GL_SCISSOR_TEST);
9133 glScissor(0, 0, w / 2, h / 2);
9134 glUniform4f(colorLoc, 0, 1, 0, 1);
9135 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9136
9137 // Draw blue front-facing.
9138 glFrontFace(GL_CCW);
9139 glScissor(w / 2, 0, w / 2, h / 2);
9140 glUniform4f(colorLoc, 0, 0, 1, 1);
9141 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9142
9143 // Draw magenta front-facing, but change cull face to front
9144 glCullFace(GL_FRONT);
9145 glScissor(0, h / 2, w / 2, h / 2);
9146 glUniform4f(colorLoc, 1, 0, 1, 1);
9147 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9148
9149 // Draw cyan front-facing, with face culling disabled
9150 glDisable(GL_CULL_FACE);
9151 glScissor(w / 2, h / 2, w / 2, h / 2);
9152 glUniform4f(colorLoc, 0, 1, 1, 1);
9153 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9154
9155 // Draw yellow front-facing, with cull face set to front and back
9156 glEnable(GL_CULL_FACE);
9157 glCullFace(GL_FRONT_AND_BACK);
9158 glDisable(GL_SCISSOR_TEST);
9159 glUniform4f(colorLoc, 1, 1, 0, 1);
9160 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9161
9162 // Verify results
9163 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9164 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9165 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
9166 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9167
9168 ASSERT_GL_NO_ERROR();
9169 }
9170
9171 // Tests state change for draw primitive mode
TEST_P(StateChangeTestES3,PrimitiveMode)9172 TEST_P(StateChangeTestES3, PrimitiveMode)
9173 {
9174 constexpr char kVS[] = R"(#version 300 es
9175 precision highp float;
9176
9177 // Hardcoded positions for a number of draw modes, using different vertex offsets.
9178 const vec2 kVertices[35] = vec2[35](
9179 // Two triangle
9180 vec2(-1, -1), vec2(1, -1), vec2(-1, 1),
9181 vec2(-1, 1), vec2(1, -1), vec2( 1, 1),
9182 // A triangle strip with 8 triangles
9183 vec2( -1, -0.5), vec2( -1, 0.5),
9184 vec2(-0.75, -0.5), vec2(-0.75, 0.5),
9185 vec2( -0.5, -0.5), vec2( -0.5, 0.5),
9186 vec2(-0.25, -0.5), vec2(-0.25, 0.5),
9187 vec2( 0, -0.5), vec2( 0, 0.5),
9188 // A triangle fan with 4 triangles
9189 vec2(0.5, 0), vec2(1, -0.5), vec2(1, 0.5), vec2(0, 0.5), vec2(0, -0.5), vec2(1, -0.5),
9190 // One line
9191 vec2(-1, -0.49), vec2(1, -0.49),
9192 // One line strip
9193 vec2(-1, 0.51), vec2(0, 0.51), vec2(1, 0.51),
9194 // One line loop
9195 vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99),
9196 // Four points
9197 vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99)
9198 );
9199
9200 void main()
9201 {
9202 gl_Position = vec4(kVertices[gl_VertexID], 0, 1);
9203 gl_PointSize = 1.;
9204 })";
9205
9206 constexpr char kFS[] = R"(#version 300 es
9207 precision highp float;
9208 out vec4 colorOut;
9209 uniform vec4 color;
9210 void main()
9211 {
9212 colorOut = color;
9213 })";
9214
9215 ANGLE_GL_PROGRAM(program, kVS, kFS);
9216 glUseProgram(program);
9217
9218 GLint colorLoc = glGetUniformLocation(program, "color");
9219 ASSERT_NE(colorLoc, -1);
9220
9221 glClearColor(0, 0, 0, 1);
9222 glClear(GL_COLOR_BUFFER_BIT);
9223
9224 // Draw the following:
9225 //
9226 // 1. Red with two triangles
9227 // 2. Green with a triangle strip
9228 // 3. Blue with a triangle fan
9229 // 4. Yellow with a line
9230 // 5. Cyan with a line strip
9231 // 6. Magenta with a line loop
9232 // 7. White with four points
9233 //
9234 //
9235 // +---------------------------+ <-- 7: corners
9236 // | |
9237 // | 1 |
9238 // | |
9239 // +-------------+-------------+ <-- 5: horizontal line
9240 // | | |
9241 // | | |
9242 // | | |
9243 // | 2 | 3 | <-- 6: border around image
9244 // | | |
9245 // | | |
9246 // | | |
9247 // +-------------+-------------+ <-- 4: horizontal line
9248 // | |
9249 // | 1 |
9250 // | |
9251 // +---------------------------+
9252
9253 glUniform4f(colorLoc, 1, 0, 0, 1);
9254 glDrawArrays(GL_TRIANGLES, 0, 6);
9255
9256 glUniform4f(colorLoc, 0, 1, 0, 1);
9257 glDrawArrays(GL_TRIANGLE_STRIP, 6, 10);
9258
9259 glUniform4f(colorLoc, 0, 0, 1, 1);
9260 glDrawArrays(GL_TRIANGLE_FAN, 16, 6);
9261
9262 glUniform4f(colorLoc, 1, 1, 0, 1);
9263 glDrawArrays(GL_LINES, 22, 2);
9264
9265 glUniform4f(colorLoc, 0, 1, 1, 1);
9266 glDrawArrays(GL_LINE_STRIP, 24, 3);
9267
9268 glUniform4f(colorLoc, 1, 0, 1, 1);
9269 glDrawArrays(GL_LINE_LOOP, 27, 4);
9270
9271 glUniform4f(colorLoc, 1, 1, 1, 1);
9272 glDrawArrays(GL_POINTS, 31, 4);
9273
9274 const int w = getWindowWidth();
9275 const int h = getWindowHeight();
9276
9277 // Verify results
9278 EXPECT_PIXEL_RECT_EQ(1, 1, w - 2, h / 4 - 2, GLColor::red);
9279 EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4 + 1, w - 2, h / 4 - 2, GLColor::red);
9280
9281 EXPECT_PIXEL_RECT_EQ(1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::green);
9282
9283 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::blue);
9284
9285 EXPECT_PIXEL_RECT_EQ(1, h / 4, w / 2 - 2, 1, GLColor::yellow);
9286
9287 EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4, w / 2 - 2, 1, GLColor::cyan);
9288
9289 EXPECT_PIXEL_RECT_EQ(1, 0, w - 2, 1, GLColor::magenta);
9290 EXPECT_PIXEL_RECT_EQ(0, 1, 1, h - 2, GLColor::magenta);
9291 EXPECT_PIXEL_RECT_EQ(w - 1, 1, 1, h - 2, GLColor::magenta);
9292 EXPECT_PIXEL_RECT_EQ(1, h - 1, w - 2, 1, GLColor::magenta);
9293
9294 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
9295 EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::white);
9296 EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::white);
9297 EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::white);
9298
9299 ASSERT_GL_NO_ERROR();
9300 }
9301
9302 // Tests that vertex attributes are correctly bound after a masked clear. In the Vulkan backend,
9303 // the masked clear is done with an internal shader that doesn't use vertex attributes.
TEST_P(StateChangeTestES3,DrawMaskedClearDraw)9304 TEST_P(StateChangeTestES3, DrawMaskedClearDraw)
9305 {
9306 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9307 glUseProgram(program);
9308
9309 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9310 ASSERT_NE(colorLoc, -1);
9311
9312 GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
9313 ASSERT_EQ(0, posAttrib);
9314
9315 std::array<GLfloat, 3 * 4> positionData = {
9316 -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9317 };
9318
9319 GLBuffer posBuffer;
9320 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9321 glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9322 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9323 glEnableVertexAttribArray(posAttrib);
9324
9325 const int w = getWindowWidth();
9326 const int h = getWindowHeight();
9327
9328 glClearColor(0, 0, 0, 1);
9329 glClear(GL_COLOR_BUFFER_BIT);
9330
9331 glEnable(GL_BLEND);
9332 glBlendFunc(GL_ONE, GL_ONE);
9333
9334 // Draw to red and alpha channels, with garbage in green and blue
9335 glUniform4f(colorLoc, 1, 0.123f, 0.456f, 0.5f);
9336 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9337
9338 // Clear the green and blue channels
9339 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
9340 glClearColor(0.333f, 0.5, 0, 0.888f);
9341 glClear(GL_COLOR_BUFFER_BIT);
9342
9343 // Blend in to saturate green and alpha
9344 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9345 glUniform4f(colorLoc, 0, 0.6f, 0, 0.6f);
9346 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9347
9348 // Verify results
9349 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::yellow);
9350
9351 ASSERT_GL_NO_ERROR();
9352 }
9353
9354 // Tests state change for vertex attribute stride
TEST_P(StateChangeTestES3,VertexStride)9355 TEST_P(StateChangeTestES3, VertexStride)
9356 {
9357 constexpr char kVS[] =
9358 R"(#version 300 es
9359 precision mediump float;
9360 in vec4 position;
9361 layout(location = 1) in vec4 test;
9362 layout(location = 5) in vec4 expected;
9363 out vec4 result;
9364 void main(void)
9365 {
9366 gl_Position = position;
9367 if (any(equal(test, vec4(0))) || any(equal(expected, vec4(0))))
9368 {
9369 result = vec4(0);
9370 }
9371 else
9372 {
9373 vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
9374 result = vec4(lessThanEqual(abs(test - expected), threshold));
9375 }
9376 })";
9377
9378 constexpr char kFS[] =
9379 R"(#version 300 es
9380 precision mediump float;
9381 in vec4 result;
9382 out vec4 colorOut;
9383 void main()
9384 {
9385 colorOut = vec4(greaterThanEqual(result, vec4(0.999)));
9386 })";
9387
9388 ANGLE_GL_PROGRAM(program, kVS, kFS);
9389 glUseProgram(program);
9390
9391 // Every draw call consists of 4 vertices. The vertex attributes are laid out as follows:
9392 //
9393 // Position: No gaps
9394 // test: 4 unorm vertices with stride 20, simultaneously 4 vertices with stride 16
9395 // expected: 4 float vertices with stride 80, simultaneously 4 vertices with stride 48
9396
9397 const std::array<GLubyte, 7 * 4> kData = {{1, 2, 3, 4, 5, 6, 7, 8, 125, 126,
9398 127, 128, 129, 250, 251, 252, 78, 79, 80, 81,
9399 155, 156, 157, 158, 20, 21, 22, 23}};
9400
9401 constexpr size_t kTestStride1 = 20;
9402 constexpr size_t kTestStride2 = 16;
9403 constexpr size_t kExpectedStride1 = 20;
9404 constexpr size_t kExpectedStride2 = 12;
9405
9406 std::array<GLubyte, kTestStride1 * 3 + 4> testInitData = {};
9407 std::array<GLfloat, kExpectedStride1 * 3 + 4> expectedInitData = {};
9408
9409 for (uint32_t vertex = 0; vertex < 7; ++vertex)
9410 {
9411 size_t testOffset = vertex * kTestStride1;
9412 size_t expectedOffset = vertex * kExpectedStride1;
9413 if (vertex >= 4)
9414 {
9415 testOffset = (vertex - 3) * kTestStride2;
9416 expectedOffset = (vertex - 3) * kExpectedStride2;
9417 }
9418
9419 for (uint32_t channel = 0; channel < 4; ++channel)
9420 {
9421 // The strides are chosen such that the two streams don't collide
9422 ASSERT_EQ(testInitData[testOffset + channel], 0);
9423 ASSERT_EQ(expectedInitData[expectedOffset + channel], 0);
9424
9425 GLubyte data = kData[vertex * 4 + channel];
9426 testInitData[testOffset + channel] = data;
9427 expectedInitData[expectedOffset + channel] = data;
9428 }
9429
9430 // For the first 4 vertices, expect perfect match (i.e. get white). For the last 3
9431 // vertices, expect the green channel test to fail (i.e. get magenta).
9432 if (vertex >= 4)
9433 {
9434 expectedInitData[expectedOffset + 1] += 2;
9435 }
9436 }
9437
9438 std::array<GLfloat, 3 * 4> positionData = {
9439 -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9440 };
9441
9442 GLBuffer posBuffer;
9443 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9444 glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9445
9446 GLBuffer testBuffer;
9447 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9448 glBufferData(GL_ARRAY_BUFFER, sizeof(testInitData), testInitData.data(), GL_STATIC_DRAW);
9449
9450 GLBuffer expectedBuffer;
9451 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9452 glBufferData(GL_ARRAY_BUFFER, sizeof(expectedInitData), expectedInitData.data(),
9453 GL_STATIC_DRAW);
9454
9455 GLint posAttrib = glGetAttribLocation(program, "position");
9456 ASSERT_EQ(0, posAttrib);
9457 GLint testAttrib = glGetAttribLocation(program, "test");
9458 ASSERT_EQ(1, testAttrib);
9459 GLint expectedAttrib = glGetAttribLocation(program, "expected");
9460 ASSERT_EQ(5, expectedAttrib);
9461
9462 const int w = getWindowWidth();
9463 const int h = getWindowHeight();
9464
9465 glClearColor(0, 0, 0, 1);
9466 glClear(GL_COLOR_BUFFER_BIT);
9467
9468 glEnableVertexAttribArray(posAttrib);
9469 glEnableVertexAttribArray(testAttrib);
9470 glEnableVertexAttribArray(expectedAttrib);
9471
9472 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9473 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9474 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9475 glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride1 * sizeof(GLubyte),
9476 nullptr);
9477 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9478 glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride1 * sizeof(GLfloat),
9479 nullptr);
9480
9481 glEnable(GL_SCISSOR_TEST);
9482 glScissor(0, 0, w / 2, h);
9483 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9484
9485 glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9486 glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride2 * sizeof(GLubyte),
9487 nullptr);
9488 glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9489 glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride2 * sizeof(GLfloat),
9490 nullptr);
9491
9492 glScissor(w / 2, 0, w / 2, h);
9493 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9494
9495 // Verify results
9496 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::white);
9497 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
9498
9499 ASSERT_GL_NO_ERROR();
9500 }
9501
9502 // Tests state change for vertex attribute format
TEST_P(StateChangeTestES3,VertexFormat)9503 TEST_P(StateChangeTestES3, VertexFormat)
9504 {
9505 constexpr char kVS[] = R"(precision highp float;
9506 attribute vec3 position;
9507 attribute vec4 color;
9508 varying vec4 colorOut;
9509
9510 void main()
9511 {
9512 gl_Position = vec4(position, 1.0);
9513 colorOut = color;
9514 })";
9515
9516 constexpr char kFS[] = R"(precision highp float;
9517 varying vec4 colorOut;
9518
9519 void main()
9520 {
9521 gl_FragColor = colorOut;
9522 })";
9523
9524 ANGLE_GL_PROGRAM(program, kVS, kFS);
9525 glUseProgram(program);
9526
9527 GLint positionLoc = glGetAttribLocation(program, "position");
9528 ASSERT_NE(positionLoc, -1);
9529 GLint colorLoc = glGetAttribLocation(program, "color");
9530 ASSERT_NE(colorLoc, -1);
9531
9532 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
9533 glClear(GL_COLOR_BUFFER_BIT);
9534
9535 std::vector<Vector4> colorAttribDataFloat(6, Vector4(255.0f, 0.0f, 0.0f, 255.0f));
9536 std::vector<GLColor> colorAttribDataUnsignedByte(6, GLColor::green);
9537
9538 // Setup position attribute
9539 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9540 GLBuffer vertexLocationBuffer;
9541 glBindBuffer(GL_ARRAY_BUFFER, vertexLocationBuffer);
9542 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
9543 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
9544 glEnableVertexAttribArray(positionLoc);
9545
9546 // Setup color attribute with float data
9547 GLBuffer floatBuffer;
9548 glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
9549 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector4) * 6, colorAttribDataFloat.data(), GL_STATIC_DRAW);
9550 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
9551 glEnableVertexAttribArray(colorLoc);
9552
9553 // Draw red using float attribute
9554 glDrawArrays(GL_TRIANGLES, 0, 6);
9555 ASSERT_GL_NO_ERROR();
9556 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9557
9558 // Setup color attribute with unsigned byte data
9559 GLBuffer unsignedByteBuffer;
9560 glBindBuffer(GL_ARRAY_BUFFER, unsignedByteBuffer);
9561 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, colorAttribDataUnsignedByte.data(),
9562 GL_STATIC_DRAW);
9563 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
9564 glEnableVertexAttribArray(colorLoc);
9565
9566 // Draw green using unsigned byte attribute
9567 glDrawArrays(GL_TRIANGLES, 0, 6);
9568 ASSERT_GL_NO_ERROR();
9569 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9570
9571 glUseProgram(0);
9572 glBindBuffer(GL_ARRAY_BUFFER, 0);
9573 }
9574
9575 // Tests state change for depth test, write and function
TEST_P(StateChangeTestES3,DepthTestWriteAndFunc)9576 TEST_P(StateChangeTestES3, DepthTestWriteAndFunc)
9577 {
9578 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9579 glUseProgram(program);
9580
9581 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9582 ASSERT_NE(colorLoc, -1);
9583
9584 const int w = getWindowWidth();
9585 const int h = getWindowHeight();
9586
9587 glClearColor(0, 0, 0, 1);
9588 glClearDepthf(0.5);
9589 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9590
9591 // Initialize the depth buffer:
9592 glEnable(GL_DEPTH_TEST);
9593 glDepthMask(GL_TRUE);
9594 glDepthFunc(GL_ALWAYS);
9595
9596 glEnable(GL_SCISSOR_TEST);
9597 glScissor(0, 0, w / 2, h / 2);
9598 glUniform4f(colorLoc, 0, 0, 0, 1);
9599 drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9600 glScissor(w / 2, 0, w / 2, h / 2);
9601 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9602 glScissor(0, h / 2, w / 2, h / 2);
9603 drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9604 glScissor(w / 2, h / 2, w / 2, h / 2);
9605 drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9606
9607 glDisable(GL_SCISSOR_TEST);
9608 glDisable(GL_DEPTH_TEST);
9609 glDepthMask(GL_FALSE);
9610 glUniform4f(colorLoc, 1, 0, 0, 1);
9611 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9612
9613 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9614
9615 // Make draw calls that test depth or not, write depth or not, and use different functions
9616
9617 // Write green to one half
9618 glEnable(GL_DEPTH_TEST);
9619 glDepthFunc(GL_LESS);
9620 glUniform4f(colorLoc, 0, 1, 0, 1);
9621 drawQuad(program, essl1_shaders::PositionAttrib(), 0.35f);
9622
9623 // Write blue to another half
9624 glDepthFunc(GL_GREATER);
9625 glUniform4f(colorLoc, 0, 0, 1, 1);
9626 drawQuad(program, essl1_shaders::PositionAttrib(), -0.15f);
9627
9628 // Write yellow to a corner, overriding depth
9629 glDepthMask(GL_TRUE);
9630 glUniform4f(colorLoc, 1, 1, 0, 1);
9631 drawQuad(program, essl1_shaders::PositionAttrib(), -0.6f);
9632
9633 // Write magenta to another corner, overriding depth
9634 glDepthFunc(GL_LESS);
9635 glUniform4f(colorLoc, 1, 0, 1, 1);
9636 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9637
9638 // No-op write
9639 glDepthFunc(GL_NEVER);
9640 glUniform4f(colorLoc, 0, 1, 1, 1);
9641 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9642
9643 // Verify results
9644 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::yellow);
9645 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9646 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9647 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::magenta);
9648
9649 // Verify the depth buffer
9650 glDepthMask(GL_FALSE);
9651 glDepthFunc(GL_LESS);
9652 glUniform4f(colorLoc, 1, 0, 0, 1);
9653 drawQuad(program, essl1_shaders::PositionAttrib(), -0.61f);
9654 glUniform4f(colorLoc, 0, 0, 0, 1);
9655 drawQuad(program, essl1_shaders::PositionAttrib(), -0.59f);
9656
9657 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9658 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9659 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9660 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9661
9662 glDepthFunc(GL_GREATER);
9663 glUniform4f(colorLoc, 0, 1, 1, 1);
9664 drawQuad(program, essl1_shaders::PositionAttrib(), 0.51f);
9665 glUniform4f(colorLoc, 0, 0, 0, 1);
9666 drawQuad(program, essl1_shaders::PositionAttrib(), 0.49f);
9667
9668 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9669 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9670 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9671 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9672
9673 glDepthFunc(GL_LESS);
9674 glUniform4f(colorLoc, 0, 1, 0, 1);
9675 drawQuad(program, essl1_shaders::PositionAttrib(), -0.21f);
9676 glUniform4f(colorLoc, 1, 1, 1, 1);
9677 drawQuad(program, essl1_shaders::PositionAttrib(), -0.19f);
9678
9679 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9680 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::green);
9681 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9682 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9683
9684 glDepthFunc(GL_GREATER);
9685 glUniform4f(colorLoc, 0, 0, 1, 1);
9686 drawQuad(program, essl1_shaders::PositionAttrib(), 0.41f);
9687 glUniform4f(colorLoc, 1, 0, 1, 1);
9688 drawQuad(program, essl1_shaders::PositionAttrib(), 0.39f);
9689
9690 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::magenta);
9691 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9692 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::blue);
9693 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9694
9695 ASSERT_GL_NO_ERROR();
9696 }
9697
9698 // Tests state change for depth test while depth write is enabled
TEST_P(StateChangeTestES3,DepthTestToggleWithDepthWrite)9699 TEST_P(StateChangeTestES3, DepthTestToggleWithDepthWrite)
9700 {
9701 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9702 glUseProgram(program);
9703
9704 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9705 ASSERT_NE(colorLoc, -1);
9706
9707 const int w = getWindowWidth();
9708 const int h = getWindowHeight();
9709
9710 glClearColor(0, 0, 0, 1);
9711 glClearDepthf(0.5);
9712 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9713
9714 // Enable depth write, but keep depth test disabled. Internally, depth write may be disabled
9715 // because of the depth test.
9716 glDisable(GL_DEPTH_TEST);
9717 glDepthMask(GL_TRUE);
9718 glDepthFunc(GL_LESS);
9719
9720 // Draw with a different depth, but because depth test is disabled, depth is not actually
9721 // changed.
9722 glUniform4f(colorLoc, 1, 0, 0, 1);
9723 drawQuad(program, essl1_shaders::PositionAttrib(), -0.3f);
9724
9725 // Enable depth test, but don't change state otherwise. The following draw must change depth.
9726 glEnable(GL_DEPTH_TEST);
9727
9728 glUniform4f(colorLoc, 0, 1, 0, 1);
9729 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9730
9731 // Verify that depth was changed in the last draw call.
9732 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9733
9734 glDepthFunc(GL_GREATER);
9735 glUniform4f(colorLoc, 0, 0, 1, 1);
9736 drawQuad(program, essl1_shaders::PositionAttrib(), -0.1f);
9737 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
9738 ASSERT_GL_NO_ERROR();
9739 }
9740
9741 // Tests state change for stencil test and function
TEST_P(StateChangeTestES3,StencilTestAndFunc)9742 TEST_P(StateChangeTestES3, StencilTestAndFunc)
9743 {
9744 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9745 glUseProgram(program);
9746
9747 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9748 ASSERT_NE(colorLoc, -1);
9749
9750 const int w = getWindowWidth();
9751 const int h = getWindowHeight();
9752
9753 glClearColor(0, 0, 0, 1);
9754 glClearDepthf(0.5);
9755 glClearStencil(0x55);
9756 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9757
9758 // Initialize the depth and stencil buffers
9759 glEnable(GL_DEPTH_TEST);
9760 glDepthMask(GL_TRUE);
9761 glDepthFunc(GL_ALWAYS);
9762
9763 glEnable(GL_STENCIL_TEST);
9764 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
9765
9766 glEnable(GL_SCISSOR_TEST);
9767 glScissor(0, 0, w / 2, h / 2);
9768 glUniform4f(colorLoc, 0, 0, 0, 1);
9769 glStencilFunc(GL_ALWAYS, 0x3E, 0xFF);
9770 drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9771 glScissor(w / 2, 0, w / 2, h / 2);
9772 glStencilFunc(GL_ALWAYS, 0xA7, 0xFF);
9773 drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9774 glScissor(0, h / 2, w / 2, h / 2);
9775 glStencilFunc(GL_ALWAYS, 0x6C, 0xFF);
9776 drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9777 glScissor(w / 2, h / 2, w / 2, h / 2);
9778 glStencilFunc(GL_ALWAYS, 0x5B, 0xFF);
9779 drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9780
9781 glDisable(GL_SCISSOR_TEST);
9782 glDisable(GL_DEPTH_TEST);
9783 glDisable(GL_STENCIL_TEST);
9784 glDepthMask(GL_FALSE);
9785 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9786 glUniform4f(colorLoc, 1, 0, 0, 1);
9787 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9788
9789 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9790
9791 // Make draw calls that manipulate stencil and use different functions and ops.
9792
9793 // Current color/depth/stencil in the four sections of the image:
9794 //
9795 // red/-0.8/3E red/-0.2/A7
9796 // red/ 0.4/6C red/0.6/5B
9797 //
9798 glEnable(GL_DEPTH_TEST);
9799 glDepthFunc(GL_LESS);
9800 glEnable(GL_STENCIL_TEST);
9801 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x2C, 0x2C);
9802 glStencilOpSeparate(GL_FRONT, GL_INCR, GL_DECR, GL_INVERT);
9803 glStencilFuncSeparate(GL_BACK, GL_GREATER, 0x7B, 0xFF);
9804 glStencilOpSeparate(GL_BACK, GL_INCR, GL_ZERO, GL_REPLACE);
9805
9806 // Draw green front-facing to get:
9807 //
9808 // red/-0.8/3D red/-0.2/A8
9809 // green/ 0.4/93 red/ 0.6/5C
9810 //
9811 glUniform4f(colorLoc, 0, 1, 0, 1);
9812 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9813
9814 // Draw blue back-facing to get:
9815 //
9816 // red/-0.8/00 red/-0.2/A9
9817 // green/ 0.4/94 blue/ 0.6/7B
9818 //
9819 glFrontFace(GL_CW);
9820 glUniform4f(colorLoc, 0, 0, 1, 1);
9821 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9822
9823 glStencilFuncSeparate(GL_FRONT, GL_LEQUAL, 0x42, 0x42);
9824 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_INCR_WRAP);
9825 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x00, 0x00);
9826 glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_INVERT);
9827
9828 // Draw yellow back-facing to get:
9829 //
9830 // yellow/-0.8/FF yellow/-0.2/56
9831 // green/ 0.4/95 blue/ 0.6/7C
9832 //
9833 glDepthFunc(GL_GREATER);
9834 glUniform4f(colorLoc, 1, 1, 0, 1);
9835 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9836
9837 // Draw cyan front-facing to get:
9838 //
9839 // cyan/-0.8/00 yellow/-0.2/55
9840 // green/ 0.4/95 blue/ 0.6/7C
9841 //
9842 glFrontFace(GL_CCW);
9843 glUniform4f(colorLoc, 0, 1, 1, 1);
9844 drawQuad(program, essl1_shaders::PositionAttrib(), -0.5);
9845
9846 // No-op draw
9847 glStencilFuncSeparate(GL_FRONT, GL_NEVER, 0x00, 0x00);
9848 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INVERT, GL_INVERT);
9849 glUniform4f(colorLoc, 1, 0, 1, 1);
9850 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9851
9852 // Verify results
9853 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9854 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9855 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9856 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9857
9858 // Verify the stencil buffer
9859 glDisable(GL_DEPTH_TEST);
9860 glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
9861 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x00, 0xFF);
9862 glUniform4f(colorLoc, 1, 0, 0, 1);
9863 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9864
9865 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9866 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9867 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9868 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9869
9870 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x55, 0xFF);
9871 glUniform4f(colorLoc, 1, 0, 1, 1);
9872 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9873
9874 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9875 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9876 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9877 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9878
9879 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x95, 0xFF);
9880 glUniform4f(colorLoc, 1, 1, 1, 1);
9881 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9882
9883 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9884 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9885 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9886 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9887
9888 glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x7C, 0xFF);
9889 glUniform4f(colorLoc, 0, 0, 0, 1);
9890 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9891
9892 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9893 EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9894 EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9895 EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9896
9897 ASSERT_GL_NO_ERROR();
9898 }
9899
9900 // Tests state change for rasterizer discard
TEST_P(StateChangeTestES3,RasterizerDiscard)9901 TEST_P(StateChangeTestES3, RasterizerDiscard)
9902 {
9903 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9904 glUseProgram(program);
9905
9906 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9907 ASSERT_NE(colorLoc, -1);
9908
9909 const int w = getWindowWidth();
9910 const int h = getWindowHeight();
9911
9912 glClearColor(0, 0, 0, 0);
9913 glClear(GL_COLOR_BUFFER_BIT);
9914
9915 glEnable(GL_BLEND);
9916 glBlendFunc(GL_ONE, GL_ONE);
9917
9918 // Start a render pass and issue three draw calls with the middle one having rasterizer discard
9919 // enabled.
9920 glUniform4f(colorLoc, 1, 0, 0, 0);
9921 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9922
9923 glEnable(GL_RASTERIZER_DISCARD);
9924
9925 glUniform4f(colorLoc, 0, 1, 1, 0);
9926 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9927
9928 glDisable(GL_RASTERIZER_DISCARD);
9929
9930 glUniform4f(colorLoc, 0, 0, 0, 1);
9931 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9932
9933 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9934
9935 // Enable rasterizer discard and make sure the state is effective.
9936 glEnable(GL_RASTERIZER_DISCARD);
9937
9938 glUniform4f(colorLoc, 0, 1, 0, 1);
9939 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9940
9941 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9942
9943 // Start a render pass and issue three draw calls with the first and last ones having rasterizer
9944 // discard enabled.
9945 glUniform4f(colorLoc, 0, 1, 0, 0);
9946 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9947
9948 glDisable(GL_RASTERIZER_DISCARD);
9949
9950 glUniform4f(colorLoc, 0, 0, 1, 0);
9951 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9952
9953 glEnable(GL_RASTERIZER_DISCARD);
9954
9955 glUniform4f(colorLoc, 0, 1, 0, 1);
9956 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9957
9958 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::magenta);
9959
9960 ASSERT_GL_NO_ERROR();
9961 }
9962
9963 // Tests state change for GL_POLYGON_OFFSET_FILL.
TEST_P(StateChangeTestES3,PolygonOffsetFill)9964 TEST_P(StateChangeTestES3, PolygonOffsetFill)
9965 {
9966 constexpr char kVS[] = R"(#version 300 es
9967 precision highp float;
9968 void main()
9969 {
9970 // gl_VertexID x y
9971 // 0 -1 -1
9972 // 1 1 -1
9973 // 2 -1 1
9974 // 3 1 1
9975 int bit0 = gl_VertexID & 1;
9976 int bit1 = gl_VertexID >> 1;
9977 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
9978 })";
9979
9980 constexpr char kFS[] = R"(#version 300 es
9981 precision highp float;
9982 out vec4 colorOut;
9983 uniform vec4 color;
9984 void main()
9985 {
9986 colorOut = color;
9987 })";
9988
9989 ANGLE_GL_PROGRAM(program, kVS, kFS);
9990 glUseProgram(program);
9991
9992 GLint colorLoc = glGetUniformLocation(program, "color");
9993 ASSERT_NE(-1, colorLoc);
9994
9995 glClearColor(0, 0, 0, 1);
9996 glClearDepthf(0);
9997 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9998
9999 // The shader creates a depth slope from left (0) to right (1).
10000 //
10001 // This test issues three draw calls:
10002 //
10003 //
10004 // Draw 3 (blue): factor width/2, enabled, depth test: Greater
10005 // ^ | __________________
10006 // | | __/ __/ __/
10007 // | V __/ __/ __/
10008 // | __/ __/ __/
10009 // | __/ __/ __/
10010 // |/ __/^ __/
10011 // | __/ | __/ <--- Draw 2: factor width/2, disabled, depth test: Greater
10012 // | __/ _\/
10013 // |/ __/ \
10014 // | __/ Draw 1 (red): factor width/4, enabled
10015 // | __/
10016 // +/------------------------------>
10017 //
10018 // Result: <-------magenta-------><--red-->
10019
10020 glEnable(GL_BLEND);
10021 glBlendFunc(GL_ONE, GL_ONE);
10022
10023 glEnable(GL_DEPTH_TEST);
10024 glDepthFunc(GL_ALWAYS);
10025
10026 glEnable(GL_POLYGON_OFFSET_FILL);
10027
10028 const int w = getWindowWidth();
10029 const int h = getWindowHeight();
10030
10031 glUniform4f(colorLoc, 1, 0, 0, 1);
10032 glPolygonOffset(getWindowWidth() / 4, 0);
10033 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10034
10035 glUniform4f(colorLoc, 0, 1, 0, 1);
10036 glPolygonOffset(getWindowWidth() / 2, 0);
10037 glDepthFunc(GL_GREATER);
10038 glDisable(GL_POLYGON_OFFSET_FILL);
10039 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10040
10041 glUniform4f(colorLoc, 0, 0, 1, 1);
10042 glEnable(GL_POLYGON_OFFSET_FILL);
10043 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10044
10045 EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::magenta);
10046 EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
10047
10048 ASSERT_GL_NO_ERROR();
10049 }
10050
10051 // Tests state change for GL_PRIMITIVE_RESTART.
TEST_P(StateChangeTestES3,PrimitiveRestart)10052 TEST_P(StateChangeTestES3, PrimitiveRestart)
10053 {
10054 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10055 glUseProgram(program);
10056
10057 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
10058 ASSERT_NE(colorLoc, -1);
10059
10060 GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
10061 ASSERT_EQ(0, posAttrib);
10062
10063 // Arrange the vertices as such:
10064 //
10065 // 1 3 4
10066 // +-----+-----+
10067 // | | |
10068 // | | |
10069 // | | |
10070 // | | |
10071 // | | |
10072 // | | |
10073 // +-----+-----+
10074 // 0 2 FF
10075 //
10076 // Drawing a triangle strip, without primitive restart, the whole framebuffer is rendered, while
10077 // with primitive restart only the left half is.
10078 std::vector<Vector3> positionData(256, {0, 0, 0});
10079
10080 positionData[0] = Vector3(-1, -1, 0);
10081 positionData[1] = Vector3(-1, 1, 0);
10082 positionData[2] = Vector3(0, -1, 0);
10083 positionData[3] = Vector3(0, 1, 0);
10084 positionData[0xFF] = Vector3(1, -1, 0);
10085 positionData[4] = Vector3(1, 1, 0);
10086
10087 constexpr std::array<GLubyte, 6> indices = {0, 1, 2, 3, 0xFF, 4};
10088
10089 GLBuffer posBuffer;
10090 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
10091 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(positionData[0]),
10092 positionData.data(), GL_STATIC_DRAW);
10093 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
10094 glEnableVertexAttribArray(posAttrib);
10095
10096 GLBuffer indexBuffer;
10097 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
10098 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
10099
10100 const int w = getWindowWidth();
10101 const int h = getWindowHeight();
10102
10103 glClearColor(0, 0, 0, 1);
10104 glClear(GL_COLOR_BUFFER_BIT);
10105
10106 glEnable(GL_BLEND);
10107 glBlendFunc(GL_ONE, GL_ONE);
10108
10109 // Draw red with primitive restart enabled
10110 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10111 glUniform4f(colorLoc, 1, 0, 0, 0);
10112 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10113
10114 // Draw green with primitive restart disabled
10115 glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10116 glUniform4f(colorLoc, 0, 1, 0, 1);
10117 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10118
10119 // Draw blue with primitive restart enabled again
10120 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10121 glUniform4f(colorLoc, 0, 0, 1, 0);
10122 glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10123
10124 // Verify results
10125 EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::white);
10126 EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 2 - 1, h, GLColor::green);
10127
10128 ASSERT_GL_NO_ERROR();
10129 }
10130
10131 // Tests that primitive restart for patches can be queried when tessellation shaders are available,
10132 // and that its value is independent of whether primitive restart is enabled.
TEST_P(StateChangeTestES31,PrimitiveRestartForPatchQuery)10133 TEST_P(StateChangeTestES31, PrimitiveRestartForPatchQuery)
10134 {
10135 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
10136
10137 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10138 GLint primitiveRestartForPatchesWhenEnabled = -1;
10139 glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10140 &primitiveRestartForPatchesWhenEnabled);
10141 ASSERT_GL_NO_ERROR();
10142 EXPECT_GE(primitiveRestartForPatchesWhenEnabled, 0);
10143
10144 glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10145 GLint primitiveRestartForPatchesWhenDisabled = -1;
10146 glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10147 &primitiveRestartForPatchesWhenDisabled);
10148 ASSERT_GL_NO_ERROR();
10149 EXPECT_GE(primitiveRestartForPatchesWhenDisabled, 0);
10150
10151 EXPECT_EQ(primitiveRestartForPatchesWhenEnabled, primitiveRestartForPatchesWhenDisabled);
10152 }
10153
10154 // Tests state change for GL_COLOR_LOGIC_OP and glLogicOp.
TEST_P(StateChangeTestES3,LogicOp)10155 TEST_P(StateChangeTestES3, LogicOp)
10156 {
10157 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_logic_op"));
10158
10159 constexpr char kVS[] = R"(#version 300 es
10160 precision highp float;
10161 void main()
10162 {
10163 // gl_VertexID x y
10164 // 0 -1 -1
10165 // 1 1 -1
10166 // 2 -1 1
10167 // 3 1 1
10168 int bit0 = gl_VertexID & 1;
10169 int bit1 = gl_VertexID >> 1;
10170 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10171 })";
10172
10173 constexpr char kFS[] = R"(#version 300 es
10174 precision highp float;
10175 out vec4 colorOut;
10176 uniform vec4 color;
10177 void main()
10178 {
10179 colorOut = color;
10180 })";
10181
10182 ANGLE_GL_PROGRAM(program, kVS, kFS);
10183 glUseProgram(program);
10184
10185 GLint colorLoc = glGetUniformLocation(program, "color");
10186 ASSERT_NE(-1, colorLoc);
10187
10188 glClearColor(0, 0, 0, 1);
10189 glClearDepthf(0);
10190 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10191
10192 auto unorm8 = [](uint8_t value) { return (value + 0.1f) / 255.0f; };
10193
10194 constexpr uint8_t kInitRed = 0xA4;
10195 constexpr uint8_t kInitGreen = 0x1E;
10196 constexpr uint8_t kInitBlue = 0x97;
10197 constexpr uint8_t kInitAlpha = 0x65;
10198
10199 // Initialize with logic op enabled, but using the default GL_COPY op.
10200 glEnable(GL_COLOR_LOGIC_OP_ANGLE);
10201
10202 glUniform4f(colorLoc, unorm8(kInitRed), unorm8(kInitGreen), unorm8(kInitBlue),
10203 unorm8(kInitAlpha));
10204 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10205
10206 // Set logic op to GL_XOR and draw again.
10207 glLogicOpANGLE(GL_LOGIC_OP_XOR_ANGLE);
10208
10209 constexpr uint8_t kXorRed = 0x4C;
10210 constexpr uint8_t kXorGreen = 0x7D;
10211 constexpr uint8_t kXorBlue = 0xB3;
10212 constexpr uint8_t kXorAlpha = 0x0F;
10213
10214 glUniform4f(colorLoc, unorm8(kXorRed), unorm8(kXorGreen), unorm8(kXorBlue), unorm8(kXorAlpha));
10215 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10216
10217 // Set logic op to GL_INVERT and draw again.
10218 glLogicOpANGLE(GL_LOGIC_OP_INVERT_ANGLE);
10219 glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10220 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10221
10222 const int w = getWindowWidth();
10223 const int h = getWindowHeight();
10224
10225 // Verify results
10226 const GLColor kExpect(static_cast<uint8_t>(~(kInitRed ^ kXorRed)),
10227 static_cast<uint8_t>(~(kInitGreen ^ kXorGreen)),
10228 static_cast<uint8_t>(~(kInitBlue ^ kXorBlue)),
10229 static_cast<uint8_t>(~(kInitAlpha ^ kXorAlpha)));
10230 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, kExpect);
10231
10232 // Render again with logic op enabled, this time with GL_COPY_INVERTED
10233 glLogicOpANGLE(GL_LOGIC_OP_COPY_INVERTED_ANGLE);
10234 glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10235 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10236
10237 // Disable logic op and render again
10238 glDisable(GL_COLOR_LOGIC_OP_ANGLE);
10239 glUniform4f(colorLoc, 0, 1, 0, 1);
10240 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10241
10242 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
10243 ASSERT_GL_NO_ERROR();
10244 }
10245
10246 // Test for a bug with the VK_EXT_graphics_pipeline_library implementation in a scenario such as
10247 // this:
10248 //
10249 // - Use blend function A, draw <-- a new pipeline is created
10250 // - Use blend function B, draw <-- a new pipeline is created,
10251 // new transition from A to B
10252 // - Switch to program 2
10253 // - Use blend function A, draw <-- a new pipeline is created
10254 // - Switch to program 1
10255 // - draw <-- the first pipeline is retrieved from cache,
10256 // new transition from B to A
10257 // - Use blend function B, draw <-- the second pipeline is retrieved from transition
10258 // - Switch to program 3
10259 // - draw <-- a new pipeline is created
10260 //
10261 // With graphics pipeline library, the fragment output partial pipeline changes as follows:
10262 //
10263 // - Use blend function A, draw <-- a new fragment output pipeline is created
10264 // - Use blend function B, draw <-- a new fragment output pipeline is created,
10265 // new transition from A to B
10266 // - Switch to program 2
10267 // - Use blend function A, draw <-- the first fragment output pipeline is retrieved from cache
10268 // - Switch to program 1
10269 // - draw <-- the first monolithic pipeline is retrieved from cache
10270 // - Use blend function B, draw <-- the second monolithic pipeline is retrieved from transition
10271 // - Switch to program 3
10272 // - draw <-- the second fragment output pipeline is retrieved from cache
10273 //
10274 // The bug was that the dirty blend state was discarded when the monolithic pipeline was retrieved
10275 // through the transition graph, and the last draw call used a stale fragment output pipeline (from
10276 // the last draw call with function A)
10277 //
TEST_P(StateChangeTestES3,FragmentOutputStateChangeAfterCachedPipelineTransition)10278 TEST_P(StateChangeTestES3, FragmentOutputStateChangeAfterCachedPipelineTransition)
10279 {
10280 // Program 1
10281 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10282 // Program 2
10283 ANGLE_GL_PROGRAM(drawColor2, essl3_shaders::vs::Simple(), R"(#version 300 es
10284 precision mediump float;
10285 out vec4 colorOut;
10286 uniform vec4 colorIn;
10287 void main()
10288 {
10289 colorOut = colorIn;
10290 }
10291 )");
10292 // Program 3
10293 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10294
10295 glUseProgram(drawColor2);
10296 GLint color2UniformLocation = glGetUniformLocation(drawColor2, "colorIn");
10297 ASSERT_NE(color2UniformLocation, -1);
10298
10299 glUseProgram(drawColor);
10300 GLint colorUniformLocation =
10301 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
10302 ASSERT_NE(colorUniformLocation, -1);
10303
10304 glEnable(GL_BLEND);
10305 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10306 glClearColor(0, 0, 0, 0);
10307 glClear(GL_COLOR_BUFFER_BIT);
10308 // Framebuffer color is now (0, 0, 0, 0)
10309
10310 glUniform4f(colorUniformLocation, 0, 0, 1, 0.25f);
10311 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10312 // Framebuffer color is now (0, 0, 0.25, 0.25*0.25)
10313
10314 glBlendFunc(GL_ONE, GL_ONE);
10315 glUniform4f(colorUniformLocation, 0, 0, 0.25, 0.5 - 0.0625);
10316 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10317 // Framebuffer color is now (0, 0, 0.5, 0.5)
10318
10319 // Draw with a different program, but same fragment output state. The fragment output pipeline
10320 // is retrieved from cache.
10321 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10322 glUseProgram(drawColor2);
10323 glUniform4f(color2UniformLocation, 1, 0, 0, 0.5);
10324 drawQuad(drawColor2, essl1_shaders::PositionAttrib(), 0.5f);
10325 // Framebuffer color is now (0.5, 0, 0.25, 0.5)
10326
10327 // Draw with the original program and the first fragment output state, so it's retrieved from
10328 // cache.
10329 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10330 glUseProgram(drawColor);
10331 glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25);
10332 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10333 // Framebuffer color is now (0.25, 0, 0.25, 0.25+0.25*0.25)
10334
10335 // Change to the second fragment output state, so it's retrieved through the transition graph.
10336 glBlendFunc(GL_ONE, GL_ONE);
10337 glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25 - 0.25 * 0.25);
10338 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10339 // Framebuffer color is now (0.25, 0, 0.75, 0.5)
10340
10341 // Draw with the third program, not changing the fragment output state.
10342 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
10343 // Framebuffer color is now (0.25, 1, 0.75, 1)
10344
10345 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 255, 192, 255), 1);
10346 ASSERT_GL_NO_ERROR();
10347 }
10348
10349 // Tests a specific case for multiview and queries.
TEST_P(SimpleStateChangeTestES3,MultiviewAndQueries)10350 TEST_P(SimpleStateChangeTestES3, MultiviewAndQueries)
10351 {
10352 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OVR_multiview"));
10353
10354 ANGLE_GL_PROGRAM(prog, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
10355 glUseProgram(prog);
10356
10357 const int PRE_QUERY_CNT = 63;
10358
10359 GLQuery qry;
10360 GLTexture tex;
10361 GLFramebuffer fb;
10362 GLFramebuffer fb2;
10363 glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10364 for (int i = 0; i < PRE_QUERY_CNT; i++)
10365 {
10366 glDrawArrays(GL_POINTS, 0, 1);
10367
10368 GLColor color;
10369 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
10370 }
10371 glEndQuery(GL_ANY_SAMPLES_PASSED);
10372 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
10373 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
10374 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2);
10375 glBindFramebuffer(GL_FRAMEBUFFER, fb);
10376 glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
10377 glClear(GL_COLOR_BUFFER_BIT);
10378 glBindFramebuffer(GL_FRAMEBUFFER, fb2);
10379 glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10380 }
10381
10382 // Tests a bug related to an ordering of certain commands.
TEST_P(SimpleStateChangeTestES3,ClearQuerySwapClear)10383 TEST_P(SimpleStateChangeTestES3, ClearQuerySwapClear)
10384 {
10385 glClear(GL_COLOR_BUFFER_BIT);
10386 {
10387 GLQuery query;
10388 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
10389 glEndQuery(GL_ANY_SAMPLES_PASSED);
10390 }
10391 swapBuffers();
10392 glClear(GL_COLOR_BUFFER_BIT);
10393 }
10394
10395 // Tests a bug around sampler2D swap and uniform locations.
TEST_P(StateChangeTestES3,SamplerSwap)10396 TEST_P(StateChangeTestES3, SamplerSwap)
10397 {
10398 constexpr char kVS[] = R"(#version 300 es
10399 precision highp float;
10400 void main()
10401 {
10402 // gl_VertexID x y
10403 // 0 -1 -1
10404 // 1 1 -1
10405 // 2 -1 1
10406 // 3 1 1
10407 int bit0 = gl_VertexID & 1;
10408 int bit1 = gl_VertexID >> 1;
10409 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10410 })";
10411
10412 constexpr char kFS1[] = R"(#version 300 es
10413 precision highp float;
10414 uniform sampler2D A;
10415 uniform sampler2D B;
10416 out vec4 colorOut;
10417 void main()
10418 {
10419 float a = texture(A, vec2(0)).x;
10420 float b = texture(B, vec2(0)).x;
10421 colorOut = vec4(a, b, 0, 1);
10422 })";
10423
10424 constexpr char kFS2[] = R"(#version 300 es
10425 precision highp float;
10426 uniform sampler2D B;
10427 uniform sampler2D A;
10428 const vec2 multiplier = vec2(0.5, 0.5);
10429 out vec4 colorOut;
10430 void main()
10431 {
10432 float a = texture(A, vec2(0)).x;
10433 float b = texture(B, vec2(0)).x;
10434 colorOut = vec4(a, b, 0, 1);
10435 })";
10436
10437 ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10438 ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10439
10440 const GLColor kColorA(123, 0, 0, 0);
10441 const GLColor kColorB(157, 0, 0, 0);
10442
10443 GLTexture texA;
10444 glActiveTexture(GL_TEXTURE0);
10445 glBindTexture(GL_TEXTURE_2D, texA);
10446 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10447 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10448
10449 GLTexture texB;
10450 glActiveTexture(GL_TEXTURE1);
10451 glBindTexture(GL_TEXTURE_2D, texB);
10452 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10453 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10454 EXPECT_GL_NO_ERROR();
10455
10456 glUseProgram(prog1);
10457 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10458 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10459
10460 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10461
10462 const GLColor kExpect(kColorA.R, kColorB.R, 0, 255);
10463
10464 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10465 ASSERT_GL_NO_ERROR();
10466
10467 // The same with the second program that has sampler2D (definitions) swapped which should have
10468 // no effect on the result.
10469 glUseProgram(prog2);
10470 glUniform1i(glGetUniformLocation(prog2, "A"), 0);
10471 glUniform1i(glGetUniformLocation(prog2, "B"), 1);
10472
10473 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10474
10475 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10476 ASSERT_GL_NO_ERROR();
10477 }
10478
10479 // Tests a bug around sampler2D reordering and uniform locations.
TEST_P(StateChangeTestES3,SamplerReordering)10480 TEST_P(StateChangeTestES3, SamplerReordering)
10481 {
10482 constexpr char kVS[] = R"(#version 300 es
10483 precision highp float;
10484 void main()
10485 {
10486 // gl_VertexID x y
10487 // 0 -1 -1
10488 // 1 1 -1
10489 // 2 -1 1
10490 // 3 1 1
10491 int bit0 = gl_VertexID & 1;
10492 int bit1 = gl_VertexID >> 1;
10493 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10494 })";
10495
10496 constexpr char kFS1[] = R"(#version 300 es
10497 precision highp float;
10498 uniform sampler2D A;
10499 uniform sampler2D B;
10500 //uniform vec2 multiplier;
10501 const vec2 multiplier = vec2(0.5, 0.5);
10502 out vec4 colorOut;
10503 void main()
10504 {
10505 float a = texture(A, vec2(0)).x;
10506 float b = texture(B, vec2(0)).x;
10507 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10508 })";
10509
10510 constexpr char kFS2[] = R"(#version 300 es
10511 precision highp float;
10512 uniform sampler2D S;
10513 uniform sampler2D P;
10514 //uniform vec2 multiplier;
10515 const vec2 multiplier = vec2(0.5, 0.5);
10516 out vec4 colorOut;
10517 void main()
10518 {
10519 float a = texture(P, vec2(0)).x;
10520 float b = texture(S, vec2(0)).x;
10521 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10522 })";
10523
10524 constexpr char kFS3[] = R"(#version 300 es
10525 precision highp float;
10526 uniform sampler2D R;
10527 uniform sampler2D S;
10528 //uniform vec2 multiplier;
10529 const vec2 multiplier = vec2(0.5, 0.5);
10530 out vec4 colorOut;
10531 void main()
10532 {
10533 float a = texture(R, vec2(0)).x;
10534 float b = texture(S, vec2(0)).x;
10535 colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10536 })";
10537
10538 ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10539 ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10540 ANGLE_GL_PROGRAM(prog3, kVS, kFS3);
10541
10542 const GLColor kColorA(123, 0, 0, 0);
10543 const GLColor kColorB(157, 0, 0, 0);
10544
10545 GLTexture texA;
10546 glActiveTexture(GL_TEXTURE0);
10547 glBindTexture(GL_TEXTURE_2D, texA);
10548 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10549 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10550
10551 GLTexture texB;
10552 glActiveTexture(GL_TEXTURE1);
10553 glBindTexture(GL_TEXTURE_2D, texB);
10554 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10555 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10556 EXPECT_GL_NO_ERROR();
10557
10558 glUseProgram(prog1);
10559 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10560 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10561
10562 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10563
10564 glUseProgram(prog2);
10565 glUniform1i(glGetUniformLocation(prog2, "S"), 0);
10566 glUniform1i(glGetUniformLocation(prog2, "P"), 1);
10567
10568 glEnable(GL_BLEND);
10569 glBlendFunc(GL_ONE, GL_ONE);
10570 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10571
10572 constexpr float kXMultiplier = 0.5;
10573 constexpr float kYMultiplier = 0.5;
10574
10575 const GLColor kExpect(static_cast<uint8_t>((kColorA.R + kColorB.R) * kXMultiplier),
10576 static_cast<uint8_t>((kColorA.R + kColorB.R) * kYMultiplier), 0, 255);
10577
10578 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10579 ASSERT_GL_NO_ERROR();
10580
10581 // Do the same thing again, but with the second shader having its samplers specified in the
10582 // opposite order. The difference between kFS2 and kFS3 is that S is now the second
10583 // declaration, and P is renamed to R. The reason for the rename is that even if the samplers
10584 // get sorted by name, they would still result in the two shaders declaring them in different
10585 // orders.
10586 glDisable(GL_BLEND);
10587
10588 glUseProgram(prog1);
10589 glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10590 glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10591
10592 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10593
10594 glUseProgram(prog3);
10595 glUniform1i(glGetUniformLocation(prog3, "S"), 0);
10596 glUniform1i(glGetUniformLocation(prog3, "R"), 1);
10597
10598 glEnable(GL_BLEND);
10599 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10600
10601 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10602 ASSERT_GL_NO_ERROR();
10603 }
10604
10605 // Test that switching FBO attachments affects sample coverage
TEST_P(StateChangeTestES3,SampleCoverageFramebufferAttachmentSwitch)10606 TEST_P(StateChangeTestES3, SampleCoverageFramebufferAttachmentSwitch)
10607 {
10608 // Keep this state unchanged during the test
10609 glEnable(GL_SAMPLE_COVERAGE);
10610 glSampleCoverage(0.0f, false);
10611
10612 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10613
10614 GLFramebuffer fbo;
10615 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10616
10617 GLRenderbuffer rbo;
10618 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10619 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10620
10621 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10622 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10623
10624 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10625 ASSERT_GL_NO_ERROR();
10626
10627 // Sample coverage must have no effect
10628 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10629
10630 GLRenderbuffer rboMS;
10631 glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10632 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10633
10634 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10635 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10636
10637 glClearColor(1, 0, 0, 1);
10638 glClear(GL_COLOR_BUFFER_BIT);
10639 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10640 ASSERT_GL_NO_ERROR();
10641
10642 // Use a temporary FBO to resolve
10643 {
10644 GLFramebuffer fboResolve;
10645 glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10646
10647 GLRenderbuffer rboResolve;
10648 glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10649 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10650
10651 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10652 rboResolve);
10653 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10654
10655 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10656 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10657 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10658 ASSERT_GL_NO_ERROR();
10659
10660 // Nothing was drawn because of zero coverage
10661 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10662 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10663 }
10664
10665 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10666
10667 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10668 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10669
10670 glClearColor(0, 0, 1, 1);
10671 glClear(GL_COLOR_BUFFER_BIT);
10672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10673
10674 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10675 ASSERT_GL_NO_ERROR();
10676
10677 // Sample coverage must have no effect
10678 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10679 }
10680
10681 // Test that switching FBO attachments affects alpha-to-coverage
TEST_P(StateChangeTestES3,AlphaToCoverageFramebufferAttachmentSwitch)10682 TEST_P(StateChangeTestES3, AlphaToCoverageFramebufferAttachmentSwitch)
10683 {
10684 // Keep this state unchanged during the test
10685 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
10686
10687 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10688 glUseProgram(program);
10689 glUniform4f(glGetUniformLocation(program, essl1_shaders::ColorUniform()), 0, 1, 0, 0);
10690
10691 GLFramebuffer fbo;
10692 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10693
10694 GLRenderbuffer rbo;
10695 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10696 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10697
10698 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10699 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10700
10701 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10702 ASSERT_GL_NO_ERROR();
10703
10704 // A2C must have no effect
10705 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10706
10707 GLRenderbuffer rboMS;
10708 glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10709 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10710
10711 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10712 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10713
10714 glClearColor(1, 0, 0, 1);
10715 glClear(GL_COLOR_BUFFER_BIT);
10716 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10717 ASSERT_GL_NO_ERROR();
10718
10719 // Use a temporary FBO to resolve
10720 {
10721 GLFramebuffer fboResolve;
10722 glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10723
10724 GLRenderbuffer rboResolve;
10725 glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10726 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10727
10728 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10729 rboResolve);
10730 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10731
10732 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10733 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10734 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10735 ASSERT_GL_NO_ERROR();
10736
10737 // Nothing was drawn because of zero alpha
10738 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10739 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10740 }
10741
10742 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10743
10744 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10745 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10746
10747 glClearColor(0, 0, 1, 1);
10748 glClear(GL_COLOR_BUFFER_BIT);
10749 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10750
10751 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10752 ASSERT_GL_NO_ERROR();
10753
10754 // A2C must have no effect
10755 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10756 }
10757
10758 // Test that switching FBO attachments affects depth test
TEST_P(StateChangeTestES3,DepthTestFramebufferAttachmentSwitch)10759 TEST_P(StateChangeTestES3, DepthTestFramebufferAttachmentSwitch)
10760 {
10761 // Keep this state unchanged during the test
10762 glEnable(GL_DEPTH_TEST);
10763 glDepthMask(GL_TRUE);
10764 glDepthFunc(GL_GREATER);
10765
10766 constexpr char kVS[] = R"(#version 300 es
10767 precision highp float;
10768 uniform float u_depth;
10769 void main()
10770 {
10771 // gl_VertexID x y
10772 // 0 -1 -1
10773 // 1 1 -1
10774 // 2 -1 1
10775 // 3 1 1
10776 int bit0 = gl_VertexID & 1;
10777 int bit1 = gl_VertexID >> 1;
10778 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, u_depth * 2. - 1., 1);
10779 })";
10780
10781 constexpr char kFS[] = R"(#version 300 es
10782 uniform mediump vec4 u_color;
10783 out mediump vec4 color;
10784 void main(void)
10785 {
10786 color = u_color;
10787 })";
10788
10789 ANGLE_GL_PROGRAM(program, kVS, kFS);
10790 glUseProgram(program);
10791 GLint depthUni = glGetUniformLocation(program, "u_depth");
10792 GLint colorUni = glGetUniformLocation(program, "u_color");
10793
10794 constexpr uint32_t kWidth = 17;
10795 constexpr uint32_t kHeight = 23;
10796
10797 GLRenderbuffer rbo;
10798 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10799 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10800
10801 GLRenderbuffer depthStencil;
10802 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
10803 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight);
10804
10805 GLFramebuffer fbo;
10806 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10807 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10808 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10809 depthStencil);
10810 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10811
10812 glEnable(GL_BLEND);
10813 glBlendFunc(GL_ONE, GL_ONE);
10814
10815 glClearColor(0, 0, 0, 0);
10816 glClearDepthf(0);
10817 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10818 ASSERT_GL_NO_ERROR();
10819
10820 // Draw with the depth buffer attached, set depth to 0.5. Should succeed and the color buffer
10821 // becomes red.
10822 glUniform4f(colorUni, 1, 0, 0, 0);
10823 glUniform1f(depthUni, 0.5);
10824 glDrawArrays(GL_TRIANGLES, 0, 6);
10825
10826 // Detach the depth buffer and draw with a smaller depth. Should still succeed because there is
10827 // no depth buffer test against. Green should be added.
10828 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
10829 glUniform4f(colorUni, 0, 0.2, 0, 0.6);
10830 glUniform1f(depthUni, 0.3);
10831 glDrawArrays(GL_TRIANGLES, 0, 6);
10832 // Higher depth should also pass
10833 glUniform1f(depthUni, 0.9);
10834 glDrawArrays(GL_TRIANGLES, 0, 6);
10835
10836 // Reattach the depth buffer and draw with a depth in between. Should fail the depth. Blue
10837 // should not be added.
10838 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10839 depthStencil);
10840 glUniform4f(colorUni, 0, 0, 1, 1);
10841 glUniform1f(depthUni, 0.4);
10842 glDrawArrays(GL_TRIANGLES, 0, 6);
10843
10844 // Reattach the depth buffer and draw with a depth larger than 0.5. Should pass the depth test.
10845 // Blue should be added.
10846 glUniform4f(colorUni, 0, 0.8, 0, 0);
10847 glUniform1f(depthUni, 0.6);
10848 glDrawArrays(GL_TRIANGLES, 0, 6);
10849
10850 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10851 ASSERT_GL_NO_ERROR();
10852 }
10853
10854 // Test that switching FBO attachments affects blend state
TEST_P(StateChangeTestES3,BlendFramebufferAttachmentSwitch)10855 TEST_P(StateChangeTestES3, BlendFramebufferAttachmentSwitch)
10856 {
10857 // Keep this state unchanged during the test
10858 glEnable(GL_BLEND);
10859 glBlendFunc(GL_ONE, GL_ONE);
10860
10861 constexpr char kVS[] = R"(#version 300 es
10862 precision highp float;
10863 void main()
10864 {
10865 // gl_VertexID x y
10866 // 0 -1 -1
10867 // 1 1 -1
10868 // 2 -1 1
10869 // 3 1 1
10870 int bit0 = gl_VertexID & 1;
10871 int bit1 = gl_VertexID >> 1;
10872 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1);
10873 })";
10874
10875 constexpr char kFS[] = R"(#version 300 es
10876 uniform mediump vec4 u_color;
10877 layout(location=0) out mediump vec4 color0;
10878 layout(location=1) out mediump vec4 color1;
10879 void main(void)
10880 {
10881 color0 = u_color;
10882 color1 = u_color;
10883 })";
10884
10885 ANGLE_GL_PROGRAM(program, kVS, kFS);
10886 glUseProgram(program);
10887 GLint colorUni = glGetUniformLocation(program, "u_color");
10888
10889 constexpr uint32_t kWidth = 17;
10890 constexpr uint32_t kHeight = 23;
10891
10892 GLRenderbuffer color0;
10893 glBindRenderbuffer(GL_RENDERBUFFER, color0);
10894 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10895
10896 GLRenderbuffer color1;
10897 glBindRenderbuffer(GL_RENDERBUFFER, color1);
10898 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10899
10900 GLFramebuffer fbo;
10901 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10902 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10903 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10904
10905 constexpr GLenum kDrawBuffers[2] = {
10906 GL_COLOR_ATTACHMENT0,
10907 GL_COLOR_ATTACHMENT1,
10908 };
10909 glDrawBuffers(2, kDrawBuffers);
10910
10911 // Clear the first attachment to transparent green
10912 glClearColor(0, 1, 0, 0);
10913 glClear(GL_COLOR_BUFFER_BIT);
10914
10915 // Clear the second attachment to transparent blue
10916 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10917 glClearColor(0, 0, 1, 0);
10918 glClear(GL_COLOR_BUFFER_BIT);
10919 ASSERT_GL_NO_ERROR();
10920
10921 // Draw with only one attachment. Attachment 0 is now transparent yellow-ish.
10922 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10923 glUniform4f(colorUni, 0.6, 0, 0, 0);
10924 glDrawArrays(GL_TRIANGLES, 0, 6);
10925
10926 // Attach the second renderbuffer and draw to both. Attachment 0 is now yellow-ish, while
10927 // attachment 1 is blue.
10928 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, color1);
10929 glUniform4f(colorUni, 0, 0, 0, 1);
10930 glDrawArrays(GL_TRIANGLES, 0, 6);
10931
10932 // Detach the second renderbuffer again and draw. Attachment 0 is now yellow.
10933 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, 0);
10934 glUniform4f(colorUni, 0.6, 0, 0, 0);
10935 glDrawArrays(GL_TRIANGLES, 0, 6);
10936
10937 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10938 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10939 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
10940 ASSERT_GL_NO_ERROR();
10941 }
10942
10943 // Tests state change for sample shading.
TEST_P(StateChangeTestES31,SampleShading)10944 TEST_P(StateChangeTestES31, SampleShading)
10945 {
10946 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
10947 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
10948
10949 constexpr GLsizei kSize = 1;
10950 constexpr GLsizei kSampleCount = 4;
10951
10952 // Create a single sampled texture and framebuffer for verifying results
10953 GLFramebuffer fbo;
10954 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10955
10956 GLTexture texture;
10957 glBindTexture(GL_TEXTURE_2D, texture);
10958 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
10959 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
10960 ASSERT_GL_NO_ERROR();
10961 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10962
10963 // Create a multisampled texture and framebuffer.
10964 GLFramebuffer msaaFBO;
10965 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
10966
10967 GLTexture msaaTexture;
10968 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
10969 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
10970 false);
10971 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
10972 msaaTexture, 0);
10973 ASSERT_GL_NO_ERROR();
10974 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10975
10976 // Create a fragment shader whose _resolved_ output is different based on whether sample shading
10977 // is enabled or not, but which doesn't use gl_SampleID (which implicitly enables sample
10978 // shading).
10979 //
10980 // This is done by non-linearly transforming a varying, resulting in a different color average
10981 // based on the location in which the varying is sampled. The framebuffer is 1x1 and the vertex
10982 // shader outputs the following triangle:
10983 //
10984 // (-3, 3)
10985 // |\
10986 // | \
10987 // | \
10988 // | \
10989 // | \
10990 // | \
10991 // +-----------+ <----- position evaluates as (1, 1)
10992 // | X | \
10993 // | W | \
10994 // | C | \
10995 // | Z | \
10996 // | Y | \
10997 // +-----------+-----------\
10998 // (-1, -1) (3, -1)
10999 //
11000 // The varying |gradient| is output as position. This means that:
11001 //
11002 // - At the center of the pixel (C), the |gradient| value is (0,0)
11003 // - At sample positions W, X, Y and Z, the |gradient| has 0.75 and 0.25 (positive or negative)
11004 // in its components. Most importantly, its length^2 (i.e. gradient.gradient) is:
11005 //
11006 // 0.25^2 + 0.75^2 = 0.625
11007 //
11008 // The fragment shader outputs gradient.gradient + (0.1, 0) as color. Without sample shading,
11009 // this outputs (0.1, 0, 0, 1) in the color. With sample shading, it outputs
11010 // (0.725, 0.625, 0, 1) (for all samples). By using additive blending, we can verify that when
11011 // only sample shading state is modified, that sample shading is indeed toggled.
11012 //
11013 constexpr char kVS[] = R"(#version 300 es
11014
11015 out mediump vec2 gradient;
11016
11017 void main()
11018 {
11019 vec2 position = vec2(-1, -1);
11020 if (gl_VertexID == 1)
11021 position = vec2(3, -1);
11022 else if (gl_VertexID == 2)
11023 position = vec2(-1, 3);
11024
11025 gradient = position;
11026 gl_Position = vec4(position, 0, 1);
11027 })";
11028
11029 constexpr char kFS[] = R"(#version 300 es
11030
11031 in mediump vec2 gradient;
11032 out mediump vec4 color;
11033
11034 uniform mediump vec2 offset;
11035
11036 void main()
11037 {
11038 mediump float len = dot(gradient, gradient);
11039 color = vec4(vec2(len, len) + offset, 0, 1);
11040 })";
11041
11042 ANGLE_GL_PROGRAM(program, kVS, kFS);
11043 glUseProgram(program);
11044 GLint offsetLoc = glGetUniformLocation(program, "offset");
11045 ASSERT_NE(offsetLoc, -1);
11046
11047 glClearColor(0, 0, 0, 0);
11048 glClear(GL_COLOR_BUFFER_BIT);
11049
11050 glEnable(GL_BLEND);
11051 glBlendFunc(GL_ONE, GL_ONE);
11052
11053 glViewport(0, 0, kSize, kSize);
11054
11055 // Issue 2 draw calls, with sample shading enabled then disabled.
11056 glUniform2f(offsetLoc, 0.1f, 0);
11057
11058 glEnable(GL_SAMPLE_SHADING_OES);
11059 glMinSampleShadingOES(1.0f);
11060 glDrawArrays(GL_TRIANGLES, 0, 3);
11061 glDisable(GL_SAMPLE_SHADING_OES);
11062 glDrawArrays(GL_TRIANGLES, 0, 3);
11063
11064 // Verify results
11065 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11066 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11067 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11068 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(210, 159, 0, 255), 1);
11069
11070 // Do the same test in opposite order (sample shading disabled first, then enabled).
11071 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
11072
11073 glUniform2f(offsetLoc, 0, 0.1f);
11074
11075 glClear(GL_COLOR_BUFFER_BIT);
11076 glDrawArrays(GL_TRIANGLES, 0, 3);
11077 glEnable(GL_SAMPLE_SHADING_OES);
11078 glDrawArrays(GL_TRIANGLES, 0, 3);
11079
11080 // Verify results
11081 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11082 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11083 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11084 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(159, 210, 0, 255), 1);
11085
11086 ASSERT_GL_NO_ERROR();
11087 }
11088
11089 // Tests value change for MinSampleShadingOES.
TEST_P(StateChangeTestES31,MinSampleShadingOES)11090 TEST_P(StateChangeTestES31, MinSampleShadingOES)
11091 {
11092 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
11093 ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_sample_variables"));
11094
11095 GLfloat value = 0.0f;
11096 glEnable(GL_SAMPLE_SHADING_OES);
11097 EXPECT_GL_TRUE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11098 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11099 ASSERT_EQ(value, 0); // initial value should be 0.
11100
11101 glDisable(GL_SAMPLE_SHADING_OES);
11102 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11103 ASSERT_EQ(value, 0);
11104
11105 glMinSampleShadingOES(0.5);
11106 EXPECT_GL_FALSE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11107 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11108 ASSERT_EQ(value, 0.5);
11109
11110 glMinSampleShadingOES(1.5);
11111 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11112 ASSERT_EQ(value, 1); // clamped to 1.
11113
11114 glMinSampleShadingOES(-0.5);
11115 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11116 ASSERT_EQ(value, 0); // clamped to 0.
11117 }
11118
11119 // Tests state changes with uniform block binding.
TEST_P(StateChangeTestES3,UniformBlockBinding)11120 TEST_P(StateChangeTestES3, UniformBlockBinding)
11121 {
11122 constexpr char kVS[] = R"(#version 300 es
11123 void main()
11124 {
11125 vec2 pos = vec2(0.0);
11126 switch (gl_VertexID) {
11127 case 0: pos = vec2(-1.0, -1.0); break;
11128 case 1: pos = vec2(3.0, -1.0); break;
11129 case 2: pos = vec2(-1.0, 3.0); break;
11130 };
11131 gl_Position = vec4(pos, 0.0, 1.0);
11132 })";
11133 constexpr char kFS[] = R"(#version 300 es
11134 out mediump vec4 colorOut;
11135
11136 layout(std140) uniform buffer { mediump vec4 color; };
11137
11138 void main()
11139 {
11140 colorOut = color;
11141 })";
11142
11143 ANGLE_GL_PROGRAM(program, kVS, kFS);
11144 glUseProgram(program);
11145 const GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
11146
11147 // Create buffers bound to bindings 1 and 2
11148 constexpr std::array<float, 4> kRed = {1, 0, 0, 1};
11149 constexpr std::array<float, 4> kTransparentGreen = {0, 1, 0, 0};
11150 GLBuffer red, transparentGreen;
11151 glBindBuffer(GL_UNIFORM_BUFFER, red);
11152 glBufferData(GL_UNIFORM_BUFFER, sizeof(kRed), kRed.data(), GL_STATIC_DRAW);
11153 glBindBuffer(GL_UNIFORM_BUFFER, transparentGreen);
11154 glBufferData(GL_UNIFORM_BUFFER, sizeof(kTransparentGreen), kTransparentGreen.data(),
11155 GL_STATIC_DRAW);
11156
11157 glBindBufferBase(GL_UNIFORM_BUFFER, 1, transparentGreen);
11158 glBindBufferBase(GL_UNIFORM_BUFFER, 2, red);
11159 glUniformBlockBinding(program, uniformBufferIndex, 2);
11160
11161 // Issue a draw call. The buffer should be transparent green now
11162 glClearColor(0, 0, 0, 0);
11163 glClear(GL_COLOR_BUFFER_BIT);
11164 glEnable(GL_BLEND);
11165 glBlendFunc(GL_ONE, GL_ONE);
11166
11167 glUseProgram(program);
11168 glDrawArrays(GL_TRIANGLES, 0, 3);
11169
11170 // Change the binding
11171 glUniformBlockBinding(program, uniformBufferIndex, 1);
11172 ASSERT_GL_NO_ERROR();
11173
11174 // Draw again, it should accumulate blue and the buffer should become magenta.
11175 glDrawArrays(GL_TRIANGLES, 0, 3);
11176
11177 // Verify results
11178 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
11179 ASSERT_GL_NO_ERROR();
11180 }
11181
11182 // Tests that viewport changes within a render pass are correct. WebGPU sets a default viewport,
11183 // cover the omission of setViewport in the backend.
TEST_P(StateChangeTest,ViewportChangeWithinRenderPass)11184 TEST_P(StateChangeTest, ViewportChangeWithinRenderPass)
11185 {
11186 glClearColor(0, 0, 0, 0);
11187 glClear(GL_COLOR_BUFFER_BIT);
11188
11189 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11190 glUseProgram(program);
11191 GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11192
11193 glViewport(0, 0, 10, 10);
11194 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11195 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11196
11197 glViewport(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11198 glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11199 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11200
11201 // Verify that the first draw is covered by the second "full" draw
11202 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11203 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11204
11205 // Go the other way, start with a full size viewport and change it to 10x10 for the second draw
11206 glViewport(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11207 glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11208 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11209
11210 glViewport(0, 0, 10, 10);
11211 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11212 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11213
11214 // Verify that the first draw is covered by the second "full" draw
11215 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11216 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11217 }
11218
11219 // Tests that scissor changes within a render pass are correct. WebGPU sets a default scissor, cover
11220 // the omission of setScissorRect in the backend.
TEST_P(StateChangeTest,ScissortChangeWithinRenderPass)11221 TEST_P(StateChangeTest, ScissortChangeWithinRenderPass)
11222 {
11223 glClearColor(0, 0, 0, 0);
11224 glClear(GL_COLOR_BUFFER_BIT);
11225 glEnable(GL_SCISSOR_TEST);
11226
11227 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11228 glUseProgram(program);
11229 GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11230
11231 glScissor(0, 0, 10, 10);
11232 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11233 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11234
11235 glScissor(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11236 glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11237 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11238
11239 // Verify that the first draw is covered by the second "full" draw
11240 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11241 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11242
11243 // Go the other way, start with a full size scissor and change it to 10x10 for the second draw
11244 glScissor(0, 0, getWindowWidth(), getWindowHeight()); // "default" size
11245 glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11246 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11247
11248 glScissor(0, 0, 10, 10);
11249 glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11250 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11251
11252 // Verify that the first draw is covered by the second "full" draw
11253 EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11254 EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11255 }
11256
11257 } // anonymous namespace
11258
11259 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
11260 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
11261 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
11262
11263 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
11264 ANGLE_INSTANTIATE_TEST_ES3_AND(
11265 StateChangeTestES3,
11266 ES3_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11267 ES3_VULKAN().disable(Feature::UseDepthWriteEnableDynamicState),
11268 ES3_VULKAN()
11269 .disable(Feature::SupportsExtendedDynamicState)
11270 .disable(Feature::SupportsExtendedDynamicState2),
11271 ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11272 ES3_VULKAN()
11273 .disable(Feature::SupportsExtendedDynamicState2)
11274 .disable(Feature::SupportsGraphicsPipelineLibrary),
11275 ES3_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11276 ES3_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11277
11278 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES31);
11279 ANGLE_INSTANTIATE_TEST_ES31_AND(
11280 StateChangeTestES31,
11281 ES31_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11282 ES31_VULKAN()
11283 .disable(Feature::SupportsExtendedDynamicState)
11284 .disable(Feature::SupportsExtendedDynamicState2),
11285 ES31_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11286 ES31_VULKAN()
11287 .disable(Feature::SupportsExtendedDynamicState2)
11288 .disable(Feature::SupportsGraphicsPipelineLibrary),
11289 ES31_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11290 ES31_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11291
11292 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestWebGL2);
11293 ANGLE_INSTANTIATE_TEST_COMBINE_1(StateChangeTestWebGL2,
11294 StateChangeTestWebGL2Print,
11295 testing::Bool(),
11296 ANGLE_ALL_TEST_PLATFORMS_ES3);
11297
11298 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
11299 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
11300
11301 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
11302
11303 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
11304 ANGLE_INSTANTIATE_TEST_ES3_AND(SimpleStateChangeTestES3,
11305 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory));
11306
11307 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
11308 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
11309
11310 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
11311 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
11312
11313 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
11314 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
11315
11316 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
11317 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
11318
11319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
11320 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
11321
11322 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
11323 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
11324
11325 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
11326 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
11327
11328 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
11329 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
11330
11331 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
11332 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
11333
11334 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttribArrayStateChangeTest);
11335 ANGLE_INSTANTIATE_TEST_ES3(VertexAttribArrayStateChangeTest);
11336