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 may trigger the texture to be re-created internally.
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
1695 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1696 glUseProgram(program);
1697
1698 // We expect to draw a triangle with the first 3 points to the left, then another triangle with
1699 // the last 3 vertices using a drawElements call.
1700 auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
1701 {-1.0f, 1.0f, 0.0f},
1702 {0.0f, 0.0f, 0.0f},
1703 {1.0f, 1.0f, 0.0f},
1704 {1.0f, -1.0f, 0.0f}};
1705
1706 // If we use these indices to draw we'll be using the last 2 vertex only to draw.
1707 auto indices = std::vector<GLushort>{2, 3, 4};
1708
1709 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1710 ASSERT_NE(-1, positionLocation);
1711
1712 GLBuffer vertexBuffer;
1713 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1714 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1715 GL_STATIC_DRAW);
1716
1717 GLBuffer indexBuffer;
1718 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1719 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1720 GL_STATIC_DRAW);
1721
1722 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1723 glEnableVertexAttribArray(positionLocation);
1724
1725 for (int i = 0; i < 10; i++)
1726 {
1727 glClear(GL_COLOR_BUFFER_BIT);
1728 glDrawArrays(GL_TRIANGLES, 0, 3); // triangle to the left
1729 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr); // triangle to the right
1730 glFinish();
1731 }
1732 glDisableVertexAttribArray(positionLocation);
1733
1734 ASSERT_GL_NO_ERROR();
1735
1736 int quarterWidth = getWindowWidth() / 4;
1737 int halfHeight = getWindowHeight() / 2;
1738
1739 // Validate triangle to the left
1740 EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::blue);
1741
1742 // Validate triangle to the right
1743 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::blue);
1744 }
1745
1746 // Draw a triangle with drawElements and a non-zero offset and draw the same
1747 // triangle with the same offset followed by binding the same element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElements)1748 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElements)
1749 {
1750 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1751
1752 glUseProgram(program);
1753
1754 // Background Red color
1755 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1756 glClear(GL_COLOR_BUFFER_BIT);
1757
1758 // We expect to draw the triangle with the last three points on the bottom right, and
1759 // rebind the same element buffer and draw with the same indices.
1760 auto vertices = std::vector<Vector3>{
1761 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1762
1763 auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1764
1765 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1766 ASSERT_NE(-1, positionLocation);
1767
1768 GLBuffer indexBuffer;
1769 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1770 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1771 GL_STATIC_DRAW);
1772
1773 GLBuffer vertexBuffer;
1774 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1775 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1776 GL_STATIC_DRAW);
1777
1778 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1779 glEnableVertexAttribArray(positionLocation);
1780
1781 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1782
1783 // Rebind the same element buffer.
1784 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1785
1786 // Draw the triangle again with the same offset.
1787 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1788
1789 glDisableVertexAttribArray(positionLocation);
1790
1791 ASSERT_GL_NO_ERROR();
1792
1793 int quarterWidth = getWindowWidth() / 4;
1794 int quarterHeight = getWindowHeight() / 4;
1795
1796 // Validate the triangle is drawn on the bottom right.
1797 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1798
1799 // Validate the triangle is NOT on the top left part.
1800 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1801 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1802 }
1803
1804 // Draw a triangle with drawElements then change the index buffer and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndexBuffer)1805 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndexBuffer)
1806 {
1807 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1808
1809 glUseProgram(program);
1810
1811 // Background Red color
1812 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1813 glClear(GL_COLOR_BUFFER_BIT);
1814
1815 // We expect to draw the triangle with the last three points on the bottom right, and
1816 // rebind the same element buffer and draw with the same indices.
1817 auto vertices = std::vector<Vector3>{
1818 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1819
1820 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
1821
1822 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1823 ASSERT_NE(-1, positionLocation);
1824
1825 GLint colorUniformLocation =
1826 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1827 ASSERT_NE(colorUniformLocation, -1);
1828
1829 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1830
1831 GLBuffer indexBuffer8;
1832 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1833 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1834 GL_STATIC_DRAW);
1835
1836 GLBuffer vertexBuffer;
1837 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1838 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1839 GL_STATIC_DRAW);
1840
1841 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1842 glEnableVertexAttribArray(positionLocation);
1843
1844 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1845
1846 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
1847
1848 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
1849 GL_STATIC_DRAW);
1850
1851 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1852
1853 // Draw the triangle again with the same offset.
1854 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1855
1856 glDisableVertexAttribArray(positionLocation);
1857
1858 ASSERT_GL_NO_ERROR();
1859
1860 int quarterWidth = getWindowWidth() / 4;
1861 int quarterHeight = getWindowHeight() / 4;
1862
1863 // Validate the triangle is drawn on the bottom left.
1864 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1865 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1866
1867 // Validate the triangle is NOT on the top right part.
1868 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1869 }
1870
1871 // Draw a triangle with drawElements then change the indices and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndices)1872 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndices)
1873 {
1874 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1875
1876 glUseProgram(program);
1877
1878 // Background Red color
1879 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1880 glClear(GL_COLOR_BUFFER_BIT);
1881
1882 // We expect to draw the triangle with the last three points on the bottom right, and
1883 // rebind the same element buffer and draw with the same indices.
1884 std::vector<Vector3> vertices = {
1885 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1886
1887 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1888
1889 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1890 ASSERT_NE(-1, positionLocation);
1891
1892 GLint colorUniformLocation =
1893 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1894 ASSERT_NE(colorUniformLocation, -1);
1895
1896 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1897
1898 GLBuffer indexBuffer8;
1899 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1900 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1901 GL_DYNAMIC_DRAW);
1902
1903 GLBuffer vertexBuffer;
1904 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1905 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1906 GL_STATIC_DRAW);
1907
1908 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1909 glEnableVertexAttribArray(positionLocation);
1910
1911 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1912
1913 std::vector<GLubyte> newIndices8 = {2, 3, 0};
1914
1915 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1916 &newIndices8[0]);
1917
1918 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1919
1920 // Draw the triangle again with the same offset.
1921 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1922
1923 glDisableVertexAttribArray(positionLocation);
1924
1925 ASSERT_GL_NO_ERROR();
1926
1927 int quarterWidth = getWindowWidth() / 4;
1928 int quarterHeight = getWindowHeight() / 4;
1929
1930 // Validate the triangle is drawn on the bottom left.
1931 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1932 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1933
1934 // Validate the triangle is NOT on the top right part.
1935 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1936 }
1937
1938 // Draw a triangle with drawElements then change the indices and draw again. Similar to
1939 // DrawElementsThenDrawElementsNewIndices, but changes the whole index buffer (not just half). This
1940 // triggers a different path in the Vulkan backend based on the fact that the majority of the buffer
1941 // is being updated.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsWholeNewIndices)1942 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsWholeNewIndices)
1943 {
1944 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1945
1946 glUseProgram(program);
1947
1948 // Background Red color
1949 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1950 glClear(GL_COLOR_BUFFER_BIT);
1951
1952 // We expect to draw the triangle with the last three points on the bottom right, and
1953 // rebind the same element buffer and draw with the same indices.
1954 std::vector<Vector3> vertices = {
1955 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1956
1957 std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1958
1959 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1960 ASSERT_NE(-1, positionLocation);
1961
1962 GLint colorUniformLocation =
1963 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1964 ASSERT_NE(colorUniformLocation, -1);
1965
1966 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1967
1968 GLBuffer indexBuffer8;
1969 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1970 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1971 GL_DYNAMIC_DRAW);
1972
1973 GLBuffer vertexBuffer;
1974 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1975 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1976 GL_STATIC_DRAW);
1977
1978 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1979 glEnableVertexAttribArray(positionLocation);
1980
1981 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1982
1983 std::vector<GLubyte> newIndices8 = {2, 3, 0, 0, 0, 0};
1984
1985 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1986 &newIndices8[0]);
1987
1988 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1989
1990 // Draw the triangle again with the same offset.
1991 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1992
1993 glDisableVertexAttribArray(positionLocation);
1994
1995 ASSERT_GL_NO_ERROR();
1996
1997 int quarterWidth = getWindowWidth() / 4;
1998 int quarterHeight = getWindowHeight() / 4;
1999
2000 // Validate the triangle is drawn on the bottom left.
2001 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2002 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2003
2004 // Validate the triangle is NOT on the top right part.
2005 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2006 }
2007
2008 // Draw a triangle with drawElements and a non-zero offset and draw the same
2009 // triangle with the same offset followed by binding a USHORT element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsUBYTEX2ThenDrawElementsUSHORT)2010 TEST_P(SimpleStateChangeTest, DrawElementsUBYTEX2ThenDrawElementsUSHORT)
2011 {
2012 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2013
2014 glUseProgram(program);
2015
2016 // Background Red color
2017 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2018 glClear(GL_COLOR_BUFFER_BIT);
2019
2020 // We expect to draw the triangle with the last three points on the bottom right, and
2021 // rebind the same element buffer and draw with the same indices.
2022 auto vertices = std::vector<Vector3>{
2023 {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2024
2025 auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
2026
2027 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2028 ASSERT_NE(-1, positionLocation);
2029
2030 GLint colorUniformLocation =
2031 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2032 ASSERT_NE(colorUniformLocation, -1);
2033
2034 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2035
2036 GLBuffer indexBuffer8;
2037 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2038 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2039 GL_STATIC_DRAW);
2040
2041 GLBuffer vertexBuffer;
2042 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2043 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2044 GL_STATIC_DRAW);
2045
2046 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2047 glEnableVertexAttribArray(positionLocation);
2048
2049 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2050
2051 auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
2052 GLBuffer indexBuffer2nd8;
2053 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2nd8);
2054 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2055 GL_STATIC_DRAW);
2056 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2057
2058 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2059
2060 // Bind the 16bit element buffer.
2061 auto indices16 = std::vector<GLushort>{0, 1, 3, 1, 2, 3};
2062 GLBuffer indexBuffer16;
2063 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2064 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices16.size() * sizeof(GLushort), &indices16[0],
2065 GL_STATIC_DRAW);
2066
2067 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2068
2069 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2070
2071 // Draw the triangle again with the same offset.
2072 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(0 * sizeof(GLushort)));
2073
2074 glDisableVertexAttribArray(positionLocation);
2075
2076 ASSERT_GL_NO_ERROR();
2077
2078 int quarterWidth = getWindowWidth() / 4;
2079 int quarterHeight = getWindowHeight() / 4;
2080
2081 // Validate green triangle is drawn on the bottom.
2082 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::green);
2083
2084 // Validate white triangle is drawn on the right.
2085 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 3, quarterHeight * 2, GLColor::white);
2086
2087 // Validate blue triangle is on the top left part.
2088 EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::blue);
2089 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2090 }
2091
2092 // Draw a points use multiple unaligned vertex buffer with same data,
2093 // verify all the rendering results are the same.
TEST_P(SimpleStateChangeTest,DrawRepeatUnalignedVboChange)2094 TEST_P(SimpleStateChangeTest, DrawRepeatUnalignedVboChange)
2095 {
2096 // http://anglebug.com/4470
2097 ANGLE_SKIP_TEST_IF(isSwiftshader() && (IsWindows() || IsLinux()));
2098
2099 const int kRepeat = 2;
2100
2101 // set up VBO, colorVBO is unaligned
2102 GLBuffer positionBuffer;
2103 constexpr size_t posOffset = 0;
2104 const GLfloat posData[] = {0.5f, 0.5f};
2105 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2106 glBufferData(GL_ARRAY_BUFFER, sizeof(posData), posData, GL_STATIC_DRAW);
2107
2108 GLBuffer colorBuffers[kRepeat];
2109 constexpr size_t colorOffset = 1;
2110 const GLfloat colorData[] = {0.515f, 0.515f, 0.515f, 1.0f};
2111 constexpr size_t colorBufferSize = colorOffset + sizeof(colorData);
2112 uint8_t colorDataUnaligned[colorBufferSize] = {0};
2113 memcpy(reinterpret_cast<void *>(colorDataUnaligned + colorOffset), colorData,
2114 sizeof(colorData));
2115 for (uint32_t i = 0; i < kRepeat; i++)
2116 {
2117 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2118 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorDataUnaligned, GL_STATIC_DRAW);
2119 }
2120
2121 // set up frame buffer
2122 GLFramebuffer framebuffer;
2123 GLTexture framebufferTexture;
2124 bindTextureToFbo(framebuffer, framebufferTexture);
2125
2126 // set up program
2127 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
2128 glUseProgram(program);
2129 GLuint colorAttrLocation = glGetAttribLocation(program, "color");
2130 glEnableVertexAttribArray(colorAttrLocation);
2131 GLuint posAttrLocation = glGetAttribLocation(program, "position");
2132 glEnableVertexAttribArray(posAttrLocation);
2133 EXPECT_GL_NO_ERROR();
2134
2135 // draw and get drawing results
2136 constexpr size_t kRenderSize = kWindowSize * kWindowSize;
2137 std::array<GLColor, kRenderSize> pixelBufs[kRepeat];
2138
2139 for (uint32_t i = 0; i < kRepeat; i++)
2140 {
2141 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2142 glClear(GL_COLOR_BUFFER_BIT);
2143
2144 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2145 glVertexAttribPointer(posAttrLocation, 2, GL_FLOAT, GL_FALSE, 0,
2146 reinterpret_cast<const void *>(posOffset));
2147 glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2148 glVertexAttribPointer(colorAttrLocation, 4, GL_FLOAT, GL_FALSE, 0,
2149 reinterpret_cast<const void *>(colorOffset));
2150
2151 glDrawArrays(GL_POINTS, 0, 1);
2152
2153 // read drawing results
2154 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
2155 pixelBufs[i].data());
2156 EXPECT_GL_NO_ERROR();
2157 }
2158
2159 // verify something is drawn
2160 static_assert(kRepeat >= 2, "More than one repetition required");
2161 std::array<GLColor, kRenderSize> pixelAllBlack{0};
2162 EXPECT_NE(pixelBufs[0], pixelAllBlack);
2163 // verify drawing results are all identical
2164 for (uint32_t i = 1; i < kRepeat; i++)
2165 {
2166 EXPECT_EQ(pixelBufs[i - 1], pixelBufs[i]);
2167 }
2168 }
2169
2170 // Handles deleting a Buffer when it's being used.
TEST_P(SimpleStateChangeTest,DeleteBufferInUse)2171 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
2172 {
2173 std::vector<GLColor> colorData(6, GLColor::red);
2174
2175 GLBuffer buffer;
2176 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2177 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * colorData.size(), colorData.data(),
2178 GL_STATIC_DRAW);
2179
2180 simpleDrawWithBuffer(&buffer);
2181
2182 buffer.reset();
2183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2184 }
2185
2186 // Tests that resizing a Buffer during a draw works as expected.
TEST_P(SimpleStateChangeTest,RedefineBufferInUse)2187 TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
2188 {
2189 std::vector<GLColor> redColorData(6, GLColor::red);
2190
2191 GLBuffer buffer;
2192 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2193 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2194 GL_STATIC_DRAW);
2195
2196 // Trigger a pull from the buffer.
2197 simpleDrawWithBuffer(&buffer);
2198
2199 // Redefine the buffer that's in-flight.
2200 std::vector<GLColor> greenColorData(1024, GLColor::green);
2201 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * greenColorData.size(), greenColorData.data(),
2202 GL_STATIC_DRAW);
2203
2204 // Trigger the flush and verify the first draw worked.
2205 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2206
2207 // Draw again and verify the new data is correct.
2208 simpleDrawWithBuffer(&buffer);
2209 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2210 }
2211
2212 // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest,UpdateBufferInUse)2213 TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
2214 {
2215 std::vector<GLColor> redColorData(6, GLColor::red);
2216
2217 GLBuffer buffer;
2218 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2219 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2220 GL_STATIC_DRAW);
2221
2222 // Trigger a pull from the buffer.
2223 simpleDrawWithBuffer(&buffer);
2224
2225 // Update the buffer that's in-flight.
2226 std::vector<GLColor> greenColorData(6, GLColor::green);
2227 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * greenColorData.size(),
2228 greenColorData.data());
2229
2230 // Trigger the flush and verify the first draw worked.
2231 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2232
2233 // Draw again and verify the new data is correct.
2234 simpleDrawWithBuffer(&buffer);
2235 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2236 }
2237
2238 // Tests that deleting an in-flight Texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTest,DeleteTextureInUse)2239 TEST_P(SimpleStateChangeTest, DeleteTextureInUse)
2240 {
2241 std::array<GLColor, 4> colors = {
2242 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2243
2244 GLTexture tex;
2245 glBindTexture(GL_TEXTURE_2D, tex);
2246 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2249
2250 draw2DTexturedQuad(0.5f, 1.0f, true);
2251 tex.reset();
2252 EXPECT_GL_NO_ERROR();
2253
2254 int w = getWindowWidth() - 2;
2255 int h = getWindowHeight() - 2;
2256
2257 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2258 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2259 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2260 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2261 }
2262
2263 // Tests that modifying a texture parameter in-flight does not cause problems.
TEST_P(SimpleStateChangeTest,ChangeTextureFilterModeBetweenTwoDraws)2264 TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
2265 {
2266 std::array<GLColor, 4> colors = {
2267 {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
2268
2269 GLTexture tex;
2270 glBindTexture(GL_TEXTURE_2D, tex);
2271 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2272
2273 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2274 glClear(GL_COLOR_BUFFER_BIT);
2275
2276 // Draw to the left side of the window only with NEAREST.
2277 glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2280 draw2DTexturedQuad(0.5f, 1.0f, true);
2281
2282 // Draw to the right side of the window only with LINEAR.
2283 glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2286 draw2DTexturedQuad(0.5f, 1.0f, true);
2287 EXPECT_GL_NO_ERROR();
2288
2289 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2290
2291 // The first half (left) should be only black followed by plain white.
2292 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2293 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
2294 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
2295 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
2296
2297 // The second half (right) should be a gradient so we shouldn't find plain black/white in the
2298 // middle.
2299 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
2300 EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
2301 }
2302
2303 // Tests that bind the same texture all the time between different draw calls.
TEST_P(SimpleStateChangeTest,RebindTextureDrawAgain)2304 TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
2305 {
2306 GLuint program = get2DTexturedQuadProgram();
2307 glUseProgram(program);
2308
2309 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2310
2311 // Setup the texture
2312 GLTexture tex;
2313 glBindTexture(GL_TEXTURE_2D, tex);
2314 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2315 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2317
2318 // Setup the vertex array to draw a quad.
2319 GLint positionLocation = glGetAttribLocation(program, "position");
2320 setupQuadVertexBuffer(1.0f, 1.0f);
2321 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2322 glEnableVertexAttribArray(positionLocation);
2323
2324 // Draw quad
2325 glDrawArrays(GL_TRIANGLES, 0, 6);
2326 ASSERT_GL_NO_ERROR();
2327
2328 // Bind again
2329 glBindTexture(GL_TEXTURE_2D, tex);
2330 ASSERT_GL_NO_ERROR();
2331
2332 // Draw again, should still work.
2333 glDrawArrays(GL_TRIANGLES, 0, 6);
2334 ASSERT_GL_NO_ERROR();
2335
2336 // Validate whole surface is filled with cyan.
2337 int h = getWindowHeight() - 1;
2338 int w = getWindowWidth() - 1;
2339
2340 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2341 }
2342
2343 // Tests that we can draw with a texture, modify the texture with a texSubImage, and then draw again
2344 // correctly.
TEST_P(SimpleStateChangeTest,DrawWithTextureTexSubImageThenDrawAgain)2345 TEST_P(SimpleStateChangeTest, DrawWithTextureTexSubImageThenDrawAgain)
2346 {
2347 GLuint program = get2DTexturedQuadProgram();
2348 ASSERT_NE(0u, program);
2349 glUseProgram(program);
2350
2351 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
2352 std::array<GLColor, 4> subColors = {
2353 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
2354
2355 // Setup the texture
2356 GLTexture tex;
2357 glBindTexture(GL_TEXTURE_2D, tex);
2358 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2361
2362 // Setup the vertex array to draw a quad.
2363 GLint positionLocation = glGetAttribLocation(program, "position");
2364 setupQuadVertexBuffer(1.0f, 1.0f);
2365 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2366 glEnableVertexAttribArray(positionLocation);
2367
2368 // Draw quad
2369 glDrawArrays(GL_TRIANGLES, 0, 6);
2370 ASSERT_GL_NO_ERROR();
2371
2372 // Update bottom-half of texture with green.
2373 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
2374 ASSERT_GL_NO_ERROR();
2375
2376 // Draw again, should still work.
2377 glDrawArrays(GL_TRIANGLES, 0, 6);
2378 ASSERT_GL_NO_ERROR();
2379
2380 // Validate first half of the screen is red and the bottom is green.
2381 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2382 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4 * 3, GLColor::red);
2383 }
2384
2385 // Test that we can alternate between textures between different draws.
TEST_P(SimpleStateChangeTest,DrawTextureAThenTextureBThenTextureA)2386 TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
2387 {
2388 GLuint program = get2DTexturedQuadProgram();
2389 glUseProgram(program);
2390
2391 std::array<GLColor, 4> colorsTex1 = {
2392 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2393
2394 std::array<GLColor, 4> colorsTex2 = {
2395 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
2396
2397 // Setup the texture
2398 GLTexture tex1;
2399 glBindTexture(GL_TEXTURE_2D, tex1);
2400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
2401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2403
2404 GLTexture tex2;
2405 glBindTexture(GL_TEXTURE_2D, tex2);
2406 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
2407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2408 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2409
2410 // Setup the vertex array to draw a quad.
2411 GLint positionLocation = glGetAttribLocation(program, "position");
2412 setupQuadVertexBuffer(1.0f, 1.0f);
2413 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2414 glEnableVertexAttribArray(positionLocation);
2415
2416 // Draw quad
2417 glBindTexture(GL_TEXTURE_2D, tex1);
2418 glDrawArrays(GL_TRIANGLES, 0, 6);
2419 ASSERT_GL_NO_ERROR();
2420
2421 // Bind again, draw again
2422 glBindTexture(GL_TEXTURE_2D, tex2);
2423 glDrawArrays(GL_TRIANGLES, 0, 6);
2424 ASSERT_GL_NO_ERROR();
2425
2426 // Bind again, draw again
2427 glBindTexture(GL_TEXTURE_2D, tex1);
2428 glDrawArrays(GL_TRIANGLES, 0, 6);
2429
2430 // Validate whole surface is filled with cyan.
2431 int h = getWindowHeight() - 1;
2432 int w = getWindowWidth() - 1;
2433
2434 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2435 }
2436
2437 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
TEST_P(SimpleStateChangeTest,RedefineTextureInUse)2438 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
2439 {
2440 std::array<GLColor, 4> colors = {
2441 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2442
2443 GLTexture tex;
2444 glBindTexture(GL_TEXTURE_2D, tex);
2445 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2448
2449 // Draw with the first texture.
2450 draw2DTexturedQuad(0.5f, 1.0f, true);
2451
2452 // Redefine the in-flight texture.
2453 constexpr int kBigSize = 32;
2454 std::vector<GLColor> bigColors;
2455 for (int y = 0; y < kBigSize; ++y)
2456 {
2457 for (int x = 0; x < kBigSize; ++x)
2458 {
2459 bool xComp = x < kBigSize / 2;
2460 bool yComp = y < kBigSize / 2;
2461 if (yComp)
2462 {
2463 bigColors.push_back(xComp ? GLColor::cyan : GLColor::magenta);
2464 }
2465 else
2466 {
2467 bigColors.push_back(xComp ? GLColor::yellow : GLColor::white);
2468 }
2469 }
2470 }
2471
2472 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigColors.data());
2473 EXPECT_GL_NO_ERROR();
2474
2475 // Verify the first draw had the correct data via ReadPixels.
2476 int w = getWindowWidth() - 2;
2477 int h = getWindowHeight() - 2;
2478
2479 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2480 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2481 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2482 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2483
2484 // Draw and verify with the redefined data.
2485 draw2DTexturedQuad(0.5f, 1.0f, true);
2486 EXPECT_GL_NO_ERROR();
2487
2488 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2489 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::magenta);
2490 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::yellow);
2491 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::white);
2492 }
2493
2494 // Test updating a Texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTest,UpdateTextureInUse)2495 TEST_P(SimpleStateChangeTest, UpdateTextureInUse)
2496 {
2497 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2498
2499 // Set up 2D quad resources.
2500 GLuint program = get2DTexturedQuadProgram();
2501 glUseProgram(program);
2502 ASSERT_EQ(0, glGetAttribLocation(program, "position"));
2503
2504 const auto &quadVerts = GetQuadVertices();
2505
2506 GLBuffer vbo;
2507 glBindBuffer(GL_ARRAY_BUFFER, vbo);
2508 glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
2509 GL_STATIC_DRAW);
2510 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2511 glEnableVertexAttribArray(0);
2512
2513 GLTexture tex;
2514 glBindTexture(GL_TEXTURE_2D, tex);
2515 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
2516 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2518
2519 // Draw RGBY to the Framebuffer. The texture is now in-use by GL.
2520 const int w = getWindowWidth() - 2;
2521 const int h = getWindowHeight() - 2;
2522 const int w2 = w >> 1;
2523
2524 glViewport(0, 0, w2, h);
2525 glDrawArrays(GL_TRIANGLES, 0, 6);
2526
2527 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the draw.
2528 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
2529 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
2530 ASSERT_GL_NO_ERROR();
2531
2532 // Draw again to the Framebuffer. The second draw call should use the updated YBGR data.
2533 glViewport(w2, 0, w2, h);
2534 glDrawArrays(GL_TRIANGLES, 0, 6);
2535
2536 // Check the Framebuffer. Both draws should have completed.
2537 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2538 EXPECT_PIXEL_COLOR_EQ(w2 - 1, 0, GLColor::green);
2539 EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::blue);
2540 EXPECT_PIXEL_COLOR_EQ(w2 - 1, h - 1, GLColor::yellow);
2541
2542 EXPECT_PIXEL_COLOR_EQ(w2 + 1, 0, GLColor::yellow);
2543 EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::blue);
2544 EXPECT_PIXEL_COLOR_EQ(w2 + 1, h - 1, GLColor::green);
2545 EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::red);
2546 ASSERT_GL_NO_ERROR();
2547 }
2548
updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)2549 void SimpleStateChangeTest::updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)
2550 {
2551 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2552
2553 std::vector<GLColor> red(4, GLColor::red);
2554 std::vector<GLColor> green(4, GLColor::green);
2555
2556 GLTexture renderTarget;
2557 glBindTexture(GL_TEXTURE_2D, renderTarget);
2558 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2559
2560 GLFramebuffer fbo;
2561 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2562 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2563 0);
2564 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2565 glViewport(0, 0, 2, 2);
2566 ASSERT_GL_NO_ERROR();
2567
2568 GLTexture tex;
2569 glBindTexture(GL_TEXTURE_2D, tex);
2570 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2572 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2573
2574 // Draw once to flush dirty state bits.
2575 draw2DTexturedQuad(0.5f, 1.0f, true);
2576
2577 ASSERT_GL_NO_ERROR();
2578
2579 // Update the (0, 1) pixel to be blue
2580 updateFunc(GL_TEXTURE_2D, &renderTarget, 0, 1, GLColor::blue);
2581
2582 // Draw green to the right half of the Framebuffer.
2583 glBindTexture(GL_TEXTURE_2D, tex);
2584 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, green.data());
2585 glViewport(1, 0, 1, 2);
2586 draw2DTexturedQuad(0.5f, 1.0f, true);
2587
2588 // Update the (1, 1) pixel to be yellow
2589 updateFunc(GL_TEXTURE_2D, &renderTarget, 1, 1, GLColor::yellow);
2590
2591 ASSERT_GL_NO_ERROR();
2592
2593 // Verify we have a quad with the right colors in the FBO.
2594 std::vector<GLColor> expected = {
2595 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2596 std::vector<GLColor> actual(4);
2597 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2598 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
2599 EXPECT_EQ(expected, actual);
2600 }
2601
2602 // Tests that TexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,TexSubImageOnTextureBoundToFrambuffer)2603 TEST_P(SimpleStateChangeTest, TexSubImageOnTextureBoundToFrambuffer)
2604 {
2605 // http://anglebug.com/4092
2606 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2607 auto updateFunc = [](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2608 const GLColor &color) {
2609 glBindTexture(textureBinding, *tex);
2610 glTexSubImage2D(textureBinding, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2611 };
2612
2613 updateTextureBoundToFramebufferHelper(updateFunc);
2614 }
2615
2616 // Tests that CopyTexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,CopyTexSubImageOnTextureBoundToFrambuffer)2617 TEST_P(SimpleStateChangeTest, CopyTexSubImageOnTextureBoundToFrambuffer)
2618 {
2619 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2620
2621 GLTexture copySource;
2622 glBindTexture(GL_TEXTURE_2D, copySource);
2623 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2624
2625 GLFramebuffer copyFBO;
2626 glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFBO);
2627 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySource, 0);
2628
2629 ASSERT_GL_NO_ERROR();
2630 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2631
2632 auto updateFunc = [©Source](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2633 const GLColor &color) {
2634 glBindTexture(GL_TEXTURE_2D, copySource);
2635 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2636
2637 glBindTexture(textureBinding, *tex);
2638 glCopyTexSubImage2D(textureBinding, 0, x, y, 0, 0, 1, 1);
2639 };
2640
2641 updateTextureBoundToFramebufferHelper(updateFunc);
2642 }
2643
2644 // Tests that the read framebuffer doesn't affect what the draw call thinks the attachments are
2645 // (which is what the draw framebuffer dictates) when a command is issued with the GL_FRAMEBUFFER
2646 // target.
TEST_P(SimpleStateChangeTestES3,ReadFramebufferDrawFramebufferDifferentAttachments)2647 TEST_P(SimpleStateChangeTestES3, ReadFramebufferDrawFramebufferDifferentAttachments)
2648 {
2649 // http://anglebug.com/4092
2650 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2651
2652 GLRenderbuffer drawColorBuffer;
2653 glBindRenderbuffer(GL_RENDERBUFFER, drawColorBuffer);
2654 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2655
2656 GLRenderbuffer drawDepthBuffer;
2657 glBindRenderbuffer(GL_RENDERBUFFER, drawDepthBuffer);
2658 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1);
2659
2660 GLRenderbuffer readColorBuffer;
2661 glBindRenderbuffer(GL_RENDERBUFFER, readColorBuffer);
2662 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2663
2664 GLFramebuffer drawFBO;
2665 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2666 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2667 drawColorBuffer);
2668 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2669 drawDepthBuffer);
2670 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2671
2672 GLFramebuffer readFBO;
2673 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2674 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2675 readColorBuffer);
2676 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2677
2678 EXPECT_GL_NO_ERROR();
2679
2680 glClearDepthf(1.0f);
2681 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2682
2683 // A handful of non-draw calls can sync framebuffer state, such as discard, invalidate,
2684 // invalidateSub and multisamplefv.
2685 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2686 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
2687 EXPECT_GL_NO_ERROR();
2688
2689 glEnable(GL_DEPTH_TEST);
2690 glDepthFunc(GL_EQUAL);
2691
2692 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
2693
2694 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
2695 EXPECT_GL_NO_ERROR();
2696
2697 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2698 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2699 }
2700
2701 // Tests that invalidate then copy then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenCopyThenBlend)2702 TEST_P(SimpleStateChangeTestES3, InvalidateThenCopyThenBlend)
2703 {
2704 // Create a framebuffer as the source of copy
2705 const GLColor kSrcData = GLColor::cyan;
2706 GLTexture copySrc;
2707 glBindTexture(GL_TEXTURE_2D, copySrc);
2708 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2709
2710 GLFramebuffer readFBO;
2711 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2712 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySrc, 0);
2713 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2714
2715 // Create the framebuffer that will be invalidated
2716 GLTexture renderTarget;
2717 glBindTexture(GL_TEXTURE_2D, renderTarget);
2718 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2719
2720 GLFramebuffer drawFBO;
2721 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2722 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2723 0);
2724 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2725
2726 EXPECT_GL_NO_ERROR();
2727
2728 // Clear the framebuffer and invalidate it.
2729 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2730 glClear(GL_COLOR_BUFFER_BIT);
2731
2732 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2733 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2734 EXPECT_GL_NO_ERROR();
2735
2736 // Copy into the framebuffer's texture. The framebuffer should now be cyan.
2737 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2738 EXPECT_GL_NO_ERROR();
2739
2740 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2741 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2742 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2743 }
2744
2745 // Tests that invalidate then blit then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenBlitThenBlend)2746 TEST_P(SimpleStateChangeTestES3, InvalidateThenBlitThenBlend)
2747 {
2748 // Create a framebuffer as the source of blit
2749 const GLColor kSrcData = GLColor::cyan;
2750 GLTexture blitSrc;
2751 glBindTexture(GL_TEXTURE_2D, blitSrc);
2752 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2753
2754 GLFramebuffer readFBO;
2755 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2756 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
2757 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2758
2759 // Create the framebuffer that will be invalidated
2760 GLTexture renderTarget;
2761 glBindTexture(GL_TEXTURE_2D, renderTarget);
2762 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2763
2764 GLFramebuffer drawFBO;
2765 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2766 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2767 0);
2768 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2769
2770 EXPECT_GL_NO_ERROR();
2771
2772 // Clear the framebuffer and invalidate it.
2773 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2774 glClear(GL_COLOR_BUFFER_BIT);
2775
2776 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2777 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2778 EXPECT_GL_NO_ERROR();
2779
2780 // Blit into the framebuffer. The framebuffer should now be cyan.
2781 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2782 EXPECT_GL_NO_ERROR();
2783
2784 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2785 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2786 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2787 }
2788
2789 // Tests that invalidate then generate mipmaps works
TEST_P(SimpleStateChangeTestES3,InvalidateThenGenerateMipmapsThenBlend)2790 TEST_P(SimpleStateChangeTestES3, InvalidateThenGenerateMipmapsThenBlend)
2791 {
2792 // Create a texture on which generate mipmaps would be called
2793 const GLColor kMip0Data[4] = {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan};
2794 const GLColor kMip1Data = GLColor::blue;
2795 GLTexture texture;
2796 glBindTexture(GL_TEXTURE_2D, texture);
2797 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data);
2798 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kMip1Data);
2799
2800 // Create the framebuffer that will be invalidated
2801 GLFramebuffer drawFBO;
2802 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2803 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
2804 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2805
2806 EXPECT_GL_NO_ERROR();
2807
2808 // Clear the framebuffer and invalidate it.
2809 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2810 glClear(GL_COLOR_BUFFER_BIT);
2811
2812 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2813 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2814 EXPECT_GL_NO_ERROR();
2815
2816 // Generate mipmaps
2817 glGenerateMipmap(GL_TEXTURE_2D);
2818
2819 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2820 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2821 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2822 }
2823
2824 // Tests that invalidate then upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenUploadThenBlend)2825 TEST_P(SimpleStateChangeTestES3, InvalidateThenUploadThenBlend)
2826 {
2827 // http://anglebug.com/4870
2828 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2829
2830 // Create the framebuffer that will be invalidated
2831 GLTexture renderTarget;
2832 glBindTexture(GL_TEXTURE_2D, renderTarget);
2833 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2834
2835 GLFramebuffer drawFBO;
2836 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2837 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2838 0);
2839 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2840
2841 EXPECT_GL_NO_ERROR();
2842
2843 // Clear the framebuffer and invalidate it.
2844 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2845 glClear(GL_COLOR_BUFFER_BIT);
2846
2847 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2848 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2849 EXPECT_GL_NO_ERROR();
2850
2851 // Upload data to it
2852 const GLColor kUploadColor = GLColor::cyan;
2853 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2854
2855 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2856 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2857 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2858 }
2859
2860 // Tests that invalidate then sub upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenSubUploadThenBlend)2861 TEST_P(SimpleStateChangeTestES3, InvalidateThenSubUploadThenBlend)
2862 {
2863 // http://anglebug.com/4870
2864 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2865
2866 // Create the framebuffer that will be invalidated
2867 GLTexture renderTarget;
2868 glBindTexture(GL_TEXTURE_2D, renderTarget);
2869 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2870
2871 GLFramebuffer drawFBO;
2872 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2873 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2874 0);
2875 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2876
2877 EXPECT_GL_NO_ERROR();
2878
2879 // Clear the framebuffer and invalidate it.
2880 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2881 glClear(GL_COLOR_BUFFER_BIT);
2882
2883 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2884 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2885 EXPECT_GL_NO_ERROR();
2886
2887 // Upload data to it
2888 const GLColor kUploadColor = GLColor::cyan;
2889 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2890
2891 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2892 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2893 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2894 }
2895
2896 // Tests that invalidate then compute write works
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlend)2897 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlend)
2898 {
2899 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2900 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2901 // http://anglebug.com/5387
2902 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
2903
2904 constexpr char kCS[] = R"(#version 310 es
2905 layout(local_size_x=1, local_size_y=1) in;
2906 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2907 void main()
2908 {
2909 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2910 })";
2911
2912 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2913 glUseProgram(program);
2914 EXPECT_GL_NO_ERROR();
2915
2916 // Create the framebuffer texture
2917 GLTexture renderTarget;
2918 glBindTexture(GL_TEXTURE_2D, renderTarget);
2919 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2920 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2921
2922 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
2923 // is already created with STORAGE usage and avoids recreate later.
2924 glDispatchCompute(1, 1, 1);
2925 EXPECT_GL_NO_ERROR();
2926
2927 // Create the framebuffer that will be invalidated
2928 GLFramebuffer drawFBO;
2929 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2930 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2931 0);
2932 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2933
2934 EXPECT_GL_NO_ERROR();
2935
2936 // Clear the framebuffer and invalidate it.
2937 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2938 glClear(GL_COLOR_BUFFER_BIT);
2939
2940 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2941 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2942 EXPECT_GL_NO_ERROR();
2943
2944 // Write to it with a compute shader
2945 glDispatchCompute(1, 1, 1);
2946 EXPECT_GL_NO_ERROR();
2947
2948 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2949
2950 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2951 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2952 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2953 }
2954
2955 // Tests that invalidate then compute write works inside PPO
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlendPpo)2956 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlendPpo)
2957 {
2958 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2959 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2960 // PPOs are only supported in the Vulkan backend
2961 ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2962
2963 constexpr char kCS[] = R"(#version 310 es
2964 layout(local_size_x=1, local_size_y=1) in;
2965 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2966 void main()
2967 {
2968 imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2969 })";
2970
2971 GLProgramPipeline pipeline;
2972 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2973 glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
2974 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, program);
2975 EXPECT_GL_NO_ERROR();
2976 glBindProgramPipeline(pipeline);
2977 EXPECT_GL_NO_ERROR();
2978 glUseProgram(0);
2979
2980 // Create the framebuffer texture
2981 GLTexture renderTarget;
2982 glBindTexture(GL_TEXTURE_2D, renderTarget);
2983 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2984 glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2985
2986 // Write to the texture with compute once. In the Vulkan backend, this will make sure the image
2987 // is already created with STORAGE usage and avoids recreate later.
2988 glDispatchCompute(1, 1, 1);
2989 EXPECT_GL_NO_ERROR();
2990
2991 // Create the framebuffer that will be invalidated
2992 GLFramebuffer drawFBO;
2993 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2994 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2995 0);
2996 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2997
2998 EXPECT_GL_NO_ERROR();
2999
3000 // Clear the framebuffer and invalidate it.
3001 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3002 glClear(GL_COLOR_BUFFER_BIT);
3003
3004 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3005 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3006 EXPECT_GL_NO_ERROR();
3007
3008 // Write to it with a compute shader
3009 glDispatchCompute(1, 1, 1);
3010 EXPECT_GL_NO_ERROR();
3011
3012 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3013
3014 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3015 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3016 blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3017 }
3018
3019 // Tests that sub-invalidate then draw works.
TEST_P(SimpleStateChangeTestES3,SubInvalidateThenDraw)3020 TEST_P(SimpleStateChangeTestES3, SubInvalidateThenDraw)
3021 {
3022 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3023 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3024
3025 // Create the framebuffer that will be invalidated
3026 GLTexture renderTarget;
3027 glBindTexture(GL_TEXTURE_2D, renderTarget);
3028 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3029
3030 GLFramebuffer drawFBO;
3031 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3032 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3033 0);
3034 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3035
3036 EXPECT_GL_NO_ERROR();
3037
3038 // Clear the framebuffer.
3039 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3040 glClear(GL_COLOR_BUFFER_BIT);
3041
3042 // Draw into a quarter of the framebuffer, then invalidate that same region.
3043 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3044 glEnable(GL_SCISSOR_TEST);
3045 glScissor(1, 1, 1, 1);
3046 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3047
3048 // Only invalidate a quarter of the framebuffer.
3049 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3050 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment, 1, 1, 1, 1);
3051 EXPECT_GL_NO_ERROR();
3052
3053 glDisable(GL_SCISSOR_TEST);
3054
3055 // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3056 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3057 blendAndVerifyColor(GLColor32F(0.0f, 0.0f, 1.0f, 0.5f), GLColor(127, 127, 127, 191));
3058 }
3059
3060 // Tests that mid-render-pass invalidate then clear works for color buffers. This test ensures that
3061 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,ColorInvalidateThenClear)3062 TEST_P(SimpleStateChangeTestES3, ColorInvalidateThenClear)
3063 {
3064 // Create the framebuffer that will be invalidated
3065 GLTexture color;
3066 glBindTexture(GL_TEXTURE_2D, color);
3067 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3068
3069 GLFramebuffer fbo;
3070 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3071 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3072 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3073
3074 EXPECT_GL_NO_ERROR();
3075
3076 // Initialize the framebuffer with a draw call.
3077 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3078 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3079
3080 // Invalidate it.
3081 GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3082 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3083
3084 // Clear the framebuffer.
3085 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3086 glClear(GL_COLOR_BUFFER_BIT);
3087
3088 // Expect the clear color, ensuring that invalidate wasn't applied after clear.
3089 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3090 }
3091
3092 // Tests that mid-render-pass invalidate then clear works for depth buffers. This test ensures that
3093 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,DepthInvalidateThenClear)3094 TEST_P(SimpleStateChangeTestES3, DepthInvalidateThenClear)
3095 {
3096 // Create the framebuffer that will be invalidated
3097 GLTexture color;
3098 glBindTexture(GL_TEXTURE_2D, color);
3099 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3100
3101 GLRenderbuffer depth;
3102 glBindRenderbuffer(GL_RENDERBUFFER, depth);
3103 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
3104
3105 GLFramebuffer fbo;
3106 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3107 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3108 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
3109 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3110
3111 EXPECT_GL_NO_ERROR();
3112
3113 // Initialize the framebuffer with a draw call.
3114 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3115 glUseProgram(drawColor);
3116 GLint colorUniformLocation =
3117 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3118 ASSERT_NE(colorUniformLocation, -1);
3119
3120 glEnable(GL_DEPTH_TEST);
3121 glDepthFunc(GL_ALWAYS);
3122
3123 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3124 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
3125
3126 // Invalidate depth.
3127 GLenum invalidateAttachment = GL_DEPTH_ATTACHMENT;
3128 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3129
3130 // Clear the framebuffer.
3131 glClearDepthf(0.8f);
3132 glClear(GL_DEPTH_BUFFER_BIT);
3133
3134 // Expect the draw color. This breaks the render pass. Later, the test ensures that invalidate
3135 // of depth wasn't applied after clear.
3136 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3137
3138 // Blend with depth test and make sure depth is as expected.
3139 glEnable(GL_BLEND);
3140 glBlendFunc(GL_ONE, GL_ONE);
3141
3142 glDepthFunc(GL_LESS);
3143 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3144 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.59f);
3145
3146 glDepthFunc(GL_GREATER);
3147 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3148 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.61f);
3149
3150 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3151 }
3152
3153 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3154 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
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 a solid red color to the framebuffer.
3171 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3172 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3173
3174 // Delete the framebuffer while the call is in flight.
3175 framebuffer.reset();
3176
3177 // Make a new framebuffer so we can read back the texture.
3178 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3179 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3180 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3181
3182 // Flush via ReadPixels and check red was drawn.
3183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3184 ASSERT_GL_NO_ERROR();
3185 }
3186
3187 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3188 // buffers too early. The test has 2 textures, we first create a texture and update it with
3189 // multiple updates, but we don't use it right away, we instead draw using another texture
3190 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3191 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3192 {
3193 constexpr int kSize = 64;
3194
3195 GLuint program = get2DTexturedQuadProgram();
3196 glUseProgram(program);
3197
3198 std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3199 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3200 GLTexture texture1;
3201 glBindTexture(GL_TEXTURE_2D, texture1);
3202 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3203
3204 for (int i = 0; i < 100; i++)
3205 {
3206 // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3207 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3208 greenPixels.data());
3209 }
3210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3212
3213 ASSERT_GL_NO_ERROR();
3214
3215 GLTexture texture2;
3216 glBindTexture(GL_TEXTURE_2D, texture2);
3217 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3220
3221 // Setup the vertex array to draw a quad.
3222 GLint positionLocation = glGetAttribLocation(program, "position");
3223 setupQuadVertexBuffer(1.0f, 1.0f);
3224 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3225 glEnableVertexAttribArray(positionLocation);
3226
3227 // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3228 glBindTexture(GL_TEXTURE_2D, texture2);
3229 glDrawArrays(GL_TRIANGLES, 0, 6);
3230 ASSERT_GL_NO_ERROR();
3231 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3232
3233 // If we now try to draw with texture1, we should trigger the issue.
3234 glBindTexture(GL_TEXTURE_2D, texture1);
3235 glDrawArrays(GL_TRIANGLES, 0, 6);
3236 ASSERT_GL_NO_ERROR();
3237
3238 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3239 }
3240
3241 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3242 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3243 {
3244 constexpr int kSize = 16;
3245
3246 // Create a simple framebuffer.
3247 GLTexture texture;
3248 glBindTexture(GL_TEXTURE_2D, texture);
3249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3250
3251 GLFramebuffer framebuffer;
3252 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3253 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3254 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3255
3256 glViewport(0, 0, kSize, kSize);
3257
3258 // Draw red to the framebuffer.
3259 simpleDrawWithColor(GLColor::red);
3260
3261 // Change the framebuffer while the call is in flight to a new texture.
3262 GLTexture otherTexture;
3263 glBindTexture(GL_TEXTURE_2D, otherTexture);
3264 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3265
3266 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3267 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3268
3269 // Draw green to the framebuffer. Verify the color.
3270 simpleDrawWithColor(GLColor::green);
3271 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3272
3273 // Make a new framebuffer so we can read back the first texture and verify red.
3274 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3275 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3276 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3277
3278 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3279 ASSERT_GL_NO_ERROR();
3280 }
3281
3282 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3283 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3284 {
3285 GLFramebuffer framebuffer;
3286 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3287
3288 // Bind a simple 8x8 texture to the framebuffer, draw red.
3289 GLTexture texture;
3290 glBindTexture(GL_TEXTURE_2D, texture);
3291 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3292 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3293
3294 glViewport(0, 0, 8, 8);
3295 simpleDrawWithColor(GLColor::red);
3296 ASSERT_GL_NO_ERROR();
3297 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3298
3299 // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3300 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3301 glViewport(0, 0, 32, 32);
3302 simpleDrawWithColor(GLColor::green);
3303 ASSERT_GL_NO_ERROR();
3304 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3305 }
3306
3307 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3308 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3309 {
3310 // Fails on 431.02 driver. http://anglebug.com/3748
3311 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3312
3313 // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3314 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3315
3316 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3317
3318 GLTexture tex;
3319 glBindTexture(GL_TEXTURE_2D, tex);
3320 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3323 ASSERT_GL_NO_ERROR();
3324
3325 GLFramebuffer fbo;
3326 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3327 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3328 ASSERT_GL_NO_ERROR();
3329 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3330
3331 glUseProgram(program);
3332
3333 GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3334 ASSERT_NE(-1, uniLoc);
3335 glUniform1i(uniLoc, 0);
3336
3337 const int numRowsCols = 2;
3338 const int cellSize = getWindowWidth() / 2;
3339
3340 for (int cellY = 0; cellY < numRowsCols; cellY++)
3341 {
3342 for (int cellX = 0; cellX < numRowsCols; cellX++)
3343 {
3344 int seed = cellX + cellY * numRowsCols;
3345 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3346
3347 // Set the texture to a constant color using glClear and a user FBO.
3348 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3349 glClearColor(color[0], color[1], color[2], color[3]);
3350 glClear(GL_COLOR_BUFFER_BIT);
3351
3352 // Draw a small colored quad to the default FBO using the viewport.
3353 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3354 glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3355 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3356 }
3357 }
3358
3359 // Verify the colored quads were drawn correctly despite no flushing.
3360 std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3361 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3362 pixelData.data());
3363
3364 ASSERT_GL_NO_ERROR();
3365
3366 for (int cellY = 0; cellY < numRowsCols; cellY++)
3367 {
3368 for (int cellX = 0; cellX < numRowsCols; cellX++)
3369 {
3370 int seed = cellX + cellY * numRowsCols;
3371 const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3372
3373 GLColor expectedColor(color);
3374
3375 int testN =
3376 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3377 GLColor actualColor = pixelData[testN];
3378 EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3379 }
3380 }
3381 }
3382
3383 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3384 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3385 {
3386 // Create a texture with red
3387 const GLColor kInitColor1 = GLColor::red;
3388 GLTexture texture1;
3389 glBindTexture(GL_TEXTURE_2D, texture1);
3390 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3391
3392 // Create a framebuffer to be cleared
3393 GLTexture texture2;
3394 glBindTexture(GL_TEXTURE_2D, texture2);
3395 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3396
3397 GLFramebuffer drawFBO;
3398 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3399 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3400 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3401
3402 EXPECT_GL_NO_ERROR();
3403
3404 // Clear the framebuffer to green
3405 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3406 glClear(GL_COLOR_BUFFER_BIT);
3407
3408 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3409 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3410 // a noop, the deferred clears will remain unflushed.
3411 glClear(0);
3412
3413 // Change framebuffer's attachment to the other texture.
3414 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3415 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3416
3417 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3418 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3419 glUseProgram(program);
3420
3421 glEnable(GL_BLEND);
3422 glBlendFunc(GL_ZERO, GL_ONE);
3423 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3424 EXPECT_GL_NO_ERROR();
3425
3426 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3427 // to the new attachment, green will be read back.
3428 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3429
3430 // Attach back to texture2. It should be cleared to green.
3431 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3432 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3433 }
3434
3435 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3436 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3437 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3438 {
3439 // Create a texture with red
3440 const GLColor kInitColor1 = GLColor::red;
3441 GLTexture texture1;
3442 glBindTexture(GL_TEXTURE_2D, texture1);
3443 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3444
3445 // Create a framebuffer to be cleared
3446 GLTexture texture2;
3447 glBindTexture(GL_TEXTURE_2D, texture2);
3448 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3449
3450 GLFramebuffer drawFBO;
3451 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3452 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3453 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3454
3455 EXPECT_GL_NO_ERROR();
3456
3457 // Clear the framebuffer to green
3458 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3459 glClear(GL_COLOR_BUFFER_BIT);
3460
3461 // Clear again, but in a way that would be a no-op. In the Vulkan backend, this will result in
3462 // a framebuffer sync state, which extracts deferred clears. However, as the clear is actually
3463 // a noop, the deferred clears will remain unflushed.
3464 glEnable(GL_SCISSOR_TEST);
3465 glScissor(0, 0, 0, 0);
3466 glClear(GL_COLOR_BUFFER_BIT);
3467 glDisable(GL_SCISSOR_TEST);
3468
3469 // Change framebuffer's attachment to the other texture.
3470 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3471 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3472
3473 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3474 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3475 glUseProgram(program);
3476
3477 glEnable(GL_BLEND);
3478 glBlendFunc(GL_ZERO, GL_ONE);
3479 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3480 EXPECT_GL_NO_ERROR();
3481
3482 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3483 // to the new attachment, green will be read back.
3484 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3485
3486 // Attach back to texture2. It should be cleared to green.
3487 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3488 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3489 }
3490
3491 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3492 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3493 {
3494 // Create a texture with red
3495 const GLColor kInitColor1 = GLColor::red;
3496 GLTexture texture1;
3497 glBindTexture(GL_TEXTURE_2D, texture1);
3498 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3499
3500 // Create a framebuffer to be cleared
3501 GLTexture texture2;
3502 glBindTexture(GL_TEXTURE_2D, texture2);
3503 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3504
3505 GLFramebuffer drawFBO;
3506 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3507 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3508 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3509
3510 EXPECT_GL_NO_ERROR();
3511
3512 // Clear the framebuffer to green
3513 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3514 glClear(GL_COLOR_BUFFER_BIT);
3515
3516 // Issue noop blit. In the Vulkan backend, this will result in a framebuffer sync state, which
3517 // extracts deferred clears. However, as the blit is actually a noop, the deferred clears will
3518 // remain unflushed.
3519 GLTexture blitSrc;
3520 glBindTexture(GL_TEXTURE_2D, blitSrc);
3521 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3522
3523 GLFramebuffer readFBO;
3524 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3525 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3526 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3527
3528 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3529 EXPECT_GL_NO_ERROR();
3530
3531 // Change framebuffer's attachment to the other texture.
3532 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3533 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3534
3535 // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3536 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3537 glUseProgram(program);
3538
3539 glEnable(GL_BLEND);
3540 glBlendFunc(GL_ZERO, GL_ONE);
3541 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3542 EXPECT_GL_NO_ERROR();
3543
3544 // Expect red, which is the original contents of texture1. If the clear is mistakenly applied
3545 // to the new attachment, green will be read back.
3546 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3547 EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3548
3549 // Attach back to texture2. It should be cleared to green.
3550 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3551 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3552 }
3553
3554 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3555 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3556 {
3557 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3558 glUseProgram(program);
3559
3560 glClear(GL_COLOR_BUFFER_BIT);
3561 glEnable(GL_CULL_FACE);
3562
3563 glCullFace(GL_FRONT);
3564
3565 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3566
3567 ASSERT_GL_NO_ERROR();
3568
3569 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3570
3571 // Disable cull face and redraw, then make sure we have the quad drawn.
3572 glDisable(GL_CULL_FACE);
3573
3574 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3575
3576 ASSERT_GL_NO_ERROR();
3577
3578 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3579 }
3580
TEST_P(SimpleStateChangeTest,ScissorTest)3581 TEST_P(SimpleStateChangeTest, ScissorTest)
3582 {
3583 // This test validates this order of state changes:
3584 // 1- Set scissor but don't enable it, validate its not used.
3585 // 2- Enable it and validate its working.
3586 // 3- Disable the scissor validate its not used anymore.
3587
3588 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3589
3590 glClear(GL_COLOR_BUFFER_BIT);
3591
3592 // Set the scissor region, but don't enable it yet.
3593 glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3594 getWindowHeight() / 2);
3595
3596 // Fill the whole screen with a quad.
3597 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3598
3599 ASSERT_GL_NO_ERROR();
3600
3601 // Test outside, scissor isnt enabled so its red.
3602 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3603
3604 // Test inside, red of the fragment shader.
3605 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3606
3607 // Clear everything and start over with the test enabled.
3608 glClear(GL_COLOR_BUFFER_BIT);
3609 glEnable(GL_SCISSOR_TEST);
3610
3611 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3612
3613 ASSERT_GL_NO_ERROR();
3614
3615 // Test outside the scissor test, pitch black.
3616 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3617
3618 // Test inside, red of the fragment shader.
3619 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3620
3621 // Now disable the scissor test, do it again, and verify the region isn't used
3622 // for the scissor test.
3623 glDisable(GL_SCISSOR_TEST);
3624
3625 // Clear everything and start over with the test enabled.
3626 glClear(GL_COLOR_BUFFER_BIT);
3627
3628 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3629
3630 ASSERT_GL_NO_ERROR();
3631
3632 // Test outside, scissor isnt enabled so its red.
3633 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3634
3635 // Test inside, red of the fragment shader.
3636 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3637 }
3638
3639 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3640 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3641 {
3642 constexpr char kPositionUniformVertexShader[] = R"(
3643 precision mediump float;
3644 attribute vec2 position;
3645 uniform vec2 uniPosModifier;
3646 void main()
3647 {
3648 gl_Position = vec4(position + uniPosModifier, 0, 1);
3649 })";
3650
3651 ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3652 glUseProgram(program);
3653
3654 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3655 glClear(GL_COLOR_BUFFER_BIT);
3656
3657 GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3658 ASSERT_NE(posUniformLocation, -1);
3659 GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3660 ASSERT_NE(colorUniformLocation, -1);
3661
3662 // draw a red quad to the left side.
3663 glUniform2f(posUniformLocation, -0.5, 0.0);
3664 glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3665 drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3666
3667 // draw a green quad to the right side.
3668 glUniform2f(posUniformLocation, 0.5, 0.0);
3669 glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3670 drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3671
3672 ASSERT_GL_NO_ERROR();
3673
3674 // Test the center of the left quad. Should be red.
3675 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3676
3677 // Test the center of the right quad. Should be green.
3678 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3679 }
3680
3681 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3682 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3683 {
3684 GLRenderbuffer renderbuffer;
3685 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3686 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3687
3688 GLFramebuffer framebuffer;
3689 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3690 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3691
3692 ASSERT_GL_NO_ERROR();
3693 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3694
3695 ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3696 GLint colorLoc = glGetAttribLocation(program, "color");
3697 ASSERT_NE(-1, colorLoc);
3698
3699 // Set up and draw red to the left half the screen.
3700 std::vector<GLColor> redData(6, GLColor::red);
3701 GLBuffer vertexBufferRed;
3702 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3703 glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3704 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3705 glEnableVertexAttribArray(colorLoc);
3706
3707 glViewport(0, 0, 16, 16);
3708 drawQuad(program, "position", 0.5f, 1.0f, true);
3709
3710 // Immediately redefine the Renderbuffer.
3711 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3712
3713 // Set up and draw green to the right half of the screen.
3714 std::vector<GLColor> greenData(6, GLColor::green);
3715 GLBuffer vertexBufferGreen;
3716 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3717 glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3718 GL_STATIC_DRAW);
3719 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3720 glEnableVertexAttribArray(colorLoc);
3721
3722 glViewport(0, 0, 64, 64);
3723 drawQuad(program, "position", 0.5f, 1.0f, true);
3724
3725 ASSERT_GL_NO_ERROR();
3726 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3727 }
3728
3729 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
3730 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)3731 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
3732 {
3733 constexpr size_t kSmallTextureSize = 2;
3734 constexpr size_t kBigTextureSize = 4;
3735
3736 // Create 2 textures, one of 2x2 and the other 4x4
3737 GLTexture texture1;
3738 glBindTexture(GL_TEXTURE_2D, texture1);
3739 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
3740 GL_UNSIGNED_BYTE, nullptr);
3741 ASSERT_GL_NO_ERROR();
3742
3743 GLTexture texture2;
3744 glBindTexture(GL_TEXTURE_2D, texture2);
3745 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
3746 GL_UNSIGNED_BYTE, nullptr);
3747 ASSERT_GL_NO_ERROR();
3748
3749 // A framebuffer for each texture to draw on.
3750 GLFramebuffer framebuffer1;
3751 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3752 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3753 ASSERT_GL_NO_ERROR();
3754 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3755
3756 GLFramebuffer framebuffer2;
3757 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3758 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3759 ASSERT_GL_NO_ERROR();
3760 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3761
3762 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3763 glUseProgram(program);
3764 GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3765 ASSERT_NE(uniformLocation, -1);
3766
3767 // Bind to the first framebuffer for drawing.
3768 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3769
3770 // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
3771 // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
3772 glScissor(0, 0, 16, 16);
3773 ASSERT_GL_NO_ERROR();
3774
3775 // Set color to red.
3776 glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3777 glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
3778
3779 // Draw a full sized red quad
3780 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3781 ASSERT_GL_NO_ERROR();
3782
3783 // Bind to the second (bigger) framebuffer
3784 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3785 glViewport(0, 0, kBigTextureSize, kBigTextureSize);
3786
3787 ASSERT_GL_NO_ERROR();
3788
3789 // Set color to green.
3790 glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3791
3792 // Draw again and we should fill everything with green and expect everything to be green.
3793 drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3794 ASSERT_GL_NO_ERROR();
3795
3796 EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
3797 }
3798
3799 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)3800 TEST_P(SimpleStateChangeTest, RelinkProgram)
3801 {
3802 // http://anglebug.com/4121
3803 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
3804 const GLuint program = glCreateProgram();
3805
3806 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
3807 GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
3808 GLuint redFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
3809
3810 glAttachShader(program, vs);
3811 glAttachShader(program, blueFs);
3812
3813 glLinkProgram(program);
3814 CheckLinkStatusAndReturnProgram(program, true);
3815
3816 glClear(GL_COLOR_BUFFER_BIT);
3817 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
3818 {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
3819 GLBuffer vertexBuffer;
3820 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3821 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3822 GL_STATIC_DRAW);
3823 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3824 ASSERT_NE(-1, positionLocation);
3825 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3826 glEnableVertexAttribArray(positionLocation);
3827
3828 // Draw a blue triangle to the right
3829 glUseProgram(program);
3830 glDrawArrays(GL_TRIANGLES, 0, 3);
3831
3832 // Relink to draw red to the left
3833 glDetachShader(program, blueFs);
3834 glAttachShader(program, redFs);
3835
3836 glLinkProgram(program);
3837 CheckLinkStatusAndReturnProgram(program, true);
3838
3839 glDrawArrays(GL_TRIANGLES, 3, 3);
3840
3841 ASSERT_GL_NO_ERROR();
3842
3843 glDisableVertexAttribArray(positionLocation);
3844
3845 // Verify we drew red and green in the right places.
3846 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
3847 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
3848
3849 glDeleteShader(vs);
3850 glDeleteShader(blueFs);
3851 glDeleteShader(redFs);
3852 glDeleteProgram(program);
3853 }
3854
3855 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
3856 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)3857 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
3858 {
3859 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3860 glUseProgram(program);
3861
3862 const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3863 EXPECT_NE(-1, uniformLoc);
3864
3865 // Set color to red.
3866 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3867
3868 glClear(GL_COLOR_BUFFER_BIT);
3869 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
3870 GLBuffer vertexBuffer;
3871 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3872 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3873 GL_STATIC_DRAW);
3874 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3875 ASSERT_NE(-1, positionLocation);
3876 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3877 glEnableVertexAttribArray(positionLocation);
3878
3879 // Release program while its in use.
3880 glDeleteProgram(program);
3881
3882 // Draw a red triangle
3883 glDrawArrays(GL_TRIANGLES, 0, 3);
3884
3885 // Set color to green
3886 glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3887
3888 // Draw a green triangle
3889 glDrawArrays(GL_TRIANGLES, 0, 3);
3890
3891 ASSERT_GL_NO_ERROR();
3892
3893 glDisableVertexAttribArray(positionLocation);
3894
3895 glUseProgram(0);
3896
3897 // Verify we drew red in the end since thats the last draw.
3898 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
3899 }
3900
3901 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)3902 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
3903 {
3904 // Create a sampler with NEAREST filtering.
3905 GLSampler sampler;
3906 glBindSampler(0, sampler);
3907 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3908 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3909 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3910 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3911 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3912 ASSERT_GL_NO_ERROR();
3913
3914 // Draw with a program that uses no textures.
3915 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3916 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
3917 ASSERT_GL_NO_ERROR();
3918 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3919
3920 // Create a simple texture with four colors and linear filtering.
3921 constexpr GLsizei kSize = 2;
3922 std::array<GLColor, 4> pixels = {
3923 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
3924 GLTexture redTex;
3925 glBindTexture(GL_TEXTURE_2D, redTex);
3926 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3927 pixels.data());
3928 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3929 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3933
3934 // Create a program that uses the texture.
3935 constexpr char kVS[] = R"(attribute vec4 position;
3936 varying vec2 texCoord;
3937 void main()
3938 {
3939 gl_Position = position;
3940 texCoord = position.xy * 0.5 + vec2(0.5);
3941 })";
3942
3943 constexpr char kFS[] = R"(precision mediump float;
3944 varying vec2 texCoord;
3945 uniform sampler2D tex;
3946 void main()
3947 {
3948 gl_FragColor = texture2D(tex, texCoord);
3949 })";
3950
3951 // Draw. The sampler should override the clamp wrap mode with nearest.
3952 ANGLE_GL_PROGRAM(program2, kVS, kFS);
3953 ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
3954 drawQuad(program2, "position", 0.5f);
3955 ASSERT_GL_NO_ERROR();
3956
3957 constexpr int kHalfSize = kWindowSize / 2;
3958
3959 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
3960 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
3961 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
3962 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
3963 }
3964
3965 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)3966 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
3967 {
3968 // Test overview - Create two separate sampler objects, initially with the same
3969 // sampling args (NEAREST). Bind the same texture object to separate texture units.
3970 // FS samples from two samplers and blends result.
3971 // Bind separate sampler objects to the same texture units as the texture object.
3972 // Render & verify initial results
3973 // Next modify sampler0 to have LINEAR filtering instead of NEAREST
3974 // Render and save results
3975 // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
3976 // Render and verify results are the same as previous
3977
3978 // Create 2 samplers with NEAREST filtering.
3979 constexpr GLsizei kNumSamplers = 2;
3980 // We create/bind an extra sampler w/o bound tex object for testing purposes
3981 GLSampler samplers[kNumSamplers + 1];
3982 // Set samplers to initially have same state w/ NEAREST filter mode
3983 for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
3984 {
3985 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3986 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3987 glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3988 glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3989 glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3990 glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
3991 glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
3992 glBindSampler(i, samplers[i]);
3993 ASSERT_GL_NO_ERROR();
3994 }
3995
3996 // Create a simple texture with four colors
3997 constexpr GLsizei kSize = 2;
3998 std::array<GLColor, 4> pixels = {
3999 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4000 GLTexture rgbyTex;
4001 // Bind same texture object to tex units 0 & 1
4002 glActiveTexture(GL_TEXTURE0);
4003 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4004 glActiveTexture(GL_TEXTURE1);
4005 glBindTexture(GL_TEXTURE_2D, rgbyTex);
4006 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4007 pixels.data());
4008
4009 // Create a program that uses the texture with 2 separate samplers.
4010 constexpr char kFS[] = R"(precision mediump float;
4011 varying vec2 v_texCoord;
4012 uniform sampler2D samp1;
4013 uniform sampler2D samp2;
4014 void main()
4015 {
4016 gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
4017 })";
4018
4019 // Create program and bind samplers to tex units 0 & 1
4020 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
4021 GLint s1loc = glGetUniformLocation(program, "samp1");
4022 GLint s2loc = glGetUniformLocation(program, "samp2");
4023 glUseProgram(program);
4024 glUniform1i(s1loc, 0);
4025 glUniform1i(s2loc, 1);
4026 // Draw. This first draw is a confidence check and not really necessary for the test
4027 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4028 ASSERT_GL_NO_ERROR();
4029
4030 constexpr int kHalfSize = kWindowSize / 2;
4031
4032 // When rendering w/ NEAREST, colors are all maxed out so should still be solid
4033 EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4034 EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4035 EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4036 EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4037
4038 // Make first sampler use linear filtering
4039 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4040 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4041
4042 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4043 ASSERT_GL_NO_ERROR();
4044 // Capture rendered pixel color with s0 linear
4045 std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
4046 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
4047
4048 // Now restore first sampler & update second sampler
4049 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4050 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4051 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4052 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4053
4054 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4055 ASSERT_GL_NO_ERROR();
4056 // Capture rendered pixel color w/ s1 linear
4057 std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
4058 glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
4059 // Results should be the same regardless of if s0 or s1 is linear
4060 EXPECT_EQ(s0LinearColors, s1LinearColors);
4061 }
4062
4063 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)4064 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
4065 {
4066 constexpr char kVertexShader[] = R"(attribute vec4 a_position;
4067 attribute vec4 a_color;
4068 varying vec4 v_color;
4069 void main()
4070 {
4071 gl_Position = a_position;
4072 v_color = a_color;
4073 })";
4074
4075 constexpr char kFragmentShader[] = R"(precision mediump float;
4076 varying vec4 v_color;
4077 void main()
4078 {
4079 gl_FragColor = v_color;
4080 })";
4081
4082 ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
4083 GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
4084 ASSERT_NE(-1, positionLoc);
4085 GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
4086 ASSERT_NE(-1, colorLoc);
4087
4088 GLVertexArray VAOS[2];
4089 GLBuffer positionBuffer;
4090 GLBuffer colorBuffer;
4091 const auto quadVertices = GetQuadVertices();
4092
4093 glBindVertexArray(VAOS[0]);
4094 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4095 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4096 GL_STATIC_DRAW);
4097 glEnableVertexAttribArray(positionLoc);
4098 glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4099
4100 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4101 std::vector<GLColor32F> blueColor(6, kFloatBlue);
4102 glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4103 GL_STATIC_DRAW);
4104 glEnableVertexAttribArray(colorLoc);
4105 glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4106
4107 glBindVertexArray(0);
4108 glBindBuffer(GL_ARRAY_BUFFER, 0);
4109
4110 glBindVertexArray(VAOS[1]);
4111 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4112 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4113 GL_STATIC_DRAW);
4114 glEnableVertexAttribArray(positionLoc);
4115 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4116
4117 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4118 std::vector<GLColor32F> greenColor(6, kFloatGreen);
4119 glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4120 GL_STATIC_DRAW);
4121 glEnableVertexAttribArray(colorLoc);
4122 glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4123
4124 glBindVertexArray(0);
4125 glBindBuffer(GL_ARRAY_BUFFER, 0);
4126
4127 glUseProgram(mProgram);
4128 ASSERT_GL_NO_ERROR();
4129
4130 glBindVertexArray(VAOS[1]);
4131 glClear(GL_COLOR_BUFFER_BIT);
4132 glDrawArrays(GL_TRIANGLES, 0, 6);
4133
4134 // This drawing should not affect the next drawing.
4135 glBindVertexArray(VAOS[0]);
4136 glClear(GL_COLOR_BUFFER_BIT);
4137 glDrawArrays(GL_TRIANGLES, 0, 6);
4138
4139 glBindVertexArray(VAOS[1]);
4140 glClear(GL_COLOR_BUFFER_BIT);
4141 glDrawArrays(GL_TRIANGLES, 0, 6);
4142
4143 EXPECT_GL_NO_ERROR();
4144 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4145 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4147 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4148
4149 ASSERT_GL_NO_ERROR();
4150 }
4151
4152 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4153 // correctly. This requires a memory barrier in between the draw calls which should not be
4154 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4155 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4156 {
4157 // http://anglebug.com/5593
4158 ANGLE_SKIP_TEST_IF(IsD3D11());
4159
4160 GLint maxFragmentImageUniforms;
4161 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4162
4163 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4164
4165 // The test uses a GL_R32F framebuffer.
4166 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4167
4168 constexpr GLsizei kSize = 1;
4169
4170 GLTexture color;
4171 glBindTexture(GL_TEXTURE_2D, color);
4172 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4173 EXPECT_GL_NO_ERROR();
4174
4175 GLFramebuffer fbo;
4176 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4177 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4178 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4179 EXPECT_GL_NO_ERROR();
4180
4181 const float kInitialValue = 0.125f;
4182
4183 GLTexture texture;
4184 glBindTexture(GL_TEXTURE_2D, texture);
4185 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4186 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4187 EXPECT_GL_NO_ERROR();
4188
4189 GLFramebuffer readbackFbo;
4190 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4191 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4192 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4193 EXPECT_GL_NO_ERROR();
4194
4195 // Create a program that outputs to the image in the fragment shader.
4196 constexpr char kFS[] = R"(#version 310 es
4197 precision mediump float;
4198 layout(r32f, binding = 0) uniform highp image2D dst;
4199 out vec4 colorOut;
4200 void main()
4201 {
4202 vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4203 colorOut = result;
4204
4205 result.x += 0.193;
4206 imageStore(dst, ivec2(gl_FragCoord.xy), result);
4207 })";
4208
4209 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4210 glUseProgram(program);
4211
4212 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4213 ASSERT_NE(-1, positionLoc);
4214
4215 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4216 EXPECT_GL_NO_ERROR();
4217
4218 // Setup the draw so that there's no state change between the draw calls.
4219 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4220 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4221
4222 GLBuffer posBuffer;
4223 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4224 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4225 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4226 glEnableVertexAttribArray(positionLoc);
4227 EXPECT_GL_NO_ERROR();
4228
4229 glDrawArrays(GL_TRIANGLES, 0, 6);
4230 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4231 glDrawArrays(GL_TRIANGLES, 0, 6);
4232 EXPECT_GL_NO_ERROR();
4233
4234 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4235 EXPECT_GL_NO_ERROR();
4236
4237 // Verify the output of the two draw calls through the image is correct
4238 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4239 0.001f);
4240
4241 // Verify the output of rendering as well
4242 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4243 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4244 }
4245
4246 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4247 // draw call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4248 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4249 {
4250 // http://anglebug.com/5593
4251 ANGLE_SKIP_TEST_IF(IsD3D11());
4252 // http://anglebug.com/5686
4253 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4254
4255 GLint maxFragmentImageUniforms;
4256 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4257
4258 ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4259
4260 constexpr GLsizei kSize = 1;
4261
4262 GLTexture color;
4263 glBindTexture(GL_TEXTURE_2D, color);
4264 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4265 EXPECT_GL_NO_ERROR();
4266
4267 GLFramebuffer fbo;
4268 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4269 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4270 EXPECT_GL_NO_ERROR();
4271
4272 const GLColor kInitialColor = GLColor::red;
4273
4274 GLTexture texture;
4275 glBindTexture(GL_TEXTURE_2D, texture);
4276 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4277 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4278 &kInitialColor);
4279 EXPECT_GL_NO_ERROR();
4280
4281 GLFramebuffer readbackFbo;
4282 glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4283 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4284 EXPECT_GL_NO_ERROR();
4285
4286 // Create a program that samples from the texture in the fragment shader.
4287 constexpr char kFSSample[] = R"(#version 310 es
4288 precision mediump float;
4289 uniform sampler2D tex;
4290 out vec4 colorOut;
4291 void main()
4292 {
4293 colorOut = texture(tex, vec2(0));
4294 })";
4295 ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4296
4297 // Create a program that outputs to the image in the fragment shader.
4298 constexpr char kFSWrite[] = R"(#version 310 es
4299 precision mediump float;
4300 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4301 out vec4 colorOut;
4302 void main()
4303 {
4304 colorOut = vec4(0, 0, 1.0, 0);
4305 imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4306 })";
4307
4308 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4309
4310 glUseProgram(sampleProgram);
4311 GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4312 ASSERT_NE(-1, positionLocSample);
4313
4314 glUseProgram(writeProgram);
4315 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4316 ASSERT_NE(-1, positionLocWrite);
4317
4318 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4319
4320 // Setup the draw so that there's no state change between the draw calls.
4321 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4322 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4323
4324 GLBuffer posBuffer;
4325 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4326 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4327 glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4328 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4329 glEnableVertexAttribArray(positionLocSample);
4330 glEnableVertexAttribArray(positionLocWrite);
4331
4332 glUseProgram(sampleProgram);
4333 glDrawArrays(GL_TRIANGLES, 0, 6);
4334
4335 glEnable(GL_BLEND);
4336 glBlendFunc(GL_ONE, GL_ONE);
4337 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4338
4339 glUseProgram(writeProgram);
4340 glDrawArrays(GL_TRIANGLES, 0, 6);
4341
4342 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4343 EXPECT_GL_NO_ERROR();
4344
4345 // Verify the output of the two draw calls through the image is correct
4346 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4347
4348 // Verify the output of rendering as well
4349 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4350 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4351 }
4352
4353 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4354 // call works correctly. This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4355 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4356 {
4357 // http://anglebug.com/5593
4358 ANGLE_SKIP_TEST_IF(IsD3D11());
4359
4360 GLint maxFragmentShaderStorageBlocks;
4361 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4362
4363 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4364
4365 constexpr GLsizei kSize = 1;
4366
4367 GLTexture color;
4368 glBindTexture(GL_TEXTURE_2D, color);
4369 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4370 EXPECT_GL_NO_ERROR();
4371
4372 GLFramebuffer fbo;
4373 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4374 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4375 EXPECT_GL_NO_ERROR();
4376
4377 constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4378 GLBuffer buffer;
4379 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4380 glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4381 GL_STATIC_DRAW);
4382 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4383
4384 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4385 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4386
4387 // Create a program that reads from the ubo in the fragment shader.
4388 constexpr char kFSRead[] = R"(#version 310 es
4389 precision mediump float;
4390 uniform block { vec4 vec; } b;
4391 out vec4 colorOut;
4392 void main()
4393 {
4394 colorOut = b.vec;
4395 })";
4396 ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4397
4398 // Create a program that outputs to the image in the fragment shader.
4399 constexpr char kFSWrite[] = R"(#version 310 es
4400 precision mediump float;
4401 layout(binding = 0, std430) buffer Output {
4402 vec4 vec;
4403 } b;
4404 out vec4 colorOut;
4405 void main()
4406 {
4407 b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4408 colorOut = vec4(0.125, 0.125, 0.125, 0);
4409 })";
4410
4411 ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4412
4413 glUseProgram(readProgram);
4414 GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4415 ASSERT_NE(-1, positionLocRead);
4416
4417 glUseProgram(writeProgram);
4418 GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4419 ASSERT_NE(-1, positionLocWrite);
4420
4421 // Setup the draw so that there's no state change between the draw calls.
4422 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4423 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4424
4425 GLBuffer posBuffer;
4426 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4427 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4428 glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4429 glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4430 glEnableVertexAttribArray(positionLocRead);
4431 glEnableVertexAttribArray(positionLocWrite);
4432
4433 glUseProgram(readProgram);
4434 glDrawArrays(GL_TRIANGLES, 0, 6);
4435
4436 glEnable(GL_BLEND);
4437 glBlendFunc(GL_ONE, GL_ONE);
4438 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4439
4440 glUseProgram(writeProgram);
4441 glDrawArrays(GL_TRIANGLES, 0, 6);
4442
4443 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4444 EXPECT_GL_NO_ERROR();
4445
4446 // Verify the output of rendering
4447 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4448
4449 // Verify the output from the second draw call
4450 const float *ptr = reinterpret_cast<const float *>(
4451 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4452
4453 EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4454 EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4455 EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4456 EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4457
4458 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4459 }
4460
4461 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4462 // call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4463 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4464 {
4465 // TODO(anglebug.com/5649): Test is failing since it was introduced on Linux AMD GLES
4466 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4467
4468 constexpr GLsizei kSize = 1;
4469 const GLColor kInitColor(111, 222, 33, 44);
4470
4471 GLTexture color;
4472 glBindTexture(GL_TEXTURE_2D, color);
4473 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4475 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4476 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4477 EXPECT_GL_NO_ERROR();
4478
4479 GLFramebuffer fbo;
4480 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4481 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4482 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4483 EXPECT_GL_NO_ERROR();
4484
4485 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4486 GLBuffer buffer;
4487 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4488 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4489 GL_STATIC_DRAW);
4490 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4491 EXPECT_GL_NO_ERROR();
4492
4493 ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4494
4495 constexpr char kCS[] = R"(#version 310 es
4496 layout(local_size_x=1, local_size_y=1) in;
4497 uniform sampler2D tex;
4498 layout(binding = 0, std430) buffer Output {
4499 vec4 vec;
4500 } b;
4501 void main()
4502 {
4503 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4504 })";
4505
4506 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4507 glUseProgram(readProgram);
4508
4509 glActiveTexture(GL_TEXTURE0);
4510 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4511
4512 drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
4513 EXPECT_GL_NO_ERROR();
4514
4515 glUseProgram(readProgram);
4516 glDispatchCompute(1, 1, 1);
4517
4518 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4519 EXPECT_GL_NO_ERROR();
4520
4521 // Verify the output of rendering
4522 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4523
4524 // Verify the output from the compute shader
4525 const float *ptr = reinterpret_cast<const float *>(
4526 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4527
4528 EXPECT_EQ(ptr[0], 1.0f);
4529 EXPECT_EQ(ptr[1], 0.0f);
4530 EXPECT_EQ(ptr[2], 0.0f);
4531 EXPECT_EQ(ptr[3], 1.0f);
4532
4533 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4534 }
4535
4536 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
4537 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)4538 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
4539 {
4540 // http://anglebug.com/5687
4541 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
4542
4543 constexpr GLsizei kSize = 1;
4544
4545 GLTexture color;
4546 glBindTexture(GL_TEXTURE_2D, color);
4547 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4548 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4549 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4550 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
4551 EXPECT_GL_NO_ERROR();
4552
4553 GLFramebuffer fbo;
4554 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4555 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4556 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4557 EXPECT_GL_NO_ERROR();
4558
4559 // Make sure the update to the texture is effective.
4560 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4561
4562 // Clear the texture through the framebuffer
4563 glClearColor(0, 1.0f, 0, 1.0f);
4564 glClear(GL_COLOR_BUFFER_BIT);
4565
4566 constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4567 GLBuffer buffer;
4568 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4569 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4570 GL_STATIC_DRAW);
4571 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4572 EXPECT_GL_NO_ERROR();
4573
4574 constexpr char kCS[] = R"(#version 310 es
4575 layout(local_size_x=1, local_size_y=1) in;
4576 uniform sampler2D tex;
4577 layout(binding = 0, std430) buffer Output {
4578 vec4 vec;
4579 } b;
4580 void main()
4581 {
4582 b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4583 })";
4584
4585 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4586 glUseProgram(readProgram);
4587
4588 glActiveTexture(GL_TEXTURE0);
4589 glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4590
4591 glUseProgram(readProgram);
4592 glDispatchCompute(1, 1, 1);
4593
4594 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4595 EXPECT_GL_NO_ERROR();
4596
4597 // Verify the clear
4598 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4599
4600 // Verify the output from the compute shader
4601 const float *ptr = reinterpret_cast<const float *>(
4602 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4603
4604 EXPECT_EQ(ptr[0], 0.0f);
4605 EXPECT_EQ(ptr[1], 1.0f);
4606 EXPECT_EQ(ptr[2], 0.0f);
4607 EXPECT_EQ(ptr[3], 1.0f);
4608
4609 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4610 }
4611
4612 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
4613 // it in a dispatch call works correctly. This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)4614 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
4615 {
4616 // http://anglebug.com/5687
4617 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
4618
4619 constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
4620 GLBuffer buffer;
4621 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
4622 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
4623 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
4624
4625 std::vector<std::string> tfVaryings = {"gl_Position"};
4626 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
4627 essl3_shaders::fs::Green(), tfVaryings,
4628 GL_INTERLEAVED_ATTRIBS);
4629 glUseProgram(program);
4630
4631 glBeginTransformFeedback(GL_TRIANGLES);
4632 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
4633 glEndTransformFeedback();
4634
4635 constexpr char kCS[] = R"(#version 310 es
4636 layout(local_size_x=1, local_size_y=1) in;
4637 layout(binding = 0) uniform Input
4638 {
4639 vec4 data[3];
4640 };
4641 layout(binding = 0, std430) buffer Output {
4642 bool pass;
4643 };
4644 void main()
4645 {
4646 pass = data[0] == vec4(-1, 1, 0, 1) &&
4647 data[1] == vec4(-1, -1, 0, 1) &&
4648 data[2] == vec4(1, -1, 0, 1);
4649 })";
4650
4651 ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4652 glUseProgram(readProgram);
4653
4654 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4655
4656 constexpr GLsizei kResultSize = sizeof(uint32_t);
4657 GLBuffer resultBuffer;
4658 glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
4659 glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
4660 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
4661
4662 glDispatchCompute(1, 1, 1);
4663
4664 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4665 EXPECT_GL_NO_ERROR();
4666
4667 // Verify the output of rendering
4668 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4669
4670 // Verify the output from the compute shader
4671 const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
4672 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
4673
4674 EXPECT_EQ(ptr[0], 1u);
4675
4676 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4677 }
4678
4679 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)4680 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
4681 {
4682 std::array<GLColor, 4> colors = {
4683 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4684 GLTexture texRead;
4685 glBindTexture(GL_TEXTURE_2D, texRead);
4686 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4687 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4688 EXPECT_GL_NO_ERROR();
4689
4690 glUseProgram(mProgram);
4691
4692 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4693 glDispatchCompute(1, 1, 1);
4694 texRead.reset();
4695
4696 std::array<GLColor, 4> results;
4697 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4698 EXPECT_GL_NO_ERROR();
4699
4700 for (int i = 0; i < 4; i++)
4701 {
4702 EXPECT_EQ(colors[i], results[i]);
4703 }
4704 }
4705
4706 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)4707 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
4708 {
4709 std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4710 GLTexture texRead;
4711 glBindTexture(GL_TEXTURE_2D, texRead);
4712 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4713 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4714
4715 glUseProgram(mProgram);
4716
4717 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4718 glDispatchCompute(1, 1, 1);
4719
4720 // Bind again
4721 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4722 glDispatchCompute(1, 1, 1);
4723 EXPECT_GL_NO_ERROR();
4724
4725 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4726 }
4727
4728 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
4729 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)4730 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
4731 {
4732 std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
4733 std::array<GLColor, 4> subColors = {
4734 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
4735
4736 GLTexture texRead;
4737 glBindTexture(GL_TEXTURE_2D, texRead);
4738 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4739 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4740
4741 glUseProgram(mProgram);
4742
4743 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4744 glDispatchCompute(1, 1, 1);
4745
4746 // Update bottom-half of image texture with green.
4747 glBindTexture(GL_TEXTURE_2D, texRead);
4748 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
4749 ASSERT_GL_NO_ERROR();
4750
4751 // Dispatch again, should still work.
4752 glDispatchCompute(1, 1, 1);
4753 ASSERT_GL_NO_ERROR();
4754
4755 // Validate first half of the image is red and the bottom is green.
4756 std::array<GLColor, 4> results;
4757 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4758 EXPECT_GL_NO_ERROR();
4759
4760 EXPECT_EQ(GLColor::green, results[0]);
4761 EXPECT_EQ(GLColor::green, results[1]);
4762 EXPECT_EQ(GLColor::red, results[2]);
4763 EXPECT_EQ(GLColor::red, results[3]);
4764 }
4765
4766 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)4767 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
4768 {
4769 std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4770
4771 GLTexture texRead;
4772 glBindTexture(GL_TEXTURE_2D, texRead);
4773 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4774 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
4775
4776 glUseProgram(mProgram);
4777
4778 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4779 glDispatchCompute(1, 1, 1);
4780
4781 // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
4782 std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
4783 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
4784 ASSERT_GL_NO_ERROR();
4785
4786 // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
4787 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4788 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
4789 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
4790 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
4791
4792 // Dispatch again. The second dispatch call should use the updated YBGR data.
4793 glDispatchCompute(1, 1, 1);
4794
4795 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4796 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
4797 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
4798 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4799 ASSERT_GL_NO_ERROR();
4800 }
4801
4802 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)4803 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
4804 {
4805 std::array<GLColor, 4> colorsTexA = {
4806 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4807
4808 std::array<GLColor, 4> colorsTexB = {
4809 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
4810
4811 GLTexture texA;
4812 glBindTexture(GL_TEXTURE_2D, texA);
4813 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4814 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
4815 GLTexture texB;
4816 glBindTexture(GL_TEXTURE_2D, texB);
4817 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4818 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
4819
4820 glUseProgram(mProgram);
4821
4822 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4823 glDispatchCompute(1, 1, 1);
4824
4825 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4826 glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4827 glDispatchCompute(1, 1, 1);
4828
4829 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4830 glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4831 glDispatchCompute(1, 1, 1);
4832
4833 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4834 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4835 ASSERT_GL_NO_ERROR();
4836 }
4837
4838 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
4839 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)4840 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
4841 {
4842 ANGLE_SKIP_TEST_IF(!IsVulkan());
4843
4844 glGenFramebuffers(1, &mFramebuffer);
4845 glGenTextures(1, &mTexture);
4846
4847 glBindTexture(GL_TEXTURE_2D, mTexture);
4848 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4849 EXPECT_GL_NO_ERROR();
4850
4851 constexpr char kCS[] = R"(#version 310 es
4852 layout(local_size_x=2, local_size_y=2) in;
4853 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
4854 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
4855 void main()
4856 {
4857 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
4858 imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
4859 })";
4860
4861 bindProgramPipeline(kCS);
4862
4863 glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4864
4865 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
4866 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
4867
4868 ASSERT_GL_NO_ERROR();
4869
4870 std::array<GLColor, 4> colors = {
4871 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4872 GLTexture texRead;
4873 glBindTexture(GL_TEXTURE_2D, texRead);
4874 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4875 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4876 EXPECT_GL_NO_ERROR();
4877
4878 glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4879 glDispatchCompute(1, 1, 1);
4880 texRead.reset();
4881
4882 std::array<GLColor, 4> results;
4883 glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4884 EXPECT_GL_NO_ERROR();
4885
4886 for (int i = 0; i < 4; i++)
4887 {
4888 EXPECT_EQ(colors[i], results[i]);
4889 }
4890 }
4891
4892 static constexpr char kColorVS[] = R"(attribute vec2 position;
4893 attribute vec4 color;
4894 varying vec4 vColor;
4895 void main()
4896 {
4897 gl_Position = vec4(position, 0, 1);
4898 vColor = color;
4899 })";
4900
4901 static constexpr char kColorFS[] = R"(precision mediump float;
4902 varying vec4 vColor;
4903 void main()
4904 {
4905 gl_FragColor = vColor;
4906 })";
4907
4908 class ValidationStateChangeTest : public ANGLETest
4909 {
4910 protected:
ValidationStateChangeTest()4911 ValidationStateChangeTest()
4912 {
4913 setWindowWidth(64);
4914 setWindowHeight(64);
4915 setConfigRedBits(8);
4916 setConfigGreenBits(8);
4917 setConfigBlueBits(8);
4918 setConfigAlphaBits(8);
4919 }
4920 };
4921
4922 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
4923 {
4924 protected:
WebGL2ValidationStateChangeTest()4925 WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4926 };
4927
4928 class ValidationStateChangeTestES31 : public ANGLETest
4929 {};
4930
4931 class WebGLComputeValidationStateChangeTest : public ANGLETest
4932 {
4933 public:
WebGLComputeValidationStateChangeTest()4934 WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4935 };
4936
4937 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
4938 {
4939 protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()4940 RobustBufferAccessWebGL2ValidationStateChangeTest()
4941 {
4942 // SwS/OSX GL do not support robustness. Mali does not support it.
4943 if (!isSwiftshader() && !IsOSX() && !IsIOS() && !IsARM())
4944 {
4945 setRobustAccess(true);
4946 }
4947 }
4948 };
4949
4950 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
4951 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)4952 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
4953 {
4954 // Initialize program and set up state.
4955 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
4956
4957 glUseProgram(program);
4958 GLint positionLoc = glGetAttribLocation(program, "position");
4959 ASSERT_NE(-1, positionLoc);
4960 GLint colorLoc = glGetAttribLocation(program, "color");
4961 ASSERT_NE(-1, colorLoc);
4962
4963 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4964 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
4965
4966 GLBuffer posBuffer;
4967 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4968 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4969
4970 // Start with position enabled.
4971 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4972 glEnableVertexAttribArray(positionLoc);
4973
4974 std::vector<GLColor> colorVertices(6, GLColor::blue);
4975 const size_t colorBufferSize = sizeof(GLColor) * 6;
4976
4977 GLBuffer colorBuffer;
4978 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4979 glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
4980
4981 // Start with color disabled.
4982 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
4983 glDisableVertexAttribArray(colorLoc);
4984
4985 ASSERT_GL_NO_ERROR();
4986
4987 // Draw without a mapped buffer. Should succeed.
4988 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
4989 glDrawArrays(GL_TRIANGLES, 0, 6);
4990 ASSERT_GL_NO_ERROR();
4991 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4992
4993 // Map position buffer and draw. Should fail.
4994 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4995 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
4996 ASSERT_GL_NO_ERROR();
4997
4998 glDrawArrays(GL_TRIANGLES, 0, 6);
4999 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
5000 glUnmapBuffer(GL_ARRAY_BUFFER);
5001
5002 // Map then enable color buffer. Should fail.
5003 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5004 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
5005 glEnableVertexAttribArray(colorLoc);
5006 ASSERT_GL_NO_ERROR();
5007
5008 glDrawArrays(GL_TRIANGLES, 0, 6);
5009 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
5010
5011 // Unmap then draw. Should succeed.
5012 glUnmapBuffer(GL_ARRAY_BUFFER);
5013 ASSERT_GL_NO_ERROR();
5014
5015 glDrawArrays(GL_TRIANGLES, 0, 6);
5016 ASSERT_GL_NO_ERROR();
5017 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5018 }
5019
5020 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
5021 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)5022 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
5023 {
5024 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5025
5026 // Initialize program and set up state.
5027 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5028
5029 glUseProgram(program);
5030 GLint positionLoc = glGetAttribLocation(program, "position");
5031 ASSERT_NE(-1, positionLoc);
5032 GLint colorLoc = glGetAttribLocation(program, "color");
5033 ASSERT_NE(-1, colorLoc);
5034
5035 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5036 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5037
5038 GLBuffer posBuffer;
5039 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5040 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5041 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5042
5043 // Start with position enabled.
5044 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5045 glEnableVertexAttribArray(positionLoc);
5046
5047 std::vector<GLColor> colorVertices(6, GLColor::blue);
5048 const size_t colorBufferSize = sizeof(GLColor) * 6;
5049
5050 GLBuffer colorBuffer;
5051 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5052 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5053 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5054
5055 // Start with color disabled.
5056 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5057 glDisableVertexAttribArray(colorLoc);
5058
5059 ASSERT_GL_NO_ERROR();
5060
5061 // Draw without a mapped buffer. Should succeed.
5062 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5063 glDrawArrays(GL_TRIANGLES, 0, 6);
5064 ASSERT_GL_NO_ERROR();
5065 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5066
5067 // Map position buffer and draw. Should succeed.
5068 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5069 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5070 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5071 ASSERT_GL_NO_ERROR();
5072
5073 glDrawArrays(GL_TRIANGLES, 0, 6);
5074 ASSERT_GL_NO_ERROR();
5075 glUnmapBuffer(GL_ARRAY_BUFFER);
5076
5077 // Map then enable color buffer. Should succeed.
5078 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5079 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5080 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5081 glEnableVertexAttribArray(colorLoc);
5082 ASSERT_GL_NO_ERROR();
5083
5084 glDrawArrays(GL_TRIANGLES, 0, 6);
5085 ASSERT_GL_NO_ERROR();
5086
5087 // Unmap then draw. Should succeed.
5088 glUnmapBuffer(GL_ARRAY_BUFFER);
5089 ASSERT_GL_NO_ERROR();
5090
5091 glDrawArrays(GL_TRIANGLES, 0, 6);
5092 ASSERT_GL_NO_ERROR();
5093 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5094 }
5095
5096 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5097 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5098 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5099 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5100 {
5101 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5102
5103 // Initialize program and set up state.
5104 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5105
5106 glUseProgram(program);
5107 GLint positionLoc = glGetAttribLocation(program, "position");
5108 ASSERT_NE(-1, positionLoc);
5109 GLint colorLoc = glGetAttribLocation(program, "color");
5110 ASSERT_NE(-1, colorLoc);
5111
5112 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5113 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5114
5115 GLBuffer posBuffer;
5116 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5117 glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5118 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5119
5120 glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5121 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5122
5123 // Start with position enabled.
5124 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5125 glEnableVertexAttribArray(positionLoc);
5126
5127 std::vector<GLColor> colorVertices(6, GLColor::blue);
5128 const size_t colorBufferSize = sizeof(GLColor) * 6;
5129
5130 GLBuffer colorBuffer;
5131 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5132 glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5133 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5134
5135 glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5136 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5137 ASSERT_GL_NO_ERROR();
5138
5139 // Start with color disabled.
5140 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5141 glDisableVertexAttribArray(colorLoc);
5142
5143 ASSERT_GL_NO_ERROR();
5144
5145 // Draw without a mapped buffer. Should succeed.
5146 glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5147 glDrawArrays(GL_TRIANGLES, 0, 6);
5148 ASSERT_GL_NO_ERROR();
5149 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5150
5151 // Unmap then draw. Should succeed.
5152 glUnmapBuffer(GL_ARRAY_BUFFER);
5153 glEnableVertexAttribArray(colorLoc);
5154 ASSERT_GL_NO_ERROR();
5155 glDrawArrays(GL_TRIANGLES, 0, 6);
5156 ASSERT_GL_NO_ERROR();
5157 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5158 }
5159
5160 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5161 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5162 {
5163 // Seems to trigger a GL error in some edge cases. http://anglebug.com/2755
5164 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5165
5166 // Initialize program and set up state.
5167 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5168
5169 glUseProgram(program);
5170 GLint positionLoc = glGetAttribLocation(program, "position");
5171 ASSERT_NE(-1, positionLoc);
5172 GLint colorLoc = glGetAttribLocation(program, "color");
5173 ASSERT_NE(-1, colorLoc);
5174
5175 // Create a user vertex array.
5176 GLVertexArray vao;
5177 glBindVertexArray(vao);
5178
5179 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5180 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5181
5182 GLBuffer posBuffer;
5183 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5184 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5185
5186 // Start with position enabled.
5187 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5188 glEnableVertexAttribArray(positionLoc);
5189
5190 std::vector<GLColor> blueVertices(6, GLColor::blue);
5191 const size_t blueBufferSize = sizeof(GLColor) * 6;
5192
5193 GLBuffer blueBuffer;
5194 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5195 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5196
5197 // Start with color enabled at an unused binding.
5198 constexpr GLint kUnusedBinding = 3;
5199 ASSERT_NE(colorLoc, kUnusedBinding);
5200 ASSERT_NE(positionLoc, kUnusedBinding);
5201 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5202 glVertexAttribBinding(colorLoc, kUnusedBinding);
5203 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5204 glEnableVertexAttribArray(colorLoc);
5205
5206 // Make binding 'colorLoc' use a mapped buffer.
5207 std::vector<GLColor> greenVertices(6, GLColor::green);
5208 const size_t greenBufferSize = sizeof(GLColor) * 6;
5209 GLBuffer greenBuffer;
5210 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5211 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5212 glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5213 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5214
5215 ASSERT_GL_NO_ERROR();
5216
5217 // Draw without a mapped buffer. Should succeed.
5218 glDrawArrays(GL_TRIANGLES, 0, 6);
5219 ASSERT_GL_NO_ERROR();
5220 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5221
5222 // Change divisor with VertexAttribDivisor. Should fail.
5223 glVertexAttribDivisor(colorLoc, 0);
5224 ASSERT_GL_NO_ERROR();
5225 glDrawArrays(GL_TRIANGLES, 0, 6);
5226 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5227
5228 // Unmap the buffer. Should succeed.
5229 glUnmapBuffer(GL_ARRAY_BUFFER);
5230 glDrawArrays(GL_TRIANGLES, 0, 6);
5231 ASSERT_GL_NO_ERROR();
5232 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5233 }
5234
5235 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5236 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5237 {
5238 // Initialize program and set up state.
5239 ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5240
5241 glUseProgram(program);
5242 GLint positionLoc = glGetAttribLocation(program, "position");
5243 ASSERT_NE(-1, positionLoc);
5244 GLint colorLoc = glGetAttribLocation(program, "color");
5245 ASSERT_NE(-1, colorLoc);
5246
5247 // Create a user vertex array.
5248 GLVertexArray vao;
5249 glBindVertexArray(vao);
5250
5251 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5252 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
5253
5254 GLBuffer posBuffer;
5255 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5256 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5257
5258 // Start with position enabled.
5259 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5260 glEnableVertexAttribArray(positionLoc);
5261
5262 std::vector<GLColor> blueVertices(6, GLColor::blue);
5263 const size_t blueBufferSize = sizeof(GLColor) * 6;
5264
5265 GLBuffer blueBuffer;
5266 glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5267 glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5268
5269 // Start with color enabled at an unused binding.
5270 constexpr GLint kUnusedBinding = 3;
5271 ASSERT_NE(colorLoc, kUnusedBinding);
5272 ASSERT_NE(positionLoc, kUnusedBinding);
5273 glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5274 glVertexAttribBinding(colorLoc, kUnusedBinding);
5275 glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5276 glEnableVertexAttribArray(colorLoc);
5277
5278 // Make binding 'colorLoc' use a small buffer.
5279 std::vector<GLColor> greenVertices(6, GLColor::green);
5280 const size_t greenBufferSize = sizeof(GLColor) * 3;
5281 GLBuffer greenBuffer;
5282 glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5283 glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5284 glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5285
5286 ASSERT_GL_NO_ERROR();
5287
5288 // Draw without a mapped buffer. Should succeed.
5289 glDrawArrays(GL_TRIANGLES, 0, 6);
5290 ASSERT_GL_NO_ERROR();
5291 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5292
5293 // Change divisor with VertexAttribDivisor. Should fail.
5294 glVertexAttribDivisor(colorLoc, 0);
5295 ASSERT_GL_NO_ERROR();
5296 glDrawArrays(GL_TRIANGLES, 0, 6);
5297 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5298
5299 // Do a small draw. Should succeed.
5300 glDrawArrays(GL_TRIANGLES, 0, 3);
5301 ASSERT_GL_NO_ERROR();
5302 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5303 }
5304
5305 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5306 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5307 {
5308 constexpr char kVS[] = R"(#version 300 es
5309 in vec2 position;
5310 void main()
5311 {
5312 gl_Position = vec4(position, 0, 1);
5313 })";
5314
5315 constexpr char kFS[] = R"(#version 300 es
5316 precision mediump float;
5317 uniform uni { vec4 vec; };
5318 out vec4 color;
5319 void main()
5320 {
5321 color = vec;
5322 })";
5323
5324 ANGLE_GL_PROGRAM(program, kVS, kFS);
5325 glUseProgram(program);
5326
5327 GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5328 ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5329
5330 glUniformBlockBinding(program, blockIndex, 0);
5331
5332 GLBuffer uniformBuffer;
5333 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5334 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5335 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5336
5337 const auto &quadVertices = GetQuadVertices();
5338
5339 GLBuffer positionBuffer;
5340 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5341 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5342 GL_STATIC_DRAW);
5343
5344 GLint positionLocation = glGetAttribLocation(program, "position");
5345 ASSERT_NE(-1, positionLocation);
5346
5347 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5348 glEnableVertexAttribArray(positionLocation);
5349 ASSERT_GL_NO_ERROR();
5350
5351 // First draw should succeed.
5352 glDrawArrays(GL_TRIANGLES, 0, 6);
5353 ASSERT_GL_NO_ERROR();
5354 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5355
5356 // Change the uniform block binding. Should fail.
5357 glUniformBlockBinding(program, blockIndex, 1);
5358 ASSERT_GL_NO_ERROR();
5359 glDrawArrays(GL_TRIANGLES, 0, 6);
5360 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5361
5362 // Reset to a correct state.
5363 glUniformBlockBinding(program, blockIndex, 0);
5364 glDrawArrays(GL_TRIANGLES, 0, 6);
5365 ASSERT_GL_NO_ERROR();
5366 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5367
5368 // Change the buffer binding. Should fail.
5369 glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5370 ASSERT_GL_NO_ERROR();
5371 glDrawArrays(GL_TRIANGLES, 0, 6);
5372 ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5373
5374 // Reset to a correct state.
5375 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5376 glDrawArrays(GL_TRIANGLES, 0, 6);
5377 ASSERT_GL_NO_ERROR();
5378 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5379
5380 // Resize the buffer to be too small. Should fail.
5381 glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5382 glDrawArrays(GL_TRIANGLES, 0, 6);
5383 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5384 }
5385
5386 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5387 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5388 {
5389 // Set up a simple draw from a Texture to a user Framebuffer.
5390 GLuint program = get2DTexturedQuadProgram();
5391 ASSERT_NE(0u, program);
5392 glUseProgram(program);
5393
5394 GLint posLoc = glGetAttribLocation(program, "position");
5395 ASSERT_NE(-1, posLoc);
5396
5397 const auto &quadVertices = GetQuadVertices();
5398
5399 GLBuffer positionBuffer;
5400 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5401 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5402 GL_STATIC_DRAW);
5403
5404 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5405 glEnableVertexAttribArray(posLoc);
5406
5407 constexpr size_t kSize = 2;
5408
5409 GLTexture colorBufferTexture;
5410 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5411 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5414
5415 GLFramebuffer framebuffer;
5416 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5417 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5418 0);
5419 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5420
5421 std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
5422
5423 GLTexture greenTexture;
5424 glBindTexture(GL_TEXTURE_2D, greenTexture);
5425 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5426 greenColor.data());
5427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5429
5430 // Second framebuffer with a feedback loop. Initially unbound.
5431 GLFramebuffer loopedFramebuffer;
5432 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5433 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
5434 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5435 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5436
5437 ASSERT_GL_NO_ERROR();
5438
5439 glDrawArrays(GL_TRIANGLES, 0, 6);
5440 ASSERT_GL_NO_ERROR();
5441 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5442
5443 // Create a rendering feedback loop. Should fail.
5444 glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5445 ASSERT_GL_NO_ERROR();
5446 glDrawArrays(GL_TRIANGLES, 0, 6);
5447 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5448
5449 // Reset to a valid state.
5450 glBindTexture(GL_TEXTURE_2D, greenTexture);
5451 glDrawArrays(GL_TRIANGLES, 0, 6);
5452 ASSERT_GL_NO_ERROR();
5453 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5454
5455 // Bind a second framebuffer with a feedback loop.
5456 glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5457 ASSERT_GL_NO_ERROR();
5458 glDrawArrays(GL_TRIANGLES, 0, 6);
5459 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5460
5461 // Update the framebuffer texture attachment. Should succeed.
5462 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5463 0);
5464 glDrawArrays(GL_TRIANGLES, 0, 6);
5465 ASSERT_GL_NO_ERROR();
5466 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5467 }
5468
5469 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)5470 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
5471 {
5472 // Crashes on 64-bit Android. http://anglebug.com/3878
5473 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
5474
5475 // Set up a program that writes to two outputs: one int and one float.
5476 constexpr char kVS[] = R"(#version 300 es
5477 layout(location = 0) in vec2 position;
5478 out vec2 texCoord;
5479 void main()
5480 {
5481 gl_Position = vec4(position, 0, 1);
5482 texCoord = position * 0.5 + vec2(0.5);
5483 })";
5484
5485 constexpr char kFS[] = R"(#version 300 es
5486 precision mediump float;
5487 in vec2 texCoord;
5488 layout(location = 0) out vec4 outFloat;
5489 layout(location = 1) out uvec4 outInt;
5490 void main()
5491 {
5492 outFloat = vec4(0, 1, 0, 1);
5493 outInt = uvec4(0, 1, 0, 1);
5494 })";
5495
5496 ANGLE_GL_PROGRAM(program, kVS, kFS);
5497 glUseProgram(program);
5498
5499 constexpr GLint kPosLoc = 0;
5500
5501 const auto &quadVertices = GetQuadVertices();
5502
5503 GLBuffer positionBuffer;
5504 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5505 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5506 GL_STATIC_DRAW);
5507
5508 glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5509 glEnableVertexAttribArray(kPosLoc);
5510
5511 constexpr size_t kSize = 2;
5512
5513 GLFramebuffer floatFramebuffer;
5514 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5515
5516 GLTexture floatTextures[2];
5517 for (int i = 0; i < 2; ++i)
5518 {
5519 glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
5520 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5521 nullptr);
5522 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5523 floatTextures[i], 0);
5524 ASSERT_GL_NO_ERROR();
5525 }
5526
5527 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5528
5529 GLFramebuffer intFramebuffer;
5530 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5531
5532 GLTexture intTextures[2];
5533 for (int i = 0; i < 2; ++i)
5534 {
5535 glBindTexture(GL_TEXTURE_2D, intTextures[i]);
5536 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
5537 GL_UNSIGNED_BYTE, nullptr);
5538 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5539 intTextures[i], 0);
5540 ASSERT_GL_NO_ERROR();
5541 }
5542
5543 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5544
5545 ASSERT_GL_NO_ERROR();
5546
5547 constexpr GLenum kColor0Enabled[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
5548 constexpr GLenum kColor1Enabled[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
5549 constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
5550
5551 // Draw float. Should work.
5552 glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5553 glDrawBuffers(2, kColor0Enabled);
5554
5555 glDrawArrays(GL_TRIANGLES, 0, 6);
5556 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5557 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5558
5559 // Set an invalid component write.
5560 glDrawBuffers(2, kColor0And1Enabled);
5561 ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
5562 glDrawArrays(GL_TRIANGLES, 0, 6);
5563 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5564 // Set all 4 channels of color mask to false. Validate success.
5565 glColorMask(false, false, false, false);
5566 glDrawArrays(GL_TRIANGLES, 0, 6);
5567 EXPECT_GL_NO_ERROR();
5568 glColorMask(false, true, false, false);
5569 glDrawArrays(GL_TRIANGLES, 0, 6);
5570 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5571 glColorMask(true, true, true, true);
5572 glDrawArrays(GL_TRIANGLES, 0, 6);
5573 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5574
5575 // Restore state.
5576 glDrawBuffers(2, kColor0Enabled);
5577 glDrawArrays(GL_TRIANGLES, 0, 6);
5578 ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5579 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5580
5581 // Bind an invalid framebuffer. Validate failure.
5582 glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5583 ASSERT_GL_NO_ERROR();
5584 glDrawArrays(GL_TRIANGLES, 0, 6);
5585 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
5586
5587 // Set draw mask to a valid mask. Validate success.
5588 glDrawBuffers(2, kColor1Enabled);
5589 glDrawArrays(GL_TRIANGLES, 0, 6);
5590 ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
5591 }
5592
5593 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)5594 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
5595 {
5596 ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5597
5598 // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
5599 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
5600
5601 constexpr char kFS[] = R"(#version 300 es
5602 precision mediump float;
5603 uniform block { vec4 color; };
5604 out vec4 colorOut;
5605 void main()
5606 {
5607 colorOut = color;
5608 })";
5609
5610 std::vector<std::string> tfVaryings = {"gl_Position"};
5611 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
5612 GL_INTERLEAVED_ATTRIBS);
5613 glUseProgram(program);
5614
5615 std::vector<Vector4> positionData;
5616 for (const Vector3 &quadVertex : GetQuadVertices())
5617 {
5618 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5619 }
5620
5621 GLBuffer arrayBuffer;
5622 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5623 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5624 GL_STATIC_DRAW);
5625
5626 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5627 ASSERT_NE(-1, positionLoc);
5628
5629 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5630 glEnableVertexAttribArray(positionLoc);
5631
5632 EXPECT_GL_NO_ERROR();
5633
5634 // Set up transform feedback.
5635 GLTransformFeedback transformFeedback;
5636 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5637
5638 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5639
5640 GLBuffer transformFeedbackBuffer;
5641 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5642 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5643 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5644
5645 // Set up uniform buffer.
5646 GLBuffer uniformBuffer;
5647 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5648 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5649 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5650
5651 ASSERT_GL_NO_ERROR();
5652
5653 // Do the draw operation. Should succeed.
5654 glBeginTransformFeedback(GL_TRIANGLES);
5655 glDrawArrays(GL_TRIANGLES, 0, 6);
5656 glEndTransformFeedback();
5657
5658 ASSERT_GL_NO_ERROR();
5659 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5660
5661 const GLvoid *mapPointer =
5662 glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
5663 ASSERT_GL_NO_ERROR();
5664 ASSERT_NE(nullptr, mapPointer);
5665 const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
5666 std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
5667 EXPECT_EQ(positionData, actualData);
5668 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5669
5670 // Draw once to update validation cache.
5671 glBeginTransformFeedback(GL_TRIANGLES);
5672 glDrawArrays(GL_TRIANGLES, 0, 6);
5673
5674 // Bind transform feedback buffer to another binding point. Should cause a conflict.
5675 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
5676 ASSERT_GL_NO_ERROR();
5677 glDrawArrays(GL_TRIANGLES, 0, 6);
5678 glEndTransformFeedback();
5679 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
5680
5681 // Reset to valid state.
5682 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
5683 glBeginTransformFeedback(GL_TRIANGLES);
5684 glDrawArrays(GL_TRIANGLES, 0, 6);
5685 glEndTransformFeedback();
5686 ASSERT_GL_NO_ERROR();
5687
5688 // Simultaneous non-vertex-array binding. Should fail.
5689 glBeginTransformFeedback(GL_TRIANGLES);
5690 glDrawArrays(GL_TRIANGLES, 0, 6);
5691 ASSERT_GL_NO_ERROR();
5692 glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
5693 ASSERT_GL_NO_ERROR();
5694 glDrawArrays(GL_TRIANGLES, 0, 6);
5695 glEndTransformFeedback();
5696 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
5697 }
5698
5699 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)5700 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
5701 {
5702 // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
5703 // DEPTH_COMPONENT24 is emulated with D32_S8X24. http://anglebug.com/3880
5704 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
5705
5706 constexpr char kFS[] = R"(#version 300 es
5707 precision mediump float;
5708 uniform sampler2D sampler;
5709 out vec4 colorOut;
5710 void main()
5711 {
5712 colorOut = texture(sampler, vec2(0));
5713 })";
5714
5715 std::vector<std::string> tfVaryings = {"gl_Position"};
5716 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5717 glUseProgram(program);
5718
5719 std::array<GLColor, 4> colors = {
5720 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5721
5722 GLTexture tex;
5723 glBindTexture(GL_TEXTURE_2D, tex);
5724 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5725
5726 const auto &quadVertices = GetQuadVertices();
5727
5728 GLBuffer arrayBuffer;
5729 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5730 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5731 GL_STATIC_DRAW);
5732
5733 GLint samplerLoc = glGetUniformLocation(program, "sampler");
5734 ASSERT_NE(-1, samplerLoc);
5735 glUniform1i(samplerLoc, 0);
5736
5737 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5738 ASSERT_NE(-1, positionLoc);
5739 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5740 glEnableVertexAttribArray(positionLoc);
5741
5742 ASSERT_GL_NO_ERROR();
5743
5744 glDrawArrays(GL_TRIANGLES, 0, 6);
5745 ASSERT_GL_NO_ERROR();
5746
5747 // TexImage2D should update the sampler format cache.
5748 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
5749 colors.data());
5750 glDrawArrays(GL_TRIANGLES, 0, 6);
5751 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
5752
5753 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
5754 GL_UNSIGNED_INT, colors.data());
5755 glDrawArrays(GL_TRIANGLES, 0, 6);
5756 ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
5757
5758 // TexParameteri should update the sampler format cache.
5759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
5760 glDrawArrays(GL_TRIANGLES, 0, 6);
5761 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
5762 }
5763
5764 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)5765 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
5766 {
5767 ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5768
5769 std::vector<std::string> tfVaryings = {"gl_Position"};
5770 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5771 essl3_shaders::fs::Red(), tfVaryings,
5772 GL_INTERLEAVED_ATTRIBS);
5773 glUseProgram(program);
5774
5775 std::vector<Vector4> positionData;
5776 for (const Vector3 &quadVertex : GetQuadVertices())
5777 {
5778 positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5779 }
5780
5781 GLBuffer arrayBuffer;
5782 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5783 glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5784 GL_STATIC_DRAW);
5785
5786 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5787 ASSERT_NE(-1, positionLoc);
5788
5789 glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5790 glEnableVertexAttribArray(positionLoc);
5791
5792 // Set up transform feedback.
5793 GLTransformFeedback transformFeedback;
5794 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5795
5796 constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5797
5798 GLBuffer transformFeedbackBuffer;
5799 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5800 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5801 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5802
5803 GLTransformFeedback pointsXFB;
5804 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5805 GLBuffer pointsXFBBuffer;
5806 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
5807 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
5808 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
5809
5810 // Begin TRIANGLES, switch to paused POINTS, should be valid.
5811 glBeginTransformFeedback(GL_POINTS);
5812 glPauseTransformFeedback();
5813 ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
5814
5815 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5816 glBeginTransformFeedback(GL_TRIANGLES);
5817 glDrawArrays(GL_TRIANGLES, 0, 6);
5818 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5819 glDrawArrays(GL_POINTS, 0, 6);
5820 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
5821 glDrawArrays(GL_LINES, 0, 6);
5822 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5823 glPauseTransformFeedback();
5824 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5825 glResumeTransformFeedback();
5826 glDrawArrays(GL_POINTS, 0, 6);
5827 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5828 glDrawArrays(GL_TRIANGLES, 0, 6);
5829 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
5830 glDrawArrays(GL_LINES, 0, 6);
5831 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5832
5833 glEndTransformFeedback();
5834 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5835 glEndTransformFeedback();
5836 ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
5837
5838 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
5839
5840 glDrawArrays(GL_POINTS, 0, 6);
5841 EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5842 glDrawArrays(GL_TRIANGLES, 0, 6);
5843 EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5844 glDrawArrays(GL_LINES, 0, 6);
5845 EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
5846 }
5847
5848 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)5849 TEST_P(ValidationStateChangeTest, TextureConflict)
5850 {
5851 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
5852
5853 GLint maxTextures = 0;
5854 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
5855 ANGLE_SKIP_TEST_IF(maxTextures < 2);
5856
5857 // Set up state.
5858 constexpr GLint kSize = 2;
5859
5860 std::vector<GLColor> greenData(4, GLColor::green);
5861
5862 GLTexture textureA;
5863 glBindTexture(GL_TEXTURE_2D, textureA);
5864 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5865 greenData.data());
5866 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5868
5869 glActiveTexture(GL_TEXTURE1);
5870
5871 GLTexture textureB;
5872 glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
5873 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5874 GL_UNSIGNED_BYTE, greenData.data());
5875 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5876 GL_UNSIGNED_BYTE, greenData.data());
5877 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5878 GL_UNSIGNED_BYTE, greenData.data());
5879 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5880 GL_UNSIGNED_BYTE, greenData.data());
5881 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5882 GL_UNSIGNED_BYTE, greenData.data());
5883 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5884 GL_UNSIGNED_BYTE, greenData.data());
5885 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5886 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5887
5888 constexpr char kVS[] = R"(attribute vec2 position;
5889 varying mediump vec2 texCoord;
5890 void main()
5891 {
5892 gl_Position = vec4(position, 0, 1);
5893 texCoord = position * 0.5 + vec2(0.5);
5894 })";
5895
5896 constexpr char kFS[] = R"(varying mediump vec2 texCoord;
5897 uniform sampler2D texA;
5898 uniform samplerCube texB;
5899 void main()
5900 {
5901 gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
5902 })";
5903
5904 ANGLE_GL_PROGRAM(program, kVS, kFS);
5905 glUseProgram(program);
5906
5907 const auto &quadVertices = GetQuadVertices();
5908
5909 GLBuffer arrayBuffer;
5910 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5911 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5912 GL_STATIC_DRAW);
5913
5914 GLint positionLoc = glGetAttribLocation(program, "position");
5915 ASSERT_NE(-1, positionLoc);
5916
5917 GLint texALoc = glGetUniformLocation(program, "texA");
5918 ASSERT_NE(-1, texALoc);
5919
5920 GLint texBLoc = glGetUniformLocation(program, "texB");
5921 ASSERT_NE(-1, texBLoc);
5922
5923 glUniform1i(texALoc, 0);
5924 glUniform1i(texBLoc, 1);
5925
5926 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5927 glEnableVertexAttribArray(positionLoc);
5928
5929 ASSERT_GL_NO_ERROR();
5930
5931 // First draw. Should succeed.
5932 glDrawArrays(GL_TRIANGLES, 0, 6);
5933 ASSERT_GL_NO_ERROR();
5934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5935
5936 // Second draw to ensure all state changes are flushed.
5937 glDrawArrays(GL_TRIANGLES, 0, 6);
5938 ASSERT_GL_NO_ERROR();
5939
5940 // Make the uniform use an invalid texture binding.
5941 glUniform1i(texBLoc, 0);
5942 glDrawArrays(GL_TRIANGLES, 0, 6);
5943 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5944 }
5945
5946 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)5947 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
5948 {
5949 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
5950 glUseProgram(program);
5951
5952 std::array<GLushort, 6> quadIndices = GetQuadIndices();
5953 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
5954
5955 GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
5956
5957 GLBuffer elementArrayBuffer;
5958 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
5959 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
5960
5961 GLBuffer arrayBuffer;
5962 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5963 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
5964 quadVertices.data(), GL_STATIC_DRAW);
5965
5966 GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5967 ASSERT_NE(-1, positionLoc);
5968 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5969 glEnableVertexAttribArray(positionLoc);
5970
5971 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5972 ASSERT_GL_NO_ERROR();
5973
5974 void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
5975 ASSERT_NE(nullptr, ptr);
5976
5977 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5978 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5979
5980 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
5981
5982 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5983 ASSERT_GL_NO_ERROR();
5984 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5985 }
5986
5987 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)5988 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
5989 {
5990 constexpr char kFS[] =
5991 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
5992 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5993 glUseProgram(program);
5994 GLint loc = glGetUniformLocation(program, "us");
5995 ASSERT_EQ(0, loc);
5996
5997 auto quadVertices = GetQuadVertices();
5998 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
5999 ASSERT_EQ(0, posLoc);
6000
6001 GLBuffer buffer;
6002 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6003 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6004 quadVertices.data(), GL_STATIC_DRAW);
6005 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6006 glEnableVertexAttribArray(posLoc);
6007
6008 constexpr size_t kSize = 2;
6009 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6010
6011 GLTexture tex;
6012 glBindTexture(GL_TEXTURE_2D, tex);
6013 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6015 glUniform1i(loc, 0);
6016
6017 glDrawArrays(GL_TRIANGLES, 0, 3);
6018 ASSERT_GL_NO_ERROR();
6019 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6020
6021 // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
6022 GLTexture tex2;
6023 glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
6024 tex2.reset();
6025
6026 glDrawArrays(GL_TRIANGLES, 0, 3);
6027 ASSERT_GL_NO_ERROR();
6028 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6029
6030 // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
6031 tex.reset();
6032
6033 glDrawArrays(GL_TRIANGLES, 0, 3);
6034 ASSERT_GL_NO_ERROR();
6035 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6036 }
6037
6038 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)6039 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
6040 {
6041 constexpr char kFS[] =
6042 "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6043 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6044 glUseProgram(program);
6045 GLint loc = glGetUniformLocation(program, "us");
6046 ASSERT_EQ(0, loc);
6047
6048 auto quadVertices = GetQuadVertices();
6049 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6050 ASSERT_EQ(0, posLoc);
6051
6052 GLBuffer buffer;
6053 glBindBuffer(GL_ARRAY_BUFFER, buffer);
6054 glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6055 quadVertices.data(), GL_STATIC_DRAW);
6056 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6057 glEnableVertexAttribArray(posLoc);
6058
6059 constexpr size_t kSize = 2;
6060 std::vector<GLColor> red(kSize * kSize, GLColor::red);
6061
6062 GLTexture tex;
6063 glBindTexture(GL_TEXTURE_2D, tex);
6064 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6065 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6066 glUniform1i(loc, 1);
6067 tex.reset();
6068
6069 glDrawArrays(GL_TRIANGLES, 0, 3);
6070 ASSERT_GL_NO_ERROR();
6071 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6072 }
6073
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)6074 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
6075 {
6076 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6077 glBindTexture(GL_TEXTURE_2D, texture);
6078 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6079 GL_UNSIGNED_BYTE, nullptr);
6080 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6081 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6082 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6083 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6084 }
6085
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6086 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6087 {
6088 // Render to an FBO
6089 GLFramebuffer fbo1;
6090 GLTexture texture1;
6091
6092 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6093 ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6094 essl1_shaders::fs::Texture2D());
6095
6096 bindTextureToFbo(fbo1, texture1);
6097
6098 // Clear the surface FBO to initialize it to a known value
6099 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6100 glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6101 glClear(GL_COLOR_BUFFER_BIT);
6102 ASSERT_GL_NO_ERROR();
6103 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6104 glFlush();
6105
6106 // Draw to FBO 1 to initialize it to a known value
6107 glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6108
6109 if (earlyFrontFaceDirty)
6110 {
6111 glEnable(GL_CULL_FACE);
6112 // Make sure we don't cull
6113 glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6114 glFrontFace(frontFace);
6115 }
6116 else
6117 {
6118 glDisable(GL_CULL_FACE);
6119 }
6120
6121 glUseProgram(greenProgram);
6122 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6123 ASSERT_GL_NO_ERROR();
6124 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6125
6126 // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6127 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6128 glBindTexture(GL_TEXTURE_2D, texture1);
6129
6130 glCullFace(GL_BACK);
6131 if (!earlyFrontFaceDirty)
6132 {
6133 // Set the culling we want to test
6134 glEnable(GL_CULL_FACE);
6135 glFrontFace(frontFace);
6136 }
6137
6138 glUseProgram(textureProgram);
6139 drawQuad(textureProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6140 ASSERT_GL_NO_ERROR();
6141
6142 if (frontFace == GL_CCW)
6143 {
6144 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6145 }
6146 else
6147 {
6148 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6149 }
6150
6151 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6152 glBindTexture(GL_TEXTURE_2D, 0);
6153 }
6154
6155 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6156 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6157 {
6158 drawToFboWithCulling(GL_CCW, true);
6159 }
6160
6161 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6162 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6163 {
6164 drawToFboWithCulling(GL_CW, true);
6165 }
6166
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6167 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6168 {
6169 drawToFboWithCulling(GL_CCW, false);
6170 }
6171
6172 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6173 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6174 {
6175 drawToFboWithCulling(GL_CW, false);
6176 }
6177
6178 // Test that vertex attribute translation is still kept after binding it to another buffer then
6179 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6180 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6181 {
6182 // http://anglebug.com/5379
6183 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6184
6185 constexpr char kVS[] = R"(attribute vec4 a_position;
6186 attribute float a_attrib;
6187 varying float v_attrib;
6188 void main()
6189 {
6190 v_attrib = a_attrib;
6191 gl_Position = a_position;
6192 })";
6193
6194 constexpr char kFS[] = R"(precision mediump float;
6195 varying float v_attrib;
6196 void main()
6197 {
6198 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6199 })";
6200
6201 ANGLE_GL_PROGRAM(program, kVS, kFS);
6202 glBindAttribLocation(program, 0, "a_position");
6203 glBindAttribLocation(program, 1, "a_attrib");
6204 glLinkProgram(program);
6205 glUseProgram(program);
6206 ASSERT_GL_NO_ERROR();
6207
6208 // Set up color data so red is drawn
6209 std::vector<GLushort> data(1000, 0xffff);
6210
6211 GLBuffer redBuffer;
6212 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6213 glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6214 // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6215 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6216 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6217 glBindBuffer(GL_ARRAY_BUFFER, 0);
6218 glEnableVertexAttribArray(1);
6219
6220 drawQuad(program, "a_position", 0.5f);
6221 // Verify red was drawn
6222 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6223
6224 glClearColor(0, 1, 0, 1);
6225 glClear(GL_COLOR_BUFFER_BIT);
6226 // Verify that green was drawn
6227 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6228
6229 // Bind black color buffer to the same attribute with zero offset
6230 std::vector<GLfloat> black(6, 0.0f);
6231 GLBuffer blackBuffer;
6232 glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6233 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6234 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6235
6236 drawQuad(program, "a_position", 0.5f);
6237 // Verify black was drawn
6238 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6239
6240 // Rebind the old buffer & offset
6241 glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6242 // Use offset not multiple of 4 GLushorts
6243 glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6244 reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6245
6246 drawQuad(program, "a_position", 0.5f);
6247 // Verify red was drawn
6248 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6249 }
6250
6251 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6252 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6253 {
6254 constexpr char kVS[] = R"(attribute vec4 a_position;
6255 varying float v_attrib;
6256 uniform float u_value;
6257 void main()
6258 {
6259 v_attrib = u_value;
6260 gl_Position = a_position;
6261 })";
6262
6263 constexpr char kFS[] = R"(precision mediump float;
6264 varying float v_attrib;
6265 void main()
6266 {
6267 gl_FragColor = vec4(v_attrib, 0, 0, 1);
6268 })";
6269
6270 ANGLE_GL_PROGRAM(program1, kVS, kFS);
6271 ANGLE_GL_PROGRAM(program2, kVS, kFS);
6272
6273 // Don't use drawQuad so there's no state changes between the draw calls other than the program
6274 // binding.
6275
6276 constexpr size_t kProgramCount = 2;
6277 GLuint programs[kProgramCount] = {program1, program2};
6278 for (size_t i = 0; i < kProgramCount; ++i)
6279 {
6280 glUseProgram(programs[i]);
6281 GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6282 ASSERT_NE(uniformLoc, -1);
6283
6284 glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6285
6286 // Ensure position is at location 0 in both programs.
6287 GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6288 ASSERT_EQ(positionLocation, 0);
6289 }
6290 ASSERT_GL_NO_ERROR();
6291
6292 std::array<Vector3, 6> quadVertices = GetQuadVertices();
6293 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6294 glEnableVertexAttribArray(0);
6295
6296 // Draw once with each so their uniforms are updated.
6297 // The first draw will clear the screen to 255, 0, 0, 255
6298 glUseProgram(program2);
6299 glDrawArrays(GL_TRIANGLES, 0, 6);
6300 // The second draw will clear the screen to 127, 0, 0, 255
6301 glUseProgram(program1);
6302 glDrawArrays(GL_TRIANGLES, 0, 6);
6303
6304 // Draw with the previous program again, to make sure its default uniforms are bound again.
6305 glUseProgram(program2);
6306 glDrawArrays(GL_TRIANGLES, 0, 6);
6307
6308 // Verify red was drawn
6309 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6310 }
6311
6312 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
6313 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)6314 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
6315 {
6316 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6317
6318 GLBuffer indexBuffer;
6319 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6320 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
6321 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
6322 ASSERT_GL_NO_ERROR();
6323
6324 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6325 }
6326
6327 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)6328 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
6329 {
6330 glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6331 glClear(GL_COLOR_BUFFER_BIT);
6332 ASSERT_GL_NO_ERROR();
6333 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6334
6335 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6336 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6337
6338 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6339 glEnable(GL_RASTERIZER_DISCARD);
6340 glUseProgram(greenProgram);
6341 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6342 ASSERT_GL_NO_ERROR();
6343 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6344
6345 // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
6346 glDisable(GL_RASTERIZER_DISCARD);
6347 glUseProgram(greenProgram);
6348 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6349 ASSERT_GL_NO_ERROR();
6350 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6351
6352 // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6353 glEnable(GL_RASTERIZER_DISCARD);
6354 glUseProgram(blueProgram);
6355 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6356 ASSERT_GL_NO_ERROR();
6357 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6358 }
6359
6360 class ImageRespecificationTest : public ANGLETest
6361 {
6362 protected:
ImageRespecificationTest()6363 ImageRespecificationTest()
6364 {
6365 setWindowWidth(128);
6366 setWindowHeight(128);
6367 setConfigRedBits(8);
6368 setConfigGreenBits(8);
6369 setConfigBlueBits(8);
6370 setConfigAlphaBits(8);
6371 setConfigDepthBits(24);
6372 }
6373
testSetUp()6374 void testSetUp() override
6375 {
6376 constexpr char kVS[] = R"(precision highp float;
6377 attribute vec4 position;
6378 varying vec2 texcoord;
6379
6380 void main()
6381 {
6382 gl_Position = position;
6383 texcoord = (position.xy * 0.5) + 0.5;
6384 })";
6385
6386 constexpr char kFS[] = R"(precision highp float;
6387 uniform sampler2D tex;
6388 varying vec2 texcoord;
6389
6390 void main()
6391 {
6392 gl_FragColor = texture2D(tex, texcoord);
6393 })";
6394
6395 mProgram = CompileProgram(kVS, kFS);
6396 ASSERT_NE(0u, mProgram);
6397
6398 mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
6399 ASSERT_NE(-1, mTextureUniformLocation);
6400
6401 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6402 ASSERT_GL_NO_ERROR();
6403 }
6404
testTearDown()6405 void testTearDown() override
6406 {
6407 if (mProgram != 0)
6408 {
6409 glDeleteProgram(mProgram);
6410 }
6411 }
6412
6413 template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)6414 void init2DSourceTexture(GLenum internalFormat,
6415 GLenum dataFormat,
6416 GLenum dataType,
6417 const T *data)
6418 {
6419 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6420 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6421
6422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6424
6425 glBindTexture(GL_TEXTURE_2D, 0);
6426 }
6427
attachTargetTextureToFramebuffer()6428 void attachTargetTextureToFramebuffer()
6429 {
6430 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6431 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
6432 0);
6433
6434 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6435 ASSERT_GL_NO_ERROR();
6436
6437 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6438 }
6439
renderToTargetTexture()6440 void renderToTargetTexture()
6441 {
6442 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6443
6444 glActiveTexture(GL_TEXTURE0);
6445 glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6446
6447 glUseProgram(mProgram);
6448 glUniform1i(mTextureUniformLocation, 0);
6449
6450 drawQuad(mProgram, "position", 0.5f);
6451 ASSERT_GL_NO_ERROR();
6452
6453 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6454 glBindTexture(GL_TEXTURE_2D, 0);
6455 glUseProgram(0);
6456 }
6457
renderToDefaultFramebuffer(GLColor * expectedData)6458 void renderToDefaultFramebuffer(GLColor *expectedData)
6459 {
6460 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6461 glUseProgram(mProgram);
6462 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6463 glUniform1i(mTextureUniformLocation, 0);
6464
6465 glClear(GL_COLOR_BUFFER_BIT);
6466 drawQuad(mProgram, "position", 0.5f);
6467 ASSERT_GL_NO_ERROR();
6468
6469 EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
6470
6471 glBindTexture(GL_TEXTURE_2D, 0);
6472 glUseProgram(0);
6473 }
6474
6475 GLuint mProgram;
6476 GLint mTextureUniformLocation;
6477
6478 GLTexture mSourceTexture;
6479 GLTexture mTargetTexture;
6480
6481 GLFramebuffer mFramebuffer;
6482 };
6483
6484 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)6485 TEST_P(ImageRespecificationTest, Swizzle)
6486 {
6487 GLubyte data[] = {1, 64, 128, 200};
6488 GLColor expectedData(data[0], data[1], data[2], data[3]);
6489
6490 // Create the source and target texture
6491 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6492
6493 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6494 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6495
6496 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6498
6499 glBindTexture(GL_TEXTURE_2D, 0);
6500
6501 // Create a framebuffer and the target texture is attached to the framebuffer.
6502 attachTargetTextureToFramebuffer();
6503
6504 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6505 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6506 glClear(GL_COLOR_BUFFER_BIT);
6507 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6508
6509 // Render content of source texture to target texture
6510 // This command triggers the creation of -
6511 // - draw imageviews of the texture
6512 // - VkFramebuffer object of the framebuffer
6513 renderToTargetTexture();
6514
6515 // This swizzle operation should cause the read imageviews of the texture to be released
6516 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
6518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
6519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
6520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
6521 glBindTexture(GL_TEXTURE_2D, 0);
6522
6523 // Draw using the newly created read imageviews
6524 renderToDefaultFramebuffer(&expectedData);
6525
6526 // Render content of source texture to target texture, again
6527 renderToTargetTexture();
6528
6529 // Make sure the content rendered to target texture is correct
6530 renderToDefaultFramebuffer(&expectedData);
6531 }
6532
6533 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
6534 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)6535 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
6536 {
6537 // This is the specific problem on the Vulkan backend and needs some extensions
6538 ANGLE_SKIP_TEST_IF(
6539 !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
6540 !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
6541
6542 GLubyte data[] = {1, 64, 128, 200};
6543 GLColor expectedData(data[0], data[1], data[2], data[3]);
6544
6545 // Create the source texture
6546 init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6547
6548 // Create the first EGL image to attach the framebuffer through the texture
6549 GLTexture firstTexture;
6550
6551 glBindTexture(GL_TEXTURE_2D, firstTexture);
6552 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6553
6554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6556
6557 glBindTexture(GL_TEXTURE_2D, 0);
6558
6559 EGLWindow *window = getEGLWindow();
6560 EGLint attribs[] = {
6561 EGL_IMAGE_PRESERVED,
6562 EGL_TRUE,
6563 EGL_NONE,
6564 };
6565 EGLImageKHR firstEGLImage = eglCreateImageKHR(
6566 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6567 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(firstTexture.get())), attribs);
6568 ASSERT_EGL_SUCCESS();
6569
6570 // Create the target texture and attach it to the framebuffer
6571 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6572 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6573
6574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6576
6577 glBindTexture(GL_TEXTURE_2D, 0);
6578
6579 attachTargetTextureToFramebuffer();
6580
6581 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6582
6583 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6584 glClear(GL_COLOR_BUFFER_BIT);
6585
6586 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6587
6588 // Render content of source texture to target texture
6589 // This command triggers the creation of -
6590 // - draw imageviews of the texture
6591 // - VkFramebuffer object of the framebuffer
6592 renderToTargetTexture();
6593
6594 // Make sure the content rendered to target texture is correct
6595 renderToDefaultFramebuffer(&expectedData);
6596
6597 // Create the second EGL image
6598 GLTexture secondTexture;
6599
6600 glBindTexture(GL_TEXTURE_2D, secondTexture);
6601 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6602
6603 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6604 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6605
6606 glBindTexture(GL_TEXTURE_2D, 0);
6607
6608 EGLImageKHR secondEGLImage = eglCreateImageKHR(
6609 window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6610 reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(secondTexture.get())), attribs);
6611 ASSERT_EGL_SUCCESS();
6612
6613 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6614 // This will release all the imageviews related to the first EGL image
6615 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
6616
6617 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6619
6620 glBindTexture(GL_TEXTURE_2D, 0);
6621
6622 // Attach the first EGL image to the target texture again
6623 glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6624 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6625
6626 // This is for checking this code can deal with the problem even if both ORPHAN and
6627 // COLOR_ATTACHMENT dirty bits are set.
6628 GLTexture tempTexture;
6629
6630 glBindTexture(GL_TEXTURE_2D, tempTexture);
6631 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6632
6633 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6635
6636 glBindTexture(GL_TEXTURE_2D, 0);
6637
6638 // This sets COLOR_ATTACHMENT dirty bit
6639 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6640 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
6641 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6642
6643 // The released imageviews related to "secondEGLImage" will be garbage collected
6644 renderToDefaultFramebuffer(&expectedData);
6645
6646 // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
6647 renderToTargetTexture();
6648
6649 // Make sure the content rendered to target texture is correct
6650 renderToDefaultFramebuffer(&expectedData);
6651
6652 // Render content of source texture to target texture
6653 attachTargetTextureToFramebuffer();
6654 renderToTargetTexture();
6655
6656 // Make sure the content rendered to target texture is correct
6657 renderToDefaultFramebuffer(&expectedData);
6658
6659 eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
6660 eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
6661 }
6662
6663 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)6664 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
6665 {
6666 GLushort indexData[] = {0, 1, 2, 3};
6667
6668 GLBuffer elementArrayBuffer;
6669 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6670 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
6671
6672 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
6673 glUseProgram(program);
6674
6675 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
6676
6677 elementArrayBuffer.reset();
6678
6679 // Must use a non-0 offset and a multiple of the type size.
6680 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
6681 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6682 }
6683
6684 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)6685 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
6686 {
6687 // SwiftShader does not currently support robustness.
6688 ANGLE_SKIP_TEST_IF(isSwiftshader());
6689
6690 // http://anglebug.com/4872
6691 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
6692
6693 // no intent to follow up on this failure.
6694 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
6695
6696 // no intent to follow up on this failure.
6697 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6698
6699 // no intent to follow up on this failure.
6700 ANGLE_SKIP_TEST_IF(IsOSX());
6701
6702 // Mali does not support robustness now.
6703 ANGLE_SKIP_TEST_IF(IsARM());
6704
6705 // TODO(anglebug.com/5491)
6706 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6707
6708 std::vector<GLubyte> data(48, 1);
6709
6710 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6711 glUseProgram(program);
6712
6713 // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
6714 GLBuffer arrayBuffer;
6715 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6716 glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
6717 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6718 glEnableVertexAttribArray(0);
6719 glDrawArrays(GL_TRIANGLES, 0, 3);
6720
6721 // Then bind a zero size buffer and draw.
6722 GLBuffer secondBuffer;
6723 glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
6724 glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
6725 glDrawArrays(GL_TRIANGLES, 0, 3);
6726
6727 // Finally delete the original buffer. This triggers the bug.
6728 arrayBuffer.reset();
6729 glDrawArrays(GL_TRIANGLES, 0, 3);
6730 ASSERT_GL_NO_ERROR();
6731 }
6732
6733 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)6734 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
6735 {
6736 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6737
6738 glUseProgram(program);
6739
6740 // Draw with empty buffer. Out of range but valid.
6741 GLBuffer buffer;
6742 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
6743 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
6744
6745 // Switch VAO. No buffer bound, should be an error.
6746 GLVertexArray vao;
6747 glBindVertexArray(vao);
6748 glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
6749 reinterpret_cast<const GLvoid *>(0x1000));
6750 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6751 }
6752
6753 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
6754 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)6755 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
6756 {
6757 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6758 // bit.
6759 GLBuffer indexBuffer;
6760 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6761
6762 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6763 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6764
6765 // Setup vertices.
6766 const std::array<GLfloat, 6> kVertices = {
6767 -1, -1, 3, -1, -1, 3,
6768 };
6769 GLBuffer vertexBuffer;
6770 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6771 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6772 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6773 glEnableVertexAttribArray(0);
6774
6775 // Create a uniform buffer that will get modified. This is used to break the render pass.
6776 const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
6777
6778 GLBuffer ubo;
6779 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
6780 glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
6781 glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
6782
6783 // Set up a program. The same program is used for all draw calls to avoid state change due to
6784 // program change.
6785 constexpr char kFS[] = R"(#version 300 es
6786 precision mediump float;
6787 uniform block { uint data; } ubo;
6788 uniform uint expect;
6789 uniform vec4 successColor;
6790 out vec4 colorOut;
6791 void main()
6792 {
6793 colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
6794 })";
6795
6796 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6797 glUseProgram(program);
6798
6799 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6800 const GLint expectLoc = glGetUniformLocation(program, "expect");
6801 const GLint successLoc = glGetUniformLocation(program, "successColor");
6802 ASSERT_NE(-1, positionLoc);
6803 ASSERT_NE(-1, expectLoc);
6804 ASSERT_NE(-1, successLoc);
6805
6806 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6807 glEnableVertexAttribArray(positionLoc);
6808
6809 glUniform1ui(expectLoc, kUboData1[0]);
6810 glUniform4f(successLoc, 0, 0, 0, 1);
6811 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6812 EXPECT_GL_NO_ERROR();
6813
6814 // Then upload data to the UBO so on next use the render pass has to break. This draw call is
6815 // not indexed.
6816 constexpr GLuint kUboData2 = 0x87654321u;
6817 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
6818
6819 glEnable(GL_BLEND);
6820 glBlendFunc(GL_ONE, GL_ONE);
6821 glUniform1ui(expectLoc, kUboData2);
6822 glUniform4f(successLoc, 0, 1, 0, 0);
6823 glDrawArrays(GL_TRIANGLES, 0, 3);
6824
6825 // Issue another draw call that is indexed. The index buffer should be bound correctly on the
6826 // new render pass.
6827 glUniform4f(successLoc, 0, 0, 1, 0);
6828 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6829 EXPECT_GL_NO_ERROR();
6830
6831 // Ensure correct rendering.
6832 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6833 }
6834
6835 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)6836 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
6837 {
6838 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6839 glClearColor(0, 0, 0, 1);
6840 glClear(GL_COLOR_BUFFER_BIT);
6841 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6842
6843 GLFramebuffer fbo;
6844 GLTexture texture;
6845
6846 glBindTexture(GL_TEXTURE_2D, texture);
6847 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6848 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6849 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6850
6851 glClear(GL_COLOR_BUFFER_BIT);
6852 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6853
6854 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6855
6856 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6857 // bit.
6858 GLBuffer indexBuffer;
6859 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6860
6861 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6862 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6863
6864 // Setup vertices.
6865 const std::array<GLfloat, 6> kVertices = {
6866 -1, -1, 3, -1, -1, 3,
6867 };
6868 GLBuffer vertexBuffer;
6869 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6870 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6871 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6872 glEnableVertexAttribArray(0);
6873
6874 // Set up a program. The same program is used for all draw calls to avoid state change due to
6875 // program change.
6876 constexpr char kFS[] = R"(#version 300 es
6877 precision mediump float;
6878 uniform vec4 colorIn;
6879 out vec4 colorOut;
6880 void main()
6881 {
6882 colorOut = colorIn;
6883 })";
6884
6885 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6886 glUseProgram(program);
6887
6888 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6889 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
6890 ASSERT_NE(-1, positionLoc);
6891 ASSERT_NE(-1, colorLoc);
6892
6893 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6894 glEnableVertexAttribArray(positionLoc);
6895
6896 glUniform4f(colorLoc, 1, 0, 0, 1);
6897 glEnable(GL_BLEND);
6898 glBlendFunc(GL_ONE, GL_ONE);
6899 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6900 EXPECT_GL_NO_ERROR();
6901
6902 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6903 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6904 glUniform4f(colorLoc, 0, 1, 0, 0);
6905 glDrawArrays(GL_TRIANGLES, 0, 3);
6906
6907 glUniform4f(colorLoc, 0, 0, 1, 0);
6908 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6909 EXPECT_GL_NO_ERROR();
6910
6911 // Ensure correct rendering.
6912 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6913
6914 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6915 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6916 }
6917
6918 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
6919 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)6920 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
6921 {
6922 // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6923 glClearColor(0, 0, 0, 1);
6924 glClear(GL_COLOR_BUFFER_BIT);
6925 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6926
6927 GLFramebuffer fbo;
6928 GLTexture texture;
6929
6930 glBindTexture(GL_TEXTURE_2D, texture);
6931 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6932 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6933 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6934
6935 glClear(GL_COLOR_BUFFER_BIT);
6936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6937
6938 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6939
6940 // First, create the index buffer and issue an indexed draw call. This clears the index dirty
6941 // bit.
6942 GLBuffer indexBuffer;
6943 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6944
6945 const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6946 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6947
6948 // Setup vertices.
6949 const std::array<GLfloat, 6> kVertices = {
6950 -1, -1, 3, -1, -1, 3,
6951 };
6952 GLBuffer vertexBuffer;
6953 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6954 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6955 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6956 glEnableVertexAttribArray(0);
6957
6958 // Set up a program. The same program is used for all draw calls to avoid state change due to
6959 // program change.
6960 constexpr char kFS[] = R"(#version 300 es
6961 precision mediump float;
6962 uniform vec4 colorIn;
6963 out vec4 colorOut;
6964 void main()
6965 {
6966 colorOut = colorIn;
6967 })";
6968
6969 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6970 glUseProgram(program);
6971
6972 const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6973 const GLint colorLoc = glGetUniformLocation(program, "colorIn");
6974 ASSERT_NE(-1, positionLoc);
6975 ASSERT_NE(-1, colorLoc);
6976
6977 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6978 glEnableVertexAttribArray(positionLoc);
6979
6980 glUniform4f(colorLoc, 0, 0, 0, 1);
6981 glEnable(GL_BLEND);
6982 glBlendFunc(GL_ONE, GL_ONE);
6983 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6984 EXPECT_GL_NO_ERROR();
6985
6986 // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6987 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6988 glUniform4f(colorLoc, 0, 1, 0, 0);
6989 glDrawArrays(GL_TRIANGLES, 0, 3);
6990
6991 // In between the two calls, make sure the first render pass is submitted, so the primary
6992 // command buffer is reset.
6993 {
6994 EGLWindow *window = getEGLWindow();
6995 EGLDisplay dpy = window->getDisplay();
6996 EGLConfig config = window->getConfig();
6997 EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
6998 EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
6999 EGLContext ctx = window->createContext(EGL_NO_CONTEXT, nullptr);
7000 EXPECT_EGL_SUCCESS();
7001 std::thread flushThread = std::thread([&]() {
7002 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
7003 EXPECT_EGL_SUCCESS();
7004
7005 glClearColor(1, 0, 0, 1);
7006 glClear(GL_COLOR_BUFFER_BIT);
7007 EXPECT_GL_NO_ERROR();
7008
7009 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7010 });
7011 flushThread.join();
7012
7013 eglDestroySurface(dpy, surface);
7014 eglDestroyContext(dpy, ctx);
7015 }
7016
7017 glUniform4f(colorLoc, 0, 0, 1, 0);
7018 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7019 EXPECT_GL_NO_ERROR();
7020
7021 // Ensure correct rendering.
7022 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7023 }
7024
7025 // Negative test for EXT_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxNegativeTest)7026 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxNegativeTest)
7027 {
7028 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_primitive_bounding_box"));
7029
7030 glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7031 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7032
7033 GLfloat boundingBox[8] = {0};
7034 glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, boundingBox);
7035 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7036 }
7037
7038 // Update an element array buffer that is already in use.
TEST_P(SimpleStateChangeTest,UpdateBoundElementArrayBuffer)7039 TEST_P(SimpleStateChangeTest, UpdateBoundElementArrayBuffer)
7040 {
7041 constexpr char kVS[] = R"(attribute vec4 position;
7042 attribute float color;
7043 varying float colorVarying;
7044 void main()
7045 {
7046 gl_Position = position;
7047 colorVarying = color;
7048 })";
7049
7050 constexpr char kFS[] = R"(precision mediump float;
7051 varying float colorVarying;
7052 void main()
7053 {
7054 if (colorVarying == 1.0)
7055 {
7056 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
7057 }
7058 else
7059 {
7060 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
7061 }
7062 })";
7063
7064 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
7065 glUseProgram(testProgram);
7066
7067 GLint posLoc = glGetAttribLocation(testProgram, "position");
7068 ASSERT_NE(-1, posLoc);
7069 GLint colorLoc = glGetAttribLocation(testProgram, "color");
7070 ASSERT_NE(-1, colorLoc);
7071
7072 std::array<GLushort, 6> quadIndices = GetQuadIndices();
7073
7074 std::vector<GLubyte> indices;
7075 for (GLushort index : quadIndices)
7076 {
7077 indices.push_back(static_cast<GLubyte>(index));
7078 }
7079
7080 GLBuffer indexBuffer;
7081 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7082 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), indices.data(),
7083 GL_STATIC_DRAW);
7084
7085 std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
7086
7087 std::vector<Vector3> positionVertices;
7088 for (Vector3 vertex : quadVertices)
7089 {
7090 positionVertices.push_back(vertex);
7091 }
7092 for (Vector3 vertex : quadVertices)
7093 {
7094 positionVertices.push_back(vertex);
7095 }
7096
7097 GLBuffer positionVertexBuffer;
7098 glBindBuffer(GL_ARRAY_BUFFER, positionVertexBuffer);
7099 glBufferData(GL_ARRAY_BUFFER, positionVertices.size() * sizeof(positionVertices[0]),
7100 positionVertices.data(), GL_STATIC_DRAW);
7101 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
7102 glEnableVertexAttribArray(posLoc);
7103
7104 std::vector<float> colorVertices = {1, 1, 1, 1, 0, 0, 0, 0};
7105
7106 GLBuffer colorVertexBuffer;
7107 glBindBuffer(GL_ARRAY_BUFFER, colorVertexBuffer);
7108 glBufferData(GL_ARRAY_BUFFER, colorVertices.size() * sizeof(colorVertices[0]),
7109 colorVertices.data(), GL_STATIC_DRAW);
7110 glVertexAttribPointer(colorLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
7111 glEnableVertexAttribArray(colorLoc);
7112
7113 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7114 ASSERT_GL_NO_ERROR();
7115 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7116
7117 indices.clear();
7118 for (GLushort index : quadIndices)
7119 {
7120 indices.push_back(static_cast<GLubyte>(index + 4));
7121 }
7122 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(indices[0]),
7123 indices.data());
7124
7125 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7126 ASSERT_GL_NO_ERROR();
7127 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7128 }
7129
7130 // Covers a bug where we would use a stale cache variable in the Vulkan back-end.
TEST_P(SimpleStateChangeTestES3,DeleteFramebufferBeforeQuery)7131 TEST_P(SimpleStateChangeTestES3, DeleteFramebufferBeforeQuery)
7132 {
7133 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7134 glUseProgram(testProgram);
7135
7136 GLFramebuffer fbo;
7137 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
7138
7139 GLRenderbuffer rbo;
7140 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
7141
7142 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, 16, 16);
7143 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
7144
7145 GLfloat floatArray[] = {1, 2, 3, 4};
7146
7147 GLBuffer buffer;
7148 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7149 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLfloat) * 4, floatArray, GL_DYNAMIC_COPY);
7150 glDrawElements(GL_TRIANGLE_FAN, 5, GL_UNSIGNED_SHORT, 0);
7151
7152 fbo.reset();
7153
7154 GLQuery query2;
7155 glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, query2);
7156
7157 ASSERT_GL_NO_ERROR();
7158 }
7159
7160 // Covers an edge case
TEST_P(SimpleStateChangeTestES3,TextureTypeConflictAfterDraw)7161 TEST_P(SimpleStateChangeTestES3, TextureTypeConflictAfterDraw)
7162 {
7163 constexpr char kVS[] = R"(precision highp float;
7164 attribute vec4 a_position;
7165 void main()
7166 {
7167 gl_Position = a_position;
7168 }
7169 )";
7170
7171 constexpr char kFS[] = R"(precision highp float;
7172 uniform sampler2D u_2d1;
7173 uniform samplerCube u_Cube1;
7174 void main()
7175 {
7176 gl_FragColor = texture2D(u_2d1, vec2(0.0, 0.0)) + textureCube(u_Cube1, vec3(0.0, 0.0, 0.0));
7177 }
7178 )";
7179
7180 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
7181 glUseProgram(testProgram);
7182
7183 GLTexture texture;
7184 glBindTexture(GL_TEXTURE_2D, texture);
7185 glTexStorage2D(GL_TEXTURE_2D, 4, GL_SRGB8, 1268, 614);
7186
7187 GLint uniformloc = glGetUniformLocation(testProgram, "u_Cube1");
7188 ASSERT_NE(-1, uniformloc);
7189 glUniform1i(uniformloc, 1);
7190
7191 glDrawArrays(GL_POINTS, 0, 1);
7192 ASSERT_GL_NO_ERROR();
7193
7194 // Trigger the state update.
7195 glLinkProgram(testProgram);
7196 texture.reset();
7197
7198 // The texture types are now conflicting, and draws should fail.
7199 glDrawArrays(GL_POINTS, 0, 1);
7200 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7201 }
7202
7203 // Regression test for a bug where a mutable texture is used with non-zero base level then rebased
7204 // to zero but made incomplete and attached to the framebuffer. The texture's image is not
7205 // recreated with level 0, leading to errors when drawing to the framebuffer.
TEST_P(SimpleStateChangeTestES3,NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)7206 TEST_P(SimpleStateChangeTestES3, NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)
7207 {
7208 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7209 glUseProgram(program);
7210
7211 const std::array<GLColor, 4> kMip0Data = {GLColor::red, GLColor::red, GLColor::red,
7212 GLColor::red};
7213 const std::array<GLColor, 2> kMip1Data = {GLColor::green, GLColor::green};
7214
7215 // Create two textures.
7216 GLTexture immutableTex;
7217 glBindTexture(GL_TEXTURE_2D, immutableTex);
7218 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
7219 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data.data());
7220
7221 GLTexture mutableTex;
7222 glBindTexture(GL_TEXTURE_2D, mutableTex);
7223 for (uint32_t mip = 0; mip < 2; ++mip)
7224 {
7225 const uint32_t size = 4 >> mip;
7226 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7227 mip == 0 ? kMip0Data.data() : kMip1Data.data());
7228 }
7229
7230 GLFramebuffer fbo;
7231 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7232
7233 // Sample from the mutable texture at non-zero base level.
7234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7236
7237 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, immutableTex, 0);
7238 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7239 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[0]);
7240
7241 // Rebase the mutable texture to zero, but enable mipmapping which makes it incomplete.
7242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
7244
7245 // Remove feedback loop for good measure.
7246 glBindTexture(GL_TEXTURE_2D, immutableTex);
7247
7248 // Draw into base zero of the texture.
7249 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutableTex, 0);
7250 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7251
7252 EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[1]);
7253 ASSERT_GL_NO_ERROR();
7254 }
7255
7256 // Regression test for a bug where the framebuffer binding was not synced during invalidate when a
7257 // clear operation was deferred.
TEST_P(SimpleStateChangeTestES3,ChangeFramebufferThenInvalidateWithClear)7258 TEST_P(SimpleStateChangeTestES3, ChangeFramebufferThenInvalidateWithClear)
7259 {
7260 // Clear the default framebuffer.
7261 glClear(GL_COLOR_BUFFER_BIT);
7262
7263 // Start rendering to another framebuffer
7264 GLFramebuffer fbo;
7265 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
7266
7267 GLRenderbuffer rbo;
7268 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
7269 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
7270 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
7271
7272 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7273 glUseProgram(program);
7274 glDrawArrays(GL_TRIANGLES, 0, 3);
7275
7276 // Switch back to the default framebuffer
7277 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
7278
7279 // Invalidate it. Don't invalidate color, as that's the one being cleared.
7280 constexpr GLenum kAttachment = GL_DEPTH;
7281 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
7282 EXPECT_GL_NO_ERROR();
7283 }
7284
7285 // Test that clear / invalidate / clear works. The invalidate is for a target that's not cleared.
7286 // Regression test for a bug where invalidate() would start a render pass to perform the first
7287 // clear, while the second clear didn't expect a render pass opened without any draw calls in it.
TEST_P(SimpleStateChangeTestES3,ClearColorInvalidateDepthClearColor)7288 TEST_P(SimpleStateChangeTestES3, ClearColorInvalidateDepthClearColor)
7289 {
7290 // Clear color.
7291 glClear(GL_COLOR_BUFFER_BIT);
7292
7293 // Invalidate depth.
7294 constexpr GLenum kAttachment = GL_DEPTH;
7295 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
7296 EXPECT_GL_NO_ERROR();
7297
7298 // Clear color again.
7299 glClear(GL_COLOR_BUFFER_BIT);
7300 ASSERT_GL_NO_ERROR();
7301 }
7302
7303 // Regression test for a bug where glInvalidateFramebuffer(GL_FRAMEBUFFER, ...) was invalidating
7304 // both the draw and read framebuffers.
TEST_P(SimpleStateChangeTestES3,InvalidateFramebufferShouldntInvalidateReadFramebuffer)7305 TEST_P(SimpleStateChangeTestES3, InvalidateFramebufferShouldntInvalidateReadFramebuffer)
7306 {
7307 // Create an invalid read framebuffer.
7308 GLFramebuffer fbo;
7309 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
7310
7311 GLTexture tex;
7312 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
7313 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, 1, 1, 1);
7314 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, tex, 0, 5);
7315
7316 // Invalidate using GL_FRAMEBUFFER. If GL_READ_FRAMEBUFFER was used, validation would fail due
7317 // to the framebuffer not being complete. A bug here was attempting to invalidate the read
7318 // framebuffer given GL_FRAMEBUFFER anyway.
7319 constexpr std::array<GLenum, 2> kAttachments = {GL_DEPTH, GL_STENCIL};
7320 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, kAttachments.data());
7321 EXPECT_GL_NO_ERROR();
7322 }
7323
7324 // Covers situations where vertex conversion could read out of bounds.
TEST_P(SimpleStateChangeTestES3,OutOfBoundsByteAttribute)7325 TEST_P(SimpleStateChangeTestES3, OutOfBoundsByteAttribute)
7326 {
7327 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
7328 glUseProgram(testProgram);
7329
7330 GLBuffer buffer;
7331 glBindBuffer(GL_ARRAY_BUFFER, buffer);
7332 glBufferData(GL_ARRAY_BUFFER, 2, nullptr, GL_STREAM_COPY);
7333
7334 glEnableVertexAttribArray(0);
7335 glVertexAttribPointer(0, 4, GL_BYTE, false, 0xff, reinterpret_cast<const void *>(0xfe));
7336
7337 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 1, 10, 1000);
7338 }
7339
7340 // Test that respecifies a buffer after we start XFB.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedback)7341 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback)
7342 {
7343 std::vector<std::string> tfVaryings = {"gl_Position"};
7344 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
7345 essl3_shaders::fs::Green(), tfVaryings,
7346 GL_INTERLEAVED_ATTRIBS);
7347
7348 glUseProgram(testProgram);
7349 GLBuffer buffer;
7350 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
7351 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
7352 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
7353 glBeginTransformFeedback(GL_TRIANGLES);
7354 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
7355 glDrawArrays(GL_TRIANGLES, 0, 6);
7356 }
7357
7358 // Regression test for a bug in the Vulkan backend where a draw-based copy after a deferred flush
7359 // would lead to an image view being destroyed too early.
TEST_P(SimpleStateChangeTestES3,DrawFlushThenCopyTexImage)7360 TEST_P(SimpleStateChangeTestES3, DrawFlushThenCopyTexImage)
7361 {
7362 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
7363
7364 // Issue a cheap draw call and a flush
7365 glEnable(GL_SCISSOR_TEST);
7366 glScissor(0, 0, 1, 1);
7367 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
7368 glDisable(GL_SCISSOR_TEST);
7369 glFlush();
7370
7371 constexpr GLsizei kSize = 32;
7372
7373 // Then an expensive copy tex image
7374 GLTexture texture;
7375 glBindTexture(GL_TEXTURE_3D, texture);
7376 glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGB8, kSize, kSize, kSize);
7377 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, kSize, kSize);
7378 glFlush();
7379 ASSERT_GL_NO_ERROR();
7380 }
7381
TEST_P(SimpleStateChangeTestES3,DrawFlushThenBlit)7382 TEST_P(SimpleStateChangeTestES3, DrawFlushThenBlit)
7383 {
7384 constexpr GLsizei kSize = 256;
7385 const std::vector<GLColor> data(kSize * kSize, GLColor::red);
7386
7387 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
7388
7389 GLFramebuffer fbo;
7390 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7391
7392 GLTexture readColor;
7393 glBindTexture(GL_TEXTURE_2D, readColor);
7394 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7395 data.data());
7396 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readColor, 0);
7397
7398 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7399
7400 // Issue a cheap draw call and a flush
7401 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
7402 glEnable(GL_SCISSOR_TEST);
7403 glScissor(0, 0, 1, 1);
7404 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
7405 glDisable(GL_SCISSOR_TEST);
7406 glFlush();
7407
7408 // Then an expensive blit
7409 glBlitFramebuffer(0, 0, kSize, kSize, kSize + 2, kSize, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
7410 glFlush();
7411 ASSERT_GL_NO_ERROR();
7412 }
7413 } // anonymous namespace
7414
7415 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
7416 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
7417 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
7418
7419 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
7420 ANGLE_INSTANTIATE_TEST_ES3(StateChangeTestES3);
7421
7422 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
7423 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
7424
7425 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
7426
7427 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
7428 ANGLE_INSTANTIATE_TEST_ES3(SimpleStateChangeTestES3);
7429
7430 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
7431 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
7432
7433 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
7434 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
7435
7436 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
7437 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
7438
7439 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
7440 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
7441
7442 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
7443 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
7444
7445 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
7446 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
7447
7448 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
7449 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
7450
7451 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
7452 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
7453
7454 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
7455 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
7456