blob: 456b1fc10b0e606191800e3b4eeae16348654b72 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -04008#include "test_utils/gl_raii.h"
Jamie Madill80b95282014-05-06 13:57:43 -04009
Jamie Madillcc6ac252017-01-25 12:57:21 -080010#include "random_utils.h"
11
Corentin Wallez178e5972015-09-14 11:52:44 -070012#include <stdint.h>
Jamie Madill18afd772014-08-04 13:22:22 -040013
Jamie Madillfa05f602015-05-07 13:47:11 -040014using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070015
Jamie Madill80b95282014-05-06 13:57:43 -040016class BufferDataTest : public ANGLETest
17{
Jamie Madill5c1e58d2014-08-04 10:47:58 -040018 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040019 BufferDataTest()
Jamie Madill80b95282014-05-06 13:57:43 -040020 {
21 setWindowWidth(16);
22 setWindowHeight(16);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 setConfigDepthBits(24);
Austin Kinross18b931d2014-09-29 12:58:31 -070028
29 mBuffer = 0;
30 mProgram = 0;
31 mAttribLocation = -1;
Jamie Madill80b95282014-05-06 13:57:43 -040032 }
33
Jamie Madill3dfcdcb2015-08-10 14:28:54 -040034 void SetUp() override
Jamie Madill80b95282014-05-06 13:57:43 -040035 {
36 ANGLETest::SetUp();
37
Olli Etuahoa20af6d2017-09-18 13:32:29 +030038 const char *vsSource =
39 R"(attribute vec4 position;
Jamie Madill80b95282014-05-06 13:57:43 -040040 attribute float in_attrib;
41 varying float v_attrib;
42 void main()
43 {
44 v_attrib = in_attrib;
45 gl_Position = position;
Olli Etuahoa20af6d2017-09-18 13:32:29 +030046 })";
Jamie Madill80b95282014-05-06 13:57:43 -040047
Olli Etuahoa20af6d2017-09-18 13:32:29 +030048 const char *fsSource =
49 R"(precision mediump float;
Jamie Madill80b95282014-05-06 13:57:43 -040050 varying float v_attrib;
51 void main()
52 {
53 gl_FragColor = vec4(v_attrib, 0, 0, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +030054 })";
Jamie Madill80b95282014-05-06 13:57:43 -040055
56 glGenBuffers(1, &mBuffer);
57 ASSERT_NE(mBuffer, 0U);
58
Jamie Madill5599c8f2014-08-26 13:16:39 -040059 mProgram = CompileProgram(vsSource, fsSource);
Jamie Madill80b95282014-05-06 13:57:43 -040060 ASSERT_NE(mProgram, 0U);
61
62 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
63 ASSERT_NE(mAttribLocation, -1);
64
65 glClearColor(0, 0, 0, 0);
66 glClearDepthf(0.0);
67 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
68
69 glDisable(GL_DEPTH_TEST);
70
71 ASSERT_GL_NO_ERROR();
72 }
73
Jamie Madill3dfcdcb2015-08-10 14:28:54 -040074 void TearDown() override
Jamie Madill80b95282014-05-06 13:57:43 -040075 {
76 glDeleteBuffers(1, &mBuffer);
77 glDeleteProgram(mProgram);
78
79 ANGLETest::TearDown();
80 }
81
82 GLuint mBuffer;
83 GLuint mProgram;
84 GLint mAttribLocation;
85};
86
Jamie Madillfa05f602015-05-07 13:47:11 -040087TEST_P(BufferDataTest, NULLData)
Jamie Madill80b95282014-05-06 13:57:43 -040088{
89 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
90 EXPECT_GL_NO_ERROR();
91
92 const int numIterations = 128;
93 for (int i = 0; i < numIterations; ++i)
94 {
95 GLsizei bufferSize = sizeof(GLfloat) * (i + 1);
Yunchao Hef81ce4a2017-04-24 10:49:17 +080096 glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
Jamie Madill80b95282014-05-06 13:57:43 -040097 EXPECT_GL_NO_ERROR();
98
99 for (int j = 0; j < bufferSize; j++)
100 {
101 for (int k = 0; k < bufferSize - j; k++)
102 {
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800103 glBufferSubData(GL_ARRAY_BUFFER, k, j, nullptr);
Jamie Madille2e406c2016-06-02 13:04:10 -0400104 ASSERT_GL_NO_ERROR();
Jamie Madill80b95282014-05-06 13:57:43 -0400105 }
106 }
107 }
108}
109
Jamie Madillfa05f602015-05-07 13:47:11 -0400110TEST_P(BufferDataTest, ZeroNonNULLData)
Jamie Madille09f1c82014-06-12 11:10:12 -0400111{
112 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
113 EXPECT_GL_NO_ERROR();
114
115 char *zeroData = new char[0];
116 glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
117 EXPECT_GL_NO_ERROR();
118
119 glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
120 EXPECT_GL_NO_ERROR();
121
122 delete [] zeroData;
123}
124
Jamie Madillfa05f602015-05-07 13:47:11 -0400125TEST_P(BufferDataTest, NULLResolvedData)
Jamie Madillee009b82014-09-19 13:17:51 -0400126{
127 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800128 glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
Jamie Madillee009b82014-09-19 13:17:51 -0400129
130 glUseProgram(mProgram);
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800131 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
Jamie Madillee009b82014-09-19 13:17:51 -0400132 glEnableVertexAttribArray(mAttribLocation);
133 glBindBuffer(GL_ARRAY_BUFFER, 0);
134
135 drawQuad(mProgram, "position", 0.5f);
136}
137
Jamie Madille50bf152015-01-20 16:04:41 -0500138// Tests that a huge allocation returns GL_OUT_OF_MEMORY
139// TODO(jmadill): Figure out how to test this reliably on the Chromium bots
Jamie Madillfa05f602015-05-07 13:47:11 -0400140TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash)
Jamie Madill80b95282014-05-06 13:57:43 -0400141{
142 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
143 EXPECT_GL_NO_ERROR();
144
Jamie Madill18afd772014-08-04 13:22:22 -0400145 GLsizei allocSize = std::numeric_limits<GLsizei>::max() >> 2;
Jamie Madill80b95282014-05-06 13:57:43 -0400146
Yunchao Hed7297bf2017-04-19 15:27:10 +0800147 uint8_t *data = nullptr;
Yunchao He4f285442017-04-21 12:15:49 +0800148 while (data == nullptr && allocSize >= 4)
Jamie Madill80b95282014-05-06 13:57:43 -0400149 {
Jamie Madill18afd772014-08-04 13:22:22 -0400150 data = new (std::nothrow) uint8_t[allocSize];
151
Yunchao He4f285442017-04-21 12:15:49 +0800152 if (data == nullptr)
Jamie Madill18afd772014-08-04 13:22:22 -0400153 {
Jamie Madill4f2bf3a2014-08-20 16:03:52 -0400154 allocSize >>= 1;
Jamie Madill18afd772014-08-04 13:22:22 -0400155 }
Jamie Madill80b95282014-05-06 13:57:43 -0400156 }
157
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800158 ASSERT_NE(static_cast<uint8_t *>(nullptr), data);
Jamie Madill18afd772014-08-04 13:22:22 -0400159 memset(data, 0, allocSize);
Jamie Madill80b95282014-05-06 13:57:43 -0400160
161 float * fValue = reinterpret_cast<float*>(data);
162 for (unsigned int f = 0; f < 6; f++)
163 {
164 fValue[f] = 1.0f;
165 }
166
Jamie Madill18afd772014-08-04 13:22:22 -0400167 glBufferData(GL_ARRAY_BUFFER, allocSize, data, GL_STATIC_DRAW);
Jamie Madill80b95282014-05-06 13:57:43 -0400168
169 GLenum error = glGetError();
170 if (error == GL_NO_ERROR)
171 {
172 // If we didn't fail because of an out of memory error, try drawing a quad
173 // using the large buffer
174
175 // DISABLED because it takes a long time, but left for posterity
176
177 //glUseProgram(mProgram);
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800178 // glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
179 // glEnableVertexAttribArray(mAttribLocation);
180 // glBindBuffer(GL_ARRAY_BUFFER, 0);
181 // drawQuad(mProgram, "position", 0.5f);
182 // swapBuffers();
Jamie Madill80b95282014-05-06 13:57:43 -0400183
184 //// Draw operations can also generate out-of-memory, which is in-spec
185 //error = glGetError();
186 //if (error == GL_NO_ERROR)
187 //{
188 // GLint viewportSize[4];
189 // glGetIntegerv(GL_VIEWPORT, viewportSize);
190
191 // GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
192 // GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
193
194 // EXPECT_PIXEL_EQ(midPixelX, midPixelY, 255, 0, 0, 255);
195 //}
196 //else
197 //{
198 // EXPECT_EQ(GL_OUT_OF_MEMORY, error);
199 //}
200 }
201 else
202 {
Corentin Wallez322653b2015-06-17 18:33:56 +0200203 EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, error);
Jamie Madill80b95282014-05-06 13:57:43 -0400204 }
205
206 delete[] data;
207}
208
Jamie Madill52b09c22016-04-11 14:12:31 -0400209// Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
210// path.
211TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
212{
213 std::vector<GLfloat> data;
214 for (int i = 0; i < 16; ++i)
215 {
216 data.push_back(static_cast<GLfloat>(i));
217 }
218
219 glUseProgram(mProgram);
220 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
221 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
222 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
223 glBindBuffer(GL_ARRAY_BUFFER, 0);
224 glEnableVertexAttribArray(mAttribLocation);
225
226 for (int drawCount = 0; drawCount < 40; ++drawCount)
227 {
228 drawQuad(mProgram, "position", 0.5f);
229 }
230
231 EXPECT_GL_NO_ERROR();
232}
233
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400234class IndexedBufferCopyTest : public ANGLETest
235{
236 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -0400237 IndexedBufferCopyTest()
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400238 {
239 setWindowWidth(16);
240 setWindowHeight(16);
241 setConfigRedBits(8);
242 setConfigGreenBits(8);
243 setConfigBlueBits(8);
244 setConfigAlphaBits(8);
245 setConfigDepthBits(24);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400246 }
247
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400248 void SetUp() override
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400249 {
250 ANGLETest::SetUp();
251
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300252 const char *vsSource =
253 R"(attribute vec3 in_attrib;
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400254 varying vec3 v_attrib;
255 void main()
256 {
257 v_attrib = in_attrib;
258 gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
259 gl_PointSize = 100.0;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300260 })";
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400261
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300262 const char *fsSource =
263 R"(precision mediump float;
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400264 varying vec3 v_attrib;
265 void main()
266 {
267 gl_FragColor = vec4(v_attrib, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300268 })";
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400269
270 glGenBuffers(2, mBuffers);
271 ASSERT_NE(mBuffers[0], 0U);
272 ASSERT_NE(mBuffers[1], 0U);
273
274 glGenBuffers(1, &mElementBuffer);
275 ASSERT_NE(mElementBuffer, 0U);
276
Jamie Madill5599c8f2014-08-26 13:16:39 -0400277 mProgram = CompileProgram(vsSource, fsSource);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400278 ASSERT_NE(mProgram, 0U);
279
280 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
281 ASSERT_NE(mAttribLocation, -1);
282
283 glClearColor(0, 0, 0, 0);
284 glDisable(GL_DEPTH_TEST);
285 glClear(GL_COLOR_BUFFER_BIT);
286
287 ASSERT_GL_NO_ERROR();
288 }
289
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400290 void TearDown() override
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400291 {
292 glDeleteBuffers(2, mBuffers);
293 glDeleteBuffers(1, &mElementBuffer);
294 glDeleteProgram(mProgram);
295
296 ANGLETest::TearDown();
297 }
298
299 GLuint mBuffers[2];
300 GLuint mElementBuffer;
301 GLuint mProgram;
302 GLint mAttribLocation;
303};
304
305// The following test covers an ANGLE bug where our index ranges
306// weren't updated from CopyBufferSubData calls
307// https://code.google.com/p/angleproject/issues/detail?id=709
Jamie Madillfa05f602015-05-07 13:47:11 -0400308TEST_P(IndexedBufferCopyTest, IndexRangeBug)
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400309{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500310 // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -0500311 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -0500312 {
313 std::cout << "Test disabled on AMD OpenGL." << std::endl;
314 return;
315 }
316
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400317 unsigned char vertexData[] = { 255, 0, 0, 0, 0, 0 };
318 unsigned int indexData[] = { 0, 1 };
319
320 glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
321 glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
322
323 glUseProgram(mProgram);
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800324 glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, nullptr);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400325 glEnableVertexAttribArray(mAttribLocation);
326
327 ASSERT_GL_NO_ERROR();
328
329 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
330 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
331
332 glUseProgram(mProgram);
333
334 ASSERT_GL_NO_ERROR();
335
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800336 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400337
338 EXPECT_GL_NO_ERROR();
339 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
340
341 glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
342 glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
343
344 glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
345
346 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
347
348 ASSERT_GL_NO_ERROR();
349
350 glClear(GL_COLOR_BUFFER_BIT);
351 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
352
353 unsigned char newData[] = { 0, 255, 0 };
354 glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
355
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800356 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400357
358 EXPECT_GL_NO_ERROR();
359 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
360}
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000361
Jamie Madillfa05f602015-05-07 13:47:11 -0400362class BufferDataTestES3 : public BufferDataTest
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000363{
364};
365
366// The following test covers an ANGLE bug where the buffer storage
367// is not resized by Buffer11::getLatestBufferStorage when needed.
368// https://code.google.com/p/angleproject/issues/detail?id=897
Jamie Madillfa05f602015-05-07 13:47:11 -0400369TEST_P(BufferDataTestES3, BufferResizing)
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000370{
371 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
372 ASSERT_GL_NO_ERROR();
373
374 // Allocate a buffer with one byte
375 uint8_t singleByte[] = { 0xaa };
376 glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
377
378 // Resize the buffer
379 // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
380 // by chunks of pages instead of the minimum number of bytes neeeded.
381 const size_t numBytes = 4096*4;
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800382 glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000383
384 // Copy the original data to the buffer
385 uint8_t srcBytes[numBytes];
386 for (size_t i = 0; i < numBytes; ++i)
387 {
Minmin Gong794e0002015-04-07 18:31:54 -0700388 srcBytes[i] = static_cast<uint8_t>(i);
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000389 }
390
391 void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
392
393 ASSERT_GL_NO_ERROR();
394
395 memcpy(dest, srcBytes, numBytes);
396 glUnmapBuffer(GL_ARRAY_BUFFER);
397
398 EXPECT_GL_NO_ERROR();
399
400 // Create a new buffer and copy the data to it
401 GLuint readBuffer;
402 glGenBuffers(1, &readBuffer);
403 glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
404 uint8_t zeros[numBytes];
405 for (size_t i = 0; i < numBytes; ++i)
406 {
407 zeros[i] = 0;
408 }
409 glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
410 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
411
412 ASSERT_GL_NO_ERROR();
413
414 // Read back the data and compare it to the original
415 uint8_t *data = reinterpret_cast<uint8_t*>(glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
416
417 ASSERT_GL_NO_ERROR();
418
419 for (size_t i = 0; i < numBytes; ++i)
420 {
421 EXPECT_EQ(srcBytes[i], data[i]);
422 }
423 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
424
425 glDeleteBuffers(1, &readBuffer);
426
427 EXPECT_GL_NO_ERROR();
428}
Jamie Madillfa05f602015-05-07 13:47:11 -0400429
Jamie Madillcc6ac252017-01-25 12:57:21 -0800430// Verify OES_mapbuffer is present if EXT_map_buffer_range is.
431TEST_P(BufferDataTest, ExtensionDependency)
432{
433 if (extensionEnabled("GL_EXT_map_buffer_range"))
434 {
435 ASSERT_TRUE(extensionEnabled("GL_OES_mapbuffer"));
436 }
437}
438
439// Test mapping with the OES extension.
440TEST_P(BufferDataTest, MapBufferOES)
441{
442 if (!extensionEnabled("GL_EXT_map_buffer_range"))
443 {
444 // Needed for test validation.
445 return;
446 }
447
448 std::vector<uint8_t> data(1024);
449 FillVectorWithRandomUBytes(&data);
450
451 GLBuffer buffer;
452 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
453 glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
454
455 // Validate that other map flags don't work.
456 void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
457 EXPECT_EQ(nullptr, badMapPtr);
458 EXPECT_GL_ERROR(GL_INVALID_ENUM);
459
460 // Map and write.
461 void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
462 ASSERT_NE(nullptr, mapPtr);
463 ASSERT_GL_NO_ERROR();
464 memcpy(mapPtr, data.data(), data.size());
465 glUnmapBufferOES(GL_ARRAY_BUFFER);
466
467 // Validate data with EXT_map_buffer_range
468 void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
469 ASSERT_NE(nullptr, readMapPtr);
470 ASSERT_GL_NO_ERROR();
471 std::vector<uint8_t> actualData(data.size());
472 memcpy(actualData.data(), readMapPtr, data.size());
473 glUnmapBufferOES(GL_ARRAY_BUFFER);
474
475 EXPECT_EQ(data, actualData);
476}
477
Jamie Madillfa05f602015-05-07 13:47:11 -0400478// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -0500479ANGLE_INSTANTIATE_TEST(BufferDataTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
480ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
481ANGLE_INSTANTIATE_TEST(IndexedBufferCopyTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -0400482
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400483#ifdef _WIN64
484
485// Test a bug where an integer overflow bug could trigger a crash in D3D.
486// The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
487// (with the internal D3D rounding to 16-byte values) and trigger the bug.
488// Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
489class BufferDataOverflowTest : public ANGLETest
490{
491 protected:
492 BufferDataOverflowTest()
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400493 {
494 }
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400495};
496
497// See description above.
498TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
499{
500 // These values are special, to trigger the rounding bug.
501 unsigned int numItems = 0x7FFFFFE;
Jamie Madilld2f0c742016-11-02 10:34:41 -0400502 constexpr GLsizei bufferCnt = 8;
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400503
Jamie Madilld2f0c742016-11-02 10:34:41 -0400504 std::vector<GLBuffer> buffers(bufferCnt);
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400505
506 std::stringstream vertexShaderStr;
507
508 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
509 {
510 vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
511 }
512
513 vertexShaderStr << "attribute vec2 position;\n"
514 "varying float v_attrib;\n"
515 "void main() {\n"
516 " gl_Position = vec4(position, 0, 1);\n"
517 " v_attrib = 0.0;\n";
518
519 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
520 {
521 vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
522 }
523
524 vertexShaderStr << "}";
525
526 const std::string &fragmentShader =
527 "varying highp float v_attrib;\n"
528 "void main() {\n"
529 " gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
530 "}";
531
Jamie Madilld2f0c742016-11-02 10:34:41 -0400532 ANGLE_GL_PROGRAM(program, vertexShaderStr.str(), fragmentShader);
533 glUseProgram(program.get());
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400534
535 std::vector<GLfloat> data(numItems, 1.0f);
536
537 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
538 {
Jamie Madilld2f0c742016-11-02 10:34:41 -0400539 glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex].get());
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400540 glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
541
542 std::stringstream attribNameStr;
543 attribNameStr << "attrib" << bufferIndex;
544
Jamie Madilld2f0c742016-11-02 10:34:41 -0400545 GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400546 ASSERT_NE(-1, attribLocation);
547
548 glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
549 glEnableVertexAttribArray(attribLocation);
550 }
551
Jamie Madilld2f0c742016-11-02 10:34:41 -0400552 GLint positionLocation = glGetAttribLocation(program.get(), "position");
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400553 ASSERT_NE(-1, positionLocation);
554 glDisableVertexAttribArray(positionLocation);
555 glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
556
557 EXPECT_GL_NO_ERROR();
558 glDrawArrays(GL_TRIANGLES, 0, numItems);
559 EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
560}
561
Jamie Madilld2f0c742016-11-02 10:34:41 -0400562// Tests a security bug in our CopyBufferSubData validation (integer overflow).
563TEST_P(BufferDataOverflowTest, CopySubDataValidation)
564{
565 GLBuffer readBuffer, writeBuffer;
566
567 glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
568 glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
569
570 constexpr int bufSize = 100;
571
572 glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
573 glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
574
575 GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
576
577 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
578 EXPECT_GL_ERROR(GL_INVALID_VALUE);
579
580 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
581 EXPECT_GL_ERROR(GL_INVALID_VALUE);
582}
583
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400584ANGLE_INSTANTIATE_TEST(BufferDataOverflowTest, ES3_D3D11());
585
586#endif // _WIN64