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