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 // IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer
8
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 #include "util/test_utils.h"
12
13 using namespace angle;
14 enum class UpdateType
15 {
16 SmallUpdate,
17 SmallThenBigUpdate,
18 BigThenSmallUpdate,
19 FullUpdate,
20 };
21
22 class IndexBufferOffsetTest : public ANGLETest<>
23 {
24 protected:
IndexBufferOffsetTest()25 IndexBufferOffsetTest()
26 {
27 setWindowWidth(128);
28 setWindowHeight(128);
29 setConfigRedBits(8);
30 setConfigGreenBits(8);
31 setConfigBlueBits(8);
32 setConfigAlphaBits(8);
33 }
34
testSetUp()35 void testSetUp() override
36 {
37 constexpr char kVS[] =
38 R"(precision highp float;
39 attribute vec2 position;
40
41 void main()
42 {
43 gl_Position = vec4(position, 0.0, 1.0);
44 })";
45
46 constexpr char kFS[] =
47 R"(precision highp float;
48 uniform vec4 color;
49
50 void main()
51 {
52 gl_FragColor = color;
53 })";
54
55 mProgram = CompileProgram(kVS, kFS);
56 ASSERT_NE(0u, mProgram);
57
58 mColorUniformLocation = glGetUniformLocation(mProgram, "color");
59 mPositionAttributeLocation = glGetAttribLocation(mProgram, "position");
60
61 const GLfloat vertices[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
62 glGenBuffers(1, &mVertexBuffer);
63 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
64 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
65
66 glGenBuffers(1, &mIndexBuffer);
67 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
68 }
69
testTearDown()70 void testTearDown() override
71 {
72 glDeleteBuffers(1, &mVertexBuffer);
73 glDeleteBuffers(1, &mIndexBuffer);
74 glDeleteProgram(mProgram);
75 }
76
preTestUpdateBuffer(GLuint framebuffer,GLuint texture,GLuint buffer,GLsizei size)77 void preTestUpdateBuffer(GLuint framebuffer, GLuint texture, GLuint buffer, GLsizei size)
78 {
79 GLsizei uboSize = std::max(size, 16);
80 const std::vector<uint32_t> initialData((uboSize + 3) / 4, 0x1234567u);
81
82 glBindTexture(GL_TEXTURE_2D, texture);
83 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
84
85 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
86 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
87 0);
88
89 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
90 glBufferData(GL_UNIFORM_BUFFER, uboSize, initialData.data(), GL_DYNAMIC_DRAW);
91 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
92
93 constexpr char kVerifyUBO[] = R"(#version 300 es
94 precision mediump float;
95 uniform block {
96 uint data;
97 } ubo;
98 out vec4 colorOut;
99 void main()
100 {
101 if (ubo.data == 0x1234567u)
102 colorOut = vec4(0, 1.0, 0, 1.0);
103 else
104 colorOut = vec4(1.0, 0, 0, 1.0);
105 })";
106
107 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
108
109 glDisable(GL_BLEND);
110 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
111
112 EXPECT_GL_NO_ERROR();
113
114 glBindFramebuffer(GL_FRAMEBUFFER, 0);
115 }
116
runTest(GLenum type,int typeWidth,void * indexDataIn,UpdateType updateType,bool useBuffersAsUboFirst)117 void runTest(GLenum type,
118 int typeWidth,
119 void *indexDataIn,
120 UpdateType updateType,
121 bool useBuffersAsUboFirst)
122 {
123 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
124 glClear(GL_COLOR_BUFFER_BIT);
125
126 size_t indexDataWidth = 6 * typeWidth;
127
128 std::vector<GLubyte> indexData(6 * 3 * sizeof(GLuint), 0);
129 memcpy(indexData.data() + indexDataWidth, indexDataIn, indexDataWidth);
130
131 GLFramebuffer elementUpdateFbo;
132 GLTexture elementUpdateTex;
133
134 if (useBuffersAsUboFirst)
135 {
136 preTestUpdateBuffer(elementUpdateFbo, elementUpdateTex, mIndexBuffer,
137 3 * indexDataWidth);
138 }
139 else
140 {
141 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth, nullptr, GL_DYNAMIC_DRAW);
142 }
143
144 if (updateType == UpdateType::SmallUpdate)
145 {
146 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexDataWidth, indexData.data());
147 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth,
148 indexData.data() + indexDataWidth);
149 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth,
150 indexData.data() + 2 * indexDataWidth);
151 }
152 else if (updateType == UpdateType::SmallThenBigUpdate)
153 {
154 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 4, indexData.data());
155 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 4, 3 * indexDataWidth - 4,
156 indexData.data() + 4);
157 }
158 else if (updateType == UpdateType::BigThenSmallUpdate)
159 {
160 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 3 * indexDataWidth - 4, indexData.data());
161 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth - 4, 4,
162 indexData.data() + 3 * indexDataWidth - 4);
163 }
164 else
165 {
166 ASSERT_EQ(updateType, UpdateType::FullUpdate);
167 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 3 * indexDataWidth, indexData.data());
168 }
169
170 glUseProgram(mProgram);
171
172 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
173 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
174 glEnableVertexAttribArray(mPositionAttributeLocation);
175
176 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
177
178 for (int i = 0; i < 16; i++)
179 {
180 glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth));
181 EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::red);
182 }
183
184 if (updateType == UpdateType::SmallUpdate)
185 {
186 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth,
187 indexData.data());
188 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth,
189 indexData.data() + indexDataWidth);
190 }
191 else if (updateType == UpdateType::SmallThenBigUpdate)
192 {
193 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, 4, indexData.data());
194 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth + 4, 2 * indexDataWidth - 4,
195 indexData.data() + 4);
196 }
197 else if (updateType == UpdateType::BigThenSmallUpdate)
198 {
199 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, 2 * indexDataWidth - 4,
200 indexData.data());
201 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth - 4, 4,
202 indexData.data() + 2 * indexDataWidth - 4);
203 }
204 else
205 {
206 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, 2 * indexDataWidth,
207 indexData.data());
208 }
209
210 glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
211 glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth * 2));
212 EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::green);
213
214 if (useBuffersAsUboFirst)
215 {
216 glBindFramebuffer(GL_FRAMEBUFFER, elementUpdateFbo);
217 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
218 }
219
220 EXPECT_GL_NO_ERROR();
221 swapBuffers();
222 }
223
224 GLuint mProgram;
225 GLint mColorUniformLocation;
226 GLint mPositionAttributeLocation;
227 GLuint mVertexBuffer;
228 GLuint mIndexBuffer;
229 };
230
231 class IndexBufferOffsetTestES3 : public IndexBufferOffsetTest
232 {};
233
234 // Test using an offset for an UInt8 index buffer
TEST_P(IndexBufferOffsetTest,UInt8Index)235 TEST_P(IndexBufferOffsetTest, UInt8Index)
236 {
237 GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
238 runTest(GL_UNSIGNED_BYTE, 1, indexData, UpdateType::FullUpdate, false);
239 }
240
241 // Test using an offset for an UInt16 index buffer
TEST_P(IndexBufferOffsetTest,UInt16Index)242 TEST_P(IndexBufferOffsetTest, UInt16Index)
243 {
244 GLushort indexData[] = {0, 1, 2, 1, 2, 3};
245 runTest(GL_UNSIGNED_SHORT, 2, indexData, UpdateType::FullUpdate, false);
246 }
247
248 // Test using an offset for an UInt32 index buffer
TEST_P(IndexBufferOffsetTest,UInt32Index)249 TEST_P(IndexBufferOffsetTest, UInt32Index)
250 {
251 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
252 !IsGLExtensionEnabled("GL_OES_element_index_uint"));
253
254 GLuint indexData[] = {0, 1, 2, 1, 2, 3};
255 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::FullUpdate, false);
256 }
257
258 // Test using an offset for an UInt8 index buffer with small buffer updates
TEST_P(IndexBufferOffsetTest,UInt8IndexSmallUpdates)259 TEST_P(IndexBufferOffsetTest, UInt8IndexSmallUpdates)
260 {
261 GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
262 runTest(GL_UNSIGNED_BYTE, 1, indexData, UpdateType::SmallUpdate, false);
263 }
264
265 // Test using an offset for an UInt16 index buffer with small buffer updates
TEST_P(IndexBufferOffsetTest,UInt16IndexSmallUpdates)266 TEST_P(IndexBufferOffsetTest, UInt16IndexSmallUpdates)
267 {
268 GLushort indexData[] = {0, 1, 2, 1, 2, 3};
269 runTest(GL_UNSIGNED_SHORT, 2, indexData, UpdateType::SmallUpdate, false);
270 }
271
272 // Test using an offset for an UInt32 index buffer with small buffer updates
TEST_P(IndexBufferOffsetTest,UInt32IndexSmallUpdates)273 TEST_P(IndexBufferOffsetTest, UInt32IndexSmallUpdates)
274 {
275 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
276 !IsGLExtensionEnabled("GL_OES_element_index_uint"));
277
278 GLuint indexData[] = {0, 1, 2, 1, 2, 3};
279 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::SmallUpdate, false);
280 }
281
282 // Test using an offset for an UInt8 index buffer after uploading data to a buffer that is in use
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt8Index)283 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt8Index)
284 {
285 // http://anglebug.com/42264483
286 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
287
288 // http://anglebug.com/42264490
289 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
290
291 GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
292 runTest(GL_UNSIGNED_BYTE, 1, indexData, UpdateType::FullUpdate, true);
293 }
294
295 // Test using an offset for an UInt16 index buffer after uploading data to a buffer that is in use
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt16Index)296 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt16Index)
297 {
298 // http://anglebug.com/42264490
299 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
300
301 GLushort indexData[] = {0, 1, 2, 1, 2, 3};
302 runTest(GL_UNSIGNED_SHORT, 2, indexData, UpdateType::FullUpdate, true);
303 }
304
305 // Test using an offset for an UInt32 index buffer after uploading data to a buffer that is in use
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt32Index)306 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt32Index)
307 {
308 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
309 !IsGLExtensionEnabled("GL_OES_element_index_uint"));
310
311 // http://anglebug.com/42264490
312 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
313
314 GLuint indexData[] = {0, 1, 2, 1, 2, 3};
315 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::FullUpdate, true);
316 }
317
318 // Test using an offset for an UInt8 index buffer after uploading data to a buffer that is in use,
319 // with small buffer updates
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt8IndexSmallUpdates)320 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt8IndexSmallUpdates)
321 {
322 // http://anglebug.com/42264483
323 ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
324
325 // http://anglebug.com/42264490
326 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
327
328 GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
329 runTest(GL_UNSIGNED_BYTE, 1, indexData, UpdateType::SmallUpdate, true);
330 }
331
332 // Test using an offset for an UInt16 index buffer after uploading data to a buffer that is in use,
333 // with small buffer updates
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt16IndexSmallUpdates)334 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt16IndexSmallUpdates)
335 {
336 // http://anglebug.com/42264490
337 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
338
339 GLushort indexData[] = {0, 1, 2, 1, 2, 3};
340 runTest(GL_UNSIGNED_SHORT, 2, indexData, UpdateType::SmallUpdate, true);
341 }
342
343 // Test using an offset for an UInt32 index buffer after uploading data to a buffer that is in use,
344 // with small buffer updates
TEST_P(IndexBufferOffsetTestES3,UseAsUBOThenUpdateThenUInt32IndexSmallUpdates)345 TEST_P(IndexBufferOffsetTestES3, UseAsUBOThenUpdateThenUInt32IndexSmallUpdates)
346 {
347 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
348 !IsGLExtensionEnabled("GL_OES_element_index_uint"));
349
350 // http://anglebug.com/42264490
351 ANGLE_SKIP_TEST_IF(IsVulkan() && (IsPixel2() || IsPixel2XL()));
352
353 GLuint indexData[] = {0, 1, 2, 1, 2, 3};
354 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::SmallUpdate, true);
355
356 // Also test with one subData call with more than half updates
357 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::SmallThenBigUpdate, true);
358 runTest(GL_UNSIGNED_INT, 4, indexData, UpdateType::BigThenSmallUpdate, true);
359 }
360
361 // Uses index buffer offset and 2 drawElement calls one of the other, makes sure the second
362 // drawElement call will use the correct offset.
TEST_P(IndexBufferOffsetTest,DrawAtDifferentOffsets)363 TEST_P(IndexBufferOffsetTest, DrawAtDifferentOffsets)
364 {
365 GLushort indexData[] = {0, 1, 2, 1, 2, 3};
366 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
367 glClear(GL_COLOR_BUFFER_BIT);
368
369 size_t indexDataWidth = 6 * sizeof(GLushort);
370
371 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW);
372 glUseProgram(mProgram);
373
374 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
375 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
376 glEnableVertexAttribArray(mPositionAttributeLocation);
377
378 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
379
380 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
381 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT,
382 reinterpret_cast<void *>(indexDataWidth / 2));
383
384 // Check the upper left triangle
385 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
386
387 // Check the down right triangle
388 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
389
390 EXPECT_GL_NO_ERROR();
391 }
392
393 // Uses index buffer offset and 2 drawElement calls one of the other, one has aligned
394 // offset and one doesn't
TEST_P(IndexBufferOffsetTest,DrawAtDifferentOffsetAlignments)395 TEST_P(IndexBufferOffsetTest, DrawAtDifferentOffsetAlignments)
396 {
397 GLubyte indexData8[] = {0, 1, 0, 1, 2, 3};
398 GLushort indexData16[] = {0, 1, 2, 1, 2, 3};
399 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
400 glClear(GL_COLOR_BUFFER_BIT);
401
402 size_t indexDataWidth16 = 6 * sizeof(GLushort);
403
404 GLuint buffer[2];
405 glGenBuffers(2, buffer);
406
407 glUseProgram(mProgram);
408 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
409
410 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
411 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
412 glEnableVertexAttribArray(mPositionAttributeLocation);
413
414 // 8 bit index with aligned offset
415 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[0]);
416 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData8), indexData8, GL_DYNAMIC_DRAW);
417
418 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(2));
419
420 // 16 bits index buffer, which unaligned offset
421 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[1]);
422 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth16, indexData16, GL_DYNAMIC_DRAW);
423
424 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT,
425 reinterpret_cast<void *>(indexDataWidth16 / 2));
426
427 // Check the upper left triangle
428 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
429
430 // Check the down right triangle
431 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
432
433 EXPECT_GL_NO_ERROR();
434 }
435
436 // Draw with the same element buffer, but with two different types of data.
TEST_P(IndexBufferOffsetTest,DrawWithSameBufferButDifferentTypes)437 TEST_P(IndexBufferOffsetTest, DrawWithSameBufferButDifferentTypes)
438 {
439 GLubyte indexData8[] = {0, 1, 2};
440 GLushort indexData16[] = {1, 2, 3};
441 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
442 glClear(GL_COLOR_BUFFER_BIT);
443
444 glUseProgram(mProgram);
445 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
446
447 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
448 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
449 glEnableVertexAttribArray(mPositionAttributeLocation);
450
451 // Create element buffer and fill offset 0 with data from indexData8 and offset 512 with data
452 // from indexData16
453 GLBuffer buffer;
454 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
455 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, nullptr, GL_DYNAMIC_DRAW);
456 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indexData8), indexData8);
457 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 512, sizeof(indexData16), indexData16);
458
459 // Draw with 8 bit index data
460 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(0));
461 // Draw with 16 bits index buffer
462 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, reinterpret_cast<void *>(512));
463
464 // Check the upper left triangle
465 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
466 // Check the down right triangle
467 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
468
469 EXPECT_GL_NO_ERROR();
470 }
471
472 // Draw with GL_LINE_LOOP and followed by GL_TRIANGLES, all using the same element buffer.
TEST_P(IndexBufferOffsetTest,DrawWithSameBufferButDifferentModes)473 TEST_P(IndexBufferOffsetTest, DrawWithSameBufferButDifferentModes)
474 {
475 GLushort indexDataLineLoop[] = {0, 1, 2};
476 GLushort indexDataTriangle[] = {1, 2, 3};
477 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
478 glClear(GL_COLOR_BUFFER_BIT);
479
480 glUseProgram(mProgram);
481 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
482
483 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
484 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
485 glEnableVertexAttribArray(mPositionAttributeLocation);
486
487 // Create element buffer and fill offset 0 with data from indexData8 and offset 512 with data
488 // from indexData16
489 GLBuffer buffer;
490 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
491 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, nullptr, GL_DYNAMIC_DRAW);
492 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indexDataLineLoop), indexDataLineLoop);
493 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 512, sizeof(indexDataTriangle), indexDataTriangle);
494
495 // Draw line loop
496 glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, 0);
497 // Draw triangle
498 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, reinterpret_cast<void *>(512));
499
500 // Check the down right triangle
501 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
502
503 EXPECT_GL_NO_ERROR();
504 }
505
506 // Draw with GL_LINE_LOOP and followed by GL_TRIANGLES, all using the same element buffer.
TEST_P(IndexBufferOffsetTest,DrawArraysLineLoopFollowedByDrawElementsTriangle)507 TEST_P(IndexBufferOffsetTest, DrawArraysLineLoopFollowedByDrawElementsTriangle)
508 {
509 GLuint indexDataLineLoop[] = {0, 1, 2};
510 GLuint indexDataTriangle[] = {1, 2, 3};
511 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
512 glClear(GL_COLOR_BUFFER_BIT);
513
514 glUseProgram(mProgram);
515 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
516
517 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
518 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
519 glEnableVertexAttribArray(mPositionAttributeLocation);
520
521 // Create element buffer and fill offset 0 with data from indexDataLineLoop and offset 512 with
522 // data from indexDataTriangle
523 GLBuffer buffer;
524 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
525 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, nullptr, GL_DYNAMIC_DRAW);
526 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indexDataLineLoop), indexDataLineLoop);
527 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 512, sizeof(indexDataTriangle), indexDataTriangle);
528
529 // First call drawElements with the same primitive and type as the final drawElement call.
530 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, reinterpret_cast<void *>(0));
531 // Then drawArray with line loop to trigger the special handling of line loop.
532 glDrawArrays(GL_LINE_LOOP, 0, 3);
533 // Finally drawElements with triangle and same type to ensure the element buffer state that was
534 // modified by line loop draw call gets restored properly.
535 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, reinterpret_cast<void *>(512));
536
537 // Check the down right triangle
538 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
539
540 EXPECT_GL_NO_ERROR();
541 }
542
543 // Uses index buffer offset and 2 drawElement calls one of the other with different counts,
544 // makes sure the second drawElement call will have its data available.
TEST_P(IndexBufferOffsetTest,DrawWithDifferentCountsSameOffset)545 TEST_P(IndexBufferOffsetTest, DrawWithDifferentCountsSameOffset)
546 {
547 GLubyte indexData[] = {99, 0, 1, 2, 1, 2, 3};
548 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
549 glClear(GL_COLOR_BUFFER_BIT);
550
551 size_t indexDataWidth = 7 * sizeof(GLubyte);
552
553 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW);
554 glUseProgram(mProgram);
555
556 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
557 glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
558 glEnableVertexAttribArray(mPositionAttributeLocation);
559
560 glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
561
562 // The first draw draws the first triangle, and the second draws a quad.
563 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1));
564 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1));
565
566 // Check the upper left triangle
567 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
568
569 // Check the down right triangle
570 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
571
572 EXPECT_GL_NO_ERROR();
573 }
574
575 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(IndexBufferOffsetTest);
576
577 ANGLE_INSTANTIATE_TEST_ES3(IndexBufferOffsetTestES3);
578