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
34 // Enable the no error extension to avoid syncing the FBO state on validation.
35 setNoErrorEnabled(true);
36 }
37
testSetUp()38 void testSetUp() override
39 {
40 glGenFramebuffers(1, &mFramebuffer);
41 glGenTextures(2, mTextures.data());
42 glGenRenderbuffers(1, &mRenderbuffer);
43
44 ASSERT_GL_NO_ERROR();
45 }
46
testTearDown()47 void testTearDown() override
48 {
49 if (mFramebuffer != 0)
50 {
51 glDeleteFramebuffers(1, &mFramebuffer);
52 mFramebuffer = 0;
53 }
54
55 if (!mTextures.empty())
56 {
57 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
58 mTextures.clear();
59 }
60
61 glDeleteRenderbuffers(1, &mRenderbuffer);
62 }
63
64 GLuint mFramebuffer = 0;
65 GLuint mRenderbuffer = 0;
66 std::vector<GLuint> mTextures = {0, 0};
67 };
68
69 class StateChangeTestES3 : public StateChangeTest
70 {
71 protected:
StateChangeTestES3()72 StateChangeTestES3() {}
73 };
74
75 // Ensure that CopyTexImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexImage2DSync)76 TEST_P(StateChangeTest, CopyTexImage2DSync)
77 {
78 // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/1291)
79 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
80
81 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
82
83 // Init first texture to red
84 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
85 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
86 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
87 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
88 glClear(GL_COLOR_BUFFER_BIT);
89 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
90
91 // Init second texture to green
92 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
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[1], 0);
95 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
96 glClear(GL_COLOR_BUFFER_BIT);
97 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
98
99 // Copy in the red texture to the green one.
100 // CopyTexImage should sync the framebuffer attachment change.
101 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
102 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
103 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
104 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
105
106 ASSERT_GL_NO_ERROR();
107 }
108
109 // Ensure that CopyTexSubImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexSubImage2DSync)110 TEST_P(StateChangeTest, CopyTexSubImage2DSync)
111 {
112 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
113
114 // Init first texture to red
115 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
117 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
118 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
119 glClear(GL_COLOR_BUFFER_BIT);
120 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
121
122 // Init second texture to green
123 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
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[1], 0);
126 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
127 glClear(GL_COLOR_BUFFER_BIT);
128 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
129
130 // Copy in the red texture to the green one.
131 // CopyTexImage should sync the framebuffer attachment change.
132 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
133 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
134 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
135 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
136
137 ASSERT_GL_NO_ERROR();
138 }
139
140 // Test that Framebuffer completeness caching works when color attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteColorAttachment)141 TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
142 {
143 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
144 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
145 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
146 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
147 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
148
149 // Change the texture at color attachment 0 to be non-color-renderable.
150 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
151 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
152 glCheckFramebufferStatus(GL_FRAMEBUFFER));
153
154 ASSERT_GL_NO_ERROR();
155 }
156
157 // Test that caching works when color attachments change with TexStorage.
TEST_P(StateChangeTest,FramebufferIncompleteWithTexStorage)158 TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
159 {
160 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
161
162 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
163 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
165 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
166 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
167
168 // Change the texture at color attachment 0 to be non-color-renderable.
169 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
170 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
171 glCheckFramebufferStatus(GL_FRAMEBUFFER));
172
173 ASSERT_GL_NO_ERROR();
174 }
175
176 // Test that caching works when color attachments change with CompressedTexImage2D.
TEST_P(StateChangeTestES3,FramebufferIncompleteWithCompressedTex)177 TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
178 {
179 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
180 ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
181
182 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
183 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
184 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
185 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
186 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
187
188 // Change the texture at color attachment 0 to be non-color-renderable.
189 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 128, nullptr);
190 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
191 glCheckFramebufferStatus(GL_FRAMEBUFFER));
192
193 ASSERT_GL_NO_ERROR();
194 }
195
196 // Test that caching works when color attachments are deleted.
TEST_P(StateChangeTestES3,FramebufferIncompleteWhenAttachmentDeleted)197 TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
198 {
199 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
200 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
201 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
202 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
203 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
204
205 // Delete the texture at color attachment 0.
206 glDeleteTextures(1, &mTextures[0]);
207 mTextures[0] = 0;
208 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
209 glCheckFramebufferStatus(GL_FRAMEBUFFER));
210
211 ASSERT_GL_NO_ERROR();
212 }
213
214 // Test that Framebuffer completeness caching works when depth attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthAttachment)215 TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
216 {
217 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
218 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
219 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
220 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
221 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
222 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
223 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
224 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
225
226 // Change the texture at color attachment 0 to be non-depth-renderable.
227 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
228 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
229 glCheckFramebufferStatus(GL_FRAMEBUFFER));
230
231 ASSERT_GL_NO_ERROR();
232 }
233
234 // Test that Framebuffer completeness caching works when stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteStencilAttachment)235 TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
236 {
237 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
238 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
239 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
240 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
241 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
242 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
243 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
244 mRenderbuffer);
245 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
246
247 // Change the texture at the stencil attachment to be non-stencil-renderable.
248 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
249 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
250 glCheckFramebufferStatus(GL_FRAMEBUFFER));
251
252 ASSERT_GL_NO_ERROR();
253 }
254
255 // Test that Framebuffer completeness caching works when depth-stencil attachments change.
TEST_P(StateChangeTestES3,FramebufferIncompleteDepthStencilAttachment)256 TEST_P(StateChangeTestES3, FramebufferIncompleteDepthStencilAttachment)
257 {
258 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
259 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
260 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
261 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
262 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
263 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
264 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
265 mRenderbuffer);
266 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
267
268 // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
269 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
270 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
271 glCheckFramebufferStatus(GL_FRAMEBUFFER));
272
273 ASSERT_GL_NO_ERROR();
274 }
275
276 // Test that enabling GL_SAMPLE_ALPHA_TO_COVERAGE doesn't generate errors.
TEST_P(StateChangeTest,AlphaToCoverageEnable)277 TEST_P(StateChangeTest, AlphaToCoverageEnable)
278 {
279 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
280
281 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
282 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
286 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
287
288 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
289
290 // We don't actually care that this does anything, just that it can be enabled without causing
291 // an error.
292 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
293
294 glUseProgram(greenProgram);
295 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
296 ASSERT_GL_NO_ERROR();
297 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
298 }
299
300 const char kSimpleAttributeVS[] = R"(attribute vec2 position;
301 attribute vec4 testAttrib;
302 varying vec4 testVarying;
303 void main()
304 {
305 gl_Position = vec4(position, 0, 1);
306 testVarying = testAttrib;
307 })";
308
309 const char kSimpleAttributeFS[] = R"(precision mediump float;
310 varying vec4 testVarying;
311 void main()
312 {
313 gl_FragColor = testVarying;
314 })";
315
316 // Tests that using a buffered attribute, then disabling it and using current value, works.
TEST_P(StateChangeTest,DisablingBufferedVertexAttribute)317 TEST_P(StateChangeTest, DisablingBufferedVertexAttribute)
318 {
319 ANGLE_GL_PROGRAM(program, kSimpleAttributeVS, kSimpleAttributeFS);
320 glUseProgram(program);
321 GLint attribLoc = glGetAttribLocation(program, "testAttrib");
322 GLint positionLoc = glGetAttribLocation(program, "position");
323 ASSERT_NE(-1, attribLoc);
324 ASSERT_NE(-1, positionLoc);
325
326 // Set up the buffered attribute.
327 std::vector<GLColor> red(6, GLColor::red);
328 GLBuffer attribBuffer;
329 glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
330 glBufferData(GL_ARRAY_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
331 glEnableVertexAttribArray(attribLoc);
332 glVertexAttribPointer(attribLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
333
334 // Also set the current value to green now.
335 glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
336
337 // Set up the position attribute as well.
338 setupQuadVertexBuffer(0.5f, 1.0f);
339 glEnableVertexAttribArray(positionLoc);
340 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
341
342 // Draw with the buffered attribute. Verify red.
343 glDrawArrays(GL_TRIANGLES, 0, 6);
344 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
345
346 // Draw with the disabled "current value attribute". Verify green.
347 glDisableVertexAttribArray(attribLoc);
348 glDrawArrays(GL_TRIANGLES, 0, 6);
349 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
350
351 // Verify setting buffer data on the disabled buffer doesn't change anything.
352 std::vector<GLColor> blue(128, GLColor::blue);
353 glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
354 glBufferData(GL_ARRAY_BUFFER, blue.size() * sizeof(GLColor), blue.data(), GL_STATIC_DRAW);
355 glDrawArrays(GL_TRIANGLES, 0, 6);
356 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
357 }
358
359 // Tests that setting value for a subset of default attributes doesn't affect others.
TEST_P(StateChangeTest,SetCurrentAttribute)360 TEST_P(StateChangeTest, SetCurrentAttribute)
361 {
362 constexpr char kVS[] = R"(attribute vec4 position;
363 attribute mat4 testAttrib; // Note that this generates 4 attributes
364 varying vec4 testVarying;
365 void main (void)
366 {
367 gl_Position = position;
368
369 testVarying = position.y < 0.0 ?
370 position.x < 0.0 ? testAttrib[0] : testAttrib[1] :
371 position.x < 0.0 ? testAttrib[2] : testAttrib[3];
372 })";
373
374 ANGLE_GL_PROGRAM(program, kVS, kSimpleAttributeFS);
375 glUseProgram(program);
376 GLint attribLoc = glGetAttribLocation(program, "testAttrib");
377 GLint positionLoc = glGetAttribLocation(program, "position");
378 ASSERT_NE(-1, attribLoc);
379 ASSERT_NE(-1, positionLoc);
380
381 // Set the current value of two of the test attributes, while leaving the other two as default.
382 glVertexAttrib4f(attribLoc + 1, 0.0f, 1.0f, 0.0f, 1.0f);
383 glVertexAttrib4f(attribLoc + 2, 0.0f, 0.0f, 1.0f, 1.0f);
384
385 // Set up the position attribute.
386 setupQuadVertexBuffer(0.5f, 1.0f);
387 glEnableVertexAttribArray(positionLoc);
388 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
389
390 // Draw and verify the four section in the output:
391 //
392 // +---------------+
393 // | Black | Green |
394 // +-------+-------+
395 // | Blue | Black |
396 // +---------------+
397 //
398 glDrawArrays(GL_TRIANGLES, 0, 6);
399
400 const int w = getWindowWidth();
401 const int h = getWindowHeight();
402 constexpr unsigned int kPixelTolerance = 5u;
403 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, kPixelTolerance);
404 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::green, kPixelTolerance);
405 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::blue, kPixelTolerance);
406 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::black, kPixelTolerance);
407 }
408
409 // Tests that drawing with transform feedback paused, then lines without transform feedback works
410 // without Vulkan validation errors.
TEST_P(StateChangeTestES3,DrawPausedXfbThenNonXfbLines)411 TEST_P(StateChangeTestES3, DrawPausedXfbThenNonXfbLines)
412 {
413 // glTransformFeedbackVaryings for program2 returns GL_INVALID_OPERATION on both Linux and
414 // windows. http://anglebug.com/4265
415 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
416 // http://anglebug.com/5388
417 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
418
419 std::vector<std::string> tfVaryings = {"gl_Position"};
420 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, essl1_shaders::vs::Simple(),
421 essl1_shaders::fs::Blue(), tfVaryings, GL_SEPARATE_ATTRIBS);
422
423 GLBuffer xfbBuffer;
424 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
425 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * sizeof(float[4]), nullptr, GL_STATIC_DRAW);
426
427 GLTransformFeedback xfb;
428 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
429 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
430
431 glUseProgram(program1);
432 glBeginTransformFeedback(GL_TRIANGLES);
433 glPauseTransformFeedback();
434 glDrawArrays(GL_TRIANGLES, 0, 6);
435
436 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
437 glUseProgram(program2);
438 glDrawArrays(GL_LINES, 0, 6);
439 glEndTransformFeedback();
440
441 ASSERT_GL_NO_ERROR();
442 }
443
444 // Tests that vertex attribute value is preserved across context switches.
TEST_P(StateChangeTest,MultiContextVertexAttribute)445 TEST_P(StateChangeTest, MultiContextVertexAttribute)
446 {
447 EGLWindow *window = getEGLWindow();
448 EGLDisplay display = window->getDisplay();
449 EGLConfig config = window->getConfig();
450 EGLSurface surface = window->getSurface();
451 EGLContext context1 = window->getContext();
452
453 // Set up program in primary context
454 ANGLE_GL_PROGRAM(program1, kSimpleAttributeVS, kSimpleAttributeFS);
455 glUseProgram(program1);
456 GLint attribLoc = glGetAttribLocation(program1, "testAttrib");
457 GLint positionLoc = glGetAttribLocation(program1, "position");
458 ASSERT_NE(-1, attribLoc);
459 ASSERT_NE(-1, positionLoc);
460
461 // Set up the position attribute in primary context
462 setupQuadVertexBuffer(0.5f, 1.0f);
463 glEnableVertexAttribArray(positionLoc);
464 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
465
466 // Set primary context attribute to green and draw quad
467 glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
468 glDrawArrays(GL_TRIANGLES, 0, 6);
469 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
470
471 // Set up and switch to secondary context
472 EGLint contextAttributes[] = {
473 EGL_CONTEXT_MAJOR_VERSION_KHR,
474 GetParam().majorVersion,
475 EGL_CONTEXT_MINOR_VERSION_KHR,
476 GetParam().minorVersion,
477 EGL_NONE,
478 };
479 EGLContext context2 = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
480 ASSERT_NE(context2, EGL_NO_CONTEXT);
481 eglMakeCurrent(display, surface, surface, context2);
482
483 // Set up program in secondary context
484 ANGLE_GL_PROGRAM(program2, kSimpleAttributeVS, kSimpleAttributeFS);
485 glUseProgram(program2);
486 ASSERT_EQ(attribLoc, glGetAttribLocation(program2, "testAttrib"));
487 ASSERT_EQ(positionLoc, glGetAttribLocation(program2, "position"));
488
489 // Set up the position attribute in secondary context
490 setupQuadVertexBuffer(0.5f, 1.0f);
491 glEnableVertexAttribArray(positionLoc);
492 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
493
494 // attribLoc current value should be default - (0,0,0,1)
495 glDrawArrays(GL_TRIANGLES, 0, 6);
496 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
497
498 // Restore primary context
499 eglMakeCurrent(display, surface, surface, context1);
500 // ReadPixels to ensure context is switched
501 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
502
503 // Switch to secondary context second time
504 eglMakeCurrent(display, surface, surface, context2);
505 // Check that it still draws black
506 glDrawArrays(GL_TRIANGLES, 0, 6);
507 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
508
509 // Restore primary context second time
510 eglMakeCurrent(display, surface, surface, context1);
511 // Check if it still draws green
512 glDrawArrays(GL_TRIANGLES, 0, 6);
513 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
514
515 // Clean up
516 eglDestroyContext(display, context2);
517 }
518
519 // Ensure that CopyTexSubImage3D syncs framebuffer changes.
TEST_P(StateChangeTestES3,CopyTexSubImage3DSync)520 TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
521 {
522 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
523
524 // Init first texture to red
525 glBindTexture(GL_TEXTURE_3D, mTextures[0]);
526 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
527 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
528 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
529 glClear(GL_COLOR_BUFFER_BIT);
530 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
531
532 // Init second texture to green
533 glBindTexture(GL_TEXTURE_3D, mTextures[1]);
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[1], 0, 0);
536 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
537 glClear(GL_COLOR_BUFFER_BIT);
538 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
539
540 // Copy in the red texture to the green one.
541 // CopyTexImage should sync the framebuffer attachment change.
542 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
543 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
544 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
545 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
546
547 ASSERT_GL_NO_ERROR();
548 }
549
550 // Ensure that BlitFramebuffer syncs framebuffer changes.
TEST_P(StateChangeTestES3,BlitFramebufferSync)551 TEST_P(StateChangeTestES3, BlitFramebufferSync)
552 {
553 // http://anglebug.com/4092
554 ANGLE_SKIP_TEST_IF(IsVulkan());
555 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
556
557 // Init first texture to red
558 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
559 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
560 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
561 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
562 glClear(GL_COLOR_BUFFER_BIT);
563 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
564
565 // Init second texture to green
566 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
567 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
568 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
569 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
570 glClear(GL_COLOR_BUFFER_BIT);
571 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
572
573 // Change to the red textures and blit.
574 // BlitFramebuffer should sync the framebuffer attachment change.
575 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
576 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
577 0);
578 glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
579 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
580 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
581
582 ASSERT_GL_NO_ERROR();
583 }
584
585 // Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
TEST_P(StateChangeTestES3,ReadBufferAndDrawBuffersSync)586 TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
587 {
588 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
589
590 // Initialize two FBO attachments
591 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
592 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
593 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
594 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
595 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
596 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
597
598 // Clear first attachment to red
599 GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
600 glDrawBuffers(2, bufs1);
601 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
602 glClear(GL_COLOR_BUFFER_BIT);
603
604 // Clear second texture to green
605 GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
606 glDrawBuffers(2, bufs2);
607 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
608 glClear(GL_COLOR_BUFFER_BIT);
609
610 // Verify first attachment is red and second is green
611 glReadBuffer(GL_COLOR_ATTACHMENT1);
612 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
613
614 glReadBuffer(GL_COLOR_ATTACHMENT0);
615 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
616
617 ASSERT_GL_NO_ERROR();
618 }
619
620 // Tests calling invalidate on incomplete framebuffers after switching attachments.
621 // Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
TEST_P(StateChangeTestES3,IncompleteRenderbufferAttachmentInvalidateSync)622 TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
623 {
624 // http://anglebug.com/4092
625 ANGLE_SKIP_TEST_IF(IsVulkan());
626 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
627 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
628 GLint samples = 0;
629 glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
630 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
631 ASSERT_GL_NO_ERROR();
632
633 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
634 // attached renderbuffer
635 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
636 glCheckFramebufferStatus(GL_FRAMEBUFFER));
637 GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
638 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
639 ASSERT_GL_NO_ERROR();
640
641 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
642 getWindowWidth(), getWindowHeight());
643 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
644 glClear(GL_COLOR_BUFFER_BIT);
645 ASSERT_GL_NO_ERROR();
646
647 GLRenderbuffer renderbuf;
648
649 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
650 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
651 renderbuf.get());
652 ASSERT_GL_NO_ERROR();
653
654 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
655 // attached renderbuffer
656 // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
657 GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
658 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
659
660 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
661 GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
662 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
663 glClear(GL_DEPTH_BUFFER_BIT);
664 ASSERT_GL_NO_ERROR();
665 }
666
667 class StateChangeRenderTest : public StateChangeTest
668 {
669 protected:
StateChangeRenderTest()670 StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
671
testSetUp()672 void testSetUp() override
673 {
674 StateChangeTest::testSetUp();
675
676 constexpr char kVS[] =
677 "attribute vec2 position;\n"
678 "void main() {\n"
679 " gl_Position = vec4(position, 0, 1);\n"
680 "}";
681 constexpr char kFS[] =
682 "uniform highp vec4 uniformColor;\n"
683 "void main() {\n"
684 " gl_FragColor = uniformColor;\n"
685 "}";
686
687 mProgram = CompileProgram(kVS, kFS);
688 ASSERT_NE(0u, mProgram);
689
690 glGenRenderbuffers(1, &mRenderbuffer);
691 }
692
testTearDown()693 void testTearDown() override
694 {
695 glDeleteProgram(mProgram);
696 glDeleteRenderbuffers(1, &mRenderbuffer);
697
698 StateChangeTest::testTearDown();
699 }
700
setUniformColor(const GLColor & color)701 void setUniformColor(const GLColor &color)
702 {
703 glUseProgram(mProgram);
704 const Vector4 &normalizedColor = color.toNormalizedVector();
705 GLint uniformLocation = glGetUniformLocation(mProgram, "uniformColor");
706 ASSERT_NE(-1, uniformLocation);
707 glUniform4fv(uniformLocation, 1, normalizedColor.data());
708 }
709
710 GLuint mProgram;
711 GLuint mRenderbuffer;
712 };
713
714 // Test that re-creating a currently attached texture works as expected.
TEST_P(StateChangeRenderTest,RecreateTexture)715 TEST_P(StateChangeRenderTest, RecreateTexture)
716 {
717 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
718
719 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
720 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
721 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
722
723 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
724 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
725
726 // Draw with red to the FBO.
727 GLColor red(255, 0, 0, 255);
728 setUniformColor(red);
729 drawQuad(mProgram, "position", 0.5f);
730 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
731
732 // Recreate the texture with green.
733 GLColor green(0, 255, 0, 255);
734 std::vector<GLColor> greenPixels(32 * 32, green);
735 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
736 greenPixels.data());
737 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
738
739 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
740 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
741
742 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
743 GLColor blue(0, 0, 255, 255);
744 setUniformColor(blue);
745 drawQuad(mProgram, "position", 0.5f);
746 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
747
748 EXPECT_GL_NO_ERROR();
749 }
750
751 // Test that re-creating a currently attached renderbuffer works as expected.
TEST_P(StateChangeRenderTest,RecreateRenderbuffer)752 TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
753 {
754 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
755
756 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
757 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
758 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
759
760 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
761 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
762
763 // Draw with red to the FBO.
764 setUniformColor(GLColor::red);
765 drawQuad(mProgram, "position", 0.5f);
766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
767
768 // Recreate the renderbuffer and clear to green.
769 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
770 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
771 glClear(GL_COLOR_BUFFER_BIT);
772 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
773
774 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
775 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
776
777 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
778 setUniformColor(GLColor::blue);
779 drawQuad(mProgram, "position", 0.5f);
780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
781
782 EXPECT_GL_NO_ERROR();
783 }
784
785 // Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
TEST_P(StateChangeRenderTest,GenerateMipmap)786 TEST_P(StateChangeRenderTest, GenerateMipmap)
787 {
788 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
789
790 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
791 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
792 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
793 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
794 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
795
796 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
797 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
798
799 // Draw once to set the RenderTarget in D3D11
800 GLColor red(255, 0, 0, 255);
801 setUniformColor(red);
802 drawQuad(mProgram, "position", 0.5f);
803 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
804
805 // This will trigger the texture to be re-created on FL9_3.
806 glGenerateMipmap(GL_TEXTURE_2D);
807
808 // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
809 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
810
811 // Now ensure we don't have a stale render target.
812 GLColor blue(0, 0, 255, 255);
813 setUniformColor(blue);
814 drawQuad(mProgram, "position", 0.5f);
815 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
816
817 EXPECT_GL_NO_ERROR();
818 }
819
820 // Tests that gl_DepthRange syncs correctly after a change.
TEST_P(StateChangeRenderTest,DepthRangeUpdates)821 TEST_P(StateChangeRenderTest, DepthRangeUpdates)
822 {
823 constexpr char kFragCoordShader[] = R"(void main()
824 {
825 if (gl_DepthRange.near == 0.2)
826 {
827 gl_FragColor = vec4(1, 0, 0, 1);
828 }
829 else if (gl_DepthRange.near == 0.5)
830 {
831 gl_FragColor = vec4(0, 1, 0, 1);
832 }
833 else
834 {
835 gl_FragColor = vec4(0, 0, 1, 1);
836 }
837 })";
838
839 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
840 glUseProgram(program);
841
842 const auto &quadVertices = GetQuadVertices();
843
844 ASSERT_EQ(0, glGetAttribLocation(program, essl1_shaders::PositionAttrib()));
845
846 GLBuffer vertexBuffer;
847 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
848 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
849 quadVertices.data(), GL_STATIC_DRAW);
850 glVertexAttribPointer(0u, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
851 glEnableVertexAttribArray(0u);
852
853 // First, clear.
854 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
855 glClear(GL_COLOR_BUFFER_BIT);
856
857 // Draw to left half viewport with a first depth range.
858 glDepthRangef(0.2f, 1.0f);
859 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
860 glDrawArrays(GL_TRIANGLES, 0, 6);
861 ASSERT_GL_NO_ERROR();
862
863 // Draw to right half viewport with a second depth range.
864 glDepthRangef(0.5f, 1.0f);
865 glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
866 glDrawArrays(GL_TRIANGLES, 0, 6);
867 ASSERT_GL_NO_ERROR();
868
869 // Verify left half of the framebuffer is red and right half is green.
870 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() / 2, getWindowHeight(), GLColor::red);
871 EXPECT_PIXEL_RECT_EQ(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight(),
872 GLColor::green);
873 }
874
875 class StateChangeRenderTestES3 : public StateChangeRenderTest
876 {};
877
TEST_P(StateChangeRenderTestES3,InvalidateNonCurrentFramebuffer)878 TEST_P(StateChangeRenderTestES3, InvalidateNonCurrentFramebuffer)
879 {
880 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
882 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
883 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
884 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
885 glBindTexture(GL_TEXTURE_2D, 0);
886 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
887 ASSERT_GL_NO_ERROR();
888
889 // Draw with red to the FBO.
890 GLColor red(255, 0, 0, 255);
891 setUniformColor(red);
892 drawQuad(mProgram, "position", 0.5f);
893 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
894
895 // Go back to default framebuffer, draw green
896 glBindFramebuffer(GL_FRAMEBUFFER, 0);
897 GLColor green(0, 255, 0, 255);
898 setUniformColor(green);
899 drawQuad(mProgram, "position", 0.5f);
900 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
901
902 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
903
904 // Invalidate color buffer of FBO
905 GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
906 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
907 ASSERT_GL_NO_ERROR();
908
909 // Verify drawing blue gives blue.
910 GLColor blue(0, 0, 255, 255);
911 setUniformColor(blue);
912 drawQuad(mProgram, "position", 0.5f);
913 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
914 }
915
916 // Tests that D3D11 dirty bit updates don't forget about BufferSubData attrib updates.
TEST_P(StateChangeTest,VertexBufferUpdatedAfterDraw)917 TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
918 {
919 constexpr char kVS[] =
920 "attribute vec2 position;\n"
921 "attribute vec4 color;\n"
922 "varying vec4 outcolor;\n"
923 "void main()\n"
924 "{\n"
925 " gl_Position = vec4(position, 0, 1);\n"
926 " outcolor = color;\n"
927 "}";
928 constexpr char kFS[] =
929 "varying mediump vec4 outcolor;\n"
930 "void main()\n"
931 "{\n"
932 " gl_FragColor = outcolor;\n"
933 "}";
934
935 ANGLE_GL_PROGRAM(program, kVS, kFS);
936 glUseProgram(program);
937
938 GLint colorLoc = glGetAttribLocation(program, "color");
939 ASSERT_NE(-1, colorLoc);
940 GLint positionLoc = glGetAttribLocation(program, "position");
941 ASSERT_NE(-1, positionLoc);
942
943 setupQuadVertexBuffer(0.5f, 1.0f);
944 glEnableVertexAttribArray(positionLoc);
945 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
946
947 GLBuffer colorBuf;
948 glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
949 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
950 glEnableVertexAttribArray(colorLoc);
951
952 // Fill with green.
953 std::vector<GLColor> colorData(6, GLColor::green);
954 glBufferData(GL_ARRAY_BUFFER, colorData.size() * sizeof(GLColor), colorData.data(),
955 GL_STATIC_DRAW);
956
957 // Draw, expect green.
958 glDrawArrays(GL_TRIANGLES, 0, 6);
959 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
960 ASSERT_GL_NO_ERROR();
961
962 // Update buffer with red.
963 std::fill(colorData.begin(), colorData.end(), GLColor::red);
964 glBufferSubData(GL_ARRAY_BUFFER, 0, colorData.size() * sizeof(GLColor), colorData.data());
965
966 // Draw, expect red.
967 glDrawArrays(GL_TRIANGLES, 0, 6);
968 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
969 ASSERT_GL_NO_ERROR();
970 }
971
972 // Tests that drawing after flush without any state change works.
TEST_P(StateChangeTestES3,DrawAfterFlushWithNoStateChange)973 TEST_P(StateChangeTestES3, DrawAfterFlushWithNoStateChange)
974 {
975 // Draw (0.125, 0.25, 0.5, 0.5) once, using additive blend
976 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
977 glUseProgram(drawColor);
978
979 GLint colorUniformLocation =
980 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
981 ASSERT_NE(colorUniformLocation, -1);
982
983 GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
984 ASSERT_NE(-1, positionLocation);
985
986 // Setup VAO
987 const auto &quadVertices = GetQuadVertices();
988
989 GLBuffer vertexBuffer;
990 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
991 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
992
993 GLVertexArray vertexArray;
994 glBindVertexArray(vertexArray);
995 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
996 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
997 glEnableVertexAttribArray(positionLocation);
998 ASSERT_GL_NO_ERROR();
999
1000 // Clear and draw
1001 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1002 glClear(GL_COLOR_BUFFER_BIT);
1003
1004 glEnable(GL_BLEND);
1005 glBlendFunc(GL_ONE, GL_ONE);
1006
1007 glUniform4f(colorUniformLocation, 0.125f, 0.25f, 0.5f, 0.5f);
1008 glDrawArrays(GL_TRIANGLES, 0, 6);
1009 ASSERT_GL_NO_ERROR();
1010
1011 // Make sure the work is submitted.
1012 glFinish();
1013
1014 // Draw again with no state change
1015 glDrawArrays(GL_TRIANGLES, 0, 6);
1016 ASSERT_GL_NO_ERROR();
1017
1018 // Make sure the pixels have the correct colors.
1019 const int h = getWindowHeight() - 1;
1020 const int w = getWindowWidth() - 1;
1021 const GLColor kExpected(63, 127, 255, 255);
1022
1023 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1024 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, kExpected, 1);
1025 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, kExpected, 1);
1026 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, kExpected, 1);
1027 }
1028
1029 // Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
TEST_P(StateChangeTestES3,VertexArrayObjectAndDisabledAttributes)1030 TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes)
1031 {
1032 constexpr char kSingleVS[] = "attribute vec4 position; void main() { gl_Position = position; }";
1033 constexpr char kSingleFS[] = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
1034 ANGLE_GL_PROGRAM(singleProgram, kSingleVS, kSingleFS);
1035
1036 constexpr char kDualVS[] =
1037 "#version 300 es\n"
1038 "in vec4 position;\n"
1039 "in vec4 color;\n"
1040 "out vec4 varyColor;\n"
1041 "void main()\n"
1042 "{\n"
1043 " gl_Position = position;\n"
1044 " varyColor = color;\n"
1045 "}";
1046 constexpr char kDualFS[] =
1047 "#version 300 es\n"
1048 "precision mediump float;\n"
1049 "in vec4 varyColor;\n"
1050 "out vec4 colorOut;\n"
1051 "void main()\n"
1052 "{\n"
1053 " colorOut = varyColor;\n"
1054 "}";
1055
1056 ANGLE_GL_PROGRAM(dualProgram, kDualVS, kDualFS);
1057
1058 // Force consistent attribute locations
1059 constexpr GLint positionLocation = 0;
1060 constexpr GLint colorLocation = 1;
1061
1062 glBindAttribLocation(singleProgram, positionLocation, "position");
1063 glBindAttribLocation(dualProgram, positionLocation, "position");
1064 glBindAttribLocation(dualProgram, colorLocation, "color");
1065
1066 {
1067 glLinkProgram(singleProgram);
1068 GLint linkStatus;
1069 glGetProgramiv(singleProgram, GL_LINK_STATUS, &linkStatus);
1070 ASSERT_NE(linkStatus, 0);
1071 }
1072
1073 {
1074 glLinkProgram(dualProgram);
1075 GLint linkStatus;
1076 glGetProgramiv(dualProgram, GL_LINK_STATUS, &linkStatus);
1077 ASSERT_NE(linkStatus, 0);
1078 }
1079
1080 glUseProgram(singleProgram);
1081
1082 // Initialize position vertex buffer.
1083 const auto &quadVertices = GetQuadVertices();
1084
1085 GLBuffer vertexBuffer;
1086 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1087 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
1088
1089 // Initialize a VAO. Draw with single program.
1090 GLVertexArray vertexArray;
1091 glBindVertexArray(vertexArray);
1092 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1093 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1094 glEnableVertexAttribArray(positionLocation);
1095
1096 // Should draw red.
1097 glDrawArrays(GL_TRIANGLES, 0, 6);
1098 ASSERT_GL_NO_ERROR();
1099 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1100
1101 // Draw with a green buffer attribute, without the VAO.
1102 glBindVertexArray(0);
1103 glUseProgram(dualProgram);
1104 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1105 glEnableVertexAttribArray(positionLocation);
1106
1107 std::vector<GLColor> greenColors(6, GLColor::green);
1108 GLBuffer greenBuffer;
1109 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
1110 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, greenColors.data(), GL_STATIC_DRAW);
1111
1112 glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4, nullptr);
1113 glEnableVertexAttribArray(colorLocation);
1114
1115 glDrawArrays(GL_TRIANGLES, 0, 6);
1116 ASSERT_GL_NO_ERROR();
1117 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1118
1119 // Re-bind VAO and try to draw with different program, without changing state.
1120 // Should draw black since current value is not initialized.
1121 glBindVertexArray(vertexArray);
1122 glDrawArrays(GL_TRIANGLES, 0, 6);
1123 ASSERT_GL_NO_ERROR();
1124 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1125 }
1126
1127 const char kSamplerMetadataVertexShader0[] = R"(#version 300 es
1128 precision mediump float;
1129 out vec4 color;
1130 uniform sampler2D texture;
1131 void main()
1132 {
1133 vec2 size = vec2(textureSize(texture, 0));
1134 color = size.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1135 vec2 pos = vec2(0.0);
1136 switch (gl_VertexID) {
1137 case 0: pos = vec2(-1.0, -1.0); break;
1138 case 1: pos = vec2(3.0, -1.0); break;
1139 case 2: pos = vec2(-1.0, 3.0); break;
1140 };
1141 gl_Position = vec4(pos, 0.0, 1.0);
1142 })";
1143
1144 const char kSamplerMetadataVertexShader1[] = R"(#version 300 es
1145 precision mediump float;
1146 out vec4 color;
1147 uniform sampler2D texture1;
1148 uniform sampler2D texture2;
1149 void main()
1150 {
1151 vec2 size1 = vec2(textureSize(texture1, 0));
1152 vec2 size2 = vec2(textureSize(texture2, 0));
1153 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);
1154 vec2 pos = vec2(0.0);
1155 switch (gl_VertexID) {
1156 case 0: pos = vec2(-1.0, -1.0); break;
1157 case 1: pos = vec2(3.0, -1.0); break;
1158 case 2: pos = vec2(-1.0, 3.0); break;
1159 };
1160 gl_Position = vec4(pos, 0.0, 1.0);
1161 })";
1162
1163 const char kSamplerMetadataFragmentShader[] = R"(#version 300 es
1164 precision mediump float;
1165 in vec4 color;
1166 out vec4 result;
1167 void main()
1168 {
1169 result = color;
1170 })";
1171
1172 // Tests that changing an active program invalidates the sampler metadata properly.
TEST_P(StateChangeTestES3,SamplerMetadataUpdateOnSetProgram)1173 TEST_P(StateChangeTestES3, SamplerMetadataUpdateOnSetProgram)
1174 {
1175 // http://anglebug.com/4092
1176 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1177 // TODO(anglebug.com/5491) Appears as though there's something wrong with textureSize on iOS
1178 // unrelated to switching programs.
1179 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
1180 GLVertexArray vertexArray;
1181 glBindVertexArray(vertexArray);
1182
1183 // Create a simple framebuffer.
1184 GLTexture texture1, texture2;
1185 glActiveTexture(GL_TEXTURE0);
1186 glBindTexture(GL_TEXTURE_2D, texture1);
1187 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1188 glActiveTexture(GL_TEXTURE1);
1189 glBindTexture(GL_TEXTURE_2D, texture2);
1190 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1191
1192 // Create 2 shader programs differing only in the number of active samplers.
1193 ANGLE_GL_PROGRAM(program1, kSamplerMetadataVertexShader0, kSamplerMetadataFragmentShader);
1194 glUseProgram(program1);
1195 glUniform1i(glGetUniformLocation(program1, "texture"), 0);
1196 ANGLE_GL_PROGRAM(program2, kSamplerMetadataVertexShader1, kSamplerMetadataFragmentShader);
1197 glUseProgram(program2);
1198 glUniform1i(glGetUniformLocation(program2, "texture1"), 0);
1199 glUniform1i(glGetUniformLocation(program2, "texture2"), 0);
1200
1201 // Draw a solid green color to the framebuffer.
1202 glUseProgram(program1);
1203 glDrawArrays(GL_TRIANGLES, 0, 3);
1204 // Test that our first program is good.
1205 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1206
1207 // Bind a different program that uses more samplers.
1208 // Draw another quad that depends on the sampler metadata.
1209 glUseProgram(program2);
1210 glDrawArrays(GL_TRIANGLES, 0, 3);
1211 // Flush via ReadPixels and check that it's still green.
1212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1213
1214 ASSERT_GL_NO_ERROR();
1215 }
1216
1217 // Tests that redefining Buffer storage syncs with the Transform Feedback object.
TEST_P(StateChangeTestES3,RedefineTransformFeedbackBuffer)1218 TEST_P(StateChangeTestES3, RedefineTransformFeedbackBuffer)
1219 {
1220 // http://anglebug.com/4092
1221 ANGLE_SKIP_TEST_IF(IsVulkan());
1222 // Create the most simple program possible - simple a passthrough for a float attribute.
1223 constexpr char kVertexShader[] = R"(#version 300 es
1224 in float valueIn;
1225 out float valueOut;
1226 void main()
1227 {
1228 gl_Position = vec4(0, 0, 0, 0);
1229 valueOut = valueIn;
1230 })";
1231
1232 constexpr char kFragmentShader[] = R"(#version 300 es
1233 out mediump float unused;
1234 void main()
1235 {
1236 unused = 1.0;
1237 })";
1238
1239 std::vector<std::string> tfVaryings = {"valueOut"};
1240 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, kVertexShader, kFragmentShader, tfVaryings,
1241 GL_SEPARATE_ATTRIBS);
1242 glUseProgram(program);
1243
1244 GLint attribLoc = glGetAttribLocation(program, "valueIn");
1245 ASSERT_NE(-1, attribLoc);
1246
1247 // Disable rasterization - we're not interested in the framebuffer.
1248 glEnable(GL_RASTERIZER_DISCARD);
1249
1250 // Initialize a float vertex buffer with 1.0.
1251 std::vector<GLfloat> data1(16, 1.0);
1252 GLsizei size1 = static_cast<GLsizei>(sizeof(GLfloat) * data1.size());
1253
1254 GLBuffer vertexBuffer;
1255 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1256 glBufferData(GL_ARRAY_BUFFER, size1, data1.data(), GL_STATIC_DRAW);
1257 glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1258 glEnableVertexAttribArray(attribLoc);
1259
1260 ASSERT_GL_NO_ERROR();
1261
1262 // Initialize a same-sized XFB buffer.
1263 GLBuffer xfbBuffer;
1264 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1265 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size1, nullptr, GL_STATIC_DRAW);
1266
1267 // Draw with XFB enabled.
1268 GLTransformFeedback xfb;
1269 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1270 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1271
1272 glBeginTransformFeedback(GL_POINTS);
1273 glDrawArrays(GL_POINTS, 0, 16);
1274 glEndTransformFeedback();
1275
1276 ASSERT_GL_NO_ERROR();
1277
1278 // Verify the XFB stage caught the 1.0 attribute values.
1279 void *mapped1 = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size1, GL_MAP_READ_BIT);
1280 GLfloat *asFloat1 = reinterpret_cast<GLfloat *>(mapped1);
1281 std::vector<GLfloat> actualData1(asFloat1, asFloat1 + data1.size());
1282 EXPECT_EQ(data1, actualData1);
1283 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1284
1285 // Now, reinitialize the XFB buffer to a larger size, and draw with 2.0.
1286 std::vector<GLfloat> data2(128, 2.0);
1287 const GLsizei size2 = static_cast<GLsizei>(sizeof(GLfloat) * data2.size());
1288 glBufferData(GL_ARRAY_BUFFER, size2, data2.data(), GL_STATIC_DRAW);
1289 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size2, nullptr, GL_STATIC_DRAW);
1290
1291 glBeginTransformFeedback(GL_POINTS);
1292 glDrawArrays(GL_POINTS, 0, 128);
1293 glEndTransformFeedback();
1294
1295 ASSERT_GL_NO_ERROR();
1296
1297 // Verify the XFB stage caught the 2.0 attribute values.
1298 void *mapped2 = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size2, GL_MAP_READ_BIT);
1299 GLfloat *asFloat2 = reinterpret_cast<GLfloat *>(mapped2);
1300 std::vector<GLfloat> actualData2(asFloat2, asFloat2 + data2.size());
1301 EXPECT_EQ(data2, actualData2);
1302 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1303 }
1304
1305 // Simple state change tests for line loop drawing. There is some very specific handling of line
1306 // line loops in Vulkan and we need to test switching between drawElements and drawArrays calls to
1307 // validate every edge cases.
1308 class LineLoopStateChangeTest : public StateChangeTest
1309 {
1310 protected:
LineLoopStateChangeTest()1311 LineLoopStateChangeTest()
1312 {
1313 setWindowWidth(32);
1314 setWindowHeight(32);
1315 setConfigRedBits(8);
1316 setConfigGreenBits(8);
1317 setConfigBlueBits(8);
1318 setConfigAlphaBits(8);
1319 }
1320
validateSquareAndHourglass() const1321 void validateSquareAndHourglass() const
1322 {
1323 ASSERT_GL_NO_ERROR();
1324
1325 int quarterWidth = getWindowWidth() / 4;
1326 int quarterHeight = getWindowHeight() / 4;
1327
1328 // Bottom left
1329 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::blue);
1330
1331 // Top left
1332 EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::blue);
1333
1334 // Top right
1335 // The last pixel isn't filled on a line loop so we check the pixel right before.
1336 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::blue);
1337
1338 // dead center to validate the hourglass.
1339 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight * 2, GLColor::blue);
1340
1341 // Verify line is closed between the 2 last vertices
1342 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::blue);
1343 }
1344 };
1345
1346 // Draw an hourglass with a drawElements call followed by a square with drawArrays.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawArrays)1347 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
1348 {
1349 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1350 glUseProgram(program);
1351
1352 // We expect to draw a square with these 4 vertices with a drawArray call.
1353 std::vector<Vector3> vertices;
1354 CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1355 getWindowHeight(), &vertices);
1356
1357 // If we use these indices to draw however, we should be drawing an hourglass.
1358 auto indices = std::vector<GLushort>{0, 2, 1, 3};
1359
1360 GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1361 ASSERT_NE(-1, mPositionLocation);
1362
1363 GLBuffer vertexBuffer;
1364 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1365 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1366 GL_STATIC_DRAW);
1367
1368 GLBuffer indexBuffer;
1369 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1370 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1371 GL_STATIC_DRAW);
1372
1373 glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1374 glEnableVertexAttribArray(mPositionLocation);
1375 glClear(GL_COLOR_BUFFER_BIT);
1376 glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr); // hourglass
1377 glDrawArrays(GL_LINE_LOOP, 0, 4); // square
1378 glDisableVertexAttribArray(mPositionLocation);
1379
1380 validateSquareAndHourglass();
1381 }
1382
1383 // Draw line loop using a drawArrays followed by an hourglass with drawElements.
TEST_P(LineLoopStateChangeTest,DrawArraysThenDrawElements)1384 TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
1385 {
1386 // http://anglebug.com/2856: Seems to fail on older drivers and pass on newer.
1387 // Tested failing on 18.3.3 and passing on 18.9.2.
1388 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
1389
1390 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1391 glUseProgram(program);
1392
1393 // We expect to draw a square with these 4 vertices with a drawArray call.
1394 std::vector<Vector3> vertices;
1395 CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1396 getWindowHeight(), &vertices);
1397
1398 // If we use these indices to draw however, we should be drawing an hourglass.
1399 auto indices = std::vector<GLushort>{0, 2, 1, 3};
1400
1401 GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1402 ASSERT_NE(-1, mPositionLocation);
1403
1404 GLBuffer vertexBuffer;
1405 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1406 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1407 GL_STATIC_DRAW);
1408
1409 GLBuffer indexBuffer;
1410 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1411 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1412 GL_STATIC_DRAW);
1413
1414 glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1415 glEnableVertexAttribArray(mPositionLocation);
1416 glClear(GL_COLOR_BUFFER_BIT);
1417 glDrawArrays(GL_LINE_LOOP, 0, 4); // square
1418 glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr); // hourglass
1419 glDisableVertexAttribArray(mPositionLocation);
1420
1421 validateSquareAndHourglass();
1422 }
1423
1424 // Draw a triangle with a drawElements call and a non-zero offset and draw the same
1425 // triangle with the same offset again followed by a line loop with drawElements.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawElements)1426 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawElements)
1427 {
1428 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1429
1430 glUseProgram(program);
1431
1432 // Background Red color
1433 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1434 glClear(GL_COLOR_BUFFER_BIT);
1435
1436 // We expect to draw a triangle with the last three points on the bottom right,
1437 // draw with LineLoop, and then draw a triangle with the same non-zero offset.
1438 auto vertices = std::vector<Vector3>{
1439 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1440
1441 auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1442
1443 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1444 ASSERT_NE(-1, positionLocation);
1445
1446 GLBuffer indexBuffer;
1447 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1448 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1449 GL_STATIC_DRAW);
1450
1451 GLBuffer vertexBuffer;
1452 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1453 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1454 GL_STATIC_DRAW);
1455
1456 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1457 glEnableVertexAttribArray(positionLocation);
1458
1459 // Draw a triangle with a non-zero offset on the bottom right.
1460 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1461
1462 // Draw with LineLoop.
1463 glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, nullptr);
1464
1465 // Draw the triangle again with the same offset.
1466 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1467
1468 glDisableVertexAttribArray(positionLocation);
1469
1470 ASSERT_GL_NO_ERROR();
1471
1472 int quarterWidth = getWindowWidth() / 4;
1473 int quarterHeight = getWindowHeight() / 4;
1474
1475 // Validate the top left point's color.
1476 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::blue);
1477
1478 // Validate the triangle is drawn on the bottom right.
1479 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1480
1481 // Validate the triangle is NOT on the top left part.
1482 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1483 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1484 }
1485
1486 // Simple state change tests, primarily focused on basic object lifetime and dependency management
1487 // with back-ends that don't support that automatically (i.e. Vulkan).
1488 class SimpleStateChangeTest : public ANGLETest
1489 {
1490 protected:
1491 static constexpr int kWindowSize = 64;
1492
SimpleStateChangeTest()1493 SimpleStateChangeTest()
1494 {
1495 setWindowWidth(kWindowSize);
1496 setWindowHeight(kWindowSize);
1497 setConfigRedBits(8);
1498 setConfigGreenBits(8);
1499 setConfigBlueBits(8);
1500 setConfigAlphaBits(8);
1501 }
1502
1503 void simpleDrawWithBuffer(GLBuffer *buffer);
1504 void simpleDrawWithColor(const GLColor &color);
1505
1506 using UpdateFunc = std::function<void(GLenum, GLTexture *, GLint, GLint, const GLColor &)>;
1507 void updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc);
1508 void bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture);
1509 void drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty);
1510 };
1511
1512 class SimpleStateChangeTestES3 : public SimpleStateChangeTest
1513 {
1514 protected:
blendAndVerifyColor(const GLColor32F blendColor,const GLColor expectedColor)1515 void blendAndVerifyColor(const GLColor32F blendColor, const GLColor expectedColor)
1516 {
1517 glEnable(GL_BLEND);
1518 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1519 EXPECT_GL_NO_ERROR();
1520
1521 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1522 glUseProgram(program);
1523
1524 GLint colorUniformLocation =
1525 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1526 ASSERT_NE(colorUniformLocation, -1);
1527
1528 glUniform4f(colorUniformLocation, blendColor.R, blendColor.G, blendColor.B, blendColor.A);
1529 EXPECT_GL_NO_ERROR();
1530
1531 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1532 EXPECT_GL_NO_ERROR();
1533 EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 1);
1534 }
1535 };
1536
1537 class SimpleStateChangeTestES31 : public SimpleStateChangeTestES3
1538 {};
1539
1540 class SimpleStateChangeTestComputeES31 : public SimpleStateChangeTest
1541 {
1542 protected:
testSetUp()1543 void testSetUp() override
1544 {
1545 glGenFramebuffers(1, &mFramebuffer);
1546 glGenTextures(1, &mTexture);
1547
1548 glBindTexture(GL_TEXTURE_2D, mTexture);
1549 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
1550 EXPECT_GL_NO_ERROR();
1551
1552 constexpr char kCS[] = R"(#version 310 es
1553 layout(local_size_x=2, local_size_y=2) in;
1554 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
1555 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
1556 void main()
1557 {
1558 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1559 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
1560 })";
1561
1562 mProgram = CompileComputeProgram(kCS);
1563 ASSERT_NE(mProgram, 0u);
1564
1565 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1566
1567 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
1568 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture,
1569 0);
1570
1571 ASSERT_GL_NO_ERROR();
1572 }
1573
testTearDown()1574 void testTearDown() override
1575 {
1576 if (mFramebuffer != 0)
1577 {
1578 glDeleteFramebuffers(1, &mFramebuffer);
1579 mFramebuffer = 0;
1580 }
1581
1582 if (mTexture != 0)
1583 {
1584 glDeleteTextures(1, &mTexture);
1585 mTexture = 0;
1586 }
1587 glDeleteProgram(mProgram);
1588 }
1589
1590 GLuint mProgram;
1591 GLuint mFramebuffer = 0;
1592 GLuint mTexture = 0;
1593 };
1594
1595 class ImageES31PPO
1596 {
1597 protected:
ImageES31PPO()1598 ImageES31PPO() : mComputeProg(0), mPipeline(0) {}
1599
bindProgramPipeline(const GLchar * computeString)1600 void bindProgramPipeline(const GLchar *computeString)
1601 {
1602 mComputeProg = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &computeString);
1603 ASSERT_NE(mComputeProg, 0u);
1604
1605 // Generate a program pipeline and attach the programs to their respective stages
1606 glGenProgramPipelines(1, &mPipeline);
1607 EXPECT_GL_NO_ERROR();
1608 glUseProgramStages(mPipeline, GL_COMPUTE_SHADER_BIT, mComputeProg);
1609 EXPECT_GL_NO_ERROR();
1610 glBindProgramPipeline(mPipeline);
1611 EXPECT_GL_NO_ERROR();
1612 glActiveShaderProgram(mPipeline, mComputeProg);
1613 EXPECT_GL_NO_ERROR();
1614 }
1615
1616 GLuint mComputeProg;
1617 GLuint mPipeline;
1618 };
1619
1620 class SimpleStateChangeTestComputeES31PPO : public ImageES31PPO, public SimpleStateChangeTest
1621 {
1622 protected:
SimpleStateChangeTestComputeES31PPO()1623 SimpleStateChangeTestComputeES31PPO() : ImageES31PPO(), SimpleStateChangeTest() {}
1624
testTearDown()1625 void testTearDown() override
1626 {
1627 if (mFramebuffer != 0)
1628 {
1629 glDeleteFramebuffers(1, &mFramebuffer);
1630 mFramebuffer = 0;
1631 }
1632
1633 if (mTexture != 0)
1634 {
1635 glDeleteTextures(1, &mTexture);
1636 mTexture = 0;
1637 }
1638 glDeleteProgramPipelines(1, &mPipeline);
1639 }
1640
1641 GLuint mFramebuffer = 0;
1642 GLuint mTexture = 0;
1643 };
1644
1645 constexpr char kSimpleVertexShader[] = R"(attribute vec2 position;
1646 attribute vec4 color;
1647 varying vec4 vColor;
1648 void main()
1649 {
1650 gl_Position = vec4(position, 0, 1);
1651 vColor = color;
1652 }
1653 )";
1654
1655 constexpr char kSimpleFragmentShader[] = R"(precision mediump float;
1656 varying vec4 vColor;
1657 void main()
1658 {
1659 gl_FragColor = vColor;
1660 }
1661 )";
1662
simpleDrawWithBuffer(GLBuffer * buffer)1663 void SimpleStateChangeTest::simpleDrawWithBuffer(GLBuffer *buffer)
1664 {
1665 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
1666 glUseProgram(program);
1667
1668 GLint colorLoc = glGetAttribLocation(program, "color");
1669 ASSERT_NE(-1, colorLoc);
1670
1671 glBindBuffer(GL_ARRAY_BUFFER, *buffer);
1672 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1673 glEnableVertexAttribArray(colorLoc);
1674
1675 drawQuad(program, "position", 0.5f, 1.0f, true);
1676 ASSERT_GL_NO_ERROR();
1677 }
1678
simpleDrawWithColor(const GLColor & color)1679 void SimpleStateChangeTest::simpleDrawWithColor(const GLColor &color)
1680 {
1681 std::vector<GLColor> colors(6, color);
1682 GLBuffer colorBuffer;
1683 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
1684 glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLColor), colors.data(), GL_STATIC_DRAW);
1685 simpleDrawWithBuffer(&colorBuffer);
1686 }
1687
1688 // Test that we can do a drawElements call successfully after making a drawArrays call in the same
1689 // frame.
TEST_P(SimpleStateChangeTest,DrawArraysThenDrawElements)1690 TEST_P(SimpleStateChangeTest, DrawArraysThenDrawElements)
1691 {
1692 // http://anglebug.com/4121
1693 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
1694 // http://anglebug.com/4177
1695 ANGLE_SKIP_TEST_IF(IsOSX() && IsMetal());
1696 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1697 glUseProgram(program);
1698
1699 // We expect to draw a triangle with the first 3 points to the left, then another triangle with
1700 // the last 3 vertices using a drawElements call.
1701 auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
1702 {-1.0f, 1.0f, 0.0f},
1703 {0.0f, 0.0f, 0.0f},
1704 {1.0f, 1.0f, 0.0f},
1705 {1.0f, -1.0f, 0.0f}};
1706
1707 // If we use these indices to draw we'll be using the last 2 vertex only to draw.
1708 auto indices = std::vector<GLushort>{2, 3, 4};
1709
1710 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1711 ASSERT_NE(-1, positionLocation);
1712
1713 GLBuffer vertexBuffer;
1714 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1715 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1716 GL_STATIC_DRAW);
1717
1718 GLBuffer indexBuffer;
1719 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1720 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1721 GL_STATIC_DRAW);
1722
1723 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1724 glEnableVertexAttribArray(positionLocation);
1725
1726 for (int i = 0; i < 10; i++)
1727 {
1728 glClear(GL_COLOR_BUFFER_BIT);
1729 glDrawArrays(GL_TRIANGLES, 0, 3); // triangle to the left
1730 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr); // triangle to the right
1731 glFinish();
1732 }
1733 glDisableVertexAttribArray(positionLocation);
1734
1735 ASSERT_GL_NO_ERROR();
1736
1737 int quarterWidth = getWindowWidth() / 4;
1738 int halfHeight = getWindowHeight() / 2;
1739
1740 // Validate triangle to the left
1741 EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::blue);
1742
1743 // Validate triangle to the right
1744 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::blue);
1745 }
1746
1747 // Draw a triangle with drawElements and a non-zero offset and draw the same
1748 // triangle with the same offset followed by binding the same element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElements)1749 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElements)
1750 {
1751 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1752
1753 glUseProgram(program);
1754
1755 // Background Red color
1756 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1757 glClear(GL_COLOR_BUFFER_BIT);
1758
1759 // We expect to draw the triangle with the last three points on the bottom right, and
1760 // rebind the same element buffer and draw with the same indices.
1761 auto vertices = std::vector<Vector3>{
1762 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1763
1764 auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1765
1766 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1767 ASSERT_NE(-1, positionLocation);
1768
1769 GLBuffer indexBuffer;
1770 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1771 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1772 GL_STATIC_DRAW);
1773
1774 GLBuffer vertexBuffer;
1775 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1776 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1777 GL_STATIC_DRAW);
1778
1779 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1780 glEnableVertexAttribArray(positionLocation);
1781
1782 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1783
1784 // Rebind the same element buffer.
1785 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1786
1787 // Draw the triangle again with the same offset.
1788 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1789
1790 glDisableVertexAttribArray(positionLocation);
1791
1792 ASSERT_GL_NO_ERROR();
1793
1794 int quarterWidth = getWindowWidth() / 4;
1795 int quarterHeight = getWindowHeight() / 4;
1796
1797 // Validate the triangle is drawn on the bottom right.
1798 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1799
1800 // Validate the triangle is NOT on the top left part.
1801 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1802 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1803 }
1804
1805 // Draw a triangle with drawElements then change the index buffer and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndexBuffer)1806 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndexBuffer)
1807 {
1808 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1809
1810 glUseProgram(program);
1811
1812 // Background Red color
1813 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1814 glClear(GL_COLOR_BUFFER_BIT);
1815
1816 // We expect to draw the triangle with the last three points on the bottom right, and
1817 // rebind the same element buffer and draw with the same indices.
1818 auto vertices = std::vector<Vector3>{
1819 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1820
1821 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
1822
1823 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1824 ASSERT_NE(-1, positionLocation);
1825
1826 GLint colorUniformLocation =
1827 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1828 ASSERT_NE(colorUniformLocation, -1);
1829
1830 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1831
1832 GLBuffer indexBuffer8;
1833 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1834 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1835 GL_STATIC_DRAW);
1836
1837 GLBuffer vertexBuffer;
1838 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1839 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1840 GL_STATIC_DRAW);
1841
1842 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1843 glEnableVertexAttribArray(positionLocation);
1844
1845 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1846
1847 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
1848
1849 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
1850 GL_STATIC_DRAW);
1851
1852 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1853
1854 // Draw the triangle again with the same offset.
1855 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1856
1857 glDisableVertexAttribArray(positionLocation);
1858
1859 ASSERT_GL_NO_ERROR();
1860
1861 int quarterWidth = getWindowWidth() / 4;
1862 int quarterHeight = getWindowHeight() / 4;
1863
1864 // Validate the triangle is drawn on the bottom left.
1865 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1866 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1867
1868 // Validate the triangle is NOT on the top right part.
1869 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1870 }
1871
1872 // Draw a triangle with drawElements then change the indices and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndices)1873 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndices)
1874 {
1875 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1876
1877 glUseProgram(program);
1878
1879 // Background Red color
1880 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1881 glClear(GL_COLOR_BUFFER_BIT);
1882
1883 // We expect to draw the triangle with the last three points on the bottom right, and
1884 // rebind the same element buffer and draw with the same indices.
1885 std::vector<Vector3> vertices = {
1886 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1887
1888 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1889
1890 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1891 ASSERT_NE(-1, positionLocation);
1892
1893 GLint colorUniformLocation =
1894 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1895 ASSERT_NE(colorUniformLocation, -1);
1896
1897 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1898
1899 GLBuffer indexBuffer8;
1900 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1901 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1902 GL_DYNAMIC_DRAW);
1903
1904 GLBuffer vertexBuffer;
1905 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1906 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1907 GL_STATIC_DRAW);
1908
1909 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1910 glEnableVertexAttribArray(positionLocation);
1911
1912 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1913
1914 std::vector<GLubyte> newIndices8 = {2, 3, 0};
1915
1916 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1917 &newIndices8[0]);
1918
1919 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1920
1921 // Draw the triangle again with the same offset.
1922 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1923
1924 glDisableVertexAttribArray(positionLocation);
1925
1926 ASSERT_GL_NO_ERROR();
1927
1928 int quarterWidth = getWindowWidth() / 4;
1929 int quarterHeight = getWindowHeight() / 4;
1930
1931 // Validate the triangle is drawn on the bottom left.
1932 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1933 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1934
1935 // Validate the triangle is NOT on the top right part.
1936 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1937 }
1938
1939 // Draw a triangle with drawElements then change the indices and draw again. Similar to
1940 // DrawElementsThenDrawElementsNewIndices, but changes the whole index buffer (not just half). This
1941 // triggers a different path in the Vulkan backend based on the fact that the majority of the buffer
1942 // is being updated.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsWholeNewIndices)1943 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsWholeNewIndices)
1944 {
1945 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1946
1947 glUseProgram(program);
1948
1949 // Background Red color
1950 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1951 glClear(GL_COLOR_BUFFER_BIT);
1952
1953 // We expect to draw the triangle with the last three points on the bottom right, and
1954 // rebind the same element buffer and draw with the same indices.
1955 std::vector<Vector3> vertices = {
1956 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1957
1958 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1959
1960 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1961 ASSERT_NE(-1, positionLocation);
1962
1963 GLint colorUniformLocation =
1964 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1965 ASSERT_NE(colorUniformLocation, -1);
1966
1967 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1968
1969 GLBuffer indexBuffer8;
1970 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1971 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1972 GL_DYNAMIC_DRAW);
1973
1974 GLBuffer vertexBuffer;
1975 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1976 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1977 GL_STATIC_DRAW);
1978
1979 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1980 glEnableVertexAttribArray(positionLocation);
1981
1982 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1983
1984 std::vector<GLubyte> newIndices8 = {2, 3, 0, 0, 0, 0};
1985
1986 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1987 &newIndices8[0]);
1988
1989 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1990
1991 // Draw the triangle again with the same offset.
1992 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1993
1994 glDisableVertexAttribArray(positionLocation);
1995
1996 ASSERT_GL_NO_ERROR();
1997
1998 int quarterWidth = getWindowWidth() / 4;
1999 int quarterHeight = getWindowHeight() / 4;
2000
2001 // Validate the triangle is drawn on the bottom left.
2002 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2003 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2004
2005 // Validate the triangle is NOT on the top right part.
2006 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2007 }
2008
2009 // Draw a triangle with drawElements and a non-zero offset and draw the same
2010 // triangle with the same offset followed by binding a USHORT element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsUBYTEX2ThenDrawElementsUSHORT)2011 TEST_P(SimpleStateChangeTest, DrawElementsUBYTEX2ThenDrawElementsUSHORT)
2012 {
2013 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2014
2015 glUseProgram(program);
2016
2017 // Background Red color
2018 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2019 glClear(GL_COLOR_BUFFER_BIT);
2020
2021 // We expect to draw the triangle with the last three points on the bottom right, and
2022 // rebind the same element buffer and draw with the same indices.
2023 auto vertices = std::vector<Vector3>{
2024 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2025
2026 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
2027
2028 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2029 ASSERT_NE(-1, positionLocation);
2030
2031 GLint colorUniformLocation =
2032 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2033 ASSERT_NE(colorUniformLocation, -1);
2034
2035 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2036
2037 GLBuffer indexBuffer8;
2038 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2039 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2040 GL_STATIC_DRAW);
2041
2042 GLBuffer vertexBuffer;
2043 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2044 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2045 GL_STATIC_DRAW);
2046
2047 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2048 glEnableVertexAttribArray(positionLocation);
2049
2050 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2051
2052 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
2053 GLBuffer indexBuffer2nd8;
2054 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2nd8);
2055 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2056 GL_STATIC_DRAW);
2057 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2058
2059 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2060
2061 // Bind the 16bit element buffer.
2062 auto indices16 = std::vector<GLushort>{0, 1, 3, 1, 2, 3};
2063 GLBuffer indexBuffer16;
2064 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2065 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices16.size() * sizeof(GLushort), &indices16[0],
2066 GL_STATIC_DRAW);
2067
2068 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2069
2070 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2071
2072 // Draw the triangle again with the same offset.
2073 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(0 * sizeof(GLushort)));
2074
2075 glDisableVertexAttribArray(positionLocation);
2076
2077 ASSERT_GL_NO_ERROR();
2078
2079 int quarterWidth = getWindowWidth() / 4;
2080 int quarterHeight = getWindowHeight() / 4;
2081
2082 // Validate green triangle is drawn on the bottom.
2083 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::green);
2084
2085 // Validate white triangle is drawn on the right.
2086 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 3, quarterHeight * 2, GLColor::white);
2087
2088 // Validate blue triangle is on the top left part.
2089 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::blue);
2090 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2091 }
2092
2093 // Draw a points use multiple unaligned vertex buffer with same data,
2094 // verify all the rendering results are the same.
TEST_P(SimpleStateChangeTest,DrawRepeatUnalignedVboChange)2095 TEST_P(SimpleStateChangeTest, DrawRepeatUnalignedVboChange)
2096 {
2097 // http://anglebug.com/4470
2098 ANGLE_SKIP_TEST_IF(isSwiftshader() && (IsWindows() || IsLinux()));
2099 // http://anglebug.com/6171
2100 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
2101
2102 const int kRepeat = 2;
2103
2104 // set up VBO, colorVBO is unaligned
2105 GLBuffer positionBuffer;
2106 constexpr size_t posOffset = 0;
2107 const GLfloat posData[] = {0.5f, 0.5f};
2108 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2109 glBufferData(GL_ARRAY_BUFFER, sizeof(posData), posData, GL_STATIC_DRAW);
2110
2111 GLBuffer colorBuffers[kRepeat];
2112 constexpr size_t colorOffset = 1;
2113 const GLfloat colorData[] = {0.515f, 0.515f, 0.515f, 1.0f};
2114 constexpr size_t colorBufferSize = colorOffset + sizeof(colorData);
2115 uint8_t colorDataUnaligned[colorBufferSize] = {0};
2116 memcpy(reinterpret_cast<void *>(colorDataUnaligned + colorOffset), colorData,
2117 sizeof(colorData));
2118 for (uint32_t i = 0; i < kRepeat; i++)
2119 {
2120 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2121 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorDataUnaligned, GL_STATIC_DRAW);
2122 }
2123
2124 // set up frame buffer
2125 GLFramebuffer framebuffer;
2126 GLTexture framebufferTexture;
2127 bindTextureToFbo(framebuffer, framebufferTexture);
2128
2129 // set up program
2130 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
2131 glUseProgram(program);
2132 GLuint colorAttrLocation = glGetAttribLocation(program, "color");
2133 glEnableVertexAttribArray(colorAttrLocation);
2134 GLuint posAttrLocation = glGetAttribLocation(program, "position");
2135 glEnableVertexAttribArray(posAttrLocation);
2136 EXPECT_GL_NO_ERROR();
2137
2138 // draw and get drawing results
2139 constexpr size_t kRenderSize = kWindowSize * kWindowSize;
2140 std::array<GLColor, kRenderSize> pixelBufs[kRepeat];
2141
2142 for (uint32_t i = 0; i < kRepeat; i++)
2143 {
2144 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2145 glClear(GL_COLOR_BUFFER_BIT);
2146
2147 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2148 glVertexAttribPointer(posAttrLocation, 2, GL_FLOAT, GL_FALSE, 0,
2149 reinterpret_cast<const void *>(posOffset));
2150 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2151 glVertexAttribPointer(colorAttrLocation, 4, GL_FLOAT, GL_FALSE, 0,
2152 reinterpret_cast<const void *>(colorOffset));
2153
2154 glDrawArrays(GL_POINTS, 0, 1);
2155
2156 // read drawing results
2157 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
2158 pixelBufs[i].data());
2159 EXPECT_GL_NO_ERROR();
2160 }
2161
2162 // verify something is drawn
2163 static_assert(kRepeat >= 2, "More than one repetition required");
2164 std::array<GLColor, kRenderSize> pixelAllBlack{0};
2165 EXPECT_NE(pixelBufs[0], pixelAllBlack);
2166 // verify drawing results are all identical
2167 for (uint32_t i = 1; i < kRepeat; i++)
2168 {
2169 EXPECT_EQ(pixelBufs[i - 1], pixelBufs[i]);
2170 }
2171 }
2172
2173 // Handles deleting a Buffer when it's being used.
TEST_P(SimpleStateChangeTest,DeleteBufferInUse)2174 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
2175 {
2176 std::vector<GLColor> colorData(6, GLColor::red);
2177
2178 GLBuffer buffer;
2179 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2180 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * colorData.size(), colorData.data(),
2181 GL_STATIC_DRAW);
2182
2183 simpleDrawWithBuffer(&buffer);
2184
2185 buffer.reset();
2186 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2187 }
2188
2189 // Tests that resizing a Buffer during a draw works as expected.
TEST_P(SimpleStateChangeTest,RedefineBufferInUse)2190 TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
2191 {
2192 std::vector<GLColor> redColorData(6, GLColor::red);
2193
2194 GLBuffer buffer;
2195 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2196 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2197 GL_STATIC_DRAW);
2198
2199 // Trigger a pull from the buffer.
2200 simpleDrawWithBuffer(&buffer);
2201
2202 // Redefine the buffer that's in-flight.
2203 std::vector<GLColor> greenColorData(1024, GLColor::green);
2204 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * greenColorData.size(), greenColorData.data(),
2205 GL_STATIC_DRAW);
2206
2207 // Trigger the flush and verify the first draw worked.
2208 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2209
2210 // Draw again and verify the new data is correct.
2211 simpleDrawWithBuffer(&buffer);
2212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2213 }
2214
2215 // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest,UpdateBufferInUse)2216 TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
2217 {
2218 std::vector<GLColor> redColorData(6, GLColor::red);
2219
2220 GLBuffer buffer;
2221 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2222 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2223 GL_STATIC_DRAW);
2224
2225 // Trigger a pull from the buffer.
2226 simpleDrawWithBuffer(&buffer);
2227
2228 // Update the buffer that's in-flight.
2229 std::vector<GLColor> greenColorData(6, GLColor::green);
2230 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * greenColorData.size(),
2231 greenColorData.data());
2232
2233 // Trigger the flush and verify the first draw worked.
2234 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2235
2236 // Draw again and verify the new data is correct.
2237 simpleDrawWithBuffer(&buffer);
2238 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2239 }
2240
2241 // Tests that deleting an in-flight Texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTest,DeleteTextureInUse)2242 TEST_P(SimpleStateChangeTest, DeleteTextureInUse)
2243 {
2244 std::array<GLColor, 4> colors = {
2245 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2246
2247 GLTexture tex;
2248 glBindTexture(GL_TEXTURE_2D, tex);
2249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2252
2253 draw2DTexturedQuad(0.5f, 1.0f, true);
2254 tex.reset();
2255 EXPECT_GL_NO_ERROR();
2256
2257 int w = getWindowWidth() - 2;
2258 int h = getWindowHeight() - 2;
2259
2260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2261 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2262 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2263 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2264 }
2265
2266 // Tests that modifying a texture parameter in-flight does not cause problems.
TEST_P(SimpleStateChangeTest,ChangeTextureFilterModeBetweenTwoDraws)2267 TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
2268 {
2269 std::array<GLColor, 4> colors = {
2270 {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
2271
2272 GLTexture tex;
2273 glBindTexture(GL_TEXTURE_2D, tex);
2274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2275
2276 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2277 glClear(GL_COLOR_BUFFER_BIT);
2278
2279 // Draw to the left side of the window only with NEAREST.
2280 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2283 draw2DTexturedQuad(0.5f, 1.0f, true);
2284
2285 // Draw to the right side of the window only with LINEAR.
2286 glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2289 draw2DTexturedQuad(0.5f, 1.0f, true);
2290 EXPECT_GL_NO_ERROR();
2291
2292 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2293
2294 // The first half (left) should be only black followed by plain white.
2295 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2296 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
2297 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
2298 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
2299
2300 // The second half (right) should be a gradient so we shouldn't find plain black/white in the
2301 // middle.
2302 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
2303 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
2304 }
2305
2306 // Tests that bind the same texture all the time between different draw calls.
TEST_P(SimpleStateChangeTest,RebindTextureDrawAgain)2307 TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
2308 {
2309 GLuint program = get2DTexturedQuadProgram();
2310 glUseProgram(program);
2311
2312 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2313
2314 // Setup the texture
2315 GLTexture tex;
2316 glBindTexture(GL_TEXTURE_2D, tex);
2317 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2320
2321 // Setup the vertex array to draw a quad.
2322 GLint positionLocation = glGetAttribLocation(program, "position");
2323 setupQuadVertexBuffer(1.0f, 1.0f);
2324 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2325 glEnableVertexAttribArray(positionLocation);
2326
2327 // Draw quad
2328 glDrawArrays(GL_TRIANGLES, 0, 6);
2329 ASSERT_GL_NO_ERROR();
2330
2331 // Bind again
2332 glBindTexture(GL_TEXTURE_2D, tex);
2333 ASSERT_GL_NO_ERROR();
2334
2335 // Draw again, should still work.
2336 glDrawArrays(GL_TRIANGLES, 0, 6);
2337 ASSERT_GL_NO_ERROR();
2338
2339 // Validate whole surface is filled with cyan.
2340 int h = getWindowHeight() - 1;
2341 int w = getWindowWidth() - 1;
2342
2343 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2344 }
2345
2346 // Tests that we can draw with a texture, modify the texture with a texSubImage, and then draw again
2347 // correctly.
TEST_P(SimpleStateChangeTest,DrawWithTextureTexSubImageThenDrawAgain)2348 TEST_P(SimpleStateChangeTest, DrawWithTextureTexSubImageThenDrawAgain)
2349 {
2350 GLuint program = get2DTexturedQuadProgram();
2351 ASSERT_NE(0u, program);
2352 glUseProgram(program);
2353
2354 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
2355 std::array<GLColor, 4> subColors = {
2356 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
2357
2358 // Setup the texture
2359 GLTexture tex;
2360 glBindTexture(GL_TEXTURE_2D, tex);
2361 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2364
2365 // Setup the vertex array to draw a quad.
2366 GLint positionLocation = glGetAttribLocation(program, "position");
2367 setupQuadVertexBuffer(1.0f, 1.0f);
2368 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2369 glEnableVertexAttribArray(positionLocation);
2370
2371 // Draw quad
2372 glDrawArrays(GL_TRIANGLES, 0, 6);
2373 ASSERT_GL_NO_ERROR();
2374
2375 // Update bottom-half of texture with green.
2376 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
2377 ASSERT_GL_NO_ERROR();
2378
2379 // Draw again, should still work.
2380 glDrawArrays(GL_TRIANGLES, 0, 6);
2381 ASSERT_GL_NO_ERROR();
2382
2383 // Validate first half of the screen is red and the bottom is green.
2384 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2385 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4 * 3, GLColor::red);
2386 }
2387
2388 // Test that we can alternate between textures between different draws.
TEST_P(SimpleStateChangeTest,DrawTextureAThenTextureBThenTextureA)2389 TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
2390 {
2391 GLuint program = get2DTexturedQuadProgram();
2392 glUseProgram(program);
2393
2394 std::array<GLColor, 4> colorsTex1 = {
2395 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2396
2397 std::array<GLColor, 4> colorsTex2 = {
2398 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
2399
2400 // Setup the texture
2401 GLTexture tex1;
2402 glBindTexture(GL_TEXTURE_2D, tex1);
2403 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
2404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2405 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2406
2407 GLTexture tex2;
2408 glBindTexture(GL_TEXTURE_2D, tex2);
2409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
2410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2412
2413 // Setup the vertex array to draw a quad.
2414 GLint positionLocation = glGetAttribLocation(program, "position");
2415 setupQuadVertexBuffer(1.0f, 1.0f);
2416 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2417 glEnableVertexAttribArray(positionLocation);
2418
2419 // Draw quad
2420 glBindTexture(GL_TEXTURE_2D, tex1);
2421 glDrawArrays(GL_TRIANGLES, 0, 6);
2422 ASSERT_GL_NO_ERROR();
2423
2424 // Bind again, draw again
2425 glBindTexture(GL_TEXTURE_2D, tex2);
2426 glDrawArrays(GL_TRIANGLES, 0, 6);
2427 ASSERT_GL_NO_ERROR();
2428
2429 // Bind again, draw again
2430 glBindTexture(GL_TEXTURE_2D, tex1);
2431 glDrawArrays(GL_TRIANGLES, 0, 6);
2432
2433 // Validate whole surface is filled with cyan.
2434 int h = getWindowHeight() - 1;
2435 int w = getWindowWidth() - 1;
2436
2437 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2438 }
2439
2440 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
TEST_P(SimpleStateChangeTest,RedefineTextureInUse)2441 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
2442 {
2443 std::array<GLColor, 4> colors = {
2444 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2445
2446 GLTexture tex;
2447 glBindTexture(GL_TEXTURE_2D, tex);
2448 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2451
2452 // Draw with the first texture.
2453 draw2DTexturedQuad(0.5f, 1.0f, true);
2454
2455 // Redefine the in-flight texture.
2456 constexpr int kBigSize = 32;
2457 std::vector<GLColor> bigColors;
2458 for (int y = 0; y < kBigSize; ++y)
2459 {
2460 for (int x = 0; x < kBigSize; ++x)
2461 {
2462 bool xComp = x < kBigSize / 2;
2463 bool yComp = y < kBigSize / 2;
2464 if (yComp)
2465 {
2466 bigColors.push_back(xComp ? GLColor::cyan : GLColor::magenta);
2467 }
2468 else
2469 {
2470 bigColors.push_back(xComp ? GLColor::yellow : GLColor::white);
2471 }
2472 }
2473 }
2474
2475 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigColors.data());
2476 EXPECT_GL_NO_ERROR();
2477
2478 // Verify the first draw had the correct data via ReadPixels.
2479 int w = getWindowWidth() - 2;
2480 int h = getWindowHeight() - 2;
2481
2482 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2483 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2484 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2485 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2486
2487 // Draw and verify with the redefined data.
2488 draw2DTexturedQuad(0.5f, 1.0f, true);
2489 EXPECT_GL_NO_ERROR();
2490
2491 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2492 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::magenta);
2493 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::yellow);
2494 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::white);
2495 }
2496
2497 // Test updating a Texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTest,UpdateTextureInUse)2498 TEST_P(SimpleStateChangeTest, UpdateTextureInUse)
2499 {
2500 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2501
2502 // Set up 2D quad resources.
2503 GLuint program = get2DTexturedQuadProgram();
2504 glUseProgram(program);
2505 ASSERT_EQ(0, glGetAttribLocation(program, "position"));
2506
2507 const auto &quadVerts = GetQuadVertices();
2508
2509 GLBuffer vbo;
2510 glBindBuffer(GL_ARRAY_BUFFER, vbo);
2511 glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
2512 GL_STATIC_DRAW);
2513 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2514 glEnableVertexAttribArray(0);
2515
2516 GLTexture tex;
2517 glBindTexture(GL_TEXTURE_2D, tex);
2518 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
2519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2521
2522 // Draw RGBY to the Framebuffer. The texture is now in-use by GL.
2523 const int w = getWindowWidth() - 2;
2524 const int h = getWindowHeight() - 2;
2525 const int w2 = w >> 1;
2526
2527 glViewport(0, 0, w2, h);
2528 glDrawArrays(GL_TRIANGLES, 0, 6);
2529
2530 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the draw.
2531 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
2532 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
2533 ASSERT_GL_NO_ERROR();
2534
2535 // Draw again to the Framebuffer. The second draw call should use the updated YBGR data.
2536 glViewport(w2, 0, w2, h);
2537 glDrawArrays(GL_TRIANGLES, 0, 6);
2538
2539 // Check the Framebuffer. Both draws should have completed.
2540 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2541 EXPECT_PIXEL_COLOR_EQ(w2 - 1, 0, GLColor::green);
2542 EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::blue);
2543 EXPECT_PIXEL_COLOR_EQ(w2 - 1, h - 1, GLColor::yellow);
2544
2545 EXPECT_PIXEL_COLOR_EQ(w2 + 1, 0, GLColor::yellow);
2546 EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::blue);
2547 EXPECT_PIXEL_COLOR_EQ(w2 + 1, h - 1, GLColor::green);
2548 EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::red);
2549 ASSERT_GL_NO_ERROR();
2550 }
2551
updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)2552 void SimpleStateChangeTest::updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)
2553 {
2554 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2555
2556 std::vector<GLColor> red(4, GLColor::red);
2557 std::vector<GLColor> green(4, GLColor::green);
2558
2559 GLTexture renderTarget;
2560 glBindTexture(GL_TEXTURE_2D, renderTarget);
2561 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2562
2563 GLFramebuffer fbo;
2564 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2565 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2566 0);
2567 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2568 glViewport(0, 0, 2, 2);
2569 ASSERT_GL_NO_ERROR();
2570
2571 GLTexture tex;
2572 glBindTexture(GL_TEXTURE_2D, tex);
2573 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2576
2577 // Draw once to flush dirty state bits.
2578 draw2DTexturedQuad(0.5f, 1.0f, true);
2579
2580 ASSERT_GL_NO_ERROR();
2581
2582 // Update the (0, 1) pixel to be blue
2583 updateFunc(GL_TEXTURE_2D, &renderTarget, 0, 1, GLColor::blue);
2584
2585 // Draw green to the right half of the Framebuffer.
2586 glBindTexture(GL_TEXTURE_2D, tex);
2587 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, green.data());
2588 glViewport(1, 0, 1, 2);
2589 draw2DTexturedQuad(0.5f, 1.0f, true);
2590
2591 // Update the (1, 1) pixel to be yellow
2592 updateFunc(GL_TEXTURE_2D, &renderTarget, 1, 1, GLColor::yellow);
2593
2594 ASSERT_GL_NO_ERROR();
2595
2596 // Verify we have a quad with the right colors in the FBO.
2597 std::vector<GLColor> expected = {
2598 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2599 std::vector<GLColor> actual(4);
2600 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2601 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
2602 EXPECT_EQ(expected, actual);
2603 }
2604
2605 // Tests that TexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,TexSubImageOnTextureBoundToFrambuffer)2606 TEST_P(SimpleStateChangeTest, TexSubImageOnTextureBoundToFrambuffer)
2607 {
2608 // http://anglebug.com/4092
2609 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2610 auto updateFunc = [](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2611 const GLColor &color) {
2612 glBindTexture(textureBinding, *tex);
2613 glTexSubImage2D(textureBinding, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2614 };
2615
2616 updateTextureBoundToFramebufferHelper(updateFunc);
2617 }
2618
2619 // Tests that CopyTexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,CopyTexSubImageOnTextureBoundToFrambuffer)2620 TEST_P(SimpleStateChangeTest, CopyTexSubImageOnTextureBoundToFrambuffer)
2621 {
2622 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2623
2624 GLTexture copySource;
2625 glBindTexture(GL_TEXTURE_2D, copySource);
2626 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2627
2628 GLFramebuffer copyFBO;
2629 glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFBO);
2630 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySource, 0);
2631
2632 ASSERT_GL_NO_ERROR();
2633 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2634
2635 auto updateFunc = [©Source](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2636 const GLColor &color) {
2637 glBindTexture(GL_TEXTURE_2D, copySource);
2638 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2639
2640 glBindTexture(textureBinding, *tex);
2641 glCopyTexSubImage2D(textureBinding, 0, x, y, 0, 0, 1, 1);
2642 };
2643
2644 updateTextureBoundToFramebufferHelper(updateFunc);
2645 }
2646
2647 // Tests that the read framebuffer doesn't affect what the draw call thinks the attachments are
2648 // (which is what the draw framebuffer dictates) when a command is issued with the GL_FRAMEBUFFER
2649 // target.
TEST_P(SimpleStateChangeTestES3,ReadFramebufferDrawFramebufferDifferentAttachments)2650 TEST_P(SimpleStateChangeTestES3, ReadFramebufferDrawFramebufferDifferentAttachments)
2651 {
2652 // http://anglebug.com/4092
2653 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2654
2655 GLRenderbuffer drawColorBuffer;
2656 glBindRenderbuffer(GL_RENDERBUFFER, drawColorBuffer);
2657 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2658
2659 GLRenderbuffer drawDepthBuffer;
2660 glBindRenderbuffer(GL_RENDERBUFFER, drawDepthBuffer);
2661 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1);
2662
2663 GLRenderbuffer readColorBuffer;
2664 glBindRenderbuffer(GL_RENDERBUFFER, readColorBuffer);
2665 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2666
2667 GLFramebuffer drawFBO;
2668 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2669 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2670 drawColorBuffer);
2671 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2672 drawDepthBuffer);
2673 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2674
2675 GLFramebuffer readFBO;
2676 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2677 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2678 readColorBuffer);
2679 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2680
2681 EXPECT_GL_NO_ERROR();
2682
2683 glClearDepthf(1.0f);
2684 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2685
2686 // A handful of non-draw calls can sync framebuffer state, such as discard, invalidate,
2687 // invalidateSub and multisamplefv. The trick here is to give GL_FRAMEBUFFER as target, which
2688 // includes both the read and draw framebuffers. The test is to make sure syncing the read
2689 // framebuffer doesn't affect the draw call.
2690 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2691 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
2692 EXPECT_GL_NO_ERROR();
2693
2694 glEnable(GL_DEPTH_TEST);
2695 glDepthFunc(GL_EQUAL);
2696
2697 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
2698
2699 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
2700 EXPECT_GL_NO_ERROR();
2701
2702 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2703 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2704 }
2705
2706 // Tests that invalidate then copy then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenCopyThenBlend)2707 TEST_P(SimpleStateChangeTestES3, InvalidateThenCopyThenBlend)
2708 {
2709 // Create a framebuffer as the source of copy
2710 const GLColor kSrcData = GLColor::cyan;
2711 GLTexture copySrc;
2712 glBindTexture(GL_TEXTURE_2D, copySrc);
2713 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2714
2715 GLFramebuffer readFBO;
2716 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2717 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySrc, 0);
2718 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2719
2720 // Create the framebuffer that will be invalidated
2721 GLTexture renderTarget;
2722 glBindTexture(GL_TEXTURE_2D, renderTarget);
2723 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2724
2725 GLFramebuffer drawFBO;
2726 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2727 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2728 0);
2729 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2730
2731 EXPECT_GL_NO_ERROR();
2732
2733 // Clear the framebuffer and invalidate it.
2734 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2735 glClear(GL_COLOR_BUFFER_BIT);
2736
2737 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2738 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2739 EXPECT_GL_NO_ERROR();
2740
2741 // Copy into the framebuffer's texture. The framebuffer should now be cyan.
2742 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2743 EXPECT_GL_NO_ERROR();
2744
2745 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2746 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2747 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2748 }
2749
2750 // Tests that invalidate then blit then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenBlitThenBlend)2751 TEST_P(SimpleStateChangeTestES3, InvalidateThenBlitThenBlend)
2752 {
2753 // Create a framebuffer as the source of blit
2754 const GLColor kSrcData = GLColor::cyan;
2755 GLTexture blitSrc;
2756 glBindTexture(GL_TEXTURE_2D, blitSrc);
2757 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2758
2759 GLFramebuffer readFBO;
2760 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2761 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
2762 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2763
2764 // Create the framebuffer that will be invalidated
2765 GLTexture renderTarget;
2766 glBindTexture(GL_TEXTURE_2D, renderTarget);
2767 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2768
2769 GLFramebuffer drawFBO;
2770 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2771 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2772 0);
2773 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2774
2775 EXPECT_GL_NO_ERROR();
2776
2777 // Clear the framebuffer and invalidate it.
2778 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2779 glClear(GL_COLOR_BUFFER_BIT);
2780
2781 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2782 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2783 EXPECT_GL_NO_ERROR();
2784
2785 // Blit into the framebuffer. The framebuffer should now be cyan.
2786 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2787 EXPECT_GL_NO_ERROR();
2788
2789 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2790 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2791 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2792 }
2793
2794 // Tests that invalidate then generate mipmaps works
TEST_P(SimpleStateChangeTestES3,InvalidateThenGenerateMipmapsThenBlend)2795 TEST_P(SimpleStateChangeTestES3, InvalidateThenGenerateMipmapsThenBlend)
2796 {
2797 // Create a texture on which generate mipmaps would be called
2798 const GLColor kMip0Data[4] = {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan};
2799 const GLColor kMip1Data = GLColor::blue;
2800 GLTexture texture;
2801 glBindTexture(GL_TEXTURE_2D, texture);
2802 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data);
2803 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kMip1Data);
2804
2805 // Create the framebuffer that will be invalidated
2806 GLFramebuffer drawFBO;
2807 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2808 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
2809 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2810
2811 EXPECT_GL_NO_ERROR();
2812
2813 // Clear the framebuffer and invalidate it.
2814 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2815 glClear(GL_COLOR_BUFFER_BIT);
2816
2817 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2818 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2819 EXPECT_GL_NO_ERROR();
2820
2821 // Generate mipmaps
2822 glGenerateMipmap(GL_TEXTURE_2D);
2823
2824 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2825 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2826 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2827 }
2828
2829 // Tests that invalidate then upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenUploadThenBlend)2830 TEST_P(SimpleStateChangeTestES3, InvalidateThenUploadThenBlend)
2831 {
2832 // http://anglebug.com/4870
2833 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2834
2835 // Create the framebuffer that will be invalidated
2836 GLTexture renderTarget;
2837 glBindTexture(GL_TEXTURE_2D, renderTarget);
2838 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2839
2840 GLFramebuffer drawFBO;
2841 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2842 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2843 0);
2844 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2845
2846 EXPECT_GL_NO_ERROR();
2847
2848 // Clear the framebuffer and invalidate it.
2849 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2850 glClear(GL_COLOR_BUFFER_BIT);
2851
2852 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2853 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2854 EXPECT_GL_NO_ERROR();
2855
2856 // Upload data to it
2857 const GLColor kUploadColor = GLColor::cyan;
2858 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2859
2860 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2861 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2862 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2863 }
2864
2865 // Tests that invalidate then sub upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenSubUploadThenBlend)2866 TEST_P(SimpleStateChangeTestES3, InvalidateThenSubUploadThenBlend)
2867 {
2868 // http://anglebug.com/4870
2869 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2870
2871 // Create the framebuffer that will be invalidated
2872 GLTexture renderTarget;
2873 glBindTexture(GL_TEXTURE_2D, renderTarget);
2874 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2875
2876 GLFramebuffer drawFBO;
2877 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2878 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2879 0);
2880 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2881
2882 EXPECT_GL_NO_ERROR();
2883
2884 // Clear the framebuffer and invalidate it.
2885 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2886 glClear(GL_COLOR_BUFFER_BIT);
2887
2888 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2889 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2890 EXPECT_GL_NO_ERROR();
2891
2892 // Upload data to it
2893 const GLColor kUploadColor = GLColor::cyan;
2894 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2895
2896 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2897 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2898 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2899 }
2900
2901 // Tests that invalidate then compute write works
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlend)2902 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlend)
2903 {
2904 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2905 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2906 // http://anglebug.com/5387
2907 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
2908
2909 constexpr char kCS[] = R"(#version 310 es
2910 layout(local_size_x=1, local_size_y=1) in;
2911 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2912 void main()
2913 {
2914 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2915 })";
2916
2917 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2918 glUseProgram(program);
2919 EXPECT_GL_NO_ERROR();
2920
2921 // Create the framebuffer texture
2922 GLTexture renderTarget;
2923 glBindTexture(GL_TEXTURE_2D, renderTarget);
2924 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2925 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2926
2927 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
2928 // is already created with STORAGE usage and avoids recreate later.
2929 glDispatchCompute(1, 1, 1);
2930 EXPECT_GL_NO_ERROR();
2931
2932 // Create the framebuffer that will be invalidated
2933 GLFramebuffer drawFBO;
2934 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2935 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2936 0);
2937 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2938
2939 EXPECT_GL_NO_ERROR();
2940
2941 // Clear the framebuffer and invalidate it.
2942 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2943 glClear(GL_COLOR_BUFFER_BIT);
2944
2945 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2946 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2947 EXPECT_GL_NO_ERROR();
2948
2949 // Write to it with a compute shader
2950 glDispatchCompute(1, 1, 1);
2951 EXPECT_GL_NO_ERROR();
2952
2953 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2954
2955 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2956 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2957 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2958 }
2959
2960 // Tests that invalidate then compute write works inside PPO
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlendPpo)2961 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlendPpo)
2962 {
2963 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2964 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2965 // PPOs are only supported in the Vulkan backend
2966 ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2967
2968 constexpr char kCS[] = R"(#version 310 es
2969 layout(local_size_x=1, local_size_y=1) in;
2970 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2971 void main()
2972 {
2973 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2974 })";
2975
2976 GLProgramPipeline pipeline;
2977 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2978 glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
2979 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, program);
2980 EXPECT_GL_NO_ERROR();
2981 glBindProgramPipeline(pipeline);
2982 EXPECT_GL_NO_ERROR();
2983 glUseProgram(0);
2984
2985 // Create the framebuffer texture
2986 GLTexture renderTarget;
2987 glBindTexture(GL_TEXTURE_2D, renderTarget);
2988 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2989 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2990
2991 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
2992 // is already created with STORAGE usage and avoids recreate later.
2993 glDispatchCompute(1, 1, 1);
2994 EXPECT_GL_NO_ERROR();
2995
2996 // Create the framebuffer that will be invalidated
2997 GLFramebuffer drawFBO;
2998 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2999 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3000 0);
3001 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3002
3003 EXPECT_GL_NO_ERROR();
3004
3005 // Clear the framebuffer and invalidate it.
3006 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3007 glClear(GL_COLOR_BUFFER_BIT);
3008
3009 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3010 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3011 EXPECT_GL_NO_ERROR();
3012
3013 // Write to it with a compute shader
3014 glDispatchCompute(1, 1, 1);
3015 EXPECT_GL_NO_ERROR();
3016
3017 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3018
3019 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3020 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3021 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3022 }
3023
3024 // Tests that sub-invalidate then draw works.
TEST_P(SimpleStateChangeTestES3,SubInvalidateThenDraw)3025 TEST_P(SimpleStateChangeTestES3, SubInvalidateThenDraw)
3026 {
3027 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3028 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3029
3030 // Create the framebuffer that will be invalidated
3031 GLTexture renderTarget;
3032 glBindTexture(GL_TEXTURE_2D, renderTarget);
3033 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3034
3035 GLFramebuffer drawFBO;
3036 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3037 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3038 0);
3039 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3040
3041 EXPECT_GL_NO_ERROR();
3042
3043 // Clear the framebuffer.
3044 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3045 glClear(GL_COLOR_BUFFER_BIT);
3046
3047 // Draw into a quarter of the framebuffer, then invalidate that same region.
3048 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3049 glEnable(GL_SCISSOR_TEST);
3050 glScissor(1, 1, 1, 1);
3051 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3052
3053 // Only invalidate a quarter of the framebuffer.
3054 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3055 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment, 1, 1, 1, 1);
3056 EXPECT_GL_NO_ERROR();
3057
3058 glDisable(GL_SCISSOR_TEST);
3059
3060 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3061 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3062 blendAndVerifyColor(GLColor32F(0.0f, 0.0f, 1.0f, 0.5f), GLColor(127, 127, 127, 191));
3063 }
3064
3065 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3066 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
3067 {
3068 constexpr int kSize = 16;
3069
3070 // Create a simple framebuffer.
3071 GLTexture texture;
3072 glBindTexture(GL_TEXTURE_2D, texture);
3073 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3074
3075 GLFramebuffer framebuffer;
3076 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3077 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3078 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3079
3080 glViewport(0, 0, kSize, kSize);
3081
3082 // Draw a solid red color to the framebuffer.
3083 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3084 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3085
3086 // Delete the framebuffer while the call is in flight.
3087 framebuffer.reset();
3088
3089 // Make a new framebuffer so we can read back the texture.
3090 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3091 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3092 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3093
3094 // Flush via ReadPixels and check red was drawn.
3095 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3096 ASSERT_GL_NO_ERROR();
3097 }
3098
3099 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3100 // buffers too early. The test has 2 textures, we first create a texture and update it with
3101 // multiple updates, but we don't use it right away, we instead draw using another texture
3102 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3103 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3104 {
3105 constexpr int kSize = 64;
3106
3107 GLuint program = get2DTexturedQuadProgram();
3108 glUseProgram(program);
3109
3110 std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3111 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3112 GLTexture texture1;
3113 glBindTexture(GL_TEXTURE_2D, texture1);
3114 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3115
3116 for (int i = 0; i < 100; i++)
3117 {
3118 // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3119 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3120 greenPixels.data());
3121 }
3122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3124
3125 ASSERT_GL_NO_ERROR();
3126
3127 GLTexture texture2;
3128 glBindTexture(GL_TEXTURE_2D, texture2);
3129 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3132
3133 // Setup the vertex array to draw a quad.
3134 GLint positionLocation = glGetAttribLocation(program, "position");
3135 setupQuadVertexBuffer(1.0f, 1.0f);
3136 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3137 glEnableVertexAttribArray(positionLocation);
3138
3139 // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3140 glBindTexture(GL_TEXTURE_2D, texture2);
3141 glDrawArrays(GL_TRIANGLES, 0, 6);
3142 ASSERT_GL_NO_ERROR();
3143 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3144
3145 // If we now try to draw with texture1, we should trigger the issue.
3146 glBindTexture(GL_TEXTURE_2D, texture1);
3147 glDrawArrays(GL_TRIANGLES, 0, 6);
3148 ASSERT_GL_NO_ERROR();
3149
3150 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3151 }
3152
3153 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3154 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3155 {
3156 constexpr int kSize = 16;
3157
3158 // Create a simple framebuffer.
3159 GLTexture texture;
3160 glBindTexture(GL_TEXTURE_2D, texture);
3161 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3162
3163 GLFramebuffer framebuffer;
3164 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3165 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3166 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3167
3168 glViewport(0, 0, kSize, kSize);
3169
3170 // Draw red to the framebuffer.
3171 simpleDrawWithColor(GLColor::red);
3172
3173 // Change the framebuffer while the call is in flight to a new texture.
3174 GLTexture otherTexture;
3175 glBindTexture(GL_TEXTURE_2D, otherTexture);
3176 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3177
3178 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3179 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3180
3181 // Draw green to the framebuffer. Verify the color.
3182 simpleDrawWithColor(GLColor::green);
3183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3184
3185 // Make a new framebuffer so we can read back the first texture and verify red.
3186 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3187 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3188 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3189
3190 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3191 ASSERT_GL_NO_ERROR();
3192 }
3193
3194 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3195 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3196 {
3197 GLFramebuffer framebuffer;
3198 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3199
3200 // Bind a simple 8x8 texture to the framebuffer, draw red.
3201 GLTexture texture;
3202 glBindTexture(GL_TEXTURE_2D, texture);
3203 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3204 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3205
3206 glViewport(0, 0, 8, 8);
3207 simpleDrawWithColor(GLColor::red);
3208 ASSERT_GL_NO_ERROR();
3209 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3210
3211 // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3212 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3213 glViewport(0, 0, 32, 32);
3214 simpleDrawWithColor(GLColor::green);
3215 ASSERT_GL_NO_ERROR();
3216 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3217 }
3218
3219 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3220 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3221 {
3222 // Fails on 431.02 driver. http://anglebug.com/3748
3223 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3224
3225 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3226 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3227
3228 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3229
3230 GLTexture tex;
3231 glBindTexture(GL_TEXTURE_2D, tex);
3232 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3235 ASSERT_GL_NO_ERROR();
3236
3237 GLFramebuffer fbo;
3238 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3239 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3240 ASSERT_GL_NO_ERROR();
3241 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3242
3243 glUseProgram(program);
3244
3245 GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3246 ASSERT_NE(-1, uniLoc);
3247 glUniform1i(uniLoc, 0);
3248
3249 const int numRowsCols = 2;
3250 const int cellSize = getWindowWidth() / 2;
3251
3252 for (int cellY = 0; cellY < numRowsCols; cellY++)
3253 {
3254 for (int cellX = 0; cellX < numRowsCols; cellX++)
3255 {
3256 int seed = cellX + cellY * numRowsCols;
3257 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3258
3259 // Set the texture to a constant color using glClear and a user FBO.
3260 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3261 glClearColor(color[0], color[1], color[2], color[3]);
3262 glClear(GL_COLOR_BUFFER_BIT);
3263
3264 // Draw a small colored quad to the default FBO using the viewport.
3265 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3266 glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3267 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3268 }
3269 }
3270
3271 // Verify the colored quads were drawn correctly despite no flushing.
3272 std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3273 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3274 pixelData.data());
3275
3276 ASSERT_GL_NO_ERROR();
3277
3278 for (int cellY = 0; cellY < numRowsCols; cellY++)
3279 {
3280 for (int cellX = 0; cellX < numRowsCols; cellX++)
3281 {
3282 int seed = cellX + cellY * numRowsCols;
3283 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3284
3285 GLColor expectedColor(color);
3286
3287 int testN =
3288 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3289 GLColor actualColor = pixelData[testN];
3290 EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3291 }
3292 }
3293 }
3294
3295 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3296 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3297 {
3298 // Create a texture with red
3299 const GLColor kInitColor1 = GLColor::red;
3300 GLTexture texture1;
3301 glBindTexture(GL_TEXTURE_2D, texture1);
3302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3303
3304 // Create a framebuffer to be cleared
3305 GLTexture texture2;
3306 glBindTexture(GL_TEXTURE_2D, texture2);
3307 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3308
3309 GLFramebuffer drawFBO;
3310 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3311 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3312 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3313
3314 EXPECT_GL_NO_ERROR();
3315
3316 // Clear the framebuffer to green
3317 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3318 glClear(GL_COLOR_BUFFER_BIT);
3319
3320 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3321 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3322 // a noop, the deferred clears will remain unflushed.
3323 glClear(0);
3324
3325 // Change framebuffer's attachment to the other texture.
3326 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3327 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3328
3329 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3330 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3331 glUseProgram(program);
3332
3333 glEnable(GL_BLEND);
3334 glBlendFunc(GL_ZERO, GL_ONE);
3335 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3336 EXPECT_GL_NO_ERROR();
3337
3338 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3339 // to the new attachment, green will be read back.
3340 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3341
3342 // Attach back to texture2. It should be cleared to green.
3343 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3344 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3345 }
3346
3347 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3348 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3349 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3350 {
3351 // Create a texture with red
3352 const GLColor kInitColor1 = GLColor::red;
3353 GLTexture texture1;
3354 glBindTexture(GL_TEXTURE_2D, texture1);
3355 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3356
3357 // Create a framebuffer to be cleared
3358 GLTexture texture2;
3359 glBindTexture(GL_TEXTURE_2D, texture2);
3360 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3361
3362 GLFramebuffer drawFBO;
3363 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3364 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3365 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3366
3367 EXPECT_GL_NO_ERROR();
3368
3369 // Clear the framebuffer to green
3370 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3371 glClear(GL_COLOR_BUFFER_BIT);
3372
3373 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3374 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3375 // a noop, the deferred clears will remain unflushed.
3376 glEnable(GL_SCISSOR_TEST);
3377 glScissor(0, 0, 0, 0);
3378 glClear(GL_COLOR_BUFFER_BIT);
3379 glDisable(GL_SCISSOR_TEST);
3380
3381 // Change framebuffer's attachment to the other texture.
3382 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3383 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3384
3385 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3386 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3387 glUseProgram(program);
3388
3389 glEnable(GL_BLEND);
3390 glBlendFunc(GL_ZERO, GL_ONE);
3391 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3392 EXPECT_GL_NO_ERROR();
3393
3394 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3395 // to the new attachment, green will be read back.
3396 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3397
3398 // Attach back to texture2. It should be cleared to green.
3399 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3400 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3401 }
3402
3403 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3404 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3405 {
3406 // Create a texture with red
3407 const GLColor kInitColor1 = GLColor::red;
3408 GLTexture texture1;
3409 glBindTexture(GL_TEXTURE_2D, texture1);
3410 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3411
3412 // Create a framebuffer to be cleared
3413 GLTexture texture2;
3414 glBindTexture(GL_TEXTURE_2D, texture2);
3415 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3416
3417 GLFramebuffer drawFBO;
3418 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3419 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3420 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3421
3422 EXPECT_GL_NO_ERROR();
3423
3424 // Clear the framebuffer to green
3425 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3426 glClear(GL_COLOR_BUFFER_BIT);
3427
3428 // Issue noop blit. In the Vulkan backend, this will result in a framebuffer sync state, which
3429 // extracts deferred clears. However, as the blit is actually a noop, the deferred clears will
3430 // remain unflushed.
3431 GLTexture blitSrc;
3432 glBindTexture(GL_TEXTURE_2D, blitSrc);
3433 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3434
3435 GLFramebuffer readFBO;
3436 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3437 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3438 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3439
3440 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3441 EXPECT_GL_NO_ERROR();
3442
3443 // Change framebuffer's attachment to the other texture.
3444 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3445 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3446
3447 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3448 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3449 glUseProgram(program);
3450
3451 glEnable(GL_BLEND);
3452 glBlendFunc(GL_ZERO, GL_ONE);
3453 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3454 EXPECT_GL_NO_ERROR();
3455
3456 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3457 // to the new attachment, green will be read back.
3458 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3459 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3460
3461 // Attach back to texture2. It should be cleared to green.
3462 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3463 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3464 }
3465
3466 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3467 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3468 {
3469 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3470 glUseProgram(program);
3471
3472 glClear(GL_COLOR_BUFFER_BIT);
3473 glEnable(GL_CULL_FACE);
3474
3475 glCullFace(GL_FRONT);
3476
3477 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3478
3479 ASSERT_GL_NO_ERROR();
3480
3481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3482
3483 // Disable cull face and redraw, then make sure we have the quad drawn.
3484 glDisable(GL_CULL_FACE);
3485
3486 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3487
3488 ASSERT_GL_NO_ERROR();
3489
3490 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3491 }
3492
TEST_P(SimpleStateChangeTest,ScissorTest)3493 TEST_P(SimpleStateChangeTest, ScissorTest)
3494 {
3495 // This test validates this order of state changes:
3496 // 1- Set scissor but don't enable it, validate its not used.
3497 // 2- Enable it and validate its working.
3498 // 3- Disable the scissor validate its not used anymore.
3499
3500 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3501
3502 glClear(GL_COLOR_BUFFER_BIT);
3503
3504 // Set the scissor region, but don't enable it yet.
3505 glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3506 getWindowHeight() / 2);
3507
3508 // Fill the whole screen with a quad.
3509 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3510
3511 ASSERT_GL_NO_ERROR();
3512
3513 // Test outside, scissor isnt enabled so its red.
3514 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3515
3516 // Test inside, red of the fragment shader.
3517 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3518
3519 // Clear everything and start over with the test enabled.
3520 glClear(GL_COLOR_BUFFER_BIT);
3521 glEnable(GL_SCISSOR_TEST);
3522
3523 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3524
3525 ASSERT_GL_NO_ERROR();
3526
3527 // Test outside the scissor test, pitch black.
3528 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3529
3530 // Test inside, red of the fragment shader.
3531 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3532
3533 // Now disable the scissor test, do it again, and verify the region isn't used
3534 // for the scissor test.
3535 glDisable(GL_SCISSOR_TEST);
3536
3537 // Clear everything and start over with the test enabled.
3538 glClear(GL_COLOR_BUFFER_BIT);
3539
3540 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3541
3542 ASSERT_GL_NO_ERROR();
3543
3544 // Test outside, scissor isnt enabled so its red.
3545 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3546
3547 // Test inside, red of the fragment shader.
3548 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3549 }
3550
3551 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3552 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3553 {
3554 constexpr char kPositionUniformVertexShader[] = R"(
3555 precision mediump float;
3556 attribute vec2 position;
3557 uniform vec2 uniPosModifier;
3558 void main()
3559 {
3560 gl_Position = vec4(position + uniPosModifier, 0, 1);
3561 })";
3562
3563 ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3564 glUseProgram(program);
3565
3566 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3567 glClear(GL_COLOR_BUFFER_BIT);
3568
3569 GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3570 ASSERT_NE(posUniformLocation, -1);
3571 GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3572 ASSERT_NE(colorUniformLocation, -1);
3573
3574 // draw a red quad to the left side.
3575 glUniform2f(posUniformLocation, -0.5, 0.0);
3576 glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3577 drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3578
3579 // draw a green quad to the right side.
3580 glUniform2f(posUniformLocation, 0.5, 0.0);
3581 glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3582 drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3583
3584 ASSERT_GL_NO_ERROR();
3585
3586 // Test the center of the left quad. Should be red.
3587 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3588
3589 // Test the center of the right quad. Should be green.
3590 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3591 }
3592
3593 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3594 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3595 {
3596 GLRenderbuffer renderbuffer;
3597 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3598 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3599
3600 GLFramebuffer framebuffer;
3601 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3602 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3603
3604 ASSERT_GL_NO_ERROR();
3605 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3606
3607 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3608 GLint colorLoc = glGetAttribLocation(program, "color");
3609 ASSERT_NE(-1, colorLoc);
3610
3611 // Set up and draw red to the left half the screen.
3612 std::vector<GLColor> redData(6, GLColor::red);
3613 GLBuffer vertexBufferRed;
3614 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3615 glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3616 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3617 glEnableVertexAttribArray(colorLoc);
3618
3619 glViewport(0, 0, 16, 16);
3620 drawQuad(program, "position", 0.5f, 1.0f, true);
3621
3622 // Immediately redefine the Renderbuffer.
3623 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3624
3625 // Set up and draw green to the right half of the screen.
3626 std::vector<GLColor> greenData(6, GLColor::green);
3627 GLBuffer vertexBufferGreen;
3628 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3629 glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3630 GL_STATIC_DRAW);
3631 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3632 glEnableVertexAttribArray(colorLoc);
3633
3634 glViewport(0, 0, 64, 64);
3635 drawQuad(program, "position", 0.5f, 1.0f, true);
3636
3637 ASSERT_GL_NO_ERROR();
3638 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3639 }
3640
3641 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
3642 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)3643 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
3644 {
3645 constexpr size_t kSmallTextureSize = 2;
3646 constexpr size_t kBigTextureSize = 4;
3647
3648 // Create 2 textures, one of 2x2 and the other 4x4
3649 GLTexture texture1;
3650 glBindTexture(GL_TEXTURE_2D, texture1);
3651 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
3652 GL_UNSIGNED_BYTE, nullptr);
3653 ASSERT_GL_NO_ERROR();
3654
3655 GLTexture texture2;
3656 glBindTexture(GL_TEXTURE_2D, texture2);
3657 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
3658 GL_UNSIGNED_BYTE, nullptr);
3659 ASSERT_GL_NO_ERROR();
3660
3661 // A framebuffer for each texture to draw on.
3662 GLFramebuffer framebuffer1;
3663 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3664 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3665 ASSERT_GL_NO_ERROR();
3666 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3667
3668 GLFramebuffer framebuffer2;
3669 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3670 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3671 ASSERT_GL_NO_ERROR();
3672 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3673
3674 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3675 glUseProgram(program);
3676 GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3677 ASSERT_NE(uniformLocation, -1);
3678
3679 // Bind to the first framebuffer for drawing.
3680 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3681
3682 // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
3683 // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
3684 glScissor(0, 0, 16, 16);
3685 ASSERT_GL_NO_ERROR();
3686
3687 // Set color to red.
3688 glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3689 glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
3690
3691 // Draw a full sized red quad
3692 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3693 ASSERT_GL_NO_ERROR();
3694
3695 // Bind to the second (bigger) framebuffer
3696 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3697 glViewport(0, 0, kBigTextureSize, kBigTextureSize);
3698
3699 ASSERT_GL_NO_ERROR();
3700
3701 // Set color to green.
3702 glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3703
3704 // Draw again and we should fill everything with green and expect everything to be green.
3705 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3706 ASSERT_GL_NO_ERROR();
3707
3708 EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
3709 }
3710
3711 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)3712 TEST_P(SimpleStateChangeTest, RelinkProgram)
3713 {
3714 // http://anglebug.com/4121
3715 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
3716 const GLuint program = glCreateProgram();
3717
3718 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
3719 GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
3720 GLuint redFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
3721
3722 glAttachShader(program, vs);
3723 glAttachShader(program, blueFs);
3724
3725 glLinkProgram(program);
3726 CheckLinkStatusAndReturnProgram(program, true);
3727
3728 glClear(GL_COLOR_BUFFER_BIT);
3729 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
3730 {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
3731 GLBuffer vertexBuffer;
3732 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3733 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3734 GL_STATIC_DRAW);
3735 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3736 ASSERT_NE(-1, positionLocation);
3737 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3738 glEnableVertexAttribArray(positionLocation);
3739
3740 // Draw a blue triangle to the right
3741 glUseProgram(program);
3742 glDrawArrays(GL_TRIANGLES, 0, 3);
3743
3744 // Relink to draw red to the left
3745 glDetachShader(program, blueFs);
3746 glAttachShader(program, redFs);
3747
3748 glLinkProgram(program);
3749 CheckLinkStatusAndReturnProgram(program, true);
3750
3751 glDrawArrays(GL_TRIANGLES, 3, 3);
3752
3753 ASSERT_GL_NO_ERROR();
3754
3755 glDisableVertexAttribArray(positionLocation);
3756
3757 // Verify we drew red and green in the right places.
3758 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
3759 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
3760
3761 glDeleteShader(vs);
3762 glDeleteShader(blueFs);
3763 glDeleteShader(redFs);
3764 glDeleteProgram(program);
3765 }
3766
3767 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
3768 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)3769 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
3770 {
3771 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3772 glUseProgram(program);
3773
3774 const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3775 EXPECT_NE(-1, uniformLoc);
3776
3777 // Set color to red.
3778 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3779
3780 glClear(GL_COLOR_BUFFER_BIT);
3781 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
3782 GLBuffer vertexBuffer;
3783 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3784 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3785 GL_STATIC_DRAW);
3786 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3787 ASSERT_NE(-1, positionLocation);
3788 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3789 glEnableVertexAttribArray(positionLocation);
3790
3791 // Release program while its in use.
3792 glDeleteProgram(program);
3793
3794 // Draw a red triangle
3795 glDrawArrays(GL_TRIANGLES, 0, 3);
3796
3797 // Set color to green
3798 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3799
3800 // Draw a green triangle
3801 glDrawArrays(GL_TRIANGLES, 0, 3);
3802
3803 ASSERT_GL_NO_ERROR();
3804
3805 glDisableVertexAttribArray(positionLocation);
3806
3807 glUseProgram(0);
3808
3809 // Verify we drew red in the end since thats the last draw.
3810 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
3811 }
3812
3813 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)3814 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
3815 {
3816 // Create a sampler with NEAREST filtering.
3817 GLSampler sampler;
3818 glBindSampler(0, sampler);
3819 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3820 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3821 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3822 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3823 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3824 ASSERT_GL_NO_ERROR();
3825
3826 // Draw with a program that uses no textures.
3827 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3828 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
3829 ASSERT_GL_NO_ERROR();
3830 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3831
3832 // Create a simple texture with four colors and linear filtering.
3833 constexpr GLsizei kSize = 2;
3834 std::array<GLColor, 4> pixels = {
3835 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
3836 GLTexture redTex;
3837 glBindTexture(GL_TEXTURE_2D, redTex);
3838 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3839 pixels.data());
3840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3845
3846 // Create a program that uses the texture.
3847 constexpr char kVS[] = R"(attribute vec4 position;
3848 varying vec2 texCoord;
3849 void main()
3850 {
3851 gl_Position = position;
3852 texCoord = position.xy * 0.5 + vec2(0.5);
3853 })";
3854
3855 constexpr char kFS[] = R"(precision mediump float;
3856 varying vec2 texCoord;
3857 uniform sampler2D tex;
3858 void main()
3859 {
3860 gl_FragColor = texture2D(tex, texCoord);
3861 })";
3862
3863 // Draw. The sampler should override the clamp wrap mode with nearest.
3864 ANGLE_GL_PROGRAM(program2, kVS, kFS);
3865 ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
3866 drawQuad(program2, "position", 0.5f);
3867 ASSERT_GL_NO_ERROR();
3868
3869 constexpr int kHalfSize = kWindowSize / 2;
3870
3871 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
3872 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
3873 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
3874 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
3875 }
3876
3877 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)3878 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
3879 {
3880 // Test overview - Create two separate sampler objects, initially with the same
3881 // sampling args (NEAREST). Bind the same texture object to separate texture units.
3882 // FS samples from two samplers and blends result.
3883 // Bind separate sampler objects to the same texture units as the texture object.
3884 // Render & verify initial results
3885 // Next modify sampler0 to have LINEAR filtering instead of NEAREST
3886 // Render and save results
3887 // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
3888 // Render and verify results are the same as previous
3889
3890 // Create 2 samplers with NEAREST filtering.
3891 constexpr GLsizei kNumSamplers = 2;
3892 // We create/bind an extra sampler w/o bound tex object for testing purposes
3893 GLSampler samplers[kNumSamplers + 1];
3894 // Set samplers to initially have same state w/ NEAREST filter mode
3895 for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
3896 {
3897 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3898 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3899 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3900 glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3901 glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3902 glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
3903 glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
3904 glBindSampler(i, samplers[i]);
3905 ASSERT_GL_NO_ERROR();
3906 }
3907
3908 // Create a simple texture with four colors
3909 constexpr GLsizei kSize = 2;
3910 std::array<GLColor, 4> pixels = {
3911 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
3912 GLTexture rgbyTex;
3913 // Bind same texture object to tex units 0 & 1
3914 glActiveTexture(GL_TEXTURE0);
3915 glBindTexture(GL_TEXTURE_2D, rgbyTex);
3916 glActiveTexture(GL_TEXTURE1);
3917 glBindTexture(GL_TEXTURE_2D, rgbyTex);
3918 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3919 pixels.data());
3920
3921 // Create a program that uses the texture with 2 separate samplers.
3922 constexpr char kFS[] = R"(precision mediump float;
3923 varying vec2 v_texCoord;
3924 uniform sampler2D samp1;
3925 uniform sampler2D samp2;
3926 void main()
3927 {
3928 gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
3929 })";
3930
3931 // Create program and bind samplers to tex units 0 & 1
3932 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
3933 GLint s1loc = glGetUniformLocation(program, "samp1");
3934 GLint s2loc = glGetUniformLocation(program, "samp2");
3935 glUseProgram(program);
3936 glUniform1i(s1loc, 0);
3937 glUniform1i(s2loc, 1);
3938 // Draw. This first draw is a confidence check and not really necessary for the test
3939 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3940 ASSERT_GL_NO_ERROR();
3941
3942 constexpr int kHalfSize = kWindowSize / 2;
3943
3944 // When rendering w/ NEAREST, colors are all maxed out so should still be solid
3945 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
3946 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
3947 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
3948 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
3949
3950 // Make first sampler use linear filtering
3951 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3952 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3953
3954 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3955 ASSERT_GL_NO_ERROR();
3956 // Capture rendered pixel color with s0 linear
3957 std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
3958 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
3959
3960 // Now restore first sampler & update second sampler
3961 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3962 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3963 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3964 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3965
3966 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3967 ASSERT_GL_NO_ERROR();
3968 // Capture rendered pixel color w/ s1 linear
3969 std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
3970 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
3971 // Results should be the same regardless of if s0 or s1 is linear
3972 EXPECT_EQ(s0LinearColors, s1LinearColors);
3973 }
3974
3975 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)3976 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
3977 {
3978 constexpr char kVertexShader[] = R"(attribute vec4 a_position;
3979 attribute vec4 a_color;
3980 varying vec4 v_color;
3981 void main()
3982 {
3983 gl_Position = a_position;
3984 v_color = a_color;
3985 })";
3986
3987 constexpr char kFragmentShader[] = R"(precision mediump float;
3988 varying vec4 v_color;
3989 void main()
3990 {
3991 gl_FragColor = v_color;
3992 })";
3993
3994 ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
3995 GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
3996 ASSERT_NE(-1, positionLoc);
3997 GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
3998 ASSERT_NE(-1, colorLoc);
3999
4000 GLVertexArray VAOS[2];
4001 GLBuffer positionBuffer;
4002 GLBuffer colorBuffer;
4003 const auto quadVertices = GetQuadVertices();
4004
4005 glBindVertexArray(VAOS[0]);
4006 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4007 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4008 GL_STATIC_DRAW);
4009 glEnableVertexAttribArray(positionLoc);
4010 glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4011
4012 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4013 std::vector<GLColor32F> blueColor(6, kFloatBlue);
4014 glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4015 GL_STATIC_DRAW);
4016 glEnableVertexAttribArray(colorLoc);
4017 glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4018
4019 glBindVertexArray(0);
4020 glBindBuffer(GL_ARRAY_BUFFER, 0);
4021
4022 glBindVertexArray(VAOS[1]);
4023 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4024 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4025 GL_STATIC_DRAW);
4026 glEnableVertexAttribArray(positionLoc);
4027 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4028
4029 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4030 std::vector<GLColor32F> greenColor(6, kFloatGreen);
4031 glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4032 GL_STATIC_DRAW);
4033 glEnableVertexAttribArray(colorLoc);
4034 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4035
4036 glBindVertexArray(0);
4037 glBindBuffer(GL_ARRAY_BUFFER, 0);
4038
4039 glUseProgram(mProgram);
4040 ASSERT_GL_NO_ERROR();
4041
4042 glBindVertexArray(VAOS[1]);
4043 glClear(GL_COLOR_BUFFER_BIT);
4044 glDrawArrays(GL_TRIANGLES, 0, 6);
4045
4046 // This drawing should not affect the next drawing.
4047 glBindVertexArray(VAOS[0]);
4048 glClear(GL_COLOR_BUFFER_BIT);
4049 glDrawArrays(GL_TRIANGLES, 0, 6);
4050
4051 glBindVertexArray(VAOS[1]);
4052 glClear(GL_COLOR_BUFFER_BIT);
4053 glDrawArrays(GL_TRIANGLES, 0, 6);
4054
4055 EXPECT_GL_NO_ERROR();
4056 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4057 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4058 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4059 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4060
4061 ASSERT_GL_NO_ERROR();
4062 }
4063
4064 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4065 // correctly. This requires a memory barrier in between the draw calls which should not be
4066 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4067 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4068 {
4069 // http://anglebug.com/5593
4070 ANGLE_SKIP_TEST_IF(IsD3D11());
4071
4072 GLint maxFragmentImageUniforms;
4073 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4074
4075 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4076
4077 // The test uses a GL_R32F framebuffer.
4078 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4079
4080 constexpr GLsizei kSize = 1;
4081
4082 GLTexture color;
4083 glBindTexture(GL_TEXTURE_2D, color);
4084 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4085 EXPECT_GL_NO_ERROR();
4086
4087 GLFramebuffer fbo;
4088 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4089 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4090 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4091 EXPECT_GL_NO_ERROR();
4092
4093 const float kInitialValue = 0.125f;
4094
4095 GLTexture texture;
4096 glBindTexture(GL_TEXTURE_2D, texture);
4097 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4098 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4099 EXPECT_GL_NO_ERROR();
4100
4101 GLFramebuffer readbackFbo;
4102 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4103 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4104 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4105 EXPECT_GL_NO_ERROR();
4106
4107 // Create a program that outputs to the image in the fragment shader.
4108 constexpr char kFS[] = R"(#version 310 es
4109 precision mediump float;
4110 layout(r32f, binding = 0) uniform highp image2D dst;
4111 out vec4 colorOut;
4112 void main()
4113 {
4114 vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4115 colorOut = result;
4116
4117 result.x += 0.193;
4118 imageStore(dst, ivec2(gl_FragCoord.xy), result);
4119 })";
4120
4121 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4122 glUseProgram(program);
4123
4124 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4125 ASSERT_NE(-1, positionLoc);
4126
4127 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4128 EXPECT_GL_NO_ERROR();
4129
4130 // Setup the draw so that there's no state change between the draw calls.
4131 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4132 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4133
4134 GLBuffer posBuffer;
4135 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4136 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4137 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4138 glEnableVertexAttribArray(positionLoc);
4139 EXPECT_GL_NO_ERROR();
4140
4141 glDrawArrays(GL_TRIANGLES, 0, 6);
4142 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4143 glDrawArrays(GL_TRIANGLES, 0, 6);
4144 EXPECT_GL_NO_ERROR();
4145
4146 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4147 EXPECT_GL_NO_ERROR();
4148
4149 // Verify the output of the two draw calls through the image is correct
4150 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4151 0.001f);
4152
4153 // Verify the output of rendering as well
4154 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4155 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4156 }
4157
4158 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4159 // draw call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4160 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4161 {
4162 // http://anglebug.com/5593
4163 ANGLE_SKIP_TEST_IF(IsD3D11());
4164 // http://anglebug.com/5686
4165 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4166
4167 GLint maxFragmentImageUniforms;
4168 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4169
4170 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4171
4172 constexpr GLsizei kSize = 1;
4173
4174 GLTexture color;
4175 glBindTexture(GL_TEXTURE_2D, color);
4176 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4177 EXPECT_GL_NO_ERROR();
4178
4179 GLFramebuffer fbo;
4180 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4181 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4182 EXPECT_GL_NO_ERROR();
4183
4184 const GLColor kInitialColor = GLColor::red;
4185
4186 GLTexture texture;
4187 glBindTexture(GL_TEXTURE_2D, texture);
4188 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4189 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4190 &kInitialColor);
4191 EXPECT_GL_NO_ERROR();
4192
4193 GLFramebuffer readbackFbo;
4194 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4195 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4196 EXPECT_GL_NO_ERROR();
4197
4198 // Create a program that samples from the texture in the fragment shader.
4199 constexpr char kFSSample[] = R"(#version 310 es
4200 precision mediump float;
4201 uniform sampler2D tex;
4202 out vec4 colorOut;
4203 void main()
4204 {
4205 colorOut = texture(tex, vec2(0));
4206 })";
4207 ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4208
4209 // Create a program that outputs to the image in the fragment shader.
4210 constexpr char kFSWrite[] = R"(#version 310 es
4211 precision mediump float;
4212 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4213 out vec4 colorOut;
4214 void main()
4215 {
4216 colorOut = vec4(0, 0, 1.0, 0);
4217 imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4218 })";
4219
4220 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4221
4222 glUseProgram(sampleProgram);
4223 GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4224 ASSERT_NE(-1, positionLocSample);
4225
4226 glUseProgram(writeProgram);
4227 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4228 ASSERT_NE(-1, positionLocWrite);
4229
4230 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4231
4232 // Setup the draw so that there's no state change between the draw calls.
4233 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4234 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4235
4236 GLBuffer posBuffer;
4237 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4238 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4239 glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4240 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4241 glEnableVertexAttribArray(positionLocSample);
4242 glEnableVertexAttribArray(positionLocWrite);
4243
4244 glUseProgram(sampleProgram);
4245 glDrawArrays(GL_TRIANGLES, 0, 6);
4246
4247 glEnable(GL_BLEND);
4248 glBlendFunc(GL_ONE, GL_ONE);
4249 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4250
4251 glUseProgram(writeProgram);
4252 glDrawArrays(GL_TRIANGLES, 0, 6);
4253
4254 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4255 EXPECT_GL_NO_ERROR();
4256
4257 // Verify the output of the two draw calls through the image is correct
4258 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4259
4260 // Verify the output of rendering as well
4261 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4262 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4263 }
4264
4265 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4266 // call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4267 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4268 {
4269 // http://anglebug.com/5593
4270 ANGLE_SKIP_TEST_IF(IsD3D11());
4271
4272 GLint maxFragmentShaderStorageBlocks;
4273 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4274
4275 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4276
4277 constexpr GLsizei kSize = 1;
4278
4279 GLTexture color;
4280 glBindTexture(GL_TEXTURE_2D, color);
4281 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4282 EXPECT_GL_NO_ERROR();
4283
4284 GLFramebuffer fbo;
4285 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4286 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4287 EXPECT_GL_NO_ERROR();
4288
4289 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4290 GLBuffer buffer;
4291 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4292 glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4293 GL_STATIC_DRAW);
4294 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4295
4296 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4297 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4298
4299 // Create a program that reads from the ubo in the fragment shader.
4300 constexpr char kFSRead[] = R"(#version 310 es
4301 precision mediump float;
4302 uniform block { vec4 vec; } b;
4303 out vec4 colorOut;
4304 void main()
4305 {
4306 colorOut = b.vec;
4307 })";
4308 ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4309
4310 // Create a program that outputs to the image in the fragment shader.
4311 constexpr char kFSWrite[] = R"(#version 310 es
4312 precision mediump float;
4313 layout(binding = 0, std430) buffer Output {
4314 vec4 vec;
4315 } b;
4316 out vec4 colorOut;
4317 void main()
4318 {
4319 b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4320 colorOut = vec4(0.125, 0.125, 0.125, 0);
4321 })";
4322
4323 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4324
4325 glUseProgram(readProgram);
4326 GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4327 ASSERT_NE(-1, positionLocRead);
4328
4329 glUseProgram(writeProgram);
4330 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4331 ASSERT_NE(-1, positionLocWrite);
4332
4333 // Setup the draw so that there's no state change between the draw calls.
4334 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4335 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4336
4337 GLBuffer posBuffer;
4338 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4339 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4340 glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4341 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4342 glEnableVertexAttribArray(positionLocRead);
4343 glEnableVertexAttribArray(positionLocWrite);
4344
4345 glUseProgram(readProgram);
4346 glDrawArrays(GL_TRIANGLES, 0, 6);
4347
4348 glEnable(GL_BLEND);
4349 glBlendFunc(GL_ONE, GL_ONE);
4350 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4351
4352 glUseProgram(writeProgram);
4353 glDrawArrays(GL_TRIANGLES, 0, 6);
4354
4355 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4356 EXPECT_GL_NO_ERROR();
4357
4358 // Verify the output of rendering
4359 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4360
4361 // Verify the output from the second draw call
4362 const float *ptr = reinterpret_cast<const float *>(
4363 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4364
4365 EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4366 EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4367 EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4368 EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4369
4370 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4371 }
4372
4373 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4374 // call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4375 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4376 {
4377 // TODO(anglebug.com/5649): Test is failing since it was introduced on Linux AMD GLES
4378 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4379
4380 constexpr GLsizei kSize = 1;
4381 const GLColor kInitColor(111, 222, 33, 44);
4382
4383 GLTexture color;
4384 glBindTexture(GL_TEXTURE_2D, color);
4385 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4388 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4389 EXPECT_GL_NO_ERROR();
4390
4391 GLFramebuffer fbo;
4392 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4393 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4394 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4395 EXPECT_GL_NO_ERROR();
4396
4397 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4398 GLBuffer buffer;
4399 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4400 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4401 GL_STATIC_DRAW);
4402 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4403 EXPECT_GL_NO_ERROR();
4404
4405 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4406
4407 constexpr char kCS[] = R"(#version 310 es
4408 layout(local_size_x=1, local_size_y=1) in;
4409 uniform sampler2D tex;
4410 layout(binding = 0, std430) buffer Output {
4411 vec4 vec;
4412 } b;
4413 void main()
4414 {
4415 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4416 })";
4417
4418 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4419 glUseProgram(readProgram);
4420
4421 glActiveTexture(GL_TEXTURE0);
4422 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4423
4424 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
4425 EXPECT_GL_NO_ERROR();
4426
4427 glUseProgram(readProgram);
4428 glDispatchCompute(1, 1, 1);
4429
4430 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4431 EXPECT_GL_NO_ERROR();
4432
4433 // Verify the output of rendering
4434 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4435
4436 // Verify the output from the compute shader
4437 const float *ptr = reinterpret_cast<const float *>(
4438 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4439
4440 EXPECT_EQ(ptr[0], 1.0f);
4441 EXPECT_EQ(ptr[1], 0.0f);
4442 EXPECT_EQ(ptr[2], 0.0f);
4443 EXPECT_EQ(ptr[3], 1.0f);
4444
4445 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4446 }
4447
4448 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
4449 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)4450 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
4451 {
4452 // http://anglebug.com/5687
4453 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
4454
4455 constexpr GLsizei kSize = 1;
4456
4457 GLTexture color;
4458 glBindTexture(GL_TEXTURE_2D, color);
4459 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4462 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
4463 EXPECT_GL_NO_ERROR();
4464
4465 GLFramebuffer fbo;
4466 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4467 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4468 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4469 EXPECT_GL_NO_ERROR();
4470
4471 // Make sure the update to the texture is effective.
4472 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4473
4474 // Clear the texture through the framebuffer
4475 glClearColor(0, 1.0f, 0, 1.0f);
4476 glClear(GL_COLOR_BUFFER_BIT);
4477
4478 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4479 GLBuffer buffer;
4480 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4481 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4482 GL_STATIC_DRAW);
4483 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4484 EXPECT_GL_NO_ERROR();
4485
4486 constexpr char kCS[] = R"(#version 310 es
4487 layout(local_size_x=1, local_size_y=1) in;
4488 uniform sampler2D tex;
4489 layout(binding = 0, std430) buffer Output {
4490 vec4 vec;
4491 } b;
4492 void main()
4493 {
4494 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4495 })";
4496
4497 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4498 glUseProgram(readProgram);
4499
4500 glActiveTexture(GL_TEXTURE0);
4501 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4502
4503 glUseProgram(readProgram);
4504 glDispatchCompute(1, 1, 1);
4505
4506 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4507 EXPECT_GL_NO_ERROR();
4508
4509 // Verify the clear
4510 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4511
4512 // Verify the output from the compute shader
4513 const float *ptr = reinterpret_cast<const float *>(
4514 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4515
4516 EXPECT_EQ(ptr[0], 0.0f);
4517 EXPECT_EQ(ptr[1], 1.0f);
4518 EXPECT_EQ(ptr[2], 0.0f);
4519 EXPECT_EQ(ptr[3], 1.0f);
4520
4521 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4522 }
4523
4524 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
4525 // it in a dispatch call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)4526 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
4527 {
4528 // http://anglebug.com/5687
4529 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
4530
4531 constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
4532 GLBuffer buffer;
4533 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
4534 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
4535 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
4536
4537 std::vector<std::string> tfVaryings = {"gl_Position"};
4538 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
4539 essl3_shaders::fs::Green(), tfVaryings,
4540 GL_INTERLEAVED_ATTRIBS);
4541 glUseProgram(program);
4542
4543 glBeginTransformFeedback(GL_TRIANGLES);
4544 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
4545 glEndTransformFeedback();
4546
4547 constexpr char kCS[] = R"(#version 310 es
4548 layout(local_size_x=1, local_size_y=1) in;
4549 layout(binding = 0) uniform Input
4550 {
4551 vec4 data[3];
4552 };
4553 layout(binding = 0, std430) buffer Output {
4554 bool pass;
4555 };
4556 void main()
4557 {
4558 pass = data[0] == vec4(-1, 1, 0, 1) &&
4559 data[1] == vec4(-1, -1, 0, 1) &&
4560 data[2] == vec4(1, -1, 0, 1);
4561 })";
4562
4563 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4564 glUseProgram(readProgram);
4565
4566 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4567
4568 constexpr GLsizei kResultSize = sizeof(uint32_t);
4569 GLBuffer resultBuffer;
4570 glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
4571 glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
4572 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
4573
4574 glDispatchCompute(1, 1, 1);
4575
4576 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4577 EXPECT_GL_NO_ERROR();
4578
4579 // Verify the output of rendering
4580 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4581
4582 // Verify the output from the compute shader
4583 const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
4584 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
4585
4586 EXPECT_EQ(ptr[0], 1u);
4587
4588 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4589 }
4590
4591 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)4592 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
4593 {
4594 std::array<GLColor, 4> colors = {
4595 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4596 GLTexture texRead;
4597 glBindTexture(GL_TEXTURE_2D, texRead);
4598 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4599 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4600 EXPECT_GL_NO_ERROR();
4601
4602 glUseProgram(mProgram);
4603
4604 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4605 glDispatchCompute(1, 1, 1);
4606 texRead.reset();
4607
4608 std::array<GLColor, 4> results;
4609 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4610 EXPECT_GL_NO_ERROR();
4611
4612 for (int i = 0; i < 4; i++)
4613 {
4614 EXPECT_EQ(colors[i], results[i]);
4615 }
4616 }
4617
4618 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)4619 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
4620 {
4621 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4622 GLTexture texRead;
4623 glBindTexture(GL_TEXTURE_2D, texRead);
4624 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4625 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4626
4627 glUseProgram(mProgram);
4628
4629 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4630 glDispatchCompute(1, 1, 1);
4631
4632 // Bind again
4633 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4634 glDispatchCompute(1, 1, 1);
4635 EXPECT_GL_NO_ERROR();
4636
4637 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4638 }
4639
4640 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
4641 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)4642 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
4643 {
4644 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
4645 std::array<GLColor, 4> subColors = {
4646 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
4647
4648 GLTexture texRead;
4649 glBindTexture(GL_TEXTURE_2D, texRead);
4650 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4651 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4652
4653 glUseProgram(mProgram);
4654
4655 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4656 glDispatchCompute(1, 1, 1);
4657
4658 // Update bottom-half of image texture with green.
4659 glBindTexture(GL_TEXTURE_2D, texRead);
4660 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
4661 ASSERT_GL_NO_ERROR();
4662
4663 // Dispatch again, should still work.
4664 glDispatchCompute(1, 1, 1);
4665 ASSERT_GL_NO_ERROR();
4666
4667 // Validate first half of the image is red and the bottom is green.
4668 std::array<GLColor, 4> results;
4669 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4670 EXPECT_GL_NO_ERROR();
4671
4672 EXPECT_EQ(GLColor::green, results[0]);
4673 EXPECT_EQ(GLColor::green, results[1]);
4674 EXPECT_EQ(GLColor::red, results[2]);
4675 EXPECT_EQ(GLColor::red, results[3]);
4676 }
4677
4678 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)4679 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
4680 {
4681 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4682
4683 GLTexture texRead;
4684 glBindTexture(GL_TEXTURE_2D, texRead);
4685 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4686 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
4687
4688 glUseProgram(mProgram);
4689
4690 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4691 glDispatchCompute(1, 1, 1);
4692
4693 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
4694 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
4695 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
4696 ASSERT_GL_NO_ERROR();
4697
4698 // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
4699 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4700 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
4701 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
4702 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
4703
4704 // Dispatch again. The second dispatch call should use the updated YBGR data.
4705 glDispatchCompute(1, 1, 1);
4706
4707 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4708 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
4709 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
4710 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4711 ASSERT_GL_NO_ERROR();
4712 }
4713
4714 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)4715 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
4716 {
4717 std::array<GLColor, 4> colorsTexA = {
4718 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4719
4720 std::array<GLColor, 4> colorsTexB = {
4721 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
4722
4723 GLTexture texA;
4724 glBindTexture(GL_TEXTURE_2D, texA);
4725 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4726 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
4727 GLTexture texB;
4728 glBindTexture(GL_TEXTURE_2D, texB);
4729 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4730 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
4731
4732 glUseProgram(mProgram);
4733
4734 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4735 glDispatchCompute(1, 1, 1);
4736
4737 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4738 glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4739 glDispatchCompute(1, 1, 1);
4740
4741 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4742 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4743 glDispatchCompute(1, 1, 1);
4744
4745 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4746 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4747 ASSERT_GL_NO_ERROR();
4748 }
4749
4750 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
4751 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)4752 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
4753 {
4754 ANGLE_SKIP_TEST_IF(!IsVulkan());
4755
4756 glGenFramebuffers(1, &mFramebuffer);
4757 glGenTextures(1, &mTexture);
4758
4759 glBindTexture(GL_TEXTURE_2D, mTexture);
4760 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4761 EXPECT_GL_NO_ERROR();
4762
4763 constexpr char kCS[] = R"(#version 310 es
4764 layout(local_size_x=2, local_size_y=2) in;
4765 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
4766 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
4767 void main()
4768 {
4769 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
4770 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
4771 })";
4772
4773 bindProgramPipeline(kCS);
4774
4775 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4776
4777 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
4778 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
4779
4780 ASSERT_GL_NO_ERROR();
4781
4782 std::array<GLColor, 4> colors = {
4783 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4784 GLTexture texRead;
4785 glBindTexture(GL_TEXTURE_2D, texRead);
4786 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4787 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4788 EXPECT_GL_NO_ERROR();
4789
4790 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4791 glDispatchCompute(1, 1, 1);
4792 texRead.reset();
4793
4794 std::array<GLColor, 4> results;
4795 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4796 EXPECT_GL_NO_ERROR();
4797
4798 for (int i = 0; i < 4; i++)
4799 {
4800 EXPECT_EQ(colors[i], results[i]);
4801 }
4802 }
4803
4804 static constexpr char kColorVS[] = R"(attribute vec2 position;
4805 attribute vec4 color;
4806 varying vec4 vColor;
4807 void main()
4808 {
4809 gl_Position = vec4(position, 0, 1);
4810 vColor = color;
4811 })";
4812
4813 static constexpr char kColorFS[] = R"(precision mediump float;
4814 varying vec4 vColor;
4815 void main()
4816 {
4817 gl_FragColor = vColor;
4818 })";
4819
4820 class ValidationStateChangeTest : public ANGLETest
4821 {
4822 protected:
ValidationStateChangeTest()4823 ValidationStateChangeTest()
4824 {
4825 setWindowWidth(64);
4826 setWindowHeight(64);
4827 setConfigRedBits(8);
4828 setConfigGreenBits(8);
4829 setConfigBlueBits(8);
4830 setConfigAlphaBits(8);
4831 }
4832 };
4833
4834 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
4835 {
4836 protected:
WebGL2ValidationStateChangeTest()4837 WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4838 };
4839
4840 class ValidationStateChangeTestES31 : public ANGLETest
4841 {};
4842
4843 class WebGLComputeValidationStateChangeTest : public ANGLETest
4844 {
4845 public:
WebGLComputeValidationStateChangeTest()4846 WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4847 };
4848
4849 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
4850 {
4851 protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()4852 RobustBufferAccessWebGL2ValidationStateChangeTest()
4853 {
4854 // SwS/OSX GL do not support robustness. Mali does not support it.
4855 if (!isSwiftshader() && !IsOSX() && !IsIOS() && !IsARM())
4856 {
4857 setRobustAccess(true);
4858 }
4859 }
4860 };
4861
4862 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
4863 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)4864 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
4865 {
4866 // Initialize program and set up state.
4867 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
4868
4869 glUseProgram(program);
4870 GLint positionLoc = glGetAttribLocation(program, "position");
4871 ASSERT_NE(-1, positionLoc);
4872 GLint colorLoc = glGetAttribLocation(program, "color");
4873 ASSERT_NE(-1, colorLoc);
4874
4875 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4876 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4877
4878 GLBuffer posBuffer;
4879 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4880 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4881
4882 // Start with position enabled.
4883 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4884 glEnableVertexAttribArray(positionLoc);
4885
4886 std::vector<GLColor> colorVertices(6, GLColor::blue);
4887 const size_t colorBufferSize = sizeof(GLColor) * 6;
4888
4889 GLBuffer colorBuffer;
4890 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4891 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
4892
4893 // Start with color disabled.
4894 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
4895 glDisableVertexAttribArray(colorLoc);
4896
4897 ASSERT_GL_NO_ERROR();
4898
4899 // Draw without a mapped buffer. Should succeed.
4900 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
4901 glDrawArrays(GL_TRIANGLES, 0, 6);
4902 ASSERT_GL_NO_ERROR();
4903 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4904
4905 // Map position buffer and draw. Should fail.
4906 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4907 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
4908 ASSERT_GL_NO_ERROR();
4909
4910 glDrawArrays(GL_TRIANGLES, 0, 6);
4911 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
4912 glUnmapBuffer(GL_ARRAY_BUFFER);
4913
4914 // Map then enable color buffer. Should fail.
4915 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4916 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
4917 glEnableVertexAttribArray(colorLoc);
4918 ASSERT_GL_NO_ERROR();
4919
4920 glDrawArrays(GL_TRIANGLES, 0, 6);
4921 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
4922
4923 // Unmap then draw. Should succeed.
4924 glUnmapBuffer(GL_ARRAY_BUFFER);
4925 ASSERT_GL_NO_ERROR();
4926
4927 glDrawArrays(GL_TRIANGLES, 0, 6);
4928 ASSERT_GL_NO_ERROR();
4929 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4930 }
4931
4932 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
4933 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)4934 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
4935 {
4936 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
4937
4938 // Initialize program and set up state.
4939 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
4940
4941 glUseProgram(program);
4942 GLint positionLoc = glGetAttribLocation(program, "position");
4943 ASSERT_NE(-1, positionLoc);
4944 GLint colorLoc = glGetAttribLocation(program, "color");
4945 ASSERT_NE(-1, colorLoc);
4946
4947 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4948 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4949
4950 GLBuffer posBuffer;
4951 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4952 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
4953 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4954
4955 // Start with position enabled.
4956 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4957 glEnableVertexAttribArray(positionLoc);
4958
4959 std::vector<GLColor> colorVertices(6, GLColor::blue);
4960 const size_t colorBufferSize = sizeof(GLColor) * 6;
4961
4962 GLBuffer colorBuffer;
4963 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4964 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
4965 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4966
4967 // Start with color disabled.
4968 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
4969 glDisableVertexAttribArray(colorLoc);
4970
4971 ASSERT_GL_NO_ERROR();
4972
4973 // Draw without a mapped buffer. Should succeed.
4974 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
4975 glDrawArrays(GL_TRIANGLES, 0, 6);
4976 ASSERT_GL_NO_ERROR();
4977 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4978
4979 // Map position buffer and draw. Should succeed.
4980 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4981 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
4982 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4983 ASSERT_GL_NO_ERROR();
4984
4985 glDrawArrays(GL_TRIANGLES, 0, 6);
4986 ASSERT_GL_NO_ERROR();
4987 glUnmapBuffer(GL_ARRAY_BUFFER);
4988
4989 // Map then enable color buffer. Should succeed.
4990 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4991 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
4992 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4993 glEnableVertexAttribArray(colorLoc);
4994 ASSERT_GL_NO_ERROR();
4995
4996 glDrawArrays(GL_TRIANGLES, 0, 6);
4997 ASSERT_GL_NO_ERROR();
4998
4999 // Unmap then draw. Should succeed.
5000 glUnmapBuffer(GL_ARRAY_BUFFER);
5001 ASSERT_GL_NO_ERROR();
5002
5003 glDrawArrays(GL_TRIANGLES, 0, 6);
5004 ASSERT_GL_NO_ERROR();
5005 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5006 }
5007
5008 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5009 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5010 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5011 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5012 {
5013 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5014
5015 // Initialize program and set up state.
5016 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5017
5018 glUseProgram(program);
5019 GLint positionLoc = glGetAttribLocation(program, "position");
5020 ASSERT_NE(-1, positionLoc);
5021 GLint colorLoc = glGetAttribLocation(program, "color");
5022 ASSERT_NE(-1, colorLoc);
5023
5024 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5025 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5026
5027 GLBuffer posBuffer;
5028 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5029 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5030 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5031
5032 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5033 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5034
5035 // Start with position enabled.
5036 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5037 glEnableVertexAttribArray(positionLoc);
5038
5039 std::vector<GLColor> colorVertices(6, GLColor::blue);
5040 const size_t colorBufferSize = sizeof(GLColor) * 6;
5041
5042 GLBuffer colorBuffer;
5043 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5044 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5045 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5046
5047 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5048 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5049 ASSERT_GL_NO_ERROR();
5050
5051 // Start with color disabled.
5052 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5053 glDisableVertexAttribArray(colorLoc);
5054
5055 ASSERT_GL_NO_ERROR();
5056
5057 // Draw without a mapped buffer. Should succeed.
5058 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5059 glDrawArrays(GL_TRIANGLES, 0, 6);
5060 ASSERT_GL_NO_ERROR();
5061 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5062
5063 // Unmap then draw. Should succeed.
5064 glUnmapBuffer(GL_ARRAY_BUFFER);
5065 glEnableVertexAttribArray(colorLoc);
5066 ASSERT_GL_NO_ERROR();
5067 glDrawArrays(GL_TRIANGLES, 0, 6);
5068 ASSERT_GL_NO_ERROR();
5069 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5070 }
5071
5072 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5073 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5074 {
5075 // Seems to trigger a GL error in some edge cases. http://anglebug.com/2755
5076 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5077
5078 // Initialize program and set up state.
5079 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5080
5081 glUseProgram(program);
5082 GLint positionLoc = glGetAttribLocation(program, "position");
5083 ASSERT_NE(-1, positionLoc);
5084 GLint colorLoc = glGetAttribLocation(program, "color");
5085 ASSERT_NE(-1, colorLoc);
5086
5087 // Create a user vertex array.
5088 GLVertexArray vao;
5089 glBindVertexArray(vao);
5090
5091 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5092 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5093
5094 GLBuffer posBuffer;
5095 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5096 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5097
5098 // Start with position enabled.
5099 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5100 glEnableVertexAttribArray(positionLoc);
5101
5102 std::vector<GLColor> blueVertices(6, GLColor::blue);
5103 const size_t blueBufferSize = sizeof(GLColor) * 6;
5104
5105 GLBuffer blueBuffer;
5106 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5107 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5108
5109 // Start with color enabled at an unused binding.
5110 constexpr GLint kUnusedBinding = 3;
5111 ASSERT_NE(colorLoc, kUnusedBinding);
5112 ASSERT_NE(positionLoc, kUnusedBinding);
5113 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5114 glVertexAttribBinding(colorLoc, kUnusedBinding);
5115 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5116 glEnableVertexAttribArray(colorLoc);
5117
5118 // Make binding 'colorLoc' use a mapped buffer.
5119 std::vector<GLColor> greenVertices(6, GLColor::green);
5120 const size_t greenBufferSize = sizeof(GLColor) * 6;
5121 GLBuffer greenBuffer;
5122 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5123 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5124 glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5125 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5126
5127 ASSERT_GL_NO_ERROR();
5128
5129 // Draw without a mapped buffer. Should succeed.
5130 glDrawArrays(GL_TRIANGLES, 0, 6);
5131 ASSERT_GL_NO_ERROR();
5132 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5133
5134 // Change divisor with VertexAttribDivisor. Should fail.
5135 glVertexAttribDivisor(colorLoc, 0);
5136 ASSERT_GL_NO_ERROR();
5137 glDrawArrays(GL_TRIANGLES, 0, 6);
5138 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5139
5140 // Unmap the buffer. Should succeed.
5141 glUnmapBuffer(GL_ARRAY_BUFFER);
5142 glDrawArrays(GL_TRIANGLES, 0, 6);
5143 ASSERT_GL_NO_ERROR();
5144 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5145 }
5146
5147 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5148 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5149 {
5150 // Initialize program and set up state.
5151 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5152
5153 glUseProgram(program);
5154 GLint positionLoc = glGetAttribLocation(program, "position");
5155 ASSERT_NE(-1, positionLoc);
5156 GLint colorLoc = glGetAttribLocation(program, "color");
5157 ASSERT_NE(-1, colorLoc);
5158
5159 // Create a user vertex array.
5160 GLVertexArray vao;
5161 glBindVertexArray(vao);
5162
5163 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5164 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5165
5166 GLBuffer posBuffer;
5167 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5168 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5169
5170 // Start with position enabled.
5171 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5172 glEnableVertexAttribArray(positionLoc);
5173
5174 std::vector<GLColor> blueVertices(6, GLColor::blue);
5175 const size_t blueBufferSize = sizeof(GLColor) * 6;
5176
5177 GLBuffer blueBuffer;
5178 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5179 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5180
5181 // Start with color enabled at an unused binding.
5182 constexpr GLint kUnusedBinding = 3;
5183 ASSERT_NE(colorLoc, kUnusedBinding);
5184 ASSERT_NE(positionLoc, kUnusedBinding);
5185 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5186 glVertexAttribBinding(colorLoc, kUnusedBinding);
5187 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5188 glEnableVertexAttribArray(colorLoc);
5189
5190 // Make binding 'colorLoc' use a small buffer.
5191 std::vector<GLColor> greenVertices(6, GLColor::green);
5192 const size_t greenBufferSize = sizeof(GLColor) * 3;
5193 GLBuffer greenBuffer;
5194 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5195 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5196 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5197
5198 ASSERT_GL_NO_ERROR();
5199
5200 // Draw without a mapped buffer. Should succeed.
5201 glDrawArrays(GL_TRIANGLES, 0, 6);
5202 ASSERT_GL_NO_ERROR();
5203 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5204
5205 // Change divisor with VertexAttribDivisor. Should fail.
5206 glVertexAttribDivisor(colorLoc, 0);
5207 ASSERT_GL_NO_ERROR();
5208 glDrawArrays(GL_TRIANGLES, 0, 6);
5209 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5210
5211 // Do a small draw. Should succeed.
5212 glDrawArrays(GL_TRIANGLES, 0, 3);
5213 ASSERT_GL_NO_ERROR();
5214 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5215 }
5216
5217 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5218 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5219 {
5220 constexpr char kVS[] = R"(#version 300 es
5221 in vec2 position;
5222 void main()
5223 {
5224 gl_Position = vec4(position, 0, 1);
5225 })";
5226
5227 constexpr char kFS[] = R"(#version 300 es
5228 precision mediump float;
5229 uniform uni { vec4 vec; };
5230 out vec4 color;
5231 void main()
5232 {
5233 color = vec;
5234 })";
5235
5236 ANGLE_GL_PROGRAM(program, kVS, kFS);
5237 glUseProgram(program);
5238
5239 GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5240 ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5241
5242 glUniformBlockBinding(program, blockIndex, 0);
5243
5244 GLBuffer uniformBuffer;
5245 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5246 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5247 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5248
5249 const auto &quadVertices = GetQuadVertices();
5250
5251 GLBuffer positionBuffer;
5252 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5253 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5254 GL_STATIC_DRAW);
5255
5256 GLint positionLocation = glGetAttribLocation(program, "position");
5257 ASSERT_NE(-1, positionLocation);
5258
5259 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5260 glEnableVertexAttribArray(positionLocation);
5261 ASSERT_GL_NO_ERROR();
5262
5263 // First draw should succeed.
5264 glDrawArrays(GL_TRIANGLES, 0, 6);
5265 ASSERT_GL_NO_ERROR();
5266 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5267
5268 // Change the uniform block binding. Should fail.
5269 glUniformBlockBinding(program, blockIndex, 1);
5270 ASSERT_GL_NO_ERROR();
5271 glDrawArrays(GL_TRIANGLES, 0, 6);
5272 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5273
5274 // Reset to a correct state.
5275 glUniformBlockBinding(program, blockIndex, 0);
5276 glDrawArrays(GL_TRIANGLES, 0, 6);
5277 ASSERT_GL_NO_ERROR();
5278 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5279
5280 // Change the buffer binding. Should fail.
5281 glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5282 ASSERT_GL_NO_ERROR();
5283 glDrawArrays(GL_TRIANGLES, 0, 6);
5284 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5285
5286 // Reset to a correct state.
5287 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5288 glDrawArrays(GL_TRIANGLES, 0, 6);
5289 ASSERT_GL_NO_ERROR();
5290 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5291
5292 // Resize the buffer to be too small. Should fail.
5293 glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5294 glDrawArrays(GL_TRIANGLES, 0, 6);
5295 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5296 }
5297
5298 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5299 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5300 {
5301 // Set up a simple draw from a Texture to a user Framebuffer.
5302 GLuint program = get2DTexturedQuadProgram();
5303 ASSERT_NE(0u, program);
5304 glUseProgram(program);
5305
5306 GLint posLoc = glGetAttribLocation(program, "position");
5307 ASSERT_NE(-1, posLoc);
5308
5309 const auto &quadVertices = GetQuadVertices();
5310
5311 GLBuffer positionBuffer;
5312 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5313 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5314 GL_STATIC_DRAW);
5315
5316 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5317 glEnableVertexAttribArray(posLoc);
5318
5319 constexpr size_t kSize = 2;
5320
5321 GLTexture colorBufferTexture;
5322 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5323 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5324 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5326
5327 GLFramebuffer framebuffer;
5328 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5329 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5330 0);
5331 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5332
5333 std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
5334
5335 GLTexture greenTexture;
5336 glBindTexture(GL_TEXTURE_2D, greenTexture);
5337 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5338 greenColor.data());
5339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5341
5342 // Second framebuffer with a feedback loop. Initially unbound.
5343 GLFramebuffer loopedFramebuffer;
5344 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5345 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
5346 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5347 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5348
5349 ASSERT_GL_NO_ERROR();
5350
5351 glDrawArrays(GL_TRIANGLES, 0, 6);
5352 ASSERT_GL_NO_ERROR();
5353 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5354
5355 // Create a rendering feedback loop. Should fail.
5356 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5357 ASSERT_GL_NO_ERROR();
5358 glDrawArrays(GL_TRIANGLES, 0, 6);
5359 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5360
5361 // Reset to a valid state.
5362 glBindTexture(GL_TEXTURE_2D, greenTexture);
5363 glDrawArrays(GL_TRIANGLES, 0, 6);
5364 ASSERT_GL_NO_ERROR();
5365 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5366
5367 // Bind a second framebuffer with a feedback loop.
5368 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5369 ASSERT_GL_NO_ERROR();
5370 glDrawArrays(GL_TRIANGLES, 0, 6);
5371 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5372
5373 // Update the framebuffer texture attachment. Should succeed.
5374 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5375 0);
5376 glDrawArrays(GL_TRIANGLES, 0, 6);
5377 ASSERT_GL_NO_ERROR();
5378 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5379 }
5380
5381 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)5382 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
5383 {
5384 // Crashes on 64-bit Android. http://anglebug.com/3878
5385 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
5386
5387 // http://anglebug.com/5233
5388 ANGLE_SKIP_TEST_IF(IsMetal());
5389
5390 // Set up a program that writes to two outputs: one int and one float.
5391 constexpr char kVS[] = R"(#version 300 es
5392 layout(location = 0) in vec2 position;
5393 out vec2 texCoord;
5394 void main()
5395 {
5396 gl_Position = vec4(position, 0, 1);
5397 texCoord = position * 0.5 + vec2(0.5);
5398 })";
5399
5400 constexpr char kFS[] = R"(#version 300 es
5401 precision mediump float;
5402 in vec2 texCoord;
5403 layout(location = 0) out vec4 outFloat;
5404 layout(location = 1) out uvec4 outInt;
5405 void main()
5406 {
5407 outFloat = vec4(0, 1, 0, 1);
5408 outInt = uvec4(0, 1, 0, 1);
5409 })";
5410
5411 ANGLE_GL_PROGRAM(program, kVS, kFS);
5412 glUseProgram(program);
5413
5414 constexpr GLint kPosLoc = 0;
5415
5416 const auto &quadVertices = GetQuadVertices();
5417
5418 GLBuffer positionBuffer;
5419 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5420 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5421 GL_STATIC_DRAW);
5422
5423 glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5424 glEnableVertexAttribArray(kPosLoc);
5425
5426 constexpr size_t kSize = 2;
5427
5428 GLFramebuffer floatFramebuffer;
5429 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5430
5431 GLTexture floatTextures[2];
5432 for (int i = 0; i < 2; ++i)
5433 {
5434 glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
5435 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5436 nullptr);
5437 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5438 floatTextures[i], 0);
5439 ASSERT_GL_NO_ERROR();
5440 }
5441
5442 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5443
5444 GLFramebuffer intFramebuffer;
5445 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5446
5447 GLTexture intTextures[2];
5448 for (int i = 0; i < 2; ++i)
5449 {
5450 glBindTexture(GL_TEXTURE_2D, intTextures[i]);
5451 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
5452 GL_UNSIGNED_BYTE, nullptr);
5453 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5454 intTextures[i], 0);
5455 ASSERT_GL_NO_ERROR();
5456 }
5457
5458 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5459
5460 ASSERT_GL_NO_ERROR();
5461
5462 constexpr GLenum kColor0Enabled[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
5463 constexpr GLenum kColor1Enabled[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
5464 constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
5465
5466 // Draw float. Should work.
5467 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5468 glDrawBuffers(2, kColor0Enabled);
5469
5470 glDrawArrays(GL_TRIANGLES, 0, 6);
5471 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5472 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5473
5474 // Set an invalid component write.
5475 glDrawBuffers(2, kColor0And1Enabled);
5476 ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
5477 glDrawArrays(GL_TRIANGLES, 0, 6);
5478 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5479 // Set all 4 channels of color mask to false. Validate success.
5480 glColorMask(false, false, false, false);
5481 glDrawArrays(GL_TRIANGLES, 0, 6);
5482 EXPECT_GL_NO_ERROR();
5483 glColorMask(false, true, false, false);
5484 glDrawArrays(GL_TRIANGLES, 0, 6);
5485 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5486 glColorMask(true, true, true, true);
5487 glDrawArrays(GL_TRIANGLES, 0, 6);
5488 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5489
5490 // Restore state.
5491 glDrawBuffers(2, kColor0Enabled);
5492 glDrawArrays(GL_TRIANGLES, 0, 6);
5493 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5494 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5495
5496 // Bind an invalid framebuffer. Validate failure.
5497 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5498 ASSERT_GL_NO_ERROR();
5499 glDrawArrays(GL_TRIANGLES, 0, 6);
5500 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
5501
5502 // Set draw mask to a valid mask. Validate success.
5503 glDrawBuffers(2, kColor1Enabled);
5504 glDrawArrays(GL_TRIANGLES, 0, 6);
5505 ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
5506 }
5507
5508 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)5509 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
5510 {
5511 ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5512
5513 // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
5514 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
5515
5516 constexpr char kFS[] = R"(#version 300 es
5517 precision mediump float;
5518 uniform block { vec4 color; };
5519 out vec4 colorOut;
5520 void main()
5521 {
5522 colorOut = color;
5523 })";
5524
5525 std::vector<std::string> tfVaryings = {"gl_Position"};
5526 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
5527 GL_INTERLEAVED_ATTRIBS);
5528 glUseProgram(program);
5529
5530 std::vector<Vector4> positionData;
5531 for (const Vector3 &quadVertex : GetQuadVertices())
5532 {
5533 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5534 }
5535
5536 GLBuffer arrayBuffer;
5537 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5538 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5539 GL_STATIC_DRAW);
5540
5541 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5542 ASSERT_NE(-1, positionLoc);
5543
5544 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5545 glEnableVertexAttribArray(positionLoc);
5546
5547 EXPECT_GL_NO_ERROR();
5548
5549 // Set up transform feedback.
5550 GLTransformFeedback transformFeedback;
5551 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5552
5553 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5554
5555 GLBuffer transformFeedbackBuffer;
5556 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5557 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5558 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5559
5560 // Set up uniform buffer.
5561 GLBuffer uniformBuffer;
5562 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5563 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5564 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5565
5566 ASSERT_GL_NO_ERROR();
5567
5568 // Do the draw operation. Should succeed.
5569 glBeginTransformFeedback(GL_TRIANGLES);
5570 glDrawArrays(GL_TRIANGLES, 0, 6);
5571 glEndTransformFeedback();
5572
5573 ASSERT_GL_NO_ERROR();
5574 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5575
5576 const GLvoid *mapPointer =
5577 glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
5578 ASSERT_GL_NO_ERROR();
5579 ASSERT_NE(nullptr, mapPointer);
5580 const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
5581 std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
5582 EXPECT_EQ(positionData, actualData);
5583 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5584
5585 // Draw once to update validation cache.
5586 glBeginTransformFeedback(GL_TRIANGLES);
5587 glDrawArrays(GL_TRIANGLES, 0, 6);
5588
5589 // Bind transform feedback buffer to another binding point. Should cause a conflict.
5590 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
5591 ASSERT_GL_NO_ERROR();
5592 glDrawArrays(GL_TRIANGLES, 0, 6);
5593 glEndTransformFeedback();
5594 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
5595
5596 // Reset to valid state.
5597 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
5598 glBeginTransformFeedback(GL_TRIANGLES);
5599 glDrawArrays(GL_TRIANGLES, 0, 6);
5600 glEndTransformFeedback();
5601 ASSERT_GL_NO_ERROR();
5602
5603 // Simultaneous non-vertex-array binding. Should fail.
5604 glBeginTransformFeedback(GL_TRIANGLES);
5605 glDrawArrays(GL_TRIANGLES, 0, 6);
5606 ASSERT_GL_NO_ERROR();
5607 glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
5608 ASSERT_GL_NO_ERROR();
5609 glDrawArrays(GL_TRIANGLES, 0, 6);
5610 glEndTransformFeedback();
5611 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
5612 }
5613
5614 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)5615 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
5616 {
5617 // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
5618 // DEPTH_COMPONENT24 is emulated with D32_S8X24. http://anglebug.com/3880
5619 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
5620
5621 constexpr char kFS[] = R"(#version 300 es
5622 precision mediump float;
5623 uniform sampler2D sampler;
5624 out vec4 colorOut;
5625 void main()
5626 {
5627 colorOut = texture(sampler, vec2(0));
5628 })";
5629
5630 std::vector<std::string> tfVaryings = {"gl_Position"};
5631 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5632 glUseProgram(program);
5633
5634 std::array<GLColor, 4> colors = {
5635 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5636
5637 GLTexture tex;
5638 glBindTexture(GL_TEXTURE_2D, tex);
5639 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5640
5641 const auto &quadVertices = GetQuadVertices();
5642
5643 GLBuffer arrayBuffer;
5644 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5645 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5646 GL_STATIC_DRAW);
5647
5648 GLint samplerLoc = glGetUniformLocation(program, "sampler");
5649 ASSERT_NE(-1, samplerLoc);
5650 glUniform1i(samplerLoc, 0);
5651
5652 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5653 ASSERT_NE(-1, positionLoc);
5654 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5655 glEnableVertexAttribArray(positionLoc);
5656
5657 ASSERT_GL_NO_ERROR();
5658
5659 glDrawArrays(GL_TRIANGLES, 0, 6);
5660 ASSERT_GL_NO_ERROR();
5661
5662 // TexImage2D should update the sampler format cache.
5663 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
5664 colors.data());
5665 glDrawArrays(GL_TRIANGLES, 0, 6);
5666 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
5667
5668 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
5669 GL_UNSIGNED_INT, colors.data());
5670 glDrawArrays(GL_TRIANGLES, 0, 6);
5671 ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
5672
5673 // TexParameteri should update the sampler format cache.
5674 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
5675 glDrawArrays(GL_TRIANGLES, 0, 6);
5676 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
5677 }
5678
5679 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)5680 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
5681 {
5682 ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5683
5684 std::vector<std::string> tfVaryings = {"gl_Position"};
5685 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5686 essl3_shaders::fs::Red(), tfVaryings,
5687 GL_INTERLEAVED_ATTRIBS);
5688 glUseProgram(program);
5689
5690 std::vector<Vector4> positionData;
5691 for (const Vector3 &quadVertex : GetQuadVertices())
5692 {
5693 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5694 }
5695
5696 GLBuffer arrayBuffer;
5697 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5698 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5699 GL_STATIC_DRAW);
5700
5701 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5702 ASSERT_NE(-1, positionLoc);
5703
5704 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5705 glEnableVertexAttribArray(positionLoc);
5706
5707 // Set up transform feedback.
5708 GLTransformFeedback transformFeedback;
5709 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5710
5711 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5712
5713 GLBuffer transformFeedbackBuffer;
5714 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5715 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5716 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5717
5718 GLTransformFeedback pointsXFB;
5719 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5720 GLBuffer pointsXFBBuffer;
5721 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
5722 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
5723 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
5724
5725 // Begin TRIANGLES, switch to paused POINTS, should be valid.
5726 glBeginTransformFeedback(GL_POINTS);
5727 glPauseTransformFeedback();
5728 ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
5729
5730 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5731 glBeginTransformFeedback(GL_TRIANGLES);
5732 glDrawArrays(GL_TRIANGLES, 0, 6);
5733 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5734 glDrawArrays(GL_POINTS, 0, 6);
5735 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
5736 glDrawArrays(GL_LINES, 0, 6);
5737 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5738 glPauseTransformFeedback();
5739 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5740 glResumeTransformFeedback();
5741 glDrawArrays(GL_POINTS, 0, 6);
5742 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5743 glDrawArrays(GL_TRIANGLES, 0, 6);
5744 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
5745 glDrawArrays(GL_LINES, 0, 6);
5746 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5747
5748 glEndTransformFeedback();
5749 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5750 glEndTransformFeedback();
5751 ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
5752
5753 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
5754
5755 glDrawArrays(GL_POINTS, 0, 6);
5756 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5757 glDrawArrays(GL_TRIANGLES, 0, 6);
5758 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5759 glDrawArrays(GL_LINES, 0, 6);
5760 EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
5761 }
5762
5763 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)5764 TEST_P(ValidationStateChangeTest, TextureConflict)
5765 {
5766 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
5767
5768 GLint maxTextures = 0;
5769 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
5770 ANGLE_SKIP_TEST_IF(maxTextures < 2);
5771
5772 // Set up state.
5773 constexpr GLint kSize = 2;
5774
5775 std::vector<GLColor> greenData(4, GLColor::green);
5776
5777 GLTexture textureA;
5778 glBindTexture(GL_TEXTURE_2D, textureA);
5779 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5780 greenData.data());
5781 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5782 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5783
5784 glActiveTexture(GL_TEXTURE1);
5785
5786 GLTexture textureB;
5787 glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
5788 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5789 GL_UNSIGNED_BYTE, greenData.data());
5790 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5791 GL_UNSIGNED_BYTE, greenData.data());
5792 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5793 GL_UNSIGNED_BYTE, greenData.data());
5794 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5795 GL_UNSIGNED_BYTE, greenData.data());
5796 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5797 GL_UNSIGNED_BYTE, greenData.data());
5798 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5799 GL_UNSIGNED_BYTE, greenData.data());
5800 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5801 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5802
5803 constexpr char kVS[] = R"(attribute vec2 position;
5804 varying mediump vec2 texCoord;
5805 void main()
5806 {
5807 gl_Position = vec4(position, 0, 1);
5808 texCoord = position * 0.5 + vec2(0.5);
5809 })";
5810
5811 constexpr char kFS[] = R"(varying mediump vec2 texCoord;
5812 uniform sampler2D texA;
5813 uniform samplerCube texB;
5814 void main()
5815 {
5816 gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
5817 })";
5818
5819 ANGLE_GL_PROGRAM(program, kVS, kFS);
5820 glUseProgram(program);
5821
5822 const auto &quadVertices = GetQuadVertices();
5823
5824 GLBuffer arrayBuffer;
5825 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5826 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5827 GL_STATIC_DRAW);
5828
5829 GLint positionLoc = glGetAttribLocation(program, "position");
5830 ASSERT_NE(-1, positionLoc);
5831
5832 GLint texALoc = glGetUniformLocation(program, "texA");
5833 ASSERT_NE(-1, texALoc);
5834
5835 GLint texBLoc = glGetUniformLocation(program, "texB");
5836 ASSERT_NE(-1, texBLoc);
5837
5838 glUniform1i(texALoc, 0);
5839 glUniform1i(texBLoc, 1);
5840
5841 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5842 glEnableVertexAttribArray(positionLoc);
5843
5844 ASSERT_GL_NO_ERROR();
5845
5846 // First draw. Should succeed.
5847 glDrawArrays(GL_TRIANGLES, 0, 6);
5848 ASSERT_GL_NO_ERROR();
5849 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5850
5851 // Second draw to ensure all state changes are flushed.
5852 glDrawArrays(GL_TRIANGLES, 0, 6);
5853 ASSERT_GL_NO_ERROR();
5854
5855 // Make the uniform use an invalid texture binding.
5856 glUniform1i(texBLoc, 0);
5857 glDrawArrays(GL_TRIANGLES, 0, 6);
5858 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5859 }
5860
5861 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)5862 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
5863 {
5864 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
5865 glUseProgram(program);
5866
5867 std::array<GLushort, 6> quadIndices = GetQuadIndices();
5868 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
5869
5870 GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
5871
5872 GLBuffer elementArrayBuffer;
5873 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
5874 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
5875
5876 GLBuffer arrayBuffer;
5877 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5878 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
5879 quadVertices.data(), GL_STATIC_DRAW);
5880
5881 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5882 ASSERT_NE(-1, positionLoc);
5883 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5884 glEnableVertexAttribArray(positionLoc);
5885
5886 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5887 ASSERT_GL_NO_ERROR();
5888
5889 void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
5890 ASSERT_NE(nullptr, ptr);
5891
5892 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5893 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5894
5895 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
5896
5897 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5898 ASSERT_GL_NO_ERROR();
5899 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5900 }
5901
5902 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)5903 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
5904 {
5905 constexpr char kFS[] =
5906 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
5907 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5908 glUseProgram(program);
5909 GLint loc = glGetUniformLocation(program, "us");
5910 ASSERT_EQ(0, loc);
5911
5912 auto quadVertices = GetQuadVertices();
5913 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
5914 ASSERT_EQ(0, posLoc);
5915
5916 GLBuffer buffer;
5917 glBindBuffer(GL_ARRAY_BUFFER, buffer);
5918 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
5919 quadVertices.data(), GL_STATIC_DRAW);
5920 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5921 glEnableVertexAttribArray(posLoc);
5922
5923 constexpr size_t kSize = 2;
5924 std::vector<GLColor> red(kSize * kSize, GLColor::red);
5925
5926 GLTexture tex;
5927 glBindTexture(GL_TEXTURE_2D, tex);
5928 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
5929 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5930 glUniform1i(loc, 0);
5931
5932 glDrawArrays(GL_TRIANGLES, 0, 3);
5933 ASSERT_GL_NO_ERROR();
5934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5935
5936 // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
5937 GLTexture tex2;
5938 glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
5939 tex2.reset();
5940
5941 glDrawArrays(GL_TRIANGLES, 0, 3);
5942 ASSERT_GL_NO_ERROR();
5943 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5944
5945 // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
5946 tex.reset();
5947
5948 glDrawArrays(GL_TRIANGLES, 0, 3);
5949 ASSERT_GL_NO_ERROR();
5950 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5951 }
5952
5953 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)5954 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
5955 {
5956 constexpr char kFS[] =
5957 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
5958 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5959 glUseProgram(program);
5960 GLint loc = glGetUniformLocation(program, "us");
5961 ASSERT_EQ(0, loc);
5962
5963 auto quadVertices = GetQuadVertices();
5964 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
5965 ASSERT_EQ(0, posLoc);
5966
5967 GLBuffer buffer;
5968 glBindBuffer(GL_ARRAY_BUFFER, buffer);
5969 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
5970 quadVertices.data(), GL_STATIC_DRAW);
5971 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5972 glEnableVertexAttribArray(posLoc);
5973
5974 constexpr size_t kSize = 2;
5975 std::vector<GLColor> red(kSize * kSize, GLColor::red);
5976
5977 GLTexture tex;
5978 glBindTexture(GL_TEXTURE_2D, tex);
5979 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
5980 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5981 glUniform1i(loc, 1);
5982 tex.reset();
5983
5984 glDrawArrays(GL_TRIANGLES, 0, 3);
5985 ASSERT_GL_NO_ERROR();
5986 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5987 }
5988
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)5989 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
5990 {
5991 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5992 glBindTexture(GL_TEXTURE_2D, texture);
5993 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5994 GL_UNSIGNED_BYTE, nullptr);
5995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5997 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5998 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5999 }
6000
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6001 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6002 {
6003 // Render to an FBO
6004 GLFramebuffer fbo1;
6005 GLTexture texture1;
6006
6007 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6008 ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6009 essl1_shaders::fs::Texture2D());
6010
6011 bindTextureToFbo(fbo1, texture1);
6012
6013 // Clear the surface FBO to initialize it to a known value
6014 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6015 glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6016 glClear(GL_COLOR_BUFFER_BIT);
6017 ASSERT_GL_NO_ERROR();
6018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6019 glFlush();
6020
6021 // Draw to FBO 1 to initialize it to a known value
6022 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6023
6024 if (earlyFrontFaceDirty)
6025 {
6026 glEnable(GL_CULL_FACE);
6027 // Make sure we don't cull
6028 glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6029 glFrontFace(frontFace);
6030 }
6031 else
6032 {
6033 glDisable(GL_CULL_FACE);
6034 }
6035
6036 glUseProgram(greenProgram);
6037 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6038 ASSERT_GL_NO_ERROR();
6039 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6040
6041 // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6042 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6043 glBindTexture(GL_TEXTURE_2D, texture1);
6044
6045 glCullFace(GL_BACK);
6046 if (!earlyFrontFaceDirty)
6047 {
6048 // Set the culling we want to test
6049 glEnable(GL_CULL_FACE);
6050 glFrontFace(frontFace);
6051 }
6052
6053 glUseProgram(textureProgram);
6054 drawQuad(textureProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6055 ASSERT_GL_NO_ERROR();
6056
6057 if (frontFace == GL_CCW)
6058 {
6059 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6060 }
6061 else
6062 {
6063 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6064 }
6065
6066 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6067 glBindTexture(GL_TEXTURE_2D, 0);
6068 }
6069
6070 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6071 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6072 {
6073 drawToFboWithCulling(GL_CCW, true);
6074 }
6075
6076 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6077 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6078 {
6079 drawToFboWithCulling(GL_CW, true);
6080 }
6081
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6082 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6083 {
6084 drawToFboWithCulling(GL_CCW, false);
6085 }
6086
6087 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6088 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6089 {
6090 drawToFboWithCulling(GL_CW, false);
6091 }
6092
6093 // Test that vertex attribute translation is still kept after binding it to another buffer then
6094 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6095 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6096 {
6097 // http://anglebug.com/5379
6098 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6099
6100 constexpr char kVS[] = R"(attribute vec4 a_position;
6101 attribute float a_attrib;
6102 varying float v_attrib;
6103 void main()
6104 {
6105 v_attrib = a_attrib;
6106 gl_Position = a_position;
6107 })";
6108
6109 constexpr char kFS[] = R"(precision mediump float;
6110 varying float v_attrib;
6111 void main()
6112 {
6113 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6114 })";
6115
6116 ANGLE_GL_PROGRAM(program, kVS, kFS);
6117 glBindAttribLocation(program, 0, "a_position");
6118 glBindAttribLocation(program, 1, "a_attrib");
6119 glLinkProgram(program);
6120 glUseProgram(program);
6121 ASSERT_GL_NO_ERROR();
6122
6123 // Set up color data so red is drawn
6124 std::vector<GLushort> data(1000, 0xffff);
6125
6126 GLBuffer redBuffer;
6127 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6128 glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6129 // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6130 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6131 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6132 glBindBuffer(GL_ARRAY_BUFFER, 0);
6133 glEnableVertexAttribArray(1);
6134
6135 drawQuad(program, "a_position", 0.5f);
6136 // Verify red was drawn
6137 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6138
6139 glClearColor(0, 1, 0, 1);
6140 glClear(GL_COLOR_BUFFER_BIT);
6141 // Verify that green was drawn
6142 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6143
6144 // Bind black color buffer to the same attribute with zero offset
6145 std::vector<GLfloat> black(6, 0.0f);
6146 GLBuffer blackBuffer;
6147 glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6148 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6149 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6150
6151 drawQuad(program, "a_position", 0.5f);
6152 // Verify black was drawn
6153 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6154
6155 // Rebind the old buffer & offset
6156 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6157 // Use offset not multiple of 4 GLushorts
6158 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6159 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6160
6161 drawQuad(program, "a_position", 0.5f);
6162 // Verify red was drawn
6163 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6164 }
6165
6166 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6167 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6168 {
6169 constexpr char kVS[] = R"(attribute vec4 a_position;
6170 varying float v_attrib;
6171 uniform float u_value;
6172 void main()
6173 {
6174 v_attrib = u_value;
6175 gl_Position = a_position;
6176 })";
6177
6178 constexpr char kFS[] = R"(precision mediump float;
6179 varying float v_attrib;
6180 void main()
6181 {
6182 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6183 })";
6184
6185 ANGLE_GL_PROGRAM(program1, kVS, kFS);
6186 ANGLE_GL_PROGRAM(program2, kVS, kFS);
6187
6188 // Don't use drawQuad so there's no state changes between the draw calls other than the program
6189 // binding.
6190
6191 constexpr size_t kProgramCount = 2;
6192 GLuint programs[kProgramCount] = {program1, program2};
6193 for (size_t i = 0; i < kProgramCount; ++i)
6194 {
6195 glUseProgram(programs[i]);
6196 GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6197 ASSERT_NE(uniformLoc, -1);
6198
6199 glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6200
6201 // Ensure position is at location 0 in both programs.
6202 GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6203 ASSERT_EQ(positionLocation, 0);
6204 }
6205 ASSERT_GL_NO_ERROR();
6206
6207 std::array<Vector3, 6> quadVertices = GetQuadVertices();
6208 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6209 glEnableVertexAttribArray(0);
6210
6211 // Draw once with each so their uniforms are updated.
6212 // The first draw will clear the screen to 255, 0, 0, 255
6213 glUseProgram(program2);
6214 glDrawArrays(GL_TRIANGLES, 0, 6);
6215 // The second draw will clear the screen to 127, 0, 0, 255
6216 glUseProgram(program1);
6217 glDrawArrays(GL_TRIANGLES, 0, 6);
6218
6219 // Draw with the previous program again, to make sure its default uniforms are bound again.
6220 glUseProgram(program2);
6221 glDrawArrays(GL_TRIANGLES, 0, 6);
6222
6223 // Verify red was drawn
6224 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6225 }
6226
6227 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
6228 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)6229 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
6230 {
6231 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6232
6233 GLBuffer indexBuffer;
6234 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6235 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
6236 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
6237 ASSERT_GL_NO_ERROR();
6238
6239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6240 }
6241
6242 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)6243 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
6244 {
6245 glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6246 glClear(GL_COLOR_BUFFER_BIT);
6247 ASSERT_GL_NO_ERROR();
6248 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6249
6250 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6251 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6252
6253 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6254 glEnable(GL_RASTERIZER_DISCARD);
6255 glUseProgram(greenProgram);
6256 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6257 ASSERT_GL_NO_ERROR();
6258 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6259
6260 // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
6261 glDisable(GL_RASTERIZER_DISCARD);
6262 glUseProgram(greenProgram);
6263 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6264 ASSERT_GL_NO_ERROR();
6265 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6266
6267 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6268 glEnable(GL_RASTERIZER_DISCARD);
6269 glUseProgram(blueProgram);
6270 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6271 ASSERT_GL_NO_ERROR();
6272 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6273 }
6274
6275 class ImageRespecificationTest : public ANGLETest
6276 {
6277 protected:
ImageRespecificationTest()6278 ImageRespecificationTest()
6279 {
6280 setWindowWidth(128);
6281 setWindowHeight(128);
6282 setConfigRedBits(8);
6283 setConfigGreenBits(8);
6284 setConfigBlueBits(8);
6285 setConfigAlphaBits(8);
6286 setConfigDepthBits(24);
6287 }
6288
testSetUp()6289 void testSetUp() override
6290 {
6291 constexpr char kVS[] = R"(precision highp float;
6292 attribute vec4 position;
6293 varying vec2 texcoord;
6294
6295 void main()
6296 {
6297 gl_Position = position;
6298 texcoord = (position.xy * 0.5) + 0.5;
6299 })";
6300
6301 constexpr char kFS[] = R"(precision highp float;
6302 uniform sampler2D tex;
6303 varying vec2 texcoord;
6304
6305 void main()
6306 {
6307 gl_FragColor = texture2D(tex, texcoord);
6308 })";
6309
6310 mProgram = CompileProgram(kVS, kFS);
6311 ASSERT_NE(0u, mProgram);
6312
6313 mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
6314 ASSERT_NE(-1, mTextureUniformLocation);
6315
6316 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6317 ASSERT_GL_NO_ERROR();
6318 }
6319
testTearDown()6320 void testTearDown() override
6321 {
6322 if (mProgram != 0)
6323 {
6324 glDeleteProgram(mProgram);
6325 }
6326 }
6327
6328 template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)6329 void init2DSourceTexture(GLenum internalFormat,
6330 GLenum dataFormat,
6331 GLenum dataType,
6332 const T *data)
6333 {
6334 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6335 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6336
6337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6339
6340 glBindTexture(GL_TEXTURE_2D, 0);
6341 }
6342
attachTargetTextureToFramebuffer()6343 void attachTargetTextureToFramebuffer()
6344 {
6345 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6346 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
6347 0);
6348
6349 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6350 ASSERT_GL_NO_ERROR();
6351
6352 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6353 }
6354
renderToTargetTexture()6355 void renderToTargetTexture()
6356 {
6357 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6358
6359 glActiveTexture(GL_TEXTURE0);
6360 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6361
6362 glUseProgram(mProgram);
6363 glUniform1i(mTextureUniformLocation, 0);
6364
6365 drawQuad(mProgram, "position", 0.5f);
6366 ASSERT_GL_NO_ERROR();
6367
6368 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6369 glBindTexture(GL_TEXTURE_2D, 0);
6370 glUseProgram(0);
6371 }
6372
renderToDefaultFramebuffer(GLColor * expectedData)6373 void renderToDefaultFramebuffer(GLColor *expectedData)
6374 {
6375 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6376 glUseProgram(mProgram);
6377 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6378 glUniform1i(mTextureUniformLocation, 0);
6379
6380 glClear(GL_COLOR_BUFFER_BIT);
6381 drawQuad(mProgram, "position", 0.5f);
6382 ASSERT_GL_NO_ERROR();
6383
6384 EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
6385
6386 glBindTexture(GL_TEXTURE_2D, 0);
6387 glUseProgram(0);
6388 }
6389
6390 GLuint mProgram;
6391 GLint mTextureUniformLocation;
6392
6393 GLTexture mSourceTexture;
6394 GLTexture mTargetTexture;
6395
6396 GLFramebuffer mFramebuffer;
6397 };
6398
6399 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)6400 TEST_P(ImageRespecificationTest, Swizzle)
6401 {
6402 GLubyte data[] = {1, 64, 128, 200};
6403 GLColor expectedData(data[0], data[1], data[2], data[3]);
6404
6405 // Create the source and target texture
6406 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6407
6408 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6410
6411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6413
6414 glBindTexture(GL_TEXTURE_2D, 0);
6415
6416 // Create a framebuffer and the target texture is attached to the framebuffer.
6417 attachTargetTextureToFramebuffer();
6418
6419 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6420 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6421 glClear(GL_COLOR_BUFFER_BIT);
6422 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6423
6424 // Render content of source texture to target texture
6425 // This command triggers the creation of -
6426 // - draw imageviews of the texture
6427 // - VkFramebuffer object of the framebuffer
6428 renderToTargetTexture();
6429
6430 // This swizzle operation should cause the read imageviews of the texture to be released
6431 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6432 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
6433 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
6434 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
6435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
6436 glBindTexture(GL_TEXTURE_2D, 0);
6437
6438 // Draw using the newly created read imageviews
6439 renderToDefaultFramebuffer(&expectedData);
6440
6441 // Render content of source texture to target texture, again
6442 renderToTargetTexture();
6443
6444 // Make sure the content rendered to target texture is correct
6445 renderToDefaultFramebuffer(&expectedData);
6446 }
6447
6448 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
6449 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)6450 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
6451 {
6452 // This is the specific problem on the Vulkan backend and needs some extensions
6453 ANGLE_SKIP_TEST_IF(
6454 !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
6455 !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
6456
6457 GLubyte data[] = {1, 64, 128, 200};
6458 GLColor expectedData(data[0], data[1], data[2], data[3]);
6459
6460 // Create the source texture
6461 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6462
6463 // Create the first EGL image to attach the framebuffer through the texture
6464 GLTexture firstTexture;
6465
6466 glBindTexture(GL_TEXTURE_2D, firstTexture);
6467 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6468
6469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6471
6472 glBindTexture(GL_TEXTURE_2D, 0);
6473
6474 EGLWindow *window = getEGLWindow();
6475 EGLint attribs[] = {
6476 EGL_IMAGE_PRESERVED,
6477 EGL_TRUE,
6478 EGL_NONE,
6479 };
6480 EGLImageKHR firstEGLImage =
6481 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6482 reinterpret_cast<EGLClientBuffer>(firstTexture.get()), attribs);
6483 ASSERT_EGL_SUCCESS();
6484
6485 // Create the target texture and attach it to the framebuffer
6486 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6487 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6488
6489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6490 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6491
6492 glBindTexture(GL_TEXTURE_2D, 0);
6493
6494 attachTargetTextureToFramebuffer();
6495
6496 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6497
6498 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6499 glClear(GL_COLOR_BUFFER_BIT);
6500
6501 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6502
6503 // Render content of source texture to target texture
6504 // This command triggers the creation of -
6505 // - draw imageviews of the texture
6506 // - VkFramebuffer object of the framebuffer
6507 renderToTargetTexture();
6508
6509 // Make sure the content rendered to target texture is correct
6510 renderToDefaultFramebuffer(&expectedData);
6511
6512 // Create the second EGL image
6513 GLTexture secondTexture;
6514
6515 glBindTexture(GL_TEXTURE_2D, secondTexture);
6516 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6517
6518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6520
6521 glBindTexture(GL_TEXTURE_2D, 0);
6522
6523 EGLImageKHR secondEGLImage =
6524 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6525 reinterpret_cast<EGLClientBuffer>(secondTexture.get()), attribs);
6526 ASSERT_EGL_SUCCESS();
6527
6528 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6529 // This will release all the imageviews related to the first EGL image
6530 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
6531
6532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6534
6535 glBindTexture(GL_TEXTURE_2D, 0);
6536
6537 // Attach the first EGL image to the target texture again
6538 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6539 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6540
6541 // This is for checking this code can deal with the problem even if both ORPHAN and
6542 // COLOR_ATTACHMENT dirty bits are set.
6543 GLTexture tempTexture;
6544
6545 glBindTexture(GL_TEXTURE_2D, tempTexture);
6546 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6547
6548 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6549 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6550
6551 glBindTexture(GL_TEXTURE_2D, 0);
6552
6553 // This sets COLOR_ATTACHMENT dirty bit
6554 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6555 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
6556 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6557
6558 // The released imageviews related to "secondEGLImage" will be garbage collected
6559 renderToDefaultFramebuffer(&expectedData);
6560
6561 // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
6562 renderToTargetTexture();
6563
6564 // Make sure the content rendered to target texture is correct
6565 renderToDefaultFramebuffer(&expectedData);
6566
6567 // Render content of source texture to target texture
6568 attachTargetTextureToFramebuffer();
6569 renderToTargetTexture();
6570
6571 // Make sure the content rendered to target texture is correct
6572 renderToDefaultFramebuffer(&expectedData);
6573
6574 eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
6575 eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
6576 }
6577
6578 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)6579 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
6580 {
6581 GLushort indexData[] = {0, 1, 2, 3};
6582
6583 GLBuffer elementArrayBuffer;
6584 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6585 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
6586
6587 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
6588 glUseProgram(program);
6589
6590 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
6591
6592 elementArrayBuffer.reset();
6593
6594 // Must use a non-0 offset and a multiple of the type size.
6595 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
6596 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6597 }
6598
6599 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)6600 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
6601 {
6602 // SwiftShader does not currently support robustness.
6603 ANGLE_SKIP_TEST_IF(isSwiftshader());
6604
6605 // http://anglebug.com/4872
6606 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
6607
6608 // no intent to follow up on this failure.
6609 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
6610
6611 // no intent to follow up on this failure.
6612 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6613
6614 // no intent to follow up on this failure.
6615 ANGLE_SKIP_TEST_IF(IsOSX());
6616
6617 // Mali does not support robustness now.
6618 ANGLE_SKIP_TEST_IF(IsARM());
6619
6620 // TODO(anglebug.com/5491)
6621 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6622
6623 std::vector<GLubyte> data(48, 1);
6624
6625 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6626 glUseProgram(program);
6627
6628 // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
6629 GLBuffer arrayBuffer;
6630 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6631 glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
6632 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6633 glEnableVertexAttribArray(0);
6634 glDrawArrays(GL_TRIANGLES, 0, 3);
6635
6636 // Then bind a zero size buffer and draw.
6637 GLBuffer secondBuffer;
6638 glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
6639 glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
6640 glDrawArrays(GL_TRIANGLES, 0, 3);
6641
6642 // Finally delete the original buffer. This triggers the bug.
6643 arrayBuffer.reset();
6644 glDrawArrays(GL_TRIANGLES, 0, 3);
6645 ASSERT_GL_NO_ERROR();
6646 }
6647
6648 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)6649 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
6650 {
6651 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6652
6653 glUseProgram(program);
6654
6655 // Draw with empty buffer. Out of range but valid.
6656 GLBuffer buffer;
6657 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
6658 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
6659
6660 // Switch VAO. No buffer bound, should be an error.
6661 GLVertexArray vao;
6662 glBindVertexArray(vao);
6663 glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
6664 reinterpret_cast<const GLvoid *>(0x1000));
6665 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6666 }
6667
6668 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
6669 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)6670 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
6671 {
6672 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6673 // bit.
6674 GLBuffer indexBuffer;
6675 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6676
6677 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6678 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6679
6680 // Setup vertices.
6681 const std::array<GLfloat, 6> kVertices = {
6682 -1, -1, 3, -1, -1, 3,
6683 };
6684 GLBuffer vertexBuffer;
6685 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6686 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6687 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6688 glEnableVertexAttribArray(0);
6689
6690 // Create a uniform buffer that will get modified. This is used to break the render pass.
6691 const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
6692
6693 GLBuffer ubo;
6694 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
6695 glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
6696 glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
6697
6698 // Set up a program. The same program is used for all draw calls to avoid state change due to
6699 // program change.
6700 constexpr char kFS[] = R"(#version 300 es
6701 precision mediump float;
6702 uniform block { uint data; } ubo;
6703 uniform uint expect;
6704 uniform vec4 successColor;
6705 out vec4 colorOut;
6706 void main()
6707 {
6708 colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
6709 })";
6710
6711 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6712 glUseProgram(program);
6713
6714 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6715 const GLint expectLoc = glGetUniformLocation(program, "expect");
6716 const GLint successLoc = glGetUniformLocation(program, "successColor");
6717 ASSERT_NE(-1, positionLoc);
6718 ASSERT_NE(-1, expectLoc);
6719 ASSERT_NE(-1, successLoc);
6720
6721 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6722 glEnableVertexAttribArray(positionLoc);
6723
6724 glUniform1ui(expectLoc, kUboData1[0]);
6725 glUniform4f(successLoc, 0, 0, 0, 1);
6726 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6727 EXPECT_GL_NO_ERROR();
6728
6729 // Then upload data to the UBO so on next use the render pass has to break. This draw call is
6730 // not indexed.
6731 constexpr GLuint kUboData2 = 0x87654321u;
6732 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
6733
6734 glEnable(GL_BLEND);
6735 glBlendFunc(GL_ONE, GL_ONE);
6736 glUniform1ui(expectLoc, kUboData2);
6737 glUniform4f(successLoc, 0, 1, 0, 0);
6738 glDrawArrays(GL_TRIANGLES, 0, 3);
6739
6740 // Issue another draw call that is indexed. The index buffer should be bound correctly on the
6741 // new render pass.
6742 glUniform4f(successLoc, 0, 0, 1, 0);
6743 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6744 EXPECT_GL_NO_ERROR();
6745
6746 // Ensure correct rendering.
6747 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6748 }
6749
6750 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)6751 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
6752 {
6753 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6754 glClearColor(0, 0, 0, 1);
6755 glClear(GL_COLOR_BUFFER_BIT);
6756 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6757
6758 GLFramebuffer fbo;
6759 GLTexture texture;
6760
6761 glBindTexture(GL_TEXTURE_2D, texture);
6762 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6763 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6764 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6765
6766 glClear(GL_COLOR_BUFFER_BIT);
6767 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6768
6769 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6770
6771 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6772 // bit.
6773 GLBuffer indexBuffer;
6774 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6775
6776 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6777 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6778
6779 // Setup vertices.
6780 const std::array<GLfloat, 6> kVertices = {
6781 -1, -1, 3, -1, -1, 3,
6782 };
6783 GLBuffer vertexBuffer;
6784 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6785 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6786 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6787 glEnableVertexAttribArray(0);
6788
6789 // Set up a program. The same program is used for all draw calls to avoid state change due to
6790 // program change.
6791 constexpr char kFS[] = R"(#version 300 es
6792 precision mediump float;
6793 uniform vec4 colorIn;
6794 out vec4 colorOut;
6795 void main()
6796 {
6797 colorOut = colorIn;
6798 })";
6799
6800 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6801 glUseProgram(program);
6802
6803 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6804 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
6805 ASSERT_NE(-1, positionLoc);
6806 ASSERT_NE(-1, colorLoc);
6807
6808 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6809 glEnableVertexAttribArray(positionLoc);
6810
6811 glUniform4f(colorLoc, 1, 0, 0, 1);
6812 glEnable(GL_BLEND);
6813 glBlendFunc(GL_ONE, GL_ONE);
6814 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6815 EXPECT_GL_NO_ERROR();
6816
6817 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6818 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6819 glUniform4f(colorLoc, 0, 1, 0, 0);
6820 glDrawArrays(GL_TRIANGLES, 0, 3);
6821
6822 glUniform4f(colorLoc, 0, 0, 1, 0);
6823 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6824 EXPECT_GL_NO_ERROR();
6825
6826 // Ensure correct rendering.
6827 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6828
6829 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6830 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6831 }
6832
6833 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
6834 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)6835 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
6836 {
6837 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6838 glClearColor(0, 0, 0, 1);
6839 glClear(GL_COLOR_BUFFER_BIT);
6840 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6841
6842 GLFramebuffer fbo;
6843 GLTexture texture;
6844
6845 glBindTexture(GL_TEXTURE_2D, texture);
6846 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6847 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6848 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6849
6850 glClear(GL_COLOR_BUFFER_BIT);
6851 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6852
6853 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6854
6855 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6856 // bit.
6857 GLBuffer indexBuffer;
6858 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6859
6860 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6861 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6862
6863 // Setup vertices.
6864 const std::array<GLfloat, 6> kVertices = {
6865 -1, -1, 3, -1, -1, 3,
6866 };
6867 GLBuffer vertexBuffer;
6868 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6869 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6870 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6871 glEnableVertexAttribArray(0);
6872
6873 // Set up a program. The same program is used for all draw calls to avoid state change due to
6874 // program change.
6875 constexpr char kFS[] = R"(#version 300 es
6876 precision mediump float;
6877 uniform vec4 colorIn;
6878 out vec4 colorOut;
6879 void main()
6880 {
6881 colorOut = colorIn;
6882 })";
6883
6884 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6885 glUseProgram(program);
6886
6887 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6888 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
6889 ASSERT_NE(-1, positionLoc);
6890 ASSERT_NE(-1, colorLoc);
6891
6892 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6893 glEnableVertexAttribArray(positionLoc);
6894
6895 glUniform4f(colorLoc, 0, 0, 0, 1);
6896 glEnable(GL_BLEND);
6897 glBlendFunc(GL_ONE, GL_ONE);
6898 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6899 EXPECT_GL_NO_ERROR();
6900
6901 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6902 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6903 glUniform4f(colorLoc, 0, 1, 0, 0);
6904 glDrawArrays(GL_TRIANGLES, 0, 3);
6905
6906 // In between the two calls, make sure the first render pass is submitted, so the primary
6907 // command buffer is reset.
6908 {
6909 EGLWindow *window = getEGLWindow();
6910 EGLDisplay dpy = window->getDisplay();
6911 EGLConfig config = window->getConfig();
6912 EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
6913 EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
6914 EGLContext ctx = window->createContext(EGL_NO_CONTEXT);
6915 EXPECT_EGL_SUCCESS();
6916 std::thread flushThread = std::thread([&]() {
6917 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
6918 EXPECT_EGL_SUCCESS();
6919
6920 glClearColor(1, 0, 0, 1);
6921 glClear(GL_COLOR_BUFFER_BIT);
6922 EXPECT_GL_NO_ERROR();
6923
6924 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6925 });
6926 flushThread.join();
6927
6928 eglDestroySurface(dpy, surface);
6929 eglDestroyContext(dpy, ctx);
6930 }
6931
6932 glUniform4f(colorLoc, 0, 0, 1, 0);
6933 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6934 EXPECT_GL_NO_ERROR();
6935
6936 // Ensure correct rendering.
6937 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6938 }
6939 } // anonymous namespace
6940
6941 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
6942 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
6943 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
6944
6945 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
6946 ANGLE_INSTANTIATE_TEST_ES3(StateChangeTestES3);
6947
6948 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
6949 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
6950
6951 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
6952
6953 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
6954 ANGLE_INSTANTIATE_TEST_ES3(SimpleStateChangeTestES3);
6955
6956 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
6957 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
6958
6959 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
6960 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
6961
6962 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
6963 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
6964
6965 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
6966 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
6967
6968 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
6969 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
6970
6971 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
6972 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
6973
6974 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
6975 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
6976
6977 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
6978 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
6979
6980 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
6981 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
6982