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 // Tests a bug where copying buffer data immediately after creation hit a nullptr in D3D11.
TEST_P(BufferDataTestES3,NoBufferInitDataCopyBug)750 TEST_P(BufferDataTestES3, NoBufferInitDataCopyBug)
751 {
752     constexpr GLsizei size = 64;
753 
754     GLBuffer sourceBuffer;
755     glBindBuffer(GL_COPY_READ_BUFFER, sourceBuffer);
756     glBufferData(GL_COPY_READ_BUFFER, size, nullptr, GL_STATIC_DRAW);
757 
758     GLBuffer destBuffer;
759     glBindBuffer(GL_ARRAY_BUFFER, destBuffer);
760     glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
761 
762     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ARRAY_BUFFER, 0, 0, size);
763     ASSERT_GL_NO_ERROR();
764 }
765 
766 // Ensures that calling glBufferData on a mapped buffer results in an unmapped buffer
TEST_P(BufferDataTestES3,BufferDataUnmap)767 TEST_P(BufferDataTestES3, BufferDataUnmap)
768 {
769     // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
770     // BufferData happens on a mapped buffer:
771     //
772     //    If any portion of the buffer object is mapped in the current context or
773     //    any context current to another thread, it is as though UnmapBuffer
774     //    (see section 2.10.3) is executed in each such context prior to deleting
775     //    the existing data store.
776     //
777 
778     std::vector<uint8_t> data1(16);
779     std::vector<uint8_t> data2(16);
780 
781     GLBuffer dataBuffer;
782     glBindBuffer(GL_ARRAY_BUFFER, dataBuffer);
783     glBufferData(GL_ARRAY_BUFFER, data1.size(), data1.data(), GL_STATIC_DRAW);
784 
785     // Map the buffer once
786     void *mappedBuffer =
787         glMapBufferRange(GL_ARRAY_BUFFER, 0, data1.size(),
788                          GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
789                              GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
790 
791     // Then repopulate the buffer. This should cause the buffer to become unmapped.
792     glBufferData(GL_ARRAY_BUFFER, data2.size(), data2.data(), GL_STATIC_DRAW);
793     ASSERT_GL_NO_ERROR();
794 
795     // Try to unmap the buffer, this should fail
796     bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
797     ASSERT_EQ(result, false);
798     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
799 
800     // Try to map the buffer again, which should succeed
801     mappedBuffer = glMapBufferRange(GL_ARRAY_BUFFER, 0, data2.size(),
802                                     GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
803                                         GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
804     ASSERT_GL_NO_ERROR();
805 }
806 
807 // Ensures that mapping buffer with GL_MAP_INVALIDATE_BUFFER_BIT followed by glBufferSubData calls
808 // works.  Regression test for the Vulkan backend where that flag caused use after free.
TEST_P(BufferDataTestES3,MapInvalidateThenBufferSubData)809 TEST_P(BufferDataTestES3, MapInvalidateThenBufferSubData)
810 {
811     // http://anglebug.com/5984
812     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsIntel());
813 
814     // http://anglebug.com/5985
815     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
816 
817     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
818                                                  GLColor::red};
819     const std::array<GLColor, 4> kUpdateData1 = {GLColor::white, GLColor::white, GLColor::white,
820                                                  GLColor::white};
821     const std::array<GLColor, 4> kUpdateData2 = {GLColor::blue, GLColor::blue, GLColor::blue,
822                                                  GLColor::blue};
823 
824     GLBuffer buffer;
825     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
826     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
827     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
828     EXPECT_GL_NO_ERROR();
829 
830     // Draw
831     constexpr char kVerifyUBO[] = R"(#version 300 es
832 precision mediump float;
833 uniform block {
834     uvec4 data;
835 } ubo;
836 uniform uint expect;
837 uniform vec4 successOutput;
838 out vec4 colorOut;
839 void main()
840 {
841     if (all(equal(ubo.data, uvec4(expect))))
842         colorOut = successOutput;
843     else
844         colorOut = vec4(1.0, 0, 0, 1.0);
845 })";
846 
847     ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
848     glUseProgram(verifyUbo);
849 
850     GLint expectLoc = glGetUniformLocation(verifyUbo, "expect");
851     EXPECT_NE(-1, expectLoc);
852     GLint successLoc = glGetUniformLocation(verifyUbo, "successOutput");
853     EXPECT_NE(-1, successLoc);
854 
855     glUniform1ui(expectLoc, kInitialData[0].asUint());
856     glUniform4f(successLoc, 0, 1, 0, 1);
857 
858     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
859     EXPECT_GL_NO_ERROR();
860 
861     // Dont't verify the buffer.  This is testing GL_MAP_INVALIDATE_BUFFER_BIT while the buffer is
862     // in use by the GPU.
863 
864     // Map the buffer and update it.
865     void *mappedBuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData),
866                                           GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
867 
868     memcpy(mappedBuffer, kUpdateData1.data(), sizeof(kInitialData));
869 
870     glUnmapBuffer(GL_UNIFORM_BUFFER);
871     EXPECT_GL_NO_ERROR();
872 
873     // Verify that the buffer has the updated value.
874     glUniform1ui(expectLoc, kUpdateData1[0].asUint());
875     glUniform4f(successLoc, 0, 0, 1, 1);
876 
877     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
878     EXPECT_GL_NO_ERROR();
879 
880     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
881 
882     // Update the buffer with glBufferSubData
883     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData2), kUpdateData2.data());
884     EXPECT_GL_NO_ERROR();
885 
886     // Verify that the buffer has the updated value.
887     glUniform1ui(expectLoc, kUpdateData2[0].asUint());
888     glUniform4f(successLoc, 0, 1, 1, 1);
889 
890     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
891     EXPECT_GL_NO_ERROR();
892 
893     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
894 }
895 
896 class BufferStorageTestES3 : public BufferDataTest
897 {};
898 
899 // Tests that proper error value is returned when bad size is passed in
TEST_P(BufferStorageTestES3,BufferStorageInvalidSize)900 TEST_P(BufferStorageTestES3, BufferStorageInvalidSize)
901 {
902     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
903 
904     std::vector<GLfloat> data(6, 1.0f);
905 
906     GLBuffer buffer;
907     glBindBuffer(GL_ARRAY_BUFFER, buffer);
908     glBufferStorageEXT(GL_ARRAY_BUFFER, 0, data.data(), 0);
909     EXPECT_GL_ERROR(GL_INVALID_VALUE);
910 }
911 
912 // Tests that buffer storage can be allocated with the GL_MAP_PERSISTENT_BIT_EXT and
913 // GL_MAP_COHERENT_BIT_EXT flags
TEST_P(BufferStorageTestES3,BufferStorageFlagsPersistentCoherentWrite)914 TEST_P(BufferStorageTestES3, BufferStorageFlagsPersistentCoherentWrite)
915 {
916     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
917 
918     std::vector<GLfloat> data(6, 1.0f);
919 
920     GLBuffer buffer;
921     glBindBuffer(GL_ARRAY_BUFFER, buffer);
922     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), data.data(),
923                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
924     ASSERT_GL_NO_ERROR();
925 }
926 
927 // Verify that glBufferStorage makes a buffer immutable
TEST_P(BufferStorageTestES3,StorageBufferBufferData)928 TEST_P(BufferStorageTestES3, StorageBufferBufferData)
929 {
930     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
931                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
932 
933     std::vector<GLfloat> data(6, 1.0f);
934 
935     GLBuffer buffer;
936     glBindBuffer(GL_ARRAY_BUFFER, buffer);
937     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
938     ASSERT_GL_NO_ERROR();
939 
940     // Verify that calling glBufferStorageEXT again produces an error.
941     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
942     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
943 
944     // Verify that calling glBufferData after calling glBufferStorageEXT produces an error.
945     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
946     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
947 }
948 
949 // Verify that glBufferStorageEXT can be called after glBufferData
TEST_P(BufferStorageTestES3,BufferDataStorageBuffer)950 TEST_P(BufferStorageTestES3, BufferDataStorageBuffer)
951 {
952     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
953                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
954 
955     std::vector<GLfloat> data(6, 1.0f);
956 
957     GLBuffer buffer;
958     glBindBuffer(GL_ARRAY_BUFFER, buffer);
959     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
960     ASSERT_GL_NO_ERROR();
961 
962     // Verify that calling glBufferStorageEXT again produces an error.
963     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
964     ASSERT_GL_NO_ERROR();
965 }
966 
967 // Verify that we can perform subdata updates to a buffer marked with GL_DYNAMIC_STORAGE_BIT_EXT
968 // usage flag
TEST_P(BufferStorageTestES3,StorageBufferSubData)969 TEST_P(BufferStorageTestES3, StorageBufferSubData)
970 {
971     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
972                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
973 
974     std::vector<GLfloat> data(6, 0.0f);
975 
976     glUseProgram(mProgram);
977     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
978     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr,
979                        GL_DYNAMIC_STORAGE_BIT_EXT);
980     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data.size(), data.data());
981     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
982     glEnableVertexAttribArray(mAttribLocation);
983 
984     drawQuad(mProgram, "position", 0.5f);
985     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::black);
986     EXPECT_GL_NO_ERROR();
987 
988     std::vector<GLfloat> data2(6, 1.0f);
989     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data2.size(), data2.data());
990 
991     drawQuad(mProgram, "position", 0.5f);
992     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
993     EXPECT_GL_NO_ERROR();
994 }
995 
996 // Test interaction between GL_OES_mapbuffer and GL_EXT_buffer_storage extensions.
TEST_P(BufferStorageTestES3,StorageBufferMapBufferOES)997 TEST_P(BufferStorageTestES3, StorageBufferMapBufferOES)
998 {
999     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1000                        !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1001                        !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1002 
1003     std::vector<uint8_t> data(1024);
1004     FillVectorWithRandomUBytes(&data);
1005 
1006     GLBuffer buffer;
1007     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1008     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
1009 
1010     // Validate that other map flags don't work.
1011     void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
1012     EXPECT_EQ(nullptr, badMapPtr);
1013     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1014 
1015     // Map and write.
1016     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
1017     ASSERT_NE(nullptr, mapPtr);
1018     ASSERT_GL_NO_ERROR();
1019     memcpy(mapPtr, data.data(), data.size());
1020     glUnmapBufferOES(GL_ARRAY_BUFFER);
1021 
1022     // Validate data with EXT_map_buffer_range
1023     void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
1024     ASSERT_NE(nullptr, readMapPtr);
1025     ASSERT_GL_NO_ERROR();
1026     std::vector<uint8_t> actualData(data.size());
1027     memcpy(actualData.data(), readMapPtr, data.size());
1028     glUnmapBufferOES(GL_ARRAY_BUFFER);
1029 
1030     EXPECT_EQ(data, actualData);
1031 }
1032 
1033 ANGLE_INSTANTIATE_TEST_ES2(BufferDataTest);
1034 
1035 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferDataTestES3);
1036 ANGLE_INSTANTIATE_TEST_ES3_AND(BufferDataTestES3, WithDirectSPIRVGeneration(ES3_VULKAN()));
1037 
1038 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3);
1039 ANGLE_INSTANTIATE_TEST_ES3(BufferStorageTestES3);
1040 
1041 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IndexedBufferCopyTest);
1042 ANGLE_INSTANTIATE_TEST_ES3(IndexedBufferCopyTest);
1043 
1044 #ifdef _WIN64
1045 
1046 // Test a bug where an integer overflow bug could trigger a crash in D3D.
1047 // The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
1048 // (with the internal D3D rounding to 16-byte values) and trigger the bug.
1049 // Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
1050 class BufferDataOverflowTest : public ANGLETest
1051 {
1052   protected:
BufferDataOverflowTest()1053     BufferDataOverflowTest() {}
1054 };
1055 
1056 // See description above.
TEST_P(BufferDataOverflowTest,VertexBufferIntegerOverflow)1057 TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
1058 {
1059     // These values are special, to trigger the rounding bug.
1060     unsigned int numItems       = 0x7FFFFFE;
1061     constexpr GLsizei bufferCnt = 8;
1062 
1063     std::vector<GLBuffer> buffers(bufferCnt);
1064 
1065     std::stringstream vertexShaderStr;
1066 
1067     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1068     {
1069         vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
1070     }
1071 
1072     vertexShaderStr << "attribute vec2 position;\n"
1073                        "varying float v_attrib;\n"
1074                        "void main() {\n"
1075                        "  gl_Position = vec4(position, 0, 1);\n"
1076                        "  v_attrib = 0.0;\n";
1077 
1078     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1079     {
1080         vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
1081     }
1082 
1083     vertexShaderStr << "}";
1084 
1085     constexpr char kFS[] =
1086         "varying highp float v_attrib;\n"
1087         "void main() {\n"
1088         "  gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
1089         "}";
1090 
1091     ANGLE_GL_PROGRAM(program, vertexShaderStr.str().c_str(), kFS);
1092     glUseProgram(program.get());
1093 
1094     std::vector<GLfloat> data(numItems, 1.0f);
1095 
1096     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1097     {
1098         glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex].get());
1099         glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
1100 
1101         std::stringstream attribNameStr;
1102         attribNameStr << "attrib" << bufferIndex;
1103 
1104         GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
1105         ASSERT_NE(-1, attribLocation);
1106 
1107         glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
1108         glEnableVertexAttribArray(attribLocation);
1109     }
1110 
1111     GLint positionLocation = glGetAttribLocation(program.get(), "position");
1112     ASSERT_NE(-1, positionLocation);
1113     glDisableVertexAttribArray(positionLocation);
1114     glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
1115 
1116     EXPECT_GL_NO_ERROR();
1117     glDrawArrays(GL_TRIANGLES, 0, numItems);
1118     EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
1119 
1120     // Test that a small draw still works.
1121     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
1122     {
1123         std::stringstream attribNameStr;
1124         attribNameStr << "attrib" << bufferIndex;
1125         GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
1126         ASSERT_NE(-1, attribLocation);
1127         glDisableVertexAttribArray(attribLocation);
1128     }
1129 
1130     glDrawArrays(GL_TRIANGLES, 0, 3);
1131     EXPECT_GL_ERROR(GL_NO_ERROR);
1132 }
1133 
1134 // Tests a security bug in our CopyBufferSubData validation (integer overflow).
TEST_P(BufferDataOverflowTest,CopySubDataValidation)1135 TEST_P(BufferDataOverflowTest, CopySubDataValidation)
1136 {
1137     GLBuffer readBuffer, writeBuffer;
1138 
1139     glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
1140     glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
1141 
1142     constexpr int bufSize = 100;
1143 
1144     glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
1145     glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
1146 
1147     GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
1148 
1149     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
1150     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1151 
1152     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
1153     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1154 }
1155 
1156 ANGLE_INSTANTIATE_TEST_ES3(BufferDataOverflowTest);
1157 
1158 #endif  // _WIN64
1159