• 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 #include <thread>
14 
15 using namespace angle;
16 
17 class BufferDataTest : public ANGLETest
18 {
19   protected:
BufferDataTest()20     BufferDataTest()
21     {
22         setWindowWidth(16);
23         setWindowHeight(16);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28         setConfigDepthBits(24);
29 
30         mBuffer         = 0;
31         mProgram        = 0;
32         mAttribLocation = -1;
33     }
34 
testSetUp()35     void testSetUp() override
36     {
37         constexpr char kVS[] = R"(attribute vec4 position;
38 attribute float in_attrib;
39 varying float v_attrib;
40 void main()
41 {
42     v_attrib = in_attrib;
43     gl_Position = position;
44 })";
45 
46         constexpr char kFS[] = R"(precision mediump float;
47 varying float v_attrib;
48 void main()
49 {
50     gl_FragColor = vec4(v_attrib, 0, 0, 1);
51 })";
52 
53         glGenBuffers(1, &mBuffer);
54         ASSERT_NE(mBuffer, 0U);
55 
56         mProgram = CompileProgram(kVS, kFS);
57         ASSERT_NE(mProgram, 0U);
58 
59         mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
60         ASSERT_NE(mAttribLocation, -1);
61 
62         glClearColor(0, 0, 0, 0);
63         glClearDepthf(0.0);
64         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65 
66         glDisable(GL_DEPTH_TEST);
67 
68         ASSERT_GL_NO_ERROR();
69     }
70 
testTearDown()71     void testTearDown() override
72     {
73         glDeleteBuffers(1, &mBuffer);
74         glDeleteProgram(mProgram);
75     }
76 
77     GLuint mBuffer;
78     GLuint mProgram;
79     GLint mAttribLocation;
80 };
81 
82 // If glBufferData was not called yet the capturing must not try to
83 // read the data. http://anglebug.com/6093
TEST_P(BufferDataTest,Uninitialized)84 TEST_P(BufferDataTest, Uninitialized)
85 {
86     // Trigger frame capture to try capturing the
87     // generated but uninitialized buffer
88     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
89     swapBuffers();
90 }
91 
TEST_P(BufferDataTest,ZeroNonNULLData)92 TEST_P(BufferDataTest, ZeroNonNULLData)
93 {
94     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
95     EXPECT_GL_NO_ERROR();
96 
97     char *zeroData = new char[0];
98     glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
99     EXPECT_GL_NO_ERROR();
100 
101     glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
102     EXPECT_GL_NO_ERROR();
103 
104     delete[] zeroData;
105 }
106 
TEST_P(BufferDataTest,NULLResolvedData)107 TEST_P(BufferDataTest, NULLResolvedData)
108 {
109     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
110     glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
111 
112     glUseProgram(mProgram);
113     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
114     glEnableVertexAttribArray(mAttribLocation);
115     glBindBuffer(GL_ARRAY_BUFFER, 0);
116 
117     drawQuad(mProgram, "position", 0.5f);
118 }
119 
120 // Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
121 // path.
TEST_P(BufferDataTest,RepeatedDrawWithDynamic)122 TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
123 {
124     std::vector<GLfloat> data;
125     for (int i = 0; i < 16; ++i)
126     {
127         data.push_back(static_cast<GLfloat>(i));
128     }
129 
130     glUseProgram(mProgram);
131     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
132     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
133     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
134     glBindBuffer(GL_ARRAY_BUFFER, 0);
135     glEnableVertexAttribArray(mAttribLocation);
136 
137     for (int drawCount = 0; drawCount < 40; ++drawCount)
138     {
139         drawQuad(mProgram, "position", 0.5f);
140     }
141 
142     EXPECT_GL_NO_ERROR();
143 }
144 
145 // Tests for a bug where vertex attribute translation was not being invalidated when switching to
146 // DYNAMIC
TEST_P(BufferDataTest,RepeatedDrawDynamicBug)147 TEST_P(BufferDataTest, RepeatedDrawDynamicBug)
148 {
149     // http://anglebug.com/2843: Seems to be an Intel driver bug.
150     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
151 
152     glUseProgram(mProgram);
153 
154     GLint positionLocation = glGetAttribLocation(mProgram, "position");
155     ASSERT_NE(-1, positionLocation);
156 
157     auto quadVertices = GetQuadVertices();
158     for (angle::Vector3 &vertex : quadVertices)
159     {
160         vertex.x() *= 1.0f;
161         vertex.y() *= 1.0f;
162         vertex.z() = 0.0f;
163     }
164 
165     // Set up quad vertices with DYNAMIC data
166     GLBuffer positionBuffer;
167     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
168     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
169                  GL_DYNAMIC_DRAW);
170     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
171     glEnableVertexAttribArray(positionLocation);
172     glBindBuffer(GL_ARRAY_BUFFER, 0);
173     EXPECT_GL_NO_ERROR();
174 
175     // Set up color data so red is drawn
176     std::vector<GLfloat> data(6, 1.0f);
177 
178     // Set data to DYNAMIC
179     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
180     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
181     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
182     glEnableVertexAttribArray(mAttribLocation);
183     EXPECT_GL_NO_ERROR();
184 
185     // Draw enough times to promote data to DIRECT mode
186     for (int i = 0; i < 20; i++)
187     {
188         glDrawArrays(GL_TRIANGLES, 0, 6);
189     }
190 
191     // Verify red was drawn
192     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
193 
194     // Set up color value so black is drawn
195     std::fill(data.begin(), data.end(), 0.0f);
196 
197     // Update the data, changing back to DYNAMIC mode.
198     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
199 
200     // This draw should produce a black quad
201     glDrawArrays(GL_TRIANGLES, 0, 6);
202     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
203     EXPECT_GL_NO_ERROR();
204 }
205 
206 class BufferSubDataTest : public ANGLETest
207 {
208   protected:
BufferSubDataTest()209     BufferSubDataTest()
210     {
211         setWindowWidth(16);
212         setWindowHeight(16);
213         setConfigRedBits(8);
214         setConfigGreenBits(8);
215         setConfigBlueBits(8);
216         setConfigAlphaBits(8);
217         setConfigDepthBits(24);
218 
219         mBuffer = 0;
220     }
221 
testSetUp()222     void testSetUp() override
223     {
224         glGenBuffers(1, &mBuffer);
225         ASSERT_NE(mBuffer, 0U);
226 
227         glClearColor(0, 0, 0, 0);
228         glClearDepthf(0.0);
229         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
230 
231         glDisable(GL_DEPTH_TEST);
232 
233         ASSERT_GL_NO_ERROR();
234     }
235 
testTearDown()236     void testTearDown() override { glDeleteBuffers(1, &mBuffer); }
237     GLuint mBuffer;
238 };
239 
240 // Test that updating a small index buffer after drawing with it works.
241 // In the Vulkan backend, the CPU may be used to perform this copy.
TEST_P(BufferSubDataTest,SmallIndexBufferUpdateAfterDraw)242 TEST_P(BufferSubDataTest, SmallIndexBufferUpdateAfterDraw)
243 {
244     constexpr std::array<GLfloat, 4> kRed   = {1.0f, 0.0f, 0.0f, 1.0f};
245     constexpr std::array<GLfloat, 4> kGreen = {0.0f, 1.0f, 0.0f, 1.0f};
246     // Index buffer data
247     GLuint indexData[] = {0, 1, 2, 0};
248     // Vertex buffer data fully cover the screen
249     float vertexData[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
250 
251     GLBuffer indexBuffer;
252     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
253     GLint vPos = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
254     ASSERT_NE(vPos, -1);
255     glUseProgram(program);
256     GLint colorUniformLocation =
257         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
258     ASSERT_NE(colorUniformLocation, -1);
259 
260     // Bind vertex buffer
261     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
262     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
263     glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
264     glEnableVertexAttribArray(vPos);
265 
266     // Bind index buffer
267     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
268     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_DYNAMIC_DRAW);
269 
270     glUniform4fv(colorUniformLocation, 1, kRed.data());
271     // Draw left red triangle
272     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
273     // Update the index buffer data.
274     indexData[1] = 1;
275     indexData[2] = 2;
276     indexData[3] = 3;
277     // Partial copy to trigger the buffer pool allocation
278     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint), 3 * sizeof(GLuint), &indexData[1]);
279     // Draw triangle with index (1, 2, 3).
280     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
281     // Update the index buffer again
282     indexData[0] = 0;
283     indexData[1] = 0;
284     indexData[2] = 2;
285     glUniform4fv(colorUniformLocation, 1, kGreen.data());
286     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 3 * sizeof(GLuint), &indexData[0]);
287     // Draw triangle with index (0, 2, 3), hope angle copy the last index 3 back.
288     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
289 
290     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
291     // Verify pixel top left corner is green
292     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
293 }
294 
295 // Test that updating a small index buffer after drawing with it works.
296 // In the Vulkan backend, the CPU may be used to perform this copy.
TEST_P(BufferSubDataTest,SmallVertexDataUpdateAfterDraw)297 TEST_P(BufferSubDataTest, SmallVertexDataUpdateAfterDraw)
298 {
299     constexpr std::array<GLfloat, 4> kGreen = {0.0f, 1.0f, 0.0f, 1.0f};
300     // Index buffer data
301     GLuint indexData[] = {0, 1, 2, 0};
302     // Vertex buffer data lower left triangle
303     // 2
304     //
305     // o    1
306     float vertexData1[] = {
307         -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
308     };
309     // Vertex buffer data upper right triangle
310     // 2      1
311     //
312     //        0
313     float vertexData2[] = {
314         1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
315     };
316     GLBuffer indexBuffer;
317     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
318     GLint vPos = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
319     ASSERT_NE(vPos, -1);
320     glUseProgram(program);
321     GLint colorUniformLocation =
322         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
323     ASSERT_NE(colorUniformLocation, -1);
324 
325     // Bind vertex buffer
326     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
327     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData1), vertexData1, GL_DYNAMIC_DRAW);
328     glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
329     glEnableVertexAttribArray(vPos);
330 
331     // Bind index buffer
332     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
333     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_DYNAMIC_DRAW);
334 
335     glUniform4fv(colorUniformLocation, 1, kGreen.data());
336     // Draw left red triangle
337     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
338     // Update the vertex buffer data.
339     // Partial copy to trigger the buffer pool allocation
340     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexData2), vertexData2);
341     // Draw triangle with index (0,1,2).
342     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
343     // Verify pixel corners are green
344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
345     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
346     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
347     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
348 }
349 class IndexedBufferCopyTest : public ANGLETest
350 {
351   protected:
IndexedBufferCopyTest()352     IndexedBufferCopyTest()
353     {
354         setWindowWidth(16);
355         setWindowHeight(16);
356         setConfigRedBits(8);
357         setConfigGreenBits(8);
358         setConfigBlueBits(8);
359         setConfigAlphaBits(8);
360         setConfigDepthBits(24);
361     }
362 
testSetUp()363     void testSetUp() override
364     {
365         constexpr char kVS[] = R"(attribute vec3 in_attrib;
366 varying vec3 v_attrib;
367 void main()
368 {
369     v_attrib = in_attrib;
370     gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
371     gl_PointSize = 100.0;
372 })";
373 
374         constexpr char kFS[] = R"(precision mediump float;
375 varying vec3 v_attrib;
376 void main()
377 {
378     gl_FragColor = vec4(v_attrib, 1);
379 })";
380 
381         glGenBuffers(2, mBuffers);
382         ASSERT_NE(mBuffers[0], 0U);
383         ASSERT_NE(mBuffers[1], 0U);
384 
385         glGenBuffers(1, &mElementBuffer);
386         ASSERT_NE(mElementBuffer, 0U);
387 
388         mProgram = CompileProgram(kVS, kFS);
389         ASSERT_NE(mProgram, 0U);
390 
391         mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
392         ASSERT_NE(mAttribLocation, -1);
393 
394         glClearColor(0, 0, 0, 0);
395         glDisable(GL_DEPTH_TEST);
396         glClear(GL_COLOR_BUFFER_BIT);
397 
398         ASSERT_GL_NO_ERROR();
399     }
400 
testTearDown()401     void testTearDown() override
402     {
403         glDeleteBuffers(2, mBuffers);
404         glDeleteBuffers(1, &mElementBuffer);
405         glDeleteProgram(mProgram);
406     }
407 
408     GLuint mBuffers[2];
409     GLuint mElementBuffer;
410     GLuint mProgram;
411     GLint mAttribLocation;
412 };
413 
414 // The following test covers an ANGLE bug where our index ranges
415 // weren't updated from CopyBufferSubData calls
416 // https://code.google.com/p/angleproject/issues/detail?id=709
TEST_P(IndexedBufferCopyTest,IndexRangeBug)417 TEST_P(IndexedBufferCopyTest, IndexRangeBug)
418 {
419     // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
420     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
421 
422     unsigned char vertexData[] = {255, 0, 0, 0, 0, 0};
423     unsigned int indexData[]   = {0, 1};
424 
425     glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
426     glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
427 
428     glUseProgram(mProgram);
429     glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, nullptr);
430     glEnableVertexAttribArray(mAttribLocation);
431 
432     ASSERT_GL_NO_ERROR();
433 
434     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
435     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
436 
437     glUseProgram(mProgram);
438 
439     ASSERT_GL_NO_ERROR();
440 
441     glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
442 
443     EXPECT_GL_NO_ERROR();
444     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
445 
446     glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
447     glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
448 
449     glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
450 
451     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
452 
453     ASSERT_GL_NO_ERROR();
454 
455     glClear(GL_COLOR_BUFFER_BIT);
456     EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
457 
458     unsigned char newData[] = {0, 255, 0};
459     glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
460 
461     glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
462 
463     EXPECT_GL_NO_ERROR();
464     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
465 }
466 
467 class BufferDataTestES3 : public BufferDataTest
468 {};
469 
470 // The following test covers an ANGLE bug where the buffer storage
471 // is not resized by Buffer11::getLatestBufferStorage when needed.
472 // https://code.google.com/p/angleproject/issues/detail?id=897
TEST_P(BufferDataTestES3,BufferResizing)473 TEST_P(BufferDataTestES3, BufferResizing)
474 {
475     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
476     ASSERT_GL_NO_ERROR();
477 
478     // Allocate a buffer with one byte
479     uint8_t singleByte[] = {0xaa};
480     glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
481 
482     // Resize the buffer
483     // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
484     // by chunks of pages instead of the minimum number of bytes needed.
485     const size_t numBytes = 4096 * 4;
486     glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
487 
488     // Copy the original data to the buffer
489     uint8_t srcBytes[numBytes];
490     for (size_t i = 0; i < numBytes; ++i)
491     {
492         srcBytes[i] = static_cast<uint8_t>(i);
493     }
494 
495     void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes,
496                                   GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
497 
498     ASSERT_GL_NO_ERROR();
499 
500     memcpy(dest, srcBytes, numBytes);
501     glUnmapBuffer(GL_ARRAY_BUFFER);
502 
503     EXPECT_GL_NO_ERROR();
504 
505     // Create a new buffer and copy the data to it
506     GLuint readBuffer;
507     glGenBuffers(1, &readBuffer);
508     glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
509     uint8_t zeros[numBytes];
510     for (size_t i = 0; i < numBytes; ++i)
511     {
512         zeros[i] = 0;
513     }
514     glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
515     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
516 
517     ASSERT_GL_NO_ERROR();
518 
519     // Read back the data and compare it to the original
520     uint8_t *data = reinterpret_cast<uint8_t *>(
521         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
522 
523     ASSERT_GL_NO_ERROR();
524 
525     for (size_t i = 0; i < numBytes; ++i)
526     {
527         EXPECT_EQ(srcBytes[i], data[i]);
528     }
529     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
530 
531     glDeleteBuffers(1, &readBuffer);
532 
533     EXPECT_GL_NO_ERROR();
534 }
535 
536 // Test to verify mapping a buffer after copying to it contains flushed/updated data
TEST_P(BufferDataTestES3,CopyBufferSubDataMapReadTest)537 TEST_P(BufferDataTestES3, CopyBufferSubDataMapReadTest)
538 {
539     const char simpleVertex[]   = R"(attribute vec2 position;
540 attribute vec4 color;
541 varying vec4 vColor;
542 void main()
543 {
544     gl_Position = vec4(position, 0, 1);
545     vColor = color;
546 }
547 )";
548     const char simpleFragment[] = R"(precision mediump float;
549 varying vec4 vColor;
550 void main()
551 {
552     gl_FragColor = vColor;
553 }
554 )";
555 
556     const uint32_t numComponents = 3;
557     const uint32_t width         = 4;
558     const uint32_t height        = 4;
559     const size_t numElements     = width * height * numComponents;
560     std::vector<uint8_t> srcData(numElements);
561     std::vector<uint8_t> dstData(numElements);
562 
563     for (uint8_t i = 0; i < srcData.size(); i++)
564     {
565         srcData[i] = 128;
566     }
567     for (uint8_t i = 0; i < dstData.size(); i++)
568     {
569         dstData[i] = 0;
570     }
571 
572     GLBuffer srcBuffer;
573     GLBuffer dstBuffer;
574 
575     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
576     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
577     ASSERT_GL_NO_ERROR();
578 
579     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
580     glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
581     ASSERT_GL_NO_ERROR();
582 
583     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
584     glUseProgram(program);
585 
586     GLint colorLoc = glGetAttribLocation(program, "color");
587     ASSERT_NE(-1, colorLoc);
588 
589     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
590     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
591     glEnableVertexAttribArray(colorLoc);
592 
593     drawQuad(program, "position", 0.5f, 1.0f, true);
594     ASSERT_GL_NO_ERROR();
595 
596     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
597 
598     // With GL_MAP_READ_BIT, we expect the data to be flushed and updated to match srcData
599     uint8_t *data = reinterpret_cast<uint8_t *>(
600         glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
601     EXPECT_GL_NO_ERROR();
602     for (size_t i = 0; i < numElements; ++i)
603     {
604         EXPECT_EQ(srcData[i], data[i]);
605     }
606     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
607     EXPECT_GL_NO_ERROR();
608 }
609 
610 // Test to verify mapping a buffer after copying to it contains expected data
611 // with GL_MAP_UNSYNCHRONIZED_BIT
TEST_P(BufferDataTestES3,MapBufferUnsynchronizedReadTest)612 TEST_P(BufferDataTestES3, MapBufferUnsynchronizedReadTest)
613 {
614     const char simpleVertex[]   = R"(attribute vec2 position;
615 attribute vec4 color;
616 varying vec4 vColor;
617 void main()
618 {
619     gl_Position = vec4(position, 0, 1);
620     vColor = color;
621 }
622 )";
623     const char simpleFragment[] = R"(precision mediump float;
624 varying vec4 vColor;
625 void main()
626 {
627     gl_FragColor = vColor;
628 }
629 )";
630 
631     const uint32_t numComponents = 3;
632     const uint32_t width         = 4;
633     const uint32_t height        = 4;
634     const size_t numElements     = width * height * numComponents;
635     std::vector<uint8_t> srcData(numElements);
636     std::vector<uint8_t> dstData(numElements);
637 
638     for (uint8_t i = 0; i < srcData.size(); i++)
639     {
640         srcData[i] = 128;
641     }
642     for (uint8_t i = 0; i < dstData.size(); i++)
643     {
644         dstData[i] = 0;
645     }
646 
647     GLBuffer srcBuffer;
648     GLBuffer dstBuffer;
649 
650     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
651     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
652     ASSERT_GL_NO_ERROR();
653 
654     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
655     glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
656     ASSERT_GL_NO_ERROR();
657 
658     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
659     glUseProgram(program);
660 
661     GLint colorLoc = glGetAttribLocation(program, "color");
662     ASSERT_NE(-1, colorLoc);
663 
664     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
665     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
666     glEnableVertexAttribArray(colorLoc);
667 
668     drawQuad(program, "position", 0.5f, 1.0f, true);
669     ASSERT_GL_NO_ERROR();
670 
671     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
672 
673     // Synchronize.
674     glFinish();
675 
676     // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data with srcData
677     uint8_t *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
678         GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
679     EXPECT_GL_NO_ERROR();
680     memcpy(data, srcData.data(), srcData.size());
681     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
682     EXPECT_GL_NO_ERROR();
683 
684     // Map without GL_MAP_UNSYNCHRONIZED_BIT and read data. We expect it to be srcData
685     data = reinterpret_cast<uint8_t *>(
686         glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
687     EXPECT_GL_NO_ERROR();
688     for (size_t i = 0; i < numElements; ++i)
689     {
690         EXPECT_EQ(srcData[i], data[i]);
691     }
692     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
693     EXPECT_GL_NO_ERROR();
694 }
695 
696 // Verify the functionality of glMapBufferRange()'s GL_MAP_UNSYNCHRONIZED_BIT
697 // NOTE: On Vulkan, if we ever use memory that's not `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`, then
698 // this could incorrectly pass.
TEST_P(BufferDataTestES3,MapBufferRangeUnsynchronizedBit)699 TEST_P(BufferDataTestES3, MapBufferRangeUnsynchronizedBit)
700 {
701     // We can currently only control the behavior of the Vulkan backend's synchronizing operation's
702     ANGLE_SKIP_TEST_IF(!IsVulkan());
703 
704     const size_t numElements = 10;
705     std::vector<uint8_t> srcData(numElements);
706     std::vector<uint8_t> dstData(numElements);
707 
708     for (uint8_t i = 0; i < srcData.size(); i++)
709     {
710         srcData[i] = i;
711     }
712     for (uint8_t i = 0; i < dstData.size(); i++)
713     {
714         dstData[i] = static_cast<uint8_t>(i + dstData.size());
715     }
716 
717     GLBuffer srcBuffer;
718     GLBuffer dstBuffer;
719 
720     glBindBuffer(GL_COPY_READ_BUFFER, srcBuffer);
721     ASSERT_GL_NO_ERROR();
722     glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
723     ASSERT_GL_NO_ERROR();
724 
725     glBufferData(GL_COPY_READ_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
726     ASSERT_GL_NO_ERROR();
727     glBufferData(GL_COPY_WRITE_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
728     ASSERT_GL_NO_ERROR();
729 
730     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numElements);
731 
732     // With GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be stale and match dstData
733     // NOTE: We are specifying GL_MAP_WRITE_BIT so we can use GL_MAP_UNSYNCHRONIZED_BIT. This is
734     // venturing into undefined behavior, since we are actually planning on reading from this
735     // pointer.
736     auto *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
737         GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
738     EXPECT_GL_NO_ERROR();
739     for (size_t i = 0; i < numElements; ++i)
740     {
741         // Allow for the possibility that data matches either "dstData" or "srcData"
742         if (dstData[i] != data[i])
743         {
744             EXPECT_EQ(srcData[i], data[i]);
745         }
746     }
747     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
748     EXPECT_GL_NO_ERROR();
749 
750     // Without GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be copied and match srcData
751     data = reinterpret_cast<uint8_t *>(
752         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_READ_BIT));
753     EXPECT_GL_NO_ERROR();
754     for (size_t i = 0; i < numElements; ++i)
755     {
756         EXPECT_EQ(srcData[i], data[i]);
757     }
758     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
759     EXPECT_GL_NO_ERROR();
760 }
761 
762 // Verify OES_mapbuffer is present if EXT_map_buffer_range is.
TEST_P(BufferDataTest,ExtensionDependency)763 TEST_P(BufferDataTest, ExtensionDependency)
764 {
765     if (IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
766     {
767         ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_mapbuffer"));
768     }
769 }
770 
771 // Test mapping with the OES extension.
TEST_P(BufferDataTest,MapBufferOES)772 TEST_P(BufferDataTest, MapBufferOES)
773 {
774     if (!IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
775     {
776         // Needed for test validation.
777         return;
778     }
779 
780     std::vector<uint8_t> data(1024);
781     FillVectorWithRandomUBytes(&data);
782 
783     GLBuffer buffer;
784     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
785     glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
786 
787     // Validate that other map flags don't work.
788     void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
789     EXPECT_EQ(nullptr, badMapPtr);
790     EXPECT_GL_ERROR(GL_INVALID_ENUM);
791 
792     // Map and write.
793     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
794     ASSERT_NE(nullptr, mapPtr);
795     ASSERT_GL_NO_ERROR();
796     memcpy(mapPtr, data.data(), data.size());
797     glUnmapBufferOES(GL_ARRAY_BUFFER);
798 
799     // Validate data with EXT_map_buffer_range
800     void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
801     ASSERT_NE(nullptr, readMapPtr);
802     ASSERT_GL_NO_ERROR();
803     std::vector<uint8_t> actualData(data.size());
804     memcpy(actualData.data(), readMapPtr, data.size());
805     glUnmapBufferOES(GL_ARRAY_BUFFER);
806 
807     EXPECT_EQ(data, actualData);
808 }
809 
810 // Test to verify mapping a dynamic buffer with GL_MAP_UNSYNCHRONIZED_BIT to modify a portion
811 // won't affect draw calls using other portions.
TEST_P(BufferDataTest,MapDynamicBufferUnsynchronizedEXTTest)812 TEST_P(BufferDataTest, MapDynamicBufferUnsynchronizedEXTTest)
813 {
814     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
815 
816     const char simpleVertex[]   = R"(attribute vec2 position;
817 attribute vec4 color;
818 varying vec4 vColor;
819 void main()
820 {
821     gl_Position = vec4(position, 0, 1);
822     vColor = color;
823 }
824 )";
825     const char simpleFragment[] = R"(precision mediump float;
826 varying vec4 vColor;
827 void main()
828 {
829     gl_FragColor = vColor;
830 }
831 )";
832 
833     constexpr int kNumVertices = 6;
834 
835     std::vector<GLubyte> color(8 * kNumVertices);
836     for (int i = 0; i < kNumVertices; ++i)
837     {
838         color[4 * i]     = 255;
839         color[4 * i + 3] = 255;
840     }
841     GLBuffer buffer;
842     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
843     glBufferData(GL_ARRAY_BUFFER, color.size(), color.data(), GL_DYNAMIC_DRAW);
844 
845     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
846     glUseProgram(program);
847 
848     GLint colorLoc = glGetAttribLocation(program, "color");
849     ASSERT_NE(-1, colorLoc);
850 
851     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
852     glEnableVertexAttribArray(colorLoc);
853 
854     glViewport(0, 0, 2, 2);
855     drawQuad(program, "position", 0.5f, 1.0f, true);
856     ASSERT_GL_NO_ERROR();
857 
858     // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data at offset 24
859     uint8_t *data = reinterpret_cast<uint8_t *>(
860         glMapBufferRangeEXT(GL_ARRAY_BUFFER, 4 * kNumVertices, 4 * kNumVertices,
861                             GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
862     EXPECT_GL_NO_ERROR();
863     for (int i = 0; i < kNumVertices; ++i)
864     {
865         data[4 * i]     = 0;
866         data[4 * i + 1] = 255;
867         data[4 * i + 2] = 0;
868         data[4 * i + 3] = 255;
869     }
870     glUnmapBufferOES(GL_ARRAY_BUFFER);
871     EXPECT_GL_NO_ERROR();
872 
873     // Re-draw using offset = 0 but to different viewport
874     glViewport(0, 2, 2, 2);
875     drawQuad(program, "position", 0.5f, 1.0f, true);
876     ASSERT_GL_NO_ERROR();
877 
878     // Change vertex attribute to use buffer starting from offset 24
879     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0,
880                           reinterpret_cast<void *>(4 * kNumVertices));
881 
882     glViewport(2, 2, 2, 2);
883     drawQuad(program, "position", 0.5f, 1.0f, true);
884     ASSERT_GL_NO_ERROR();
885 
886     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
887     EXPECT_PIXEL_COLOR_EQ(1, 3, GLColor::red);
888     EXPECT_PIXEL_COLOR_EQ(3, 3, GLColor::green);
889 }
890 
891 // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
892 // data, using drawQuad().
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawQuad)893 TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawQuad)
894 {
895     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
896 
897     std::vector<GLfloat> data(6, 0.0f);
898 
899     glUseProgram(mProgram);
900     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
901     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
902     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
903     glEnableVertexAttribArray(mAttribLocation);
904 
905     // Don't read back to verify black, so we don't break the render pass.
906     drawQuad(mProgram, "position", 0.5f);
907     EXPECT_GL_NO_ERROR();
908 
909     // Map and write.
910     std::vector<GLfloat> data2(6, 1.0f);
911     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
912     ASSERT_NE(nullptr, mapPtr);
913     ASSERT_GL_NO_ERROR();
914     memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
915     glUnmapBufferOES(GL_ARRAY_BUFFER);
916 
917     drawQuad(mProgram, "position", 0.5f);
918     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
919     EXPECT_GL_NO_ERROR();
920 }
921 
922 // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
923 // data, calling glDrawArrays() directly.
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawArrays)924 TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawArrays)
925 {
926     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
927 
928     std::vector<GLfloat> data(6, 0.0f);
929 
930     glUseProgram(mProgram);
931 
932     GLint positionLocation = glGetAttribLocation(mProgram, "position");
933     ASSERT_NE(-1, positionLocation);
934 
935     // Set up position attribute, don't use drawQuad.
936     auto quadVertices = GetQuadVertices();
937 
938     GLBuffer positionBuffer;
939     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
940     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
941                  GL_DYNAMIC_DRAW);
942     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
943     glEnableVertexAttribArray(positionLocation);
944     EXPECT_GL_NO_ERROR();
945 
946     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
947     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
948     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
949     glEnableVertexAttribArray(mAttribLocation);
950     EXPECT_GL_NO_ERROR();
951 
952     // Don't read back to verify black, so we don't break the render pass.
953     glDrawArrays(GL_TRIANGLES, 0, 6);
954     EXPECT_GL_NO_ERROR();
955 
956     // Map and write.
957     std::vector<GLfloat> data2(6, 1.0f);
958     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
959     ASSERT_NE(nullptr, mapPtr);
960     ASSERT_GL_NO_ERROR();
961     memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
962     glUnmapBufferOES(GL_ARRAY_BUFFER);
963 
964     glDrawArrays(GL_TRIANGLES, 0, 6);
965     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
966     EXPECT_GL_NO_ERROR();
967 }
968 
969 // Verify that buffer sub data uploads are properly validated within the buffer size range on 32-bit
970 // systems.
TEST_P(BufferDataTest,BufferSizeValidation32Bit)971 TEST_P(BufferDataTest, BufferSizeValidation32Bit)
972 {
973     GLBuffer buffer;
974     glBindBuffer(GL_ARRAY_BUFFER, buffer);
975     glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
976 
977     GLubyte data = 0;
978     glBufferSubData(GL_ARRAY_BUFFER, std::numeric_limits<uint32_t>::max(), 1, &data);
979     EXPECT_GL_ERROR(GL_INVALID_VALUE);
980 }
981 
982 // Tests a null crash bug caused by copying from null back-end buffer pointer
983 // when calling bufferData again after drawing without calling bufferData in D3D11.
TEST_P(BufferDataTestES3,DrawWithNotCallingBufferData)984 TEST_P(BufferDataTestES3, DrawWithNotCallingBufferData)
985 {
986     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
987     glUseProgram(drawRed);
988 
989     GLint mem = 0;
990     GLBuffer buffer;
991     glBindBuffer(GL_ARRAY_BUFFER, buffer);
992     glEnableVertexAttribArray(0);
993     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
994     glDrawArrays(GL_TRIANGLES, 0, 3);
995     glBindBuffer(GL_COPY_WRITE_BUFFER, buffer);
996     glBufferData(GL_COPY_WRITE_BUFFER, 1, &mem, GL_STREAM_DRAW);
997     ASSERT_GL_NO_ERROR();
998 }
999 
1000 // Tests a bug where copying buffer data immediately after creation hit a nullptr in D3D11.
TEST_P(BufferDataTestES3,NoBufferInitDataCopyBug)1001 TEST_P(BufferDataTestES3, NoBufferInitDataCopyBug)
1002 {
1003     constexpr GLsizei size = 64;
1004 
1005     GLBuffer sourceBuffer;
1006     glBindBuffer(GL_COPY_READ_BUFFER, sourceBuffer);
1007     glBufferData(GL_COPY_READ_BUFFER, size, nullptr, GL_STATIC_DRAW);
1008 
1009     GLBuffer destBuffer;
1010     glBindBuffer(GL_ARRAY_BUFFER, destBuffer);
1011     glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
1012 
1013     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ARRAY_BUFFER, 0, 0, size);
1014     ASSERT_GL_NO_ERROR();
1015 }
1016 
1017 // Ensures that calling glBufferData on a mapped buffer results in an unmapped buffer
TEST_P(BufferDataTestES3,BufferDataUnmap)1018 TEST_P(BufferDataTestES3, BufferDataUnmap)
1019 {
1020     // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
1021     // BufferData happens on a mapped buffer:
1022     //
1023     //    If any portion of the buffer object is mapped in the current context or
1024     //    any context current to another thread, it is as though UnmapBuffer
1025     //    (see section 2.10.3) is executed in each such context prior to deleting
1026     //    the existing data store.
1027     //
1028 
1029     std::vector<uint8_t> data1(16);
1030     std::vector<uint8_t> data2(16);
1031 
1032     GLBuffer dataBuffer;
1033     glBindBuffer(GL_ARRAY_BUFFER, dataBuffer);
1034     glBufferData(GL_ARRAY_BUFFER, data1.size(), data1.data(), GL_STATIC_DRAW);
1035 
1036     // Map the buffer once
1037     glMapBufferRange(GL_ARRAY_BUFFER, 0, data1.size(),
1038                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
1039                          GL_MAP_UNSYNCHRONIZED_BIT);
1040 
1041     // Then repopulate the buffer. This should cause the buffer to become unmapped.
1042     glBufferData(GL_ARRAY_BUFFER, data2.size(), data2.data(), GL_STATIC_DRAW);
1043     ASSERT_GL_NO_ERROR();
1044 
1045     // Try to unmap the buffer, this should fail
1046     bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
1047     ASSERT_EQ(result, false);
1048     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1049 
1050     // Try to map the buffer again, which should succeed
1051     glMapBufferRange(GL_ARRAY_BUFFER, 0, data2.size(),
1052                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
1053                          GL_MAP_UNSYNCHRONIZED_BIT);
1054     ASSERT_GL_NO_ERROR();
1055 }
1056 
1057 // Ensures that mapping buffer with GL_MAP_INVALIDATE_BUFFER_BIT followed by glBufferSubData calls
1058 // works.  Regression test for the Vulkan backend where that flag caused use after free.
TEST_P(BufferDataTestES3,MapInvalidateThenBufferSubData)1059 TEST_P(BufferDataTestES3, MapInvalidateThenBufferSubData)
1060 {
1061     // http://anglebug.com/5984
1062     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsIntel());
1063 
1064     // http://anglebug.com/5985
1065     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1066 
1067     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
1068                                                  GLColor::red};
1069     const std::array<GLColor, 4> kUpdateData1 = {GLColor::white, GLColor::white, GLColor::white,
1070                                                  GLColor::white};
1071     const std::array<GLColor, 4> kUpdateData2 = {GLColor::blue, GLColor::blue, GLColor::blue,
1072                                                  GLColor::blue};
1073 
1074     GLBuffer buffer;
1075     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
1076     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1077     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
1078     EXPECT_GL_NO_ERROR();
1079 
1080     // Draw
1081     constexpr char kVerifyUBO[] = R"(#version 300 es
1082 precision mediump float;
1083 uniform block {
1084     uvec4 data;
1085 } ubo;
1086 uniform uint expect;
1087 uniform vec4 successOutput;
1088 out vec4 colorOut;
1089 void main()
1090 {
1091     if (all(equal(ubo.data, uvec4(expect))))
1092         colorOut = successOutput;
1093     else
1094         colorOut = vec4(1.0, 0, 0, 1.0);
1095 })";
1096 
1097     ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
1098     glUseProgram(verifyUbo);
1099 
1100     GLint expectLoc = glGetUniformLocation(verifyUbo, "expect");
1101     EXPECT_NE(-1, expectLoc);
1102     GLint successLoc = glGetUniformLocation(verifyUbo, "successOutput");
1103     EXPECT_NE(-1, successLoc);
1104 
1105     glUniform1ui(expectLoc, kInitialData[0].asUint());
1106     glUniform4f(successLoc, 0, 1, 0, 1);
1107 
1108     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1109     EXPECT_GL_NO_ERROR();
1110 
1111     // Dont't verify the buffer.  This is testing GL_MAP_INVALIDATE_BUFFER_BIT while the buffer is
1112     // in use by the GPU.
1113 
1114     // Map the buffer and update it.
1115     void *mappedBuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData),
1116                                           GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
1117 
1118     memcpy(mappedBuffer, kUpdateData1.data(), sizeof(kInitialData));
1119 
1120     glUnmapBuffer(GL_UNIFORM_BUFFER);
1121     EXPECT_GL_NO_ERROR();
1122 
1123     // Verify that the buffer has the updated value.
1124     glUniform1ui(expectLoc, kUpdateData1[0].asUint());
1125     glUniform4f(successLoc, 0, 0, 1, 1);
1126 
1127     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1128     EXPECT_GL_NO_ERROR();
1129 
1130     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1131 
1132     // Update the buffer with glBufferSubData
1133     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData2), kUpdateData2.data());
1134     EXPECT_GL_NO_ERROR();
1135 
1136     // Verify that the buffer has the updated value.
1137     glUniform1ui(expectLoc, kUpdateData2[0].asUint());
1138     glUniform4f(successLoc, 0, 1, 1, 1);
1139 
1140     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1141     EXPECT_GL_NO_ERROR();
1142 
1143     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
1144 }
1145 
1146 // Verify that previous draws are not affected when a buffer is respecified with null data
1147 // and updated by calling map.
TEST_P(BufferDataTestES3,BufferDataWithNullFollowedByMap)1148 TEST_P(BufferDataTestES3, BufferDataWithNullFollowedByMap)
1149 {
1150     // Draw without using drawQuad.
1151     glUseProgram(mProgram);
1152 
1153     // Set up position attribute
1154     const auto &quadVertices = GetQuadVertices();
1155     GLint positionLocation   = glGetAttribLocation(mProgram, "position");
1156     ASSERT_NE(-1, positionLocation);
1157     GLBuffer positionBuffer;
1158     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1159     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
1160                  GL_DYNAMIC_DRAW);
1161     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1162     glEnableVertexAttribArray(positionLocation);
1163     EXPECT_GL_NO_ERROR();
1164 
1165     // Set up "in_attrib" attribute
1166     const std::vector<GLfloat> kData(6, 1.0f);
1167     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1168     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * kData.size(), kData.data(), GL_STATIC_DRAW);
1169     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1170     glEnableVertexAttribArray(mAttribLocation);
1171     EXPECT_GL_NO_ERROR();
1172 
1173     // This draw (draw_0) renders red to the entire window.
1174     glDrawArrays(GL_TRIANGLES, 0, 6);
1175     EXPECT_GL_NO_ERROR();
1176 
1177     // Respecify buffer bound to "in_attrib" attribute then map it and fill it with zeroes.
1178     const std::vector<GLfloat> kZeros(6, 0.0f);
1179     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * kZeros.size(), nullptr, GL_STATIC_DRAW);
1180     uint8_t *mapPtr = reinterpret_cast<uint8_t *>(
1181         glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * kZeros.size(),
1182                          GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
1183     ASSERT_NE(nullptr, mapPtr);
1184     ASSERT_GL_NO_ERROR();
1185     memcpy(mapPtr, kZeros.data(), sizeof(GLfloat) * kZeros.size());
1186     glUnmapBuffer(GL_ARRAY_BUFFER);
1187     ASSERT_GL_NO_ERROR();
1188 
1189     // This draw (draw_1) renders black to the upper right triangle.
1190     glDrawArrays(GL_TRIANGLES, 3, 3);
1191     EXPECT_GL_NO_ERROR();
1192 
1193     // Respecification and data update of mBuffer should not have affected draw_0.
1194     // Expect bottom left to be red and top right to be black.
1195     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
1196     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::black);
1197     EXPECT_GL_NO_ERROR();
1198 }
1199 
1200 class BufferStorageTestES3 : public BufferDataTest
1201 {};
1202 
1203 // Tests that proper error value is returned when bad size is passed in
TEST_P(BufferStorageTestES3,BufferStorageInvalidSize)1204 TEST_P(BufferStorageTestES3, BufferStorageInvalidSize)
1205 {
1206     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1207 
1208     std::vector<GLfloat> data(6, 1.0f);
1209 
1210     GLBuffer buffer;
1211     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1212     glBufferStorageEXT(GL_ARRAY_BUFFER, 0, data.data(), 0);
1213     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1214 }
1215 
1216 // Tests that buffer storage can be allocated with the GL_MAP_PERSISTENT_BIT_EXT and
1217 // GL_MAP_COHERENT_BIT_EXT flags
TEST_P(BufferStorageTestES3,BufferStorageFlagsPersistentCoherentWrite)1218 TEST_P(BufferStorageTestES3, BufferStorageFlagsPersistentCoherentWrite)
1219 {
1220     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1221 
1222     std::vector<GLfloat> data(6, 1.0f);
1223 
1224     GLBuffer buffer;
1225     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1226     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), data.data(),
1227                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1228     ASSERT_GL_NO_ERROR();
1229 }
1230 
1231 // Verify that glBufferStorage makes a buffer immutable
TEST_P(BufferStorageTestES3,StorageBufferBufferData)1232 TEST_P(BufferStorageTestES3, StorageBufferBufferData)
1233 {
1234     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1235                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1236 
1237     std::vector<GLfloat> data(6, 1.0f);
1238 
1239     GLBuffer buffer;
1240     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1241     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1242     ASSERT_GL_NO_ERROR();
1243 
1244     // Verify that calling glBufferStorageEXT again produces an error.
1245     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1246     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1247 
1248     // Verify that calling glBufferData after calling glBufferStorageEXT produces an error.
1249     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1250     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1251 }
1252 
1253 // Verify that glBufferStorageEXT can be called after glBufferData
TEST_P(BufferStorageTestES3,BufferDataStorageBuffer)1254 TEST_P(BufferStorageTestES3, BufferDataStorageBuffer)
1255 {
1256     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1257                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1258 
1259     std::vector<GLfloat> data(6, 1.0f);
1260 
1261     GLBuffer buffer;
1262     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1263     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1264     ASSERT_GL_NO_ERROR();
1265 
1266     // Verify that calling glBufferStorageEXT again produces an error.
1267     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1268     ASSERT_GL_NO_ERROR();
1269 }
1270 
1271 // Verify that we can perform subdata updates to a buffer marked with GL_DYNAMIC_STORAGE_BIT_EXT
1272 // usage flag
TEST_P(BufferStorageTestES3,StorageBufferSubData)1273 TEST_P(BufferStorageTestES3, StorageBufferSubData)
1274 {
1275     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1276                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1277 
1278     std::vector<GLfloat> data(6, 0.0f);
1279 
1280     glUseProgram(mProgram);
1281     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1282     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr,
1283                        GL_DYNAMIC_STORAGE_BIT_EXT);
1284     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data.size(), data.data());
1285     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1286     glEnableVertexAttribArray(mAttribLocation);
1287 
1288     drawQuad(mProgram, "position", 0.5f);
1289     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::black);
1290     EXPECT_GL_NO_ERROR();
1291 
1292     std::vector<GLfloat> data2(6, 1.0f);
1293     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data2.size(), data2.data());
1294 
1295     drawQuad(mProgram, "position", 0.5f);
1296     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1297     EXPECT_GL_NO_ERROR();
1298 }
1299 
1300 // Test interaction between GL_OES_mapbuffer and GL_EXT_buffer_storage extensions.
TEST_P(BufferStorageTestES3,StorageBufferMapBufferOES)1301 TEST_P(BufferStorageTestES3, StorageBufferMapBufferOES)
1302 {
1303     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1304                        !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1305                        !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1306 
1307     std::vector<uint8_t> data(1024);
1308     FillVectorWithRandomUBytes(&data);
1309 
1310     GLBuffer buffer;
1311     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1312     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
1313 
1314     // Validate that other map flags don't work.
1315     void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
1316     EXPECT_EQ(nullptr, badMapPtr);
1317     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1318 
1319     // Map and write.
1320     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
1321     ASSERT_NE(nullptr, mapPtr);
1322     ASSERT_GL_NO_ERROR();
1323     memcpy(mapPtr, data.data(), data.size());
1324     glUnmapBufferOES(GL_ARRAY_BUFFER);
1325 
1326     // Validate data with EXT_map_buffer_range
1327     void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
1328     ASSERT_NE(nullptr, readMapPtr);
1329     ASSERT_GL_NO_ERROR();
1330     std::vector<uint8_t> actualData(data.size());
1331     memcpy(actualData.data(), readMapPtr, data.size());
1332     glUnmapBufferOES(GL_ARRAY_BUFFER);
1333 
1334     EXPECT_EQ(data, actualData);
1335 }
1336 
1337 // Verify persistently mapped buffers can use glCopyBufferSubData
1338 // Tests a pattern used by Fortnite's GLES backend
TEST_P(BufferStorageTestES3,StorageCopyBufferSubDataMapped)1339 TEST_P(BufferStorageTestES3, StorageCopyBufferSubDataMapped)
1340 {
1341     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1342                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1343 
1344     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::green, GLColor::blue,
1345                                                  GLColor::yellow};
1346 
1347     // Set up the read buffer
1348     GLBuffer readBuffer;
1349     glBindBuffer(GL_ARRAY_BUFFER, readBuffer.get());
1350     glBufferData(GL_ARRAY_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1351 
1352     // Set up the write buffer to be persistently mapped
1353     GLBuffer writeBuffer;
1354     glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
1355     glBufferStorageEXT(GL_COPY_WRITE_BUFFER, 16, nullptr,
1356                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1357     void *readMapPtr =
1358         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, 16,
1359                          GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1360     ASSERT_NE(nullptr, readMapPtr);
1361     ASSERT_GL_NO_ERROR();
1362 
1363     // Verify we can copy into the write buffer
1364     glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
1365     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, 16);
1366     ASSERT_GL_NO_ERROR();
1367 
1368     // Flush the buffer.
1369     glFinish();
1370 
1371     // Check the contents
1372     std::array<GLColor, 4> resultingData;
1373     memcpy(resultingData.data(), readMapPtr, resultingData.size() * sizeof(GLColor));
1374     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
1375     EXPECT_EQ(kInitialData, resultingData);
1376     ASSERT_GL_NO_ERROR();
1377 }
1378 
1379 // Verify persistently mapped element array buffers can use glDrawElements
TEST_P(BufferStorageTestES3,DrawElementsElementArrayBufferMapped)1380 TEST_P(BufferStorageTestES3, DrawElementsElementArrayBufferMapped)
1381 {
1382     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1383                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1384 
1385     GLfloat kVertexBuffer[] = {-1.0f, -1.0f, 1.0f,  // (x, y, R)
1386                                -1.0f, 1.0f,  1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
1387     // Set up array buffer
1388     GLBuffer readBuffer;
1389     glBindBuffer(GL_ARRAY_BUFFER, readBuffer.get());
1390     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexBuffer), kVertexBuffer, GL_DYNAMIC_DRAW);
1391     GLint vLoc = glGetAttribLocation(mProgram, "position");
1392     GLint cLoc = mAttribLocation;
1393     glVertexAttribPointer(vLoc, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
1394     glEnableVertexAttribArray(vLoc);
1395     glVertexAttribPointer(cLoc, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const GLvoid *)8);
1396     glEnableVertexAttribArray(cLoc);
1397 
1398     // Set up the element array buffer to be persistently mapped
1399     GLshort kElementArrayBuffer[] = {0, 0, 0, 0, 0, 0};
1400 
1401     GLBuffer indexBuffer;
1402     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1403     glBufferStorageEXT(GL_ELEMENT_ARRAY_BUFFER, sizeof(kElementArrayBuffer), kElementArrayBuffer,
1404                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1405                            GL_MAP_COHERENT_BIT_EXT);
1406 
1407     glUseProgram(mProgram);
1408 
1409     glClearColor(0, 0, 0, 0);
1410     glClear(GL_COLOR_BUFFER_BIT);
1411 
1412     glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1413     ASSERT_GL_NO_ERROR();
1414     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1415 
1416     GLshort *mappedPtr = (GLshort *)glMapBufferRange(
1417         GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(kElementArrayBuffer),
1418         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1419     ASSERT_NE(nullptr, mappedPtr);
1420     ASSERT_GL_NO_ERROR();
1421 
1422     mappedPtr[0] = 0;
1423     mappedPtr[1] = 1;
1424     mappedPtr[2] = 2;
1425     mappedPtr[3] = 2;
1426     mappedPtr[4] = 1;
1427     mappedPtr[5] = 3;
1428     glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1429 
1430     glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
1431 
1432     ASSERT_GL_NO_ERROR();
1433 
1434     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1435 }
1436 
1437 // Test that maps a coherent buffer storage and does not call glUnmapBuffer.
TEST_P(BufferStorageTestES3,NoUnmap)1438 TEST_P(BufferStorageTestES3, NoUnmap)
1439 {
1440     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1441                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1442 
1443     GLsizei size = sizeof(GLfloat) * 128;
1444 
1445     GLBuffer buffer;
1446     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1447     glBufferStorageEXT(GL_ARRAY_BUFFER, size, nullptr,
1448                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1449                            GL_MAP_COHERENT_BIT_EXT);
1450 
1451     GLshort *mappedPtr = (GLshort *)glMapBufferRange(
1452         GL_ARRAY_BUFFER, 0, size,
1453         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1454     ASSERT_NE(nullptr, mappedPtr);
1455 
1456     ASSERT_GL_NO_ERROR();
1457 }
1458 
1459 // Test that we are able to perform glTex*D calls while a pixel unpack buffer is bound
1460 // and persistently mapped.
TEST_P(BufferStorageTestES3,TexImage2DPixelUnpackBufferMappedPersistently)1461 TEST_P(BufferStorageTestES3, TexImage2DPixelUnpackBufferMappedPersistently)
1462 {
1463     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1464                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1465 
1466     std::vector<uint8_t> data(64);
1467     FillVectorWithRandomUBytes(&data);
1468 
1469     GLBuffer buffer;
1470     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.get());
1471     glBufferStorageEXT(GL_PIXEL_UNPACK_BUFFER, data.size(), data.data(),
1472                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1473 
1474     // Map the buffer.
1475     void *mapPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, data.size(),
1476                                     GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1477     ASSERT_NE(nullptr, mapPtr);
1478     ASSERT_GL_NO_ERROR();
1479 
1480     // Create a 2D texture and fill it using the persistenly mapped unpack buffer
1481     GLTexture tex;
1482     glBindTexture(GL_TEXTURE_2D, tex);
1483 
1484     constexpr GLsizei kTextureWidth  = 4;
1485     constexpr GLsizei kTextureHeight = 4;
1486     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTextureWidth, kTextureHeight, 0, GL_RGBA,
1487                  GL_UNSIGNED_BYTE, 0);
1488     ASSERT_GL_NO_ERROR();
1489 
1490     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1491     ASSERT_GL_NO_ERROR();
1492 }
1493 
1494 // Verify persistently mapped buffers can use glBufferSubData
TEST_P(BufferStorageTestES3,StorageBufferSubDataMapped)1495 TEST_P(BufferStorageTestES3, StorageBufferSubDataMapped)
1496 {
1497     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1498                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1499 
1500     const std::array<GLColor, 4> kUpdateData1 = {GLColor::red, GLColor::green, GLColor::blue,
1501                                                  GLColor::yellow};
1502 
1503     // Set up the buffer to be persistently mapped and dynamic
1504     GLBuffer buffer;
1505     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1506     glBufferStorageEXT(GL_ARRAY_BUFFER, 16, nullptr,
1507                        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1508                            GL_MAP_COHERENT_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
1509     void *readMapPtr = glMapBufferRange(
1510         GL_ARRAY_BUFFER, 0, 16,
1511         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1512     ASSERT_NE(nullptr, readMapPtr);
1513     ASSERT_GL_NO_ERROR();
1514 
1515     // Verify we can push new data into the buffer
1516     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * kUpdateData1.size(), kUpdateData1.data());
1517     ASSERT_GL_NO_ERROR();
1518 
1519     // Flush the buffer.
1520     glFinish();
1521 
1522     // Check the contents
1523     std::array<GLColor, 4> persistentData1;
1524     memcpy(persistentData1.data(), readMapPtr, persistentData1.size() * sizeof(GLColor));
1525     EXPECT_EQ(kUpdateData1, persistentData1);
1526     glUnmapBuffer(GL_ARRAY_BUFFER);
1527     ASSERT_GL_NO_ERROR();
1528 }
1529 
1530 // Verify that persistently mapped coherent buffers can be used as uniform buffers,
1531 // and written to by using the pointer from glMapBufferRange.
TEST_P(BufferStorageTestES3,UniformBufferMapped)1532 TEST_P(BufferStorageTestES3, UniformBufferMapped)
1533 {
1534     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1535                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1536 
1537     const char *mkFS = R"(#version 300 es
1538 precision highp float;
1539 uniform uni { vec4 color; };
1540 out vec4 fragColor;
1541 void main()
1542 {
1543     fragColor = color;
1544 })";
1545 
1546     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), mkFS);
1547     ASSERT_NE(program, 0u);
1548 
1549     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
1550     ASSERT_NE(uniformBufferIndex, -1);
1551 
1552     GLBuffer uniformBuffer;
1553 
1554     ASSERT_GL_NO_ERROR();
1555 
1556     glViewport(0, 0, getWindowWidth(), getWindowHeight());
1557     glClear(GL_COLOR_BUFFER_BIT);
1558 
1559     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer.get());
1560 
1561     glBufferStorageEXT(GL_UNIFORM_BUFFER, sizeof(float) * 4, nullptr,
1562                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1563 
1564     float *mapPtr = static_cast<float *>(
1565         glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4,
1566                          GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1567                              GL_MAP_COHERENT_BIT_EXT));
1568 
1569     ASSERT_NE(mapPtr, nullptr);
1570 
1571     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer.get());
1572 
1573     glUniformBlockBinding(program, uniformBufferIndex, 0);
1574 
1575     mapPtr[0] = 0.5f;
1576     mapPtr[1] = 0.75f;
1577     mapPtr[2] = 0.25f;
1578     mapPtr[3] = 1.0f;
1579 
1580     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1581 
1582     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
1583 
1584     glUnmapBuffer(GL_UNIFORM_BUFFER);
1585 
1586     glDeleteProgram(program);
1587 
1588     ASSERT_GL_NO_ERROR();
1589 }
1590 
1591 // Verify that persistently mapped coherent buffers can be used as vertex array buffers,
1592 // and written to by using the pointer from glMapBufferRange.
TEST_P(BufferStorageTestES3,VertexBufferMapped)1593 TEST_P(BufferStorageTestES3, VertexBufferMapped)
1594 {
1595     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1596                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1597 
1598     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
1599     ASSERT_NE(program, 0u);
1600 
1601     glUseProgram(program);
1602 
1603     auto quadVertices = GetQuadVertices();
1604 
1605     size_t bufferSize = sizeof(GLfloat) * quadVertices.size() * 3;
1606 
1607     GLBuffer positionBuffer;
1608     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer.get());
1609 
1610     glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
1611                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1612                            GL_MAP_COHERENT_BIT_EXT);
1613 
1614     GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
1615     ASSERT_NE(-1, positionLocation);
1616     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1617     glEnableVertexAttribArray(positionLocation);
1618 
1619     void *mappedPtr =
1620         glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize,
1621                          GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1622     ASSERT_NE(nullptr, mappedPtr);
1623 
1624     memcpy(mappedPtr, reinterpret_cast<void *>(quadVertices.data()), bufferSize);
1625 
1626     glDrawArrays(GL_TRIANGLES, 0, quadVertices.size());
1627     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1628 
1629     glUnmapBuffer(GL_ARRAY_BUFFER);
1630     glDeleteProgram(program);
1631 
1632     EXPECT_GL_NO_ERROR();
1633 }
1634 
TestPageSharingBuffers(std::function<void (void)> swapCallback,size_t bufferSize,const std::array<Vector3,6> & quadVertices,GLint positionLocation)1635 void TestPageSharingBuffers(std::function<void(void)> swapCallback,
1636                             size_t bufferSize,
1637                             const std::array<Vector3, 6> &quadVertices,
1638                             GLint positionLocation)
1639 {
1640     size_t dataSize = sizeof(GLfloat) * quadVertices.size() * 3;
1641 
1642     if (bufferSize == 0)
1643     {
1644         bufferSize = dataSize;
1645     }
1646 
1647     constexpr size_t bufferCount = 10;
1648 
1649     std::vector<GLBuffer> buffers(bufferCount);
1650     std::vector<void *> mapPointers(bufferCount);
1651 
1652     // Init and map
1653     for (uint32_t i = 0; i < bufferCount; i++)
1654     {
1655         glBindBuffer(GL_ARRAY_BUFFER, buffers[i].get());
1656 
1657         glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
1658                            GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT |
1659                                GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1660 
1661         glEnableVertexAttribArray(positionLocation);
1662 
1663         mapPointers[i] = glMapBufferRange(
1664             GL_ARRAY_BUFFER, 0, bufferSize,
1665             GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1666         ASSERT_NE(nullptr, mapPointers[i]);
1667     }
1668 
1669     // Write, draw and unmap
1670     for (uint32_t i = 0; i < bufferCount; i++)
1671     {
1672         memcpy(mapPointers[i], reinterpret_cast<const void *>(quadVertices.data()), dataSize);
1673 
1674         // Write something to last float
1675         if (bufferSize > dataSize + sizeof(GLfloat))
1676         {
1677             size_t lastPosition = bufferSize / sizeof(GLfloat) - 1;
1678             reinterpret_cast<float *>(mapPointers[i])[lastPosition] = 1.0f;
1679         }
1680 
1681         glBindBuffer(GL_ARRAY_BUFFER, buffers[i].get());
1682         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1683         glDrawArrays(GL_TRIANGLES, 0, quadVertices.size());
1684         EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1685         swapCallback();
1686         glUnmapBuffer(GL_ARRAY_BUFFER);
1687     }
1688 }
1689 
1690 // Create multiple persistently mapped coherent buffers of different sizes that will likely share a
1691 // page. Map all buffers together and unmap each buffer after writing to it and using it for a draw.
1692 // This tests the behaviour of the coherent buffer tracker in frame capture when buffers that share
1693 // a page are written to after the other one is removed.
TEST_P(BufferStorageTestES3,PageSharingBuffers)1694 TEST_P(BufferStorageTestES3, PageSharingBuffers)
1695 {
1696     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1697                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1698 
1699     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
1700     ASSERT_NE(program, 0u);
1701 
1702     glUseProgram(program);
1703 
1704     auto quadVertices = GetQuadVertices();
1705 
1706     std::function<void(void)> swapCallback = [this]() { swapBuffers(); };
1707 
1708     GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
1709     ASSERT_NE(-1, positionLocation);
1710 
1711     TestPageSharingBuffers(swapCallback, 0, quadVertices, positionLocation);
1712     TestPageSharingBuffers(swapCallback, 1000, quadVertices, positionLocation);
1713     TestPageSharingBuffers(swapCallback, 4096, quadVertices, positionLocation);
1714     TestPageSharingBuffers(swapCallback, 6144, quadVertices, positionLocation);
1715     TestPageSharingBuffers(swapCallback, 40960, quadVertices, positionLocation);
1716 
1717     glDeleteProgram(program);
1718 
1719     EXPECT_GL_NO_ERROR();
1720 }
1721 
1722 class BufferStorageTestES3Threaded : public ANGLETest
1723 {
1724   protected:
BufferStorageTestES3Threaded()1725     BufferStorageTestES3Threaded()
1726     {
1727         setWindowWidth(16);
1728         setWindowHeight(16);
1729         setConfigRedBits(8);
1730         setConfigGreenBits(8);
1731         setConfigBlueBits(8);
1732         setConfigAlphaBits(8);
1733         setConfigDepthBits(24);
1734 
1735         mProgram = 0;
1736     }
1737 
testSetUp()1738     void testSetUp() override
1739     {
1740         constexpr char kVS[] = R"(#version 300 es
1741 
1742 in vec4 position;
1743 in vec4 color;
1744 out vec4 out_color;
1745 
1746 void main()
1747 {
1748     out_color = color;
1749     gl_Position = position;
1750 })";
1751 
1752         constexpr char kFS[] = R"(#version 300 es
1753 precision highp float;
1754 
1755 in vec4 out_color;
1756 out vec4 fragColor;
1757 
1758 void main()
1759 {
1760     fragColor = vec4(out_color);
1761 })";
1762 
1763         mProgram = CompileProgram(kVS, kFS);
1764         ASSERT_NE(mProgram, 0U);
1765 
1766         glClearColor(0, 0, 0, 0);
1767         glClearDepthf(0.0);
1768         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1769 
1770         glDisable(GL_DEPTH_TEST);
1771 
1772         ASSERT_GL_NO_ERROR();
1773     }
1774 
testTearDown()1775     void testTearDown() override { glDeleteProgram(mProgram); }
1776 
updateColors(int i,int offset,const GLColor & color)1777     void updateColors(int i, int offset, const GLColor &color)
1778     {
1779         Vector4 colorVec               = color.toNormalizedVector();
1780         mMappedPtr[offset + i * 4 + 0] = colorVec.x();
1781         mMappedPtr[offset + i * 4 + 1] = colorVec.y();
1782         mMappedPtr[offset + i * 4 + 2] = colorVec.z();
1783         mMappedPtr[offset + i * 4 + 3] = colorVec.w();
1784     }
1785 
updateThreadedAndDraw(int offset,const GLColor & color)1786     void updateThreadedAndDraw(int offset, const GLColor &color)
1787     {
1788         std::mutex mutex;
1789         std::vector<std::thread> threads(4);
1790         for (size_t i = 0; i < 4; i++)
1791         {
1792             threads[i] = std::thread([&, i]() {
1793                 std::lock_guard<decltype(mutex)> lock(mutex);
1794                 updateColors(i, offset, color);
1795             });
1796         }
1797 
1798         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1799 
1800         for (std::thread &thread : threads)
1801         {
1802             thread.join();
1803         }
1804     }
1805 
1806     GLuint mProgram;
1807     GLfloat *mMappedPtr = nullptr;
1808 };
1809 
1810 // Test using a large buffer storage for a color vertex array buffer, which is
1811 // off set every iteration step via glVertexAttribPointer.
1812 // Write to the buffer storage map pointer from multiple threads for the next iteration,
1813 // while drawing the current one.
TEST_P(BufferStorageTestES3Threaded,VertexBuffer)1814 TEST_P(BufferStorageTestES3Threaded, VertexBuffer)
1815 {
1816     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1817                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1818 
1819     auto vertices = GetIndexedQuadVertices();
1820 
1821     // Set up position buffer
1822     GLBuffer positionBuffer;
1823     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer.get());
1824     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1825                  GL_STATIC_DRAW);
1826 
1827     GLint positionLoc = glGetAttribLocation(mProgram, "position");
1828     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
1829     glEnableVertexAttribArray(positionLoc);
1830 
1831     // Set up color buffer
1832     GLBuffer colorBuffer;
1833     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer.get());
1834 
1835     // Let's create a big buffer which fills 10 pages at pagesize 4096
1836     GLint bufferSize   = sizeof(GLfloat) * 1024 * 10;
1837     GLint offsetFloats = 0;
1838 
1839     glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
1840                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1841                            GL_MAP_COHERENT_BIT_EXT);
1842     GLint colorLoc = glGetAttribLocation(mProgram, "color");
1843     glEnableVertexAttribArray(colorLoc);
1844 
1845     auto indices = GetQuadIndices();
1846 
1847     GLBuffer indexBuffer;
1848     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1849     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
1850                  GL_STATIC_DRAW);
1851 
1852     glUseProgram(mProgram);
1853 
1854     glClearColor(0, 0, 0, 0);
1855     glClear(GL_COLOR_BUFFER_BIT);
1856 
1857     ASSERT_GL_NO_ERROR();
1858 
1859     mMappedPtr = (GLfloat *)glMapBufferRange(
1860         GL_ARRAY_BUFFER, 0, bufferSize,
1861         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1862     ASSERT_NE(nullptr, mMappedPtr);
1863     ASSERT_GL_NO_ERROR();
1864 
1865     // Initial color
1866     for (int i = 0; i < 4; i++)
1867     {
1868         updateColors(i, offsetFloats, GLColor::black);
1869     }
1870 
1871     std::vector<GLColor> colors = {GLColor::red, GLColor::green, GLColor::blue};
1872 
1873     // 4 vertices, 4 floats
1874     GLint contentSize = 4 * 4;
1875 
1876     // Update and draw last
1877     int i = 0;
1878     while (bufferSize > (int)((offsetFloats + contentSize) * sizeof(GLfloat)))
1879     {
1880         glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
1881                               reinterpret_cast<const GLvoid *>(offsetFloats * sizeof(GLfloat)));
1882 
1883         offsetFloats += contentSize;
1884         GLColor color = colors[i % colors.size()];
1885         updateThreadedAndDraw(offsetFloats, color);
1886 
1887         if (i > 0)
1888         {
1889             GLColor lastColor = colors[(i - 1) % colors.size()];
1890             EXPECT_PIXEL_COLOR_EQ(0, 0, lastColor);
1891         }
1892         ASSERT_GL_NO_ERROR();
1893         i++;
1894     }
1895 
1896     // Last draw
1897     glVertexAttribPointer(colorLoc, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
1898                           reinterpret_cast<const GLvoid *>(offsetFloats * sizeof(GLfloat)));
1899     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1900 
1901     glUnmapBuffer(GL_ARRAY_BUFFER);
1902 
1903     ASSERT_GL_NO_ERROR();
1904 }
1905 
1906 ANGLE_INSTANTIATE_TEST_ES2(BufferDataTest);
1907 
1908 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferSubDataTest);
1909 ANGLE_INSTANTIATE_TEST_ES3_AND(BufferSubDataTest,
1910                                ES3_VULKAN().enable(Feature::PreferCPUForBufferSubData));
1911 
1912 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferDataTestES3);
1913 ANGLE_INSTANTIATE_TEST_ES3(BufferDataTestES3);
1914 
1915 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3);
1916 ANGLE_INSTANTIATE_TEST_ES3(BufferStorageTestES3);
1917 
1918 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IndexedBufferCopyTest);
1919 ANGLE_INSTANTIATE_TEST_ES3(IndexedBufferCopyTest);
1920 
1921 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3Threaded);
1922 ANGLE_INSTANTIATE_TEST_ES3(BufferStorageTestES3Threaded);
1923 
1924 #ifdef _WIN64
1925 
1926 // Test a bug where an integer overflow bug could trigger a crash in D3D.
1927 // The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
1928 // (with the internal D3D rounding to 16-byte values) and trigger the bug.
1929 // Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
1930 class BufferDataOverflowTest : public ANGLETest
1931 {
1932   protected:
BufferDataOverflowTest()1933     BufferDataOverflowTest() {}
1934 };
1935 
1936 // See description above.
TEST_P(BufferDataOverflowTest,VertexBufferIntegerOverflow)1937 TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
1938 {
1939     // These values are special, to trigger the rounding bug.
1940     unsigned int numItems       = 0x7FFFFFE;
1941     constexpr GLsizei bufferCnt = 8;
1942 
1943     std::vector<GLBuffer> buffers(bufferCnt);
1944 
1945     std::stringstream vertexShaderStr;
1946 
1947     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1948     {
1949         vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
1950     }
1951 
1952     vertexShaderStr << "attribute vec2 position;\n"
1953                        "varying float v_attrib;\n"
1954                        "void main() {\n"
1955                        "  gl_Position = vec4(position, 0, 1);\n"
1956                        "  v_attrib = 0.0;\n";
1957 
1958     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1959     {
1960         vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
1961     }
1962 
1963     vertexShaderStr << "}";
1964 
1965     constexpr char kFS[] =
1966         "varying highp float v_attrib;\n"
1967         "void main() {\n"
1968         "  gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
1969         "}";
1970 
1971     ANGLE_GL_PROGRAM(program, vertexShaderStr.str().c_str(), kFS);
1972     glUseProgram(program.get());
1973 
1974     std::vector<GLfloat> data(numItems, 1.0f);
1975 
1976     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1977     {
1978         glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex].get());
1979         glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
1980 
1981         std::stringstream attribNameStr;
1982         attribNameStr << "attrib" << bufferIndex;
1983 
1984         GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
1985         ASSERT_NE(-1, attribLocation);
1986 
1987         glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
1988         glEnableVertexAttribArray(attribLocation);
1989     }
1990 
1991     GLint positionLocation = glGetAttribLocation(program.get(), "position");
1992     ASSERT_NE(-1, positionLocation);
1993     glDisableVertexAttribArray(positionLocation);
1994     glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
1995 
1996     EXPECT_GL_NO_ERROR();
1997     glDrawArrays(GL_TRIANGLES, 0, numItems);
1998     EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
1999 
2000     // Test that a small draw still works.
2001     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
2002     {
2003         std::stringstream attribNameStr;
2004         attribNameStr << "attrib" << bufferIndex;
2005         GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
2006         ASSERT_NE(-1, attribLocation);
2007         glDisableVertexAttribArray(attribLocation);
2008     }
2009 
2010     glDrawArrays(GL_TRIANGLES, 0, 3);
2011     EXPECT_GL_ERROR(GL_NO_ERROR);
2012 }
2013 
2014 // Tests a security bug in our CopyBufferSubData validation (integer overflow).
TEST_P(BufferDataOverflowTest,CopySubDataValidation)2015 TEST_P(BufferDataOverflowTest, CopySubDataValidation)
2016 {
2017     GLBuffer readBuffer, writeBuffer;
2018 
2019     glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
2020     glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
2021 
2022     constexpr int bufSize = 100;
2023 
2024     glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
2025     glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
2026 
2027     GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
2028 
2029     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
2030     EXPECT_GL_ERROR(GL_INVALID_VALUE);
2031 
2032     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
2033     EXPECT_GL_ERROR(GL_INVALID_VALUE);
2034 }
2035 
2036 ANGLE_INSTANTIATE_TEST_ES3(BufferDataOverflowTest);
2037 
2038 #endif  // _WIN64
2039