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