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