blob: 6e23ecce5920c12669b4ca3fbd552560a911f5b5 [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 Madill80b95282014-05-06 13:57:43 -04008
Corentin Wallez178e5972015-09-14 11:52:44 -07009#include <stdint.h>
Jamie Madill18afd772014-08-04 13:22:22 -040010
Jamie Madillfa05f602015-05-07 13:47:11 -040011using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070012
Jamie Madill80b95282014-05-06 13:57:43 -040013class BufferDataTest : public ANGLETest
14{
Jamie Madill5c1e58d2014-08-04 10:47:58 -040015 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040016 BufferDataTest()
Jamie Madill80b95282014-05-06 13:57:43 -040017 {
18 setWindowWidth(16);
19 setWindowHeight(16);
20 setConfigRedBits(8);
21 setConfigGreenBits(8);
22 setConfigBlueBits(8);
23 setConfigAlphaBits(8);
24 setConfigDepthBits(24);
Austin Kinross18b931d2014-09-29 12:58:31 -070025
26 mBuffer = 0;
27 mProgram = 0;
28 mAttribLocation = -1;
Jamie Madill80b95282014-05-06 13:57:43 -040029 }
30
Jamie Madill3dfcdcb2015-08-10 14:28:54 -040031 void SetUp() override
Jamie Madill80b95282014-05-06 13:57:43 -040032 {
33 ANGLETest::SetUp();
34
35 const char * vsSource = SHADER_SOURCE
36 (
37 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
47 const char * fsSource = SHADER_SOURCE
48 (
49 precision mediump float;
50 varying float v_attrib;
51 void main()
52 {
53 gl_FragColor = vec4(v_attrib, 0, 0, 1);
54 }
55 );
56
57 glGenBuffers(1, &mBuffer);
58 ASSERT_NE(mBuffer, 0U);
59
Jamie Madill5599c8f2014-08-26 13:16:39 -040060 mProgram = CompileProgram(vsSource, fsSource);
Jamie Madill80b95282014-05-06 13:57:43 -040061 ASSERT_NE(mProgram, 0U);
62
63 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
64 ASSERT_NE(mAttribLocation, -1);
65
66 glClearColor(0, 0, 0, 0);
67 glClearDepthf(0.0);
68 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
69
70 glDisable(GL_DEPTH_TEST);
71
72 ASSERT_GL_NO_ERROR();
73 }
74
Jamie Madill3dfcdcb2015-08-10 14:28:54 -040075 void TearDown() override
Jamie Madill80b95282014-05-06 13:57:43 -040076 {
77 glDeleteBuffers(1, &mBuffer);
78 glDeleteProgram(mProgram);
79
80 ANGLETest::TearDown();
81 }
82
83 GLuint mBuffer;
84 GLuint mProgram;
85 GLint mAttribLocation;
86};
87
Jamie Madillfa05f602015-05-07 13:47:11 -040088TEST_P(BufferDataTest, NULLData)
Jamie Madill80b95282014-05-06 13:57:43 -040089{
90 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
91 EXPECT_GL_NO_ERROR();
92
93 const int numIterations = 128;
94 for (int i = 0; i < numIterations; ++i)
95 {
96 GLsizei bufferSize = sizeof(GLfloat) * (i + 1);
97 glBufferData(GL_ARRAY_BUFFER, bufferSize, NULL, GL_STATIC_DRAW);
98 EXPECT_GL_NO_ERROR();
99
100 for (int j = 0; j < bufferSize; j++)
101 {
102 for (int k = 0; k < bufferSize - j; k++)
103 {
104 glBufferSubData(GL_ARRAY_BUFFER, k, j, NULL);
105 EXPECT_GL_NO_ERROR();
106 }
107 }
108 }
109}
110
Jamie Madillfa05f602015-05-07 13:47:11 -0400111TEST_P(BufferDataTest, ZeroNonNULLData)
Jamie Madille09f1c82014-06-12 11:10:12 -0400112{
113 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
114 EXPECT_GL_NO_ERROR();
115
116 char *zeroData = new char[0];
117 glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
118 EXPECT_GL_NO_ERROR();
119
120 glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
121 EXPECT_GL_NO_ERROR();
122
123 delete [] zeroData;
124}
125
Jamie Madillfa05f602015-05-07 13:47:11 -0400126TEST_P(BufferDataTest, NULLResolvedData)
Jamie Madillee009b82014-09-19 13:17:51 -0400127{
128 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
129 glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_DYNAMIC_DRAW);
130
131 glUseProgram(mProgram);
132 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, NULL);
133 glEnableVertexAttribArray(mAttribLocation);
134 glBindBuffer(GL_ARRAY_BUFFER, 0);
135
136 drawQuad(mProgram, "position", 0.5f);
137}
138
Jamie Madille50bf152015-01-20 16:04:41 -0500139// Tests that a huge allocation returns GL_OUT_OF_MEMORY
140// TODO(jmadill): Figure out how to test this reliably on the Chromium bots
Jamie Madillfa05f602015-05-07 13:47:11 -0400141TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash)
Jamie Madill80b95282014-05-06 13:57:43 -0400142{
143 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
144 EXPECT_GL_NO_ERROR();
145
Jamie Madill18afd772014-08-04 13:22:22 -0400146 GLsizei allocSize = std::numeric_limits<GLsizei>::max() >> 2;
Jamie Madill80b95282014-05-06 13:57:43 -0400147
Jamie Madill18afd772014-08-04 13:22:22 -0400148 uint8_t *data = NULL;
149 while (data == NULL && allocSize >= 4)
Jamie Madill80b95282014-05-06 13:57:43 -0400150 {
Jamie Madill18afd772014-08-04 13:22:22 -0400151 data = new (std::nothrow) uint8_t[allocSize];
152
153 if (data == NULL)
154 {
Jamie Madill4f2bf3a2014-08-20 16:03:52 -0400155 allocSize >>= 1;
Jamie Madill18afd772014-08-04 13:22:22 -0400156 }
Jamie Madill80b95282014-05-06 13:57:43 -0400157 }
158
Jamie Madill18afd772014-08-04 13:22:22 -0400159 ASSERT_NE(static_cast<uint8_t*>(NULL), data);
160 memset(data, 0, allocSize);
Jamie Madill80b95282014-05-06 13:57:43 -0400161
162 float * fValue = reinterpret_cast<float*>(data);
163 for (unsigned int f = 0; f < 6; f++)
164 {
165 fValue[f] = 1.0f;
166 }
167
Jamie Madill18afd772014-08-04 13:22:22 -0400168 glBufferData(GL_ARRAY_BUFFER, allocSize, data, GL_STATIC_DRAW);
Jamie Madill80b95282014-05-06 13:57:43 -0400169
170 GLenum error = glGetError();
171 if (error == GL_NO_ERROR)
172 {
173 // If we didn't fail because of an out of memory error, try drawing a quad
174 // using the large buffer
175
176 // DISABLED because it takes a long time, but left for posterity
177
178 //glUseProgram(mProgram);
179 //glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, NULL);
180 //glEnableVertexAttribArray(mAttribLocation);
181 //glBindBuffer(GL_ARRAY_BUFFER, 0);
182 //drawQuad(mProgram, "position", 0.5f);
183 //swapBuffers();
184
185 //// Draw operations can also generate out-of-memory, which is in-spec
186 //error = glGetError();
187 //if (error == GL_NO_ERROR)
188 //{
189 // GLint viewportSize[4];
190 // glGetIntegerv(GL_VIEWPORT, viewportSize);
191
192 // GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
193 // GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
194
195 // EXPECT_PIXEL_EQ(midPixelX, midPixelY, 255, 0, 0, 255);
196 //}
197 //else
198 //{
199 // EXPECT_EQ(GL_OUT_OF_MEMORY, error);
200 //}
201 }
202 else
203 {
Corentin Wallez322653b2015-06-17 18:33:56 +0200204 EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, error);
Jamie Madill80b95282014-05-06 13:57:43 -0400205 }
206
207 delete[] data;
208}
209
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400210class IndexedBufferCopyTest : public ANGLETest
211{
212 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -0400213 IndexedBufferCopyTest()
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400214 {
215 setWindowWidth(16);
216 setWindowHeight(16);
217 setConfigRedBits(8);
218 setConfigGreenBits(8);
219 setConfigBlueBits(8);
220 setConfigAlphaBits(8);
221 setConfigDepthBits(24);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400222 }
223
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400224 void SetUp() override
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400225 {
226 ANGLETest::SetUp();
227
228 const char * vsSource = SHADER_SOURCE
229 (
230 attribute vec3 in_attrib;
231 varying vec3 v_attrib;
232 void main()
233 {
234 v_attrib = in_attrib;
235 gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
236 gl_PointSize = 100.0;
237 }
238 );
239
240 const char * fsSource = SHADER_SOURCE
241 (
242 precision mediump float;
243 varying vec3 v_attrib;
244 void main()
245 {
246 gl_FragColor = vec4(v_attrib, 1);
247 }
248 );
249
250 glGenBuffers(2, mBuffers);
251 ASSERT_NE(mBuffers[0], 0U);
252 ASSERT_NE(mBuffers[1], 0U);
253
254 glGenBuffers(1, &mElementBuffer);
255 ASSERT_NE(mElementBuffer, 0U);
256
Jamie Madill5599c8f2014-08-26 13:16:39 -0400257 mProgram = CompileProgram(vsSource, fsSource);
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400258 ASSERT_NE(mProgram, 0U);
259
260 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
261 ASSERT_NE(mAttribLocation, -1);
262
263 glClearColor(0, 0, 0, 0);
264 glDisable(GL_DEPTH_TEST);
265 glClear(GL_COLOR_BUFFER_BIT);
266
267 ASSERT_GL_NO_ERROR();
268 }
269
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400270 void TearDown() override
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400271 {
272 glDeleteBuffers(2, mBuffers);
273 glDeleteBuffers(1, &mElementBuffer);
274 glDeleteProgram(mProgram);
275
276 ANGLETest::TearDown();
277 }
278
279 GLuint mBuffers[2];
280 GLuint mElementBuffer;
281 GLuint mProgram;
282 GLint mAttribLocation;
283};
284
285// The following test covers an ANGLE bug where our index ranges
286// weren't updated from CopyBufferSubData calls
287// https://code.google.com/p/angleproject/issues/detail?id=709
Jamie Madillfa05f602015-05-07 13:47:11 -0400288TEST_P(IndexedBufferCopyTest, IndexRangeBug)
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400289{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500290 // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
Jamie Madill7208f692016-02-29 10:47:35 -0500291 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -0500292 {
293 std::cout << "Test disabled on AMD OpenGL." << std::endl;
294 return;
295 }
296
Jamie Madill5c1e58d2014-08-04 10:47:58 -0400297 unsigned char vertexData[] = { 255, 0, 0, 0, 0, 0 };
298 unsigned int indexData[] = { 0, 1 };
299
300 glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
301 glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
302
303 glUseProgram(mProgram);
304 glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, NULL);
305 glEnableVertexAttribArray(mAttribLocation);
306
307 ASSERT_GL_NO_ERROR();
308
309 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
310 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
311
312 glUseProgram(mProgram);
313
314 ASSERT_GL_NO_ERROR();
315
316 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
317
318 EXPECT_GL_NO_ERROR();
319 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
320
321 glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
322 glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
323
324 glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
325
326 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
327
328 ASSERT_GL_NO_ERROR();
329
330 glClear(GL_COLOR_BUFFER_BIT);
331 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
332
333 unsigned char newData[] = { 0, 255, 0 };
334 glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
335
336 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
337
338 EXPECT_GL_NO_ERROR();
339 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
340}
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000341
Jamie Madillfa05f602015-05-07 13:47:11 -0400342class BufferDataTestES3 : public BufferDataTest
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000343{
344};
345
346// The following test covers an ANGLE bug where the buffer storage
347// is not resized by Buffer11::getLatestBufferStorage when needed.
348// https://code.google.com/p/angleproject/issues/detail?id=897
Jamie Madillfa05f602015-05-07 13:47:11 -0400349TEST_P(BufferDataTestES3, BufferResizing)
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000350{
351 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
352 ASSERT_GL_NO_ERROR();
353
354 // Allocate a buffer with one byte
355 uint8_t singleByte[] = { 0xaa };
356 glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
357
358 // Resize the buffer
359 // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
360 // by chunks of pages instead of the minimum number of bytes neeeded.
361 const size_t numBytes = 4096*4;
362 glBufferData(GL_ARRAY_BUFFER, numBytes, NULL, GL_STATIC_DRAW);
363
364 // Copy the original data to the buffer
365 uint8_t srcBytes[numBytes];
366 for (size_t i = 0; i < numBytes; ++i)
367 {
Minmin Gong794e0002015-04-07 18:31:54 -0700368 srcBytes[i] = static_cast<uint8_t>(i);
Gregoire Payen de La Garanderie4b3a29e2015-01-23 15:46:22 +0000369 }
370
371 void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
372
373 ASSERT_GL_NO_ERROR();
374
375 memcpy(dest, srcBytes, numBytes);
376 glUnmapBuffer(GL_ARRAY_BUFFER);
377
378 EXPECT_GL_NO_ERROR();
379
380 // Create a new buffer and copy the data to it
381 GLuint readBuffer;
382 glGenBuffers(1, &readBuffer);
383 glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
384 uint8_t zeros[numBytes];
385 for (size_t i = 0; i < numBytes; ++i)
386 {
387 zeros[i] = 0;
388 }
389 glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
390 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
391
392 ASSERT_GL_NO_ERROR();
393
394 // Read back the data and compare it to the original
395 uint8_t *data = reinterpret_cast<uint8_t*>(glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
396
397 ASSERT_GL_NO_ERROR();
398
399 for (size_t i = 0; i < numBytes; ++i)
400 {
401 EXPECT_EQ(srcBytes[i], data[i]);
402 }
403 glUnmapBuffer(GL_COPY_WRITE_BUFFER);
404
405 glDeleteBuffers(1, &readBuffer);
406
407 EXPECT_GL_NO_ERROR();
408}
Jamie Madillfa05f602015-05-07 13:47:11 -0400409
410// 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 -0500411ANGLE_INSTANTIATE_TEST(BufferDataTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
412ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
413ANGLE_INSTANTIATE_TEST(IndexedBufferCopyTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -0400414
Jamie Madill3dfcdcb2015-08-10 14:28:54 -0400415#ifdef _WIN64
416
417// Test a bug where an integer overflow bug could trigger a crash in D3D.
418// The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
419// (with the internal D3D rounding to 16-byte values) and trigger the bug.
420// Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
421class BufferDataOverflowTest : public ANGLETest
422{
423 protected:
424 BufferDataOverflowTest()
425 : mProgram(0)
426 {
427 }
428
429 ~BufferDataOverflowTest()
430 {
431 if (!mBuffers.empty())
432 {
433 glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);
434 }
435 if (mProgram != 0u)
436 {
437 glDeleteProgram(mProgram);
438 }
439 }
440
441 std::vector<GLuint> mBuffers;
442 GLuint mProgram;
443};
444
445// See description above.
446TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
447{
448 // These values are special, to trigger the rounding bug.
449 unsigned int numItems = 0x7FFFFFE;
450 GLsizei bufferCnt = 8;
451
452 mBuffers.resize(bufferCnt);
453
454 std::stringstream vertexShaderStr;
455
456 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
457 {
458 vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
459 }
460
461 vertexShaderStr << "attribute vec2 position;\n"
462 "varying float v_attrib;\n"
463 "void main() {\n"
464 " gl_Position = vec4(position, 0, 1);\n"
465 " v_attrib = 0.0;\n";
466
467 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
468 {
469 vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
470 }
471
472 vertexShaderStr << "}";
473
474 const std::string &fragmentShader =
475 "varying highp float v_attrib;\n"
476 "void main() {\n"
477 " gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
478 "}";
479
480 mProgram = CompileProgram(vertexShaderStr.str(), fragmentShader);
481 ASSERT_NE(0u, mProgram);
482 glUseProgram(mProgram);
483
484 glGenBuffers(bufferCnt, &mBuffers[0]);
485
486 std::vector<GLfloat> data(numItems, 1.0f);
487
488 for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
489 {
490 glBindBuffer(GL_ARRAY_BUFFER, mBuffers[bufferIndex]);
491 glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
492
493 std::stringstream attribNameStr;
494 attribNameStr << "attrib" << bufferIndex;
495
496 GLint attribLocation = glGetAttribLocation(mProgram, attribNameStr.str().c_str());
497 ASSERT_NE(-1, attribLocation);
498
499 glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
500 glEnableVertexAttribArray(attribLocation);
501 }
502
503 GLint positionLocation = glGetAttribLocation(mProgram, "position");
504 ASSERT_NE(-1, positionLocation);
505 glDisableVertexAttribArray(positionLocation);
506 glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
507
508 EXPECT_GL_NO_ERROR();
509 glDrawArrays(GL_TRIANGLES, 0, numItems);
510 EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
511}
512
513ANGLE_INSTANTIATE_TEST(BufferDataOverflowTest, ES3_D3D11());
514
515#endif // _WIN64