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
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9
10 #include "util/random_utils.h"
11
12 #include <stdint.h>
13
14 using namespace angle;
15
16 class BufferDataTest : public ANGLETest
17 {
18 protected:
BufferDataTest()19 BufferDataTest()
20 {
21 setWindowWidth(16);
22 setWindowHeight(16);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 setConfigDepthBits(24);
28
29 mBuffer = 0;
30 mProgram = 0;
31 mAttribLocation = -1;
32 }
33
testSetUp()34 void testSetUp() override
35 {
36 constexpr char kVS[] = R"(attribute vec4 position;
37 attribute float in_attrib;
38 varying float v_attrib;
39 void main()
40 {
41 v_attrib = in_attrib;
42 gl_Position = position;
43 })";
44
45 constexpr char kFS[] = R"(precision mediump float;
46 varying float v_attrib;
47 void main()
48 {
49 gl_FragColor = vec4(v_attrib, 0, 0, 1);
50 })";
51
52 glGenBuffers(1, &mBuffer);
53 ASSERT_NE(mBuffer, 0U);
54
55 mProgram = CompileProgram(kVS, kFS);
56 ASSERT_NE(mProgram, 0U);
57
58 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
59 ASSERT_NE(mAttribLocation, -1);
60
61 glClearColor(0, 0, 0, 0);
62 glClearDepthf(0.0);
63 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
64
65 glDisable(GL_DEPTH_TEST);
66
67 ASSERT_GL_NO_ERROR();
68 }
69
testTearDown()70 void testTearDown() override
71 {
72 glDeleteBuffers(1, &mBuffer);
73 glDeleteProgram(mProgram);
74 }
75
76 GLuint mBuffer;
77 GLuint mProgram;
78 GLint mAttribLocation;
79 };
80
81 // If glBufferData was not called yet the capturing must not try to
82 // read the data. http://anglebug.com/6093
TEST_P(BufferDataTest,Uninitialized)83 TEST_P(BufferDataTest, Uninitialized)
84 {
85 // Trigger frame capture to try capturing the
86 // generated but uninitialized buffer
87 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
88 swapBuffers();
89 }
90
TEST_P(BufferDataTest,ZeroNonNULLData)91 TEST_P(BufferDataTest, ZeroNonNULLData)
92 {
93 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
94 EXPECT_GL_NO_ERROR();
95
96 char *zeroData = new char[0];
97 glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
98 EXPECT_GL_NO_ERROR();
99
100 glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
101 EXPECT_GL_NO_ERROR();
102
103 delete[] zeroData;
104 }
105
TEST_P(BufferDataTest,NULLResolvedData)106 TEST_P(BufferDataTest, NULLResolvedData)
107 {
108 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
109 glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
110
111 glUseProgram(mProgram);
112 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
113 glEnableVertexAttribArray(mAttribLocation);
114 glBindBuffer(GL_ARRAY_BUFFER, 0);
115
116 drawQuad(mProgram, "position", 0.5f);
117 }
118
119 // Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
120 // path.
TEST_P(BufferDataTest,RepeatedDrawWithDynamic)121 TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
122 {
123 std::vector<GLfloat> data;
124 for (int i = 0; i < 16; ++i)
125 {
126 data.push_back(static_cast<GLfloat>(i));
127 }
128
129 glUseProgram(mProgram);
130 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
131 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
132 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
133 glBindBuffer(GL_ARRAY_BUFFER, 0);
134 glEnableVertexAttribArray(mAttribLocation);
135
136 for (int drawCount = 0; drawCount < 40; ++drawCount)
137 {
138 drawQuad(mProgram, "position", 0.5f);
139 }
140
141 EXPECT_GL_NO_ERROR();
142 }
143
144 // Tests for a bug where vertex attribute translation was not being invalidated when switching to
145 // DYNAMIC
TEST_P(BufferDataTest,RepeatedDrawDynamicBug)146 TEST_P(BufferDataTest, RepeatedDrawDynamicBug)
147 {
148 // http://anglebug.com/2843: Seems to be an Intel driver bug.
149 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
150
151 glUseProgram(mProgram);
152
153 GLint positionLocation = glGetAttribLocation(mProgram, "position");
154 ASSERT_NE(-1, positionLocation);
155
156 auto quadVertices = GetQuadVertices();
157 for (angle::Vector3 &vertex : quadVertices)
158 {
159 vertex.x() *= 1.0f;
160 vertex.y() *= 1.0f;
161 vertex.z() = 0.0f;
162 }
163
164 // Set up quad vertices with DYNAMIC data
165 GLBuffer positionBuffer;
166 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
167 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
168 GL_DYNAMIC_DRAW);
169 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
170 glEnableVertexAttribArray(positionLocation);
171 glBindBuffer(GL_ARRAY_BUFFER, 0);
172 EXPECT_GL_NO_ERROR();
173
174 // Set up color data so red is drawn
175 std::vector<GLfloat> data(6, 1.0f);
176
177 // Set data to DYNAMIC
178 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
179 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
180 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
181 glEnableVertexAttribArray(mAttribLocation);
182 EXPECT_GL_NO_ERROR();
183
184 // Draw enough times to promote data to DIRECT mode
185 for (int i = 0; i < 20; i++)
186 {
187 glDrawArrays(GL_TRIANGLES, 0, 6);
188 }
189
190 // Verify red was drawn
191 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
192
193 // Set up color value so black is drawn
194 std::fill(data.begin(), data.end(), 0.0f);
195
196 // Update the data, changing back to DYNAMIC mode.
197 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
198
199 // This draw should produce a black quad
200 glDrawArrays(GL_TRIANGLES, 0, 6);
201 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
202 EXPECT_GL_NO_ERROR();
203 }
204
205 class IndexedBufferCopyTest : public ANGLETest
206 {
207 protected:
IndexedBufferCopyTest()208 IndexedBufferCopyTest()
209 {
210 setWindowWidth(16);
211 setWindowHeight(16);
212 setConfigRedBits(8);
213 setConfigGreenBits(8);
214 setConfigBlueBits(8);
215 setConfigAlphaBits(8);
216 setConfigDepthBits(24);
217 }
218
testSetUp()219 void testSetUp() override
220 {
221 constexpr char kVS[] = R"(attribute vec3 in_attrib;
222 varying vec3 v_attrib;
223 void main()
224 {
225 v_attrib = in_attrib;
226 gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
227 gl_PointSize = 100.0;
228 })";
229
230 constexpr char kFS[] = R"(precision mediump float;
231 varying vec3 v_attrib;
232 void main()
233 {
234 gl_FragColor = vec4(v_attrib, 1);
235 })";
236
237 glGenBuffers(2, mBuffers);
238 ASSERT_NE(mBuffers[0], 0U);
239 ASSERT_NE(mBuffers[1], 0U);
240
241 glGenBuffers(1, &mElementBuffer);
242 ASSERT_NE(mElementBuffer, 0U);
243
244 mProgram = CompileProgram(kVS, kFS);
245 ASSERT_NE(mProgram, 0U);
246
247 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
248 ASSERT_NE(mAttribLocation, -1);
249
250 glClearColor(0, 0, 0, 0);
251 glDisable(GL_DEPTH_TEST);
252 glClear(GL_COLOR_BUFFER_BIT);
253
254 ASSERT_GL_NO_ERROR();
255 }
256
testTearDown()257 void testTearDown() override
258 {
259 glDeleteBuffers(2, mBuffers);
260 glDeleteBuffers(1, &mElementBuffer);
261 glDeleteProgram(mProgram);
262 }
263
264 GLuint mBuffers[2];
265 GLuint mElementBuffer;
266 GLuint mProgram;
267 GLint mAttribLocation;
268 };
269
270 // The following test covers an ANGLE bug where our index ranges
271 // weren't updated from CopyBufferSubData calls
272 // https://code.google.com/p/angleproject/issues/detail?id=709
TEST_P(IndexedBufferCopyTest,IndexRangeBug)273 TEST_P(IndexedBufferCopyTest, IndexRangeBug)
274 {
275 // http://anglebug.com/4092
276 ANGLE_SKIP_TEST_IF(isSwiftshader());
277 // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
278 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
279
280 unsigned char vertexData[] = {255, 0, 0, 0, 0, 0};
281 unsigned int indexData[] = {0, 1};
282
283 glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
284 glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
285
286 glUseProgram(mProgram);
287 glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, nullptr);
288 glEnableVertexAttribArray(mAttribLocation);
289
290 ASSERT_GL_NO_ERROR();
291
292 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
293 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
294
295 glUseProgram(mProgram);
296
297 ASSERT_GL_NO_ERROR();
298
299 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
300
301 EXPECT_GL_NO_ERROR();
302 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
303
304 glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
305 glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
306
307 glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
308
309 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
310
311 ASSERT_GL_NO_ERROR();
312
313 glClear(GL_COLOR_BUFFER_BIT);
314 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
315
316 unsigned char newData[] = {0, 255, 0};
317 glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
318
319 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
320
321 EXPECT_GL_NO_ERROR();
322 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
323 }
324
325 class BufferDataTestES3 : public BufferDataTest
326 {};
327
328 // The following test covers an ANGLE bug where the buffer storage
329 // is not resized by Buffer11::getLatestBufferStorage when needed.
330 // https://code.google.com/p/angleproject/issues/detail?id=897
TEST_P(BufferDataTestES3,BufferResizing)331 TEST_P(BufferDataTestES3, BufferResizing)
332 {
333 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
334 ASSERT_GL_NO_ERROR();
335
336 // Allocate a buffer with one byte
337 uint8_t singleByte[] = {0xaa};
338 glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
339
340 // Resize the buffer
341 // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
342 // by chunks of pages instead of the minimum number of bytes needed.
343 const size_t numBytes = 4096 * 4;
344 glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
345
346 // Copy the original data to the buffer
347 uint8_t srcBytes[numBytes];
348 for (size_t i = 0; i < numBytes; ++i)
349 {
350 srcBytes[i] = static_cast<uint8_t>(i);
351 }
352
353 void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes,
354 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
355
356 ASSERT_GL_NO_ERROR();
357
358 memcpy(dest, srcBytes, numBytes);
359 glUnmapBuffer(GL_ARRAY_BUFFER);
360
361 EXPECT_GL_NO_ERROR();
362
363 // Create a new buffer and copy the data to it
364 GLuint readBuffer;
365 glGenBuffers(1, &readBuffer);
366 glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
367 uint8_t zeros[numBytes];
368 for (size_t i = 0; i < numBytes; ++i)
369 {
370 zeros[i] = 0;
371 }
372 glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
373 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
374
375 ASSERT_GL_NO_ERROR();
376
377 // Read back the data and compare it to the original
378 uint8_t *data = reinterpret_cast<uint8_t *>(
379 glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
380
381 ASSERT_GL_NO_ERROR();
382
383 for (size_t i = 0; i < numBytes; ++i)
384 {
385 EXPECT_EQ(srcBytes[i], data[i]);
386 }
387 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
388
389 glDeleteBuffers(1, &readBuffer);
390
391 EXPECT_GL_NO_ERROR();
392 }
393
394 // Test to verify mapping a buffer after copying to it contains flushed/updated data
TEST_P(BufferDataTestES3,CopyBufferSubDataMapReadTest)395 TEST_P(BufferDataTestES3, CopyBufferSubDataMapReadTest)
396 {
397 const char simpleVertex[] = R"(attribute vec2 position;
398 attribute vec4 color;
399 varying vec4 vColor;
400 void main()
401 {
402 gl_Position = vec4(position, 0, 1);
403 vColor = color;
404 }
405 )";
406 const char simpleFragment[] = R"(precision mediump float;
407 varying vec4 vColor;
408 void main()
409 {
410 gl_FragColor = vColor;
411 }
412 )";
413
414 const uint32_t numComponents = 3;
415 const uint32_t width = 4;
416 const uint32_t height = 4;
417 const size_t numElements = width * height * numComponents;
418 std::vector<uint8_t> srcData(numElements);
419 std::vector<uint8_t> dstData(numElements);
420
421 for (uint8_t i = 0; i < srcData.size(); i++)
422 {
423 srcData[i] = 128;
424 }
425 for (uint8_t i = 0; i < dstData.size(); i++)
426 {
427 dstData[i] = 0;
428 }
429
430 GLBuffer srcBuffer;
431 GLBuffer dstBuffer;
432
433 glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
434 glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
435 ASSERT_GL_NO_ERROR();
436
437 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
438 glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
439 ASSERT_GL_NO_ERROR();
440
441 ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
442 glUseProgram(program);
443
444 GLint colorLoc = glGetAttribLocation(program, "color");
445 ASSERT_NE(-1, colorLoc);
446
447 glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
448 glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
449 glEnableVertexAttribArray(colorLoc);
450
451 drawQuad(program, "position", 0.5f, 1.0f, true);
452 ASSERT_GL_NO_ERROR();
453
454 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
455
456 // With GL_MAP_READ_BIT, we expect the data to be flushed and updated to match srcData
457 uint8_t *data = reinterpret_cast<uint8_t *>(
458 glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
459 EXPECT_GL_NO_ERROR();
460 for (size_t i = 0; i < numElements; ++i)
461 {
462 EXPECT_EQ(srcData[i], data[i]);
463 }
464 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
465 EXPECT_GL_NO_ERROR();
466 }
467
468 // Test to verify mapping a buffer after copying to it contains expected data
469 // with GL_MAP_UNSYNCHRONIZED_BIT
TEST_P(BufferDataTestES3,MapBufferUnsynchronizedReadTest)470 TEST_P(BufferDataTestES3, MapBufferUnsynchronizedReadTest)
471 {
472 const char simpleVertex[] = R"(attribute vec2 position;
473 attribute vec4 color;
474 varying vec4 vColor;
475 void main()
476 {
477 gl_Position = vec4(position, 0, 1);
478 vColor = color;
479 }
480 )";
481 const char simpleFragment[] = R"(precision mediump float;
482 varying vec4 vColor;
483 void main()
484 {
485 gl_FragColor = vColor;
486 }
487 )";
488
489 const uint32_t numComponents = 3;
490 const uint32_t width = 4;
491 const uint32_t height = 4;
492 const size_t numElements = width * height * numComponents;
493 std::vector<uint8_t> srcData(numElements);
494 std::vector<uint8_t> dstData(numElements);
495
496 for (uint8_t i = 0; i < srcData.size(); i++)
497 {
498 srcData[i] = 128;
499 }
500 for (uint8_t i = 0; i < dstData.size(); i++)
501 {
502 dstData[i] = 0;
503 }
504
505 GLBuffer srcBuffer;
506 GLBuffer dstBuffer;
507
508 glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
509 glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
510 ASSERT_GL_NO_ERROR();
511
512 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
513 glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
514 ASSERT_GL_NO_ERROR();
515
516 ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
517 glUseProgram(program);
518
519 GLint colorLoc = glGetAttribLocation(program, "color");
520 ASSERT_NE(-1, colorLoc);
521
522 glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
523 glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
524 glEnableVertexAttribArray(colorLoc);
525
526 drawQuad(program, "position", 0.5f, 1.0f, true);
527 ASSERT_GL_NO_ERROR();
528
529 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
530
531 // Synchronize.
532 glFinish();
533
534 // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data with srcData
535 uint8_t *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
536 GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
537 EXPECT_GL_NO_ERROR();
538 memcpy(data, srcData.data(), srcData.size());
539 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
540 EXPECT_GL_NO_ERROR();
541
542 // Map without GL_MAP_UNSYNCHRONIZED_BIT and read data. We expect it to be srcData
543 data = reinterpret_cast<uint8_t *>(
544 glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
545 EXPECT_GL_NO_ERROR();
546 for (size_t i = 0; i < numElements; ++i)
547 {
548 EXPECT_EQ(srcData[i], data[i]);
549 }
550 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
551 EXPECT_GL_NO_ERROR();
552 }
553
554 // Verify the functionality of glMapBufferRange()'s GL_MAP_UNSYNCHRONIZED_BIT
555 // NOTE: On Vulkan, if we ever use memory that's not `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`, then
556 // this could incorrectly pass.
TEST_P(BufferDataTestES3,MapBufferRangeUnsynchronizedBit)557 TEST_P(BufferDataTestES3, MapBufferRangeUnsynchronizedBit)
558 {
559 // We can currently only control the behavior of the Vulkan backend's synchronizing operation's
560 ANGLE_SKIP_TEST_IF(!IsVulkan());
561
562 const size_t numElements = 10;
563 std::vector<uint8_t> srcData(numElements);
564 std::vector<uint8_t> dstData(numElements);
565
566 for (uint8_t i = 0; i < srcData.size(); i++)
567 {
568 srcData[i] = i;
569 }
570 for (uint8_t i = 0; i < dstData.size(); i++)
571 {
572 dstData[i] = static_cast<uint8_t>(i + dstData.size());
573 }
574
575 GLBuffer srcBuffer;
576 GLBuffer dstBuffer;
577
578 glBindBuffer(GL_COPY_READ_BUFFER, srcBuffer);
579 ASSERT_GL_NO_ERROR();
580 glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
581 ASSERT_GL_NO_ERROR();
582
583 glBufferData(GL_COPY_READ_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
584 ASSERT_GL_NO_ERROR();
585 glBufferData(GL_COPY_WRITE_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
586 ASSERT_GL_NO_ERROR();
587
588 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numElements);
589
590 // With GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be stale and match dstData
591 // NOTE: We are specifying GL_MAP_WRITE_BIT so we can use GL_MAP_UNSYNCHRONIZED_BIT. This is
592 // venturing into undefined behavior, since we are actually planning on reading from this
593 // pointer.
594 auto *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
595 GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
596 EXPECT_GL_NO_ERROR();
597 for (size_t i = 0; i < numElements; ++i)
598 {
599 // Allow for the possibility that data matches either "dstData" or "srcData"
600 if (dstData[i] != data[i])
601 {
602 EXPECT_EQ(srcData[i], data[i]);
603 }
604 }
605 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
606 EXPECT_GL_NO_ERROR();
607
608 // Without GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be copied and match srcData
609 data = reinterpret_cast<uint8_t *>(
610 glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_READ_BIT));
611 EXPECT_GL_NO_ERROR();
612 for (size_t i = 0; i < numElements; ++i)
613 {
614 EXPECT_EQ(srcData[i], data[i]);
615 }
616 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
617 EXPECT_GL_NO_ERROR();
618 }
619
620 // Verify OES_mapbuffer is present if EXT_map_buffer_range is.
TEST_P(BufferDataTest,ExtensionDependency)621 TEST_P(BufferDataTest, ExtensionDependency)
622 {
623 if (IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
624 {
625 ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_mapbuffer"));
626 }
627 }
628
629 // Test mapping with the OES extension.
TEST_P(BufferDataTest,MapBufferOES)630 TEST_P(BufferDataTest, MapBufferOES)
631 {
632 if (!IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
633 {
634 // Needed for test validation.
635 return;
636 }
637
638 std::vector<uint8_t> data(1024);
639 FillVectorWithRandomUBytes(&data);
640
641 GLBuffer buffer;
642 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
643 glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
644
645 // Validate that other map flags don't work.
646 void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
647 EXPECT_EQ(nullptr, badMapPtr);
648 EXPECT_GL_ERROR(GL_INVALID_ENUM);
649
650 // Map and write.
651 void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
652 ASSERT_NE(nullptr, mapPtr);
653 ASSERT_GL_NO_ERROR();
654 memcpy(mapPtr, data.data(), data.size());
655 glUnmapBufferOES(GL_ARRAY_BUFFER);
656
657 // Validate data with EXT_map_buffer_range
658 void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
659 ASSERT_NE(nullptr, readMapPtr);
660 ASSERT_GL_NO_ERROR();
661 std::vector<uint8_t> actualData(data.size());
662 memcpy(actualData.data(), readMapPtr, data.size());
663 glUnmapBufferOES(GL_ARRAY_BUFFER);
664
665 EXPECT_EQ(data, actualData);
666 }
667
668 // Test to verify mapping a dynamic buffer with GL_MAP_UNSYNCHRONIZED_BIT to modify a portion
669 // won't affect draw calls using other portions.
TEST_P(BufferDataTest,MapDynamicBufferUnsynchronizedEXTTest)670 TEST_P(BufferDataTest, MapDynamicBufferUnsynchronizedEXTTest)
671 {
672 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
673
674 const char simpleVertex[] = R"(attribute vec2 position;
675 attribute vec4 color;
676 varying vec4 vColor;
677 void main()
678 {
679 gl_Position = vec4(position, 0, 1);
680 vColor = color;
681 }
682 )";
683 const char simpleFragment[] = R"(precision mediump float;
684 varying vec4 vColor;
685 void main()
686 {
687 gl_FragColor = vColor;
688 }
689 )";
690
691 constexpr int kNumVertices = 6;
692
693 std::vector<GLubyte> color(8 * kNumVertices);
694 for (int i = 0; i < kNumVertices; ++i)
695 {
696 color[4 * i] = 255;
697 color[4 * i + 3] = 255;
698 }
699 GLBuffer buffer;
700 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
701 glBufferData(GL_ARRAY_BUFFER, color.size(), color.data(), GL_DYNAMIC_DRAW);
702
703 ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
704 glUseProgram(program);
705
706 GLint colorLoc = glGetAttribLocation(program, "color");
707 ASSERT_NE(-1, colorLoc);
708
709 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
710 glEnableVertexAttribArray(colorLoc);
711
712 glViewport(0, 0, 2, 2);
713 drawQuad(program, "position", 0.5f, 1.0f, true);
714 ASSERT_GL_NO_ERROR();
715
716 // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data at offset 24
717 uint8_t *data = reinterpret_cast<uint8_t *>(
718 glMapBufferRangeEXT(GL_ARRAY_BUFFER, 4 * kNumVertices, 4 * kNumVertices,
719 GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
720 EXPECT_GL_NO_ERROR();
721 for (int i = 0; i < kNumVertices; ++i)
722 {
723 data[4 * i] = 0;
724 data[4 * i + 1] = 255;
725 data[4 * i + 2] = 0;
726 data[4 * i + 3] = 255;
727 }
728 glUnmapBufferOES(GL_ARRAY_BUFFER);
729 EXPECT_GL_NO_ERROR();
730
731 // Re-draw using offset = 0 but to different viewport
732 glViewport(0, 2, 2, 2);
733 drawQuad(program, "position", 0.5f, 1.0f, true);
734 ASSERT_GL_NO_ERROR();
735
736 // Change vertex attribute to use buffer starting from offset 24
737 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0,
738 reinterpret_cast<void *>(4 * kNumVertices));
739
740 glViewport(2, 2, 2, 2);
741 drawQuad(program, "position", 0.5f, 1.0f, true);
742 ASSERT_GL_NO_ERROR();
743
744 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
745 EXPECT_PIXEL_COLOR_EQ(1, 3, GLColor::red);
746 EXPECT_PIXEL_COLOR_EQ(3, 3, GLColor::green);
747 }
748
749 // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
750 // data, using drawQuad().
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawQuad)751 TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawQuad)
752 {
753 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
754
755 std::vector<GLfloat> data(6, 0.0f);
756
757 glUseProgram(mProgram);
758 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
759 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
760 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
761 glEnableVertexAttribArray(mAttribLocation);
762
763 // Don't read back to verify black, so we don't break the render pass.
764 drawQuad(mProgram, "position", 0.5f);
765 EXPECT_GL_NO_ERROR();
766
767 // Map and write.
768 std::vector<GLfloat> data2(6, 1.0f);
769 void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
770 ASSERT_NE(nullptr, mapPtr);
771 ASSERT_GL_NO_ERROR();
772 memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
773 glUnmapBufferOES(GL_ARRAY_BUFFER);
774
775 drawQuad(mProgram, "position", 0.5f);
776 EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
777 EXPECT_GL_NO_ERROR();
778 }
779
780 // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
781 // data, calling glDrawArrays() directly.
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawArrays)782 TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawArrays)
783 {
784 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
785
786 std::vector<GLfloat> data(6, 0.0f);
787
788 glUseProgram(mProgram);
789
790 GLint positionLocation = glGetAttribLocation(mProgram, "position");
791 ASSERT_NE(-1, positionLocation);
792
793 // Set up position attribute, don't use drawQuad.
794 auto quadVertices = GetQuadVertices();
795
796 GLBuffer positionBuffer;
797 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
798 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
799 GL_DYNAMIC_DRAW);
800 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
801 glEnableVertexAttribArray(positionLocation);
802 EXPECT_GL_NO_ERROR();
803
804 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
805 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
806 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
807 glEnableVertexAttribArray(mAttribLocation);
808 EXPECT_GL_NO_ERROR();
809
810 // Don't read back to verify black, so we don't break the render pass.
811 glDrawArrays(GL_TRIANGLES, 0, 6);
812 EXPECT_GL_NO_ERROR();
813
814 // Map and write.
815 std::vector<GLfloat> data2(6, 1.0f);
816 void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
817 ASSERT_NE(nullptr, mapPtr);
818 ASSERT_GL_NO_ERROR();
819 memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
820 glUnmapBufferOES(GL_ARRAY_BUFFER);
821
822 glDrawArrays(GL_TRIANGLES, 0, 6);
823 EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
824 EXPECT_GL_NO_ERROR();
825 }
826
827 // Tests a null crash bug caused by copying from null back-end buffer pointer
828 // when calling bufferData again after drawing without calling bufferData in D3D11.
TEST_P(BufferDataTestES3,DrawWithNotCallingBufferData)829 TEST_P(BufferDataTestES3, DrawWithNotCallingBufferData)
830 {
831 ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
832 glUseProgram(drawRed);
833
834 GLint mem = 0;
835 GLBuffer buffer;
836 glBindBuffer(GL_ARRAY_BUFFER, buffer);
837 glEnableVertexAttribArray(0);
838 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
839 glDrawArrays(GL_TRIANGLES, 0, 3);
840 glBindBuffer(GL_COPY_WRITE_BUFFER, buffer);
841 glBufferData(GL_COPY_WRITE_BUFFER, 1, &mem, GL_STREAM_DRAW);
842 ASSERT_GL_NO_ERROR();
843 }
844
845 // Tests a bug where copying buffer data immediately after creation hit a nullptr in D3D11.
TEST_P(BufferDataTestES3,NoBufferInitDataCopyBug)846 TEST_P(BufferDataTestES3, NoBufferInitDataCopyBug)
847 {
848 constexpr GLsizei size = 64;
849
850 GLBuffer sourceBuffer;
851 glBindBuffer(GL_COPY_READ_BUFFER, sourceBuffer);
852 glBufferData(GL_COPY_READ_BUFFER, size, nullptr, GL_STATIC_DRAW);
853
854 GLBuffer destBuffer;
855 glBindBuffer(GL_ARRAY_BUFFER, destBuffer);
856 glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
857
858 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ARRAY_BUFFER, 0, 0, size);
859 ASSERT_GL_NO_ERROR();
860 }
861
862 // Ensures that calling glBufferData on a mapped buffer results in an unmapped buffer
TEST_P(BufferDataTestES3,BufferDataUnmap)863 TEST_P(BufferDataTestES3, BufferDataUnmap)
864 {
865 // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
866 // BufferData happens on a mapped buffer:
867 //
868 // If any portion of the buffer object is mapped in the current context or
869 // any context current to another thread, it is as though UnmapBuffer
870 // (see section 2.10.3) is executed in each such context prior to deleting
871 // the existing data store.
872 //
873
874 std::vector<uint8_t> data1(16);
875 std::vector<uint8_t> data2(16);
876
877 GLBuffer dataBuffer;
878 glBindBuffer(GL_ARRAY_BUFFER, dataBuffer);
879 glBufferData(GL_ARRAY_BUFFER, data1.size(), data1.data(), GL_STATIC_DRAW);
880
881 // Map the buffer once
882 glMapBufferRange(GL_ARRAY_BUFFER, 0, data1.size(),
883 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
884 GL_MAP_UNSYNCHRONIZED_BIT);
885
886 // Then repopulate the buffer. This should cause the buffer to become unmapped.
887 glBufferData(GL_ARRAY_BUFFER, data2.size(), data2.data(), GL_STATIC_DRAW);
888 ASSERT_GL_NO_ERROR();
889
890 // Try to unmap the buffer, this should fail
891 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
892 ASSERT_EQ(result, false);
893 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
894
895 // Try to map the buffer again, which should succeed
896 glMapBufferRange(GL_ARRAY_BUFFER, 0, data2.size(),
897 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
898 GL_MAP_UNSYNCHRONIZED_BIT);
899 ASSERT_GL_NO_ERROR();
900 }
901
902 // Ensures that mapping buffer with GL_MAP_INVALIDATE_BUFFER_BIT followed by glBufferSubData calls
903 // works. Regression test for the Vulkan backend where that flag caused use after free.
TEST_P(BufferDataTestES3,MapInvalidateThenBufferSubData)904 TEST_P(BufferDataTestES3, MapInvalidateThenBufferSubData)
905 {
906 // http://anglebug.com/5984
907 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsIntel());
908
909 // http://anglebug.com/5985
910 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
911
912 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
913 GLColor::red};
914 const std::array<GLColor, 4> kUpdateData1 = {GLColor::white, GLColor::white, GLColor::white,
915 GLColor::white};
916 const std::array<GLColor, 4> kUpdateData2 = {GLColor::blue, GLColor::blue, GLColor::blue,
917 GLColor::blue};
918
919 GLBuffer buffer;
920 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
921 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
922 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
923 EXPECT_GL_NO_ERROR();
924
925 // Draw
926 constexpr char kVerifyUBO[] = R"(#version 300 es
927 precision mediump float;
928 uniform block {
929 uvec4 data;
930 } ubo;
931 uniform uint expect;
932 uniform vec4 successOutput;
933 out vec4 colorOut;
934 void main()
935 {
936 if (all(equal(ubo.data, uvec4(expect))))
937 colorOut = successOutput;
938 else
939 colorOut = vec4(1.0, 0, 0, 1.0);
940 })";
941
942 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
943 glUseProgram(verifyUbo);
944
945 GLint expectLoc = glGetUniformLocation(verifyUbo, "expect");
946 EXPECT_NE(-1, expectLoc);
947 GLint successLoc = glGetUniformLocation(verifyUbo, "successOutput");
948 EXPECT_NE(-1, successLoc);
949
950 glUniform1ui(expectLoc, kInitialData[0].asUint());
951 glUniform4f(successLoc, 0, 1, 0, 1);
952
953 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
954 EXPECT_GL_NO_ERROR();
955
956 // Dont't verify the buffer. This is testing GL_MAP_INVALIDATE_BUFFER_BIT while the buffer is
957 // in use by the GPU.
958
959 // Map the buffer and update it.
960 void *mappedBuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData),
961 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
962
963 memcpy(mappedBuffer, kUpdateData1.data(), sizeof(kInitialData));
964
965 glUnmapBuffer(GL_UNIFORM_BUFFER);
966 EXPECT_GL_NO_ERROR();
967
968 // Verify that the buffer has the updated value.
969 glUniform1ui(expectLoc, kUpdateData1[0].asUint());
970 glUniform4f(successLoc, 0, 0, 1, 1);
971
972 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
973 EXPECT_GL_NO_ERROR();
974
975 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
976
977 // Update the buffer with glBufferSubData
978 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData2), kUpdateData2.data());
979 EXPECT_GL_NO_ERROR();
980
981 // Verify that the buffer has the updated value.
982 glUniform1ui(expectLoc, kUpdateData2[0].asUint());
983 glUniform4f(successLoc, 0, 1, 1, 1);
984
985 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
986 EXPECT_GL_NO_ERROR();
987
988 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
989 }
990
991 class BufferStorageTestES3 : public BufferDataTest
992 {};
993
994 // Tests that proper error value is returned when bad size is passed in
TEST_P(BufferStorageTestES3,BufferStorageInvalidSize)995 TEST_P(BufferStorageTestES3, BufferStorageInvalidSize)
996 {
997 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
998
999 std::vector<GLfloat> data(6, 1.0f);
1000
1001 GLBuffer buffer;
1002 glBindBuffer(GL_ARRAY_BUFFER, buffer);
1003 glBufferStorageEXT(GL_ARRAY_BUFFER, 0, data.data(), 0);
1004 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1005 }
1006
1007 // Tests that buffer storage can be allocated with the GL_MAP_PERSISTENT_BIT_EXT and
1008 // GL_MAP_COHERENT_BIT_EXT flags
TEST_P(BufferStorageTestES3,BufferStorageFlagsPersistentCoherentWrite)1009 TEST_P(BufferStorageTestES3, BufferStorageFlagsPersistentCoherentWrite)
1010 {
1011 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1012
1013 std::vector<GLfloat> data(6, 1.0f);
1014
1015 GLBuffer buffer;
1016 glBindBuffer(GL_ARRAY_BUFFER, buffer);
1017 glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), data.data(),
1018 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1019 ASSERT_GL_NO_ERROR();
1020 }
1021
1022 // Verify that glBufferStorage makes a buffer immutable
TEST_P(BufferStorageTestES3,StorageBufferBufferData)1023 TEST_P(BufferStorageTestES3, StorageBufferBufferData)
1024 {
1025 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1026 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1027
1028 std::vector<GLfloat> data(6, 1.0f);
1029
1030 GLBuffer buffer;
1031 glBindBuffer(GL_ARRAY_BUFFER, buffer);
1032 glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1033 ASSERT_GL_NO_ERROR();
1034
1035 // Verify that calling glBufferStorageEXT again produces an error.
1036 glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1037 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1038
1039 // Verify that calling glBufferData after calling glBufferStorageEXT produces an error.
1040 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1041 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1042 }
1043
1044 // Verify that glBufferStorageEXT can be called after glBufferData
TEST_P(BufferStorageTestES3,BufferDataStorageBuffer)1045 TEST_P(BufferStorageTestES3, BufferDataStorageBuffer)
1046 {
1047 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1048 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1049
1050 std::vector<GLfloat> data(6, 1.0f);
1051
1052 GLBuffer buffer;
1053 glBindBuffer(GL_ARRAY_BUFFER, buffer);
1054 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1055 ASSERT_GL_NO_ERROR();
1056
1057 // Verify that calling glBufferStorageEXT again produces an error.
1058 glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1059 ASSERT_GL_NO_ERROR();
1060 }
1061
1062 // Verify that we can perform subdata updates to a buffer marked with GL_DYNAMIC_STORAGE_BIT_EXT
1063 // usage flag
TEST_P(BufferStorageTestES3,StorageBufferSubData)1064 TEST_P(BufferStorageTestES3, StorageBufferSubData)
1065 {
1066 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1067 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1068
1069 std::vector<GLfloat> data(6, 0.0f);
1070
1071 glUseProgram(mProgram);
1072 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1073 glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr,
1074 GL_DYNAMIC_STORAGE_BIT_EXT);
1075 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data.size(), data.data());
1076 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1077 glEnableVertexAttribArray(mAttribLocation);
1078
1079 drawQuad(mProgram, "position", 0.5f);
1080 EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::black);
1081 EXPECT_GL_NO_ERROR();
1082
1083 std::vector<GLfloat> data2(6, 1.0f);
1084 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data2.size(), data2.data());
1085
1086 drawQuad(mProgram, "position", 0.5f);
1087 EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1088 EXPECT_GL_NO_ERROR();
1089 }
1090
1091 // Test interaction between GL_OES_mapbuffer and GL_EXT_buffer_storage extensions.
TEST_P(BufferStorageTestES3,StorageBufferMapBufferOES)1092 TEST_P(BufferStorageTestES3, StorageBufferMapBufferOES)
1093 {
1094 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1095 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1096 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1097
1098 std::vector<uint8_t> data(1024);
1099 FillVectorWithRandomUBytes(&data);
1100
1101 GLBuffer buffer;
1102 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1103 glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
1104
1105 // Validate that other map flags don't work.
1106 void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
1107 EXPECT_EQ(nullptr, badMapPtr);
1108 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1109
1110 // Map and write.
1111 void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
1112 ASSERT_NE(nullptr, mapPtr);
1113 ASSERT_GL_NO_ERROR();
1114 memcpy(mapPtr, data.data(), data.size());
1115 glUnmapBufferOES(GL_ARRAY_BUFFER);
1116
1117 // Validate data with EXT_map_buffer_range
1118 void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
1119 ASSERT_NE(nullptr, readMapPtr);
1120 ASSERT_GL_NO_ERROR();
1121 std::vector<uint8_t> actualData(data.size());
1122 memcpy(actualData.data(), readMapPtr, data.size());
1123 glUnmapBufferOES(GL_ARRAY_BUFFER);
1124
1125 EXPECT_EQ(data, actualData);
1126 }
1127
1128 // Verify persistently mapped buffers can use glCopyBufferSubData
1129 // Tests a pattern used by Fortnite's GLES backend
TEST_P(BufferStorageTestES3,StorageCopyBufferSubDataMapped)1130 TEST_P(BufferStorageTestES3, StorageCopyBufferSubDataMapped)
1131 {
1132 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1133 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1134 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1135
1136 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::green, GLColor::blue,
1137 GLColor::yellow};
1138
1139 // Set up the read buffer
1140 GLBuffer readBuffer;
1141 glBindBuffer(GL_ARRAY_BUFFER, readBuffer.get());
1142 glBufferData(GL_ARRAY_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1143
1144 // Set up the write buffer to be persistently mapped
1145 GLBuffer writeBuffer;
1146 glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
1147 glBufferStorageEXT(GL_COPY_WRITE_BUFFER, 16, nullptr,
1148 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1149 void *readMapPtr =
1150 glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, 16,
1151 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1152 ASSERT_NE(nullptr, readMapPtr);
1153 ASSERT_GL_NO_ERROR();
1154
1155 // Verify we can copy into the write buffer
1156 glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
1157 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, 16);
1158 ASSERT_GL_NO_ERROR();
1159
1160 // Flush the buffer.
1161 glFinish();
1162
1163 // Check the contents
1164 std::array<GLColor, 4> resultingData;
1165 memcpy(resultingData.data(), readMapPtr, resultingData.size() * sizeof(GLColor));
1166 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
1167 EXPECT_EQ(kInitialData, resultingData);
1168 ASSERT_GL_NO_ERROR();
1169 }
1170
1171 // Verify persistently mapped element array buffers can use glDrawElements
TEST_P(BufferStorageTestES3,DrawElementsElementArrayBufferMapped)1172 TEST_P(BufferStorageTestES3, DrawElementsElementArrayBufferMapped)
1173 {
1174 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1175 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1176 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1177
1178 GLfloat kVertexBuffer[] = {-1.0f, -1.0f, 1.0f, // (x, y, R)
1179 -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
1180 // Set up array buffer
1181 GLBuffer readBuffer;
1182 glBindBuffer(GL_ARRAY_BUFFER, readBuffer.get());
1183 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexBuffer), kVertexBuffer, GL_DYNAMIC_DRAW);
1184 GLint vLoc = glGetAttribLocation(mProgram, "position");
1185 GLint cLoc = mAttribLocation;
1186 glVertexAttribPointer(vLoc, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
1187 glEnableVertexAttribArray(vLoc);
1188 glVertexAttribPointer(cLoc, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const GLvoid *)8);
1189 glEnableVertexAttribArray(cLoc);
1190
1191 // Set up the element array buffer to be persistently mapped
1192 GLshort kElementArrayBuffer[] = {0, 0, 0, 0, 0, 0};
1193
1194 GLBuffer indexBuffer;
1195 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1196 glBufferStorageEXT(GL_ELEMENT_ARRAY_BUFFER, sizeof(kElementArrayBuffer), kElementArrayBuffer,
1197 GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1198 GL_MAP_COHERENT_BIT_EXT);
1199
1200 glUseProgram(mProgram);
1201
1202 glClearColor(0, 0, 0, 0);
1203 glClear(GL_COLOR_BUFFER_BIT);
1204
1205 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1206 ASSERT_GL_NO_ERROR();
1207 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1208
1209 GLshort *mappedPtr = (GLshort *)glMapBufferRange(
1210 GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(kElementArrayBuffer),
1211 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1212 ASSERT_NE(nullptr, mappedPtr);
1213 ASSERT_GL_NO_ERROR();
1214
1215 mappedPtr[0] = 0;
1216 mappedPtr[1] = 1;
1217 mappedPtr[2] = 2;
1218 mappedPtr[3] = 2;
1219 mappedPtr[4] = 1;
1220 mappedPtr[5] = 3;
1221 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1222
1223 ASSERT_GL_NO_ERROR();
1224
1225 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1226 }
1227
1228 // Test that we are able to perform glTex*D calls while a pixel unpack buffer is bound
1229 // and persistently mapped.
TEST_P(BufferStorageTestES3,TexImage2DPixelUnpackBufferMappedPersistently)1230 TEST_P(BufferStorageTestES3, TexImage2DPixelUnpackBufferMappedPersistently)
1231 {
1232 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1233 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1234
1235 std::vector<uint8_t> data(64);
1236 FillVectorWithRandomUBytes(&data);
1237
1238 GLBuffer buffer;
1239 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.get());
1240 glBufferStorageEXT(GL_PIXEL_UNPACK_BUFFER, data.size(), data.data(),
1241 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1242
1243 // Map the buffer.
1244 void *mapPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, data.size(),
1245 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1246 ASSERT_NE(nullptr, mapPtr);
1247 ASSERT_GL_NO_ERROR();
1248
1249 // Create a 2D texture and fill it using the persistenly mapped unpack buffer
1250 GLTexture tex;
1251 glBindTexture(GL_TEXTURE_2D, tex);
1252
1253 constexpr GLsizei kTextureWidth = 4;
1254 constexpr GLsizei kTextureHeight = 4;
1255 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTextureWidth, kTextureHeight, 0, GL_RGBA,
1256 GL_UNSIGNED_BYTE, 0);
1257 ASSERT_GL_NO_ERROR();
1258
1259 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1260 ASSERT_GL_NO_ERROR();
1261 }
1262
1263 // Verify persistently mapped buffers can use glBufferSubData
TEST_P(BufferStorageTestES3,StorageBufferSubDataMapped)1264 TEST_P(BufferStorageTestES3, StorageBufferSubDataMapped)
1265 {
1266 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1267 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1268 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1269
1270 const std::array<GLColor, 4> kUpdateData1 = {GLColor::red, GLColor::green, GLColor::blue,
1271 GLColor::yellow};
1272
1273 // Set up the buffer to be persistently mapped and dynamic
1274 GLBuffer buffer;
1275 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1276 glBufferStorageEXT(GL_ARRAY_BUFFER, 16, nullptr,
1277 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1278 GL_MAP_COHERENT_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
1279 void *readMapPtr = glMapBufferRange(
1280 GL_ARRAY_BUFFER, 0, 16,
1281 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1282 ASSERT_NE(nullptr, readMapPtr);
1283 ASSERT_GL_NO_ERROR();
1284
1285 // Verify we can push new data into the buffer
1286 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * kUpdateData1.size(), kUpdateData1.data());
1287 ASSERT_GL_NO_ERROR();
1288
1289 // Flush the buffer.
1290 glFinish();
1291
1292 // Check the contents
1293 std::array<GLColor, 4> persistentData1;
1294 memcpy(persistentData1.data(), readMapPtr, persistentData1.size() * sizeof(GLColor));
1295 EXPECT_EQ(kUpdateData1, persistentData1);
1296 glUnmapBuffer(GL_ARRAY_BUFFER);
1297 ASSERT_GL_NO_ERROR();
1298 }
1299
1300 ANGLE_INSTANTIATE_TEST_ES2(BufferDataTest);
1301
1302 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferDataTestES3);
1303 ANGLE_INSTANTIATE_TEST_ES3(BufferDataTestES3);
1304
1305 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3);
1306 ANGLE_INSTANTIATE_TEST_ES3(BufferStorageTestES3);
1307
1308 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IndexedBufferCopyTest);
1309 ANGLE_INSTANTIATE_TEST_ES3(IndexedBufferCopyTest);
1310
1311 #ifdef _WIN64
1312
1313 // Test a bug where an integer overflow bug could trigger a crash in D3D.
1314 // The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
1315 // (with the internal D3D rounding to 16-byte values) and trigger the bug.
1316 // Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
1317 class BufferDataOverflowTest : public ANGLETest
1318 {
1319 protected:
BufferDataOverflowTest()1320 BufferDataOverflowTest() {}
1321 };
1322
1323 // See description above.
TEST_P(BufferDataOverflowTest,VertexBufferIntegerOverflow)1324 TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
1325 {
1326 // These values are special, to trigger the rounding bug.
1327 unsigned int numItems = 0x7FFFFFE;
1328 constexpr GLsizei bufferCnt = 8;
1329
1330 std::vector<GLBuffer> buffers(bufferCnt);
1331
1332 std::stringstream vertexShaderStr;
1333
1334 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1335 {
1336 vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
1337 }
1338
1339 vertexShaderStr << "attribute vec2 position;\n"
1340 "varying float v_attrib;\n"
1341 "void main() {\n"
1342 " gl_Position = vec4(position, 0, 1);\n"
1343 " v_attrib = 0.0;\n";
1344
1345 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1346 {
1347 vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
1348 }
1349
1350 vertexShaderStr << "}";
1351
1352 constexpr char kFS[] =
1353 "varying highp float v_attrib;\n"
1354 "void main() {\n"
1355 " gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
1356 "}";
1357
1358 ANGLE_GL_PROGRAM(program, vertexShaderStr.str().c_str(), kFS);
1359 glUseProgram(program.get());
1360
1361 std::vector<GLfloat> data(numItems, 1.0f);
1362
1363 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1364 {
1365 glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex].get());
1366 glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
1367
1368 std::stringstream attribNameStr;
1369 attribNameStr << "attrib" << bufferIndex;
1370
1371 GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
1372 ASSERT_NE(-1, attribLocation);
1373
1374 glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
1375 glEnableVertexAttribArray(attribLocation);
1376 }
1377
1378 GLint positionLocation = glGetAttribLocation(program.get(), "position");
1379 ASSERT_NE(-1, positionLocation);
1380 glDisableVertexAttribArray(positionLocation);
1381 glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
1382
1383 EXPECT_GL_NO_ERROR();
1384 glDrawArrays(GL_TRIANGLES, 0, numItems);
1385 EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
1386
1387 // Test that a small draw still works.
1388 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1389 {
1390 std::stringstream attribNameStr;
1391 attribNameStr << "attrib" << bufferIndex;
1392 GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
1393 ASSERT_NE(-1, attribLocation);
1394 glDisableVertexAttribArray(attribLocation);
1395 }
1396
1397 glDrawArrays(GL_TRIANGLES, 0, 3);
1398 EXPECT_GL_ERROR(GL_NO_ERROR);
1399 }
1400
1401 // Tests a security bug in our CopyBufferSubData validation (integer overflow).
TEST_P(BufferDataOverflowTest,CopySubDataValidation)1402 TEST_P(BufferDataOverflowTest, CopySubDataValidation)
1403 {
1404 GLBuffer readBuffer, writeBuffer;
1405
1406 glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
1407 glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
1408
1409 constexpr int bufSize = 100;
1410
1411 glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
1412 glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
1413
1414 GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
1415
1416 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
1417 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1418
1419 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
1420 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1421 }
1422
1423 ANGLE_INSTANTIATE_TEST_ES3(BufferDataOverflowTest);
1424
1425 #endif // _WIN64
1426