• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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