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