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
9 #include "test_utils/gl_raii.h"
10
11 using namespace angle;
12
13 class LineLoopTest : public ANGLETest
14 {
15 protected:
LineLoopTest()16 LineLoopTest()
17 {
18 setWindowWidth(256);
19 setWindowHeight(256);
20 setConfigRedBits(8);
21 setConfigGreenBits(8);
22 setConfigBlueBits(8);
23 setConfigAlphaBits(8);
24 }
25
testSetUp()26 void testSetUp() override
27 {
28 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
29 if (mProgram == 0)
30 {
31 FAIL() << "shader compilation failed.";
32 }
33
34 mPositionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
35 mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
36
37 glBlendFunc(GL_ONE, GL_ONE);
38 glEnable(GL_BLEND);
39 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
40
41 ASSERT_GL_NO_ERROR();
42 }
43
testTearDown()44 void testTearDown() override { glDeleteProgram(mProgram); }
45
checkPixels()46 void checkPixels()
47 {
48 std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
49 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
50 &pixels[0]);
51
52 ASSERT_GL_NO_ERROR();
53
54 for (int y = 0; y < getWindowHeight(); y++)
55 {
56 for (int x = 0; x < getWindowWidth(); x++)
57 {
58 const GLubyte *pixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
59
60 EXPECT_EQ(pixel[0], 0) << "Failed at " << x << ", " << y << std::endl;
61 EXPECT_EQ(pixel[1], pixel[2]) << "Failed at " << x << ", " << y << std::endl;
62 ASSERT_EQ(pixel[3], 255) << "Failed at " << x << ", " << y << std::endl;
63 }
64 }
65 }
66
preTestUpdateBuffer(GLuint framebuffer,GLuint texture,GLuint buffer,GLsizei size)67 void preTestUpdateBuffer(GLuint framebuffer, GLuint texture, GLuint buffer, GLsizei size)
68 {
69 GLsizei uboSize = std::max(size, 16);
70 const std::vector<uint32_t> initialData((uboSize + 3) / 4, 0x1234567u);
71
72 glBindTexture(GL_TEXTURE_2D, texture);
73 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
74
75 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
76 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
77 0);
78
79 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
80 glBufferData(GL_UNIFORM_BUFFER, uboSize, initialData.data(), GL_DYNAMIC_DRAW);
81 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
82
83 constexpr char kVerifyUBO[] = R"(#version 300 es
84 precision mediump float;
85 uniform block {
86 uint data;
87 } ubo;
88 out vec4 colorOut;
89 void main()
90 {
91 if (ubo.data == 0x1234567u)
92 colorOut = vec4(0, 1.0, 0, 1.0);
93 else
94 colorOut = vec4(1.0, 0, 0, 1.0);
95 })";
96
97 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
98
99 glDisable(GL_BLEND);
100 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
101
102 EXPECT_GL_NO_ERROR();
103
104 glBindFramebuffer(GL_FRAMEBUFFER, 0);
105 }
106
runTest(GLenum indexType,GLuint indexBuffer,const void * indexPtr)107 void runTest(GLenum indexType, GLuint indexBuffer, const void *indexPtr)
108 {
109 glClear(GL_COLOR_BUFFER_BIT);
110
111 static const GLfloat loopPositions[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
112 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f,
113 -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f};
114
115 static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f,
116 0.5f, 0.5f, 0.5f, -0.5f};
117 static const GLubyte stripIndices[] = {1, 0, 3, 2, 1};
118
119 glEnable(GL_BLEND);
120
121 glUseProgram(mProgram);
122 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
123 glEnableVertexAttribArray(mPositionLocation);
124 glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, loopPositions);
125 glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
126 glDrawElements(GL_LINE_LOOP, 4, indexType, indexPtr);
127
128 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
129 glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions);
130 glUniform4f(mColorLocation, 0, 1, 0, 1);
131 glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices);
132
133 checkPixels();
134 }
135
136 GLuint mProgram;
137 GLint mPositionLocation;
138 GLint mColorLocation;
139 };
140
TEST_P(LineLoopTest,LineLoopUByteIndices)141 TEST_P(LineLoopTest, LineLoopUByteIndices)
142 {
143 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
144 // On Win7, the D3D SDK Layers emits a false warning for these tests.
145 // This doesn't occur on Windows 10 (Version 1511) though.
146 ignoreD3D11SDKLayersWarnings();
147
148 static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
149 runTest(GL_UNSIGNED_BYTE, 0, indices + 1);
150 }
151
TEST_P(LineLoopTest,LineLoopUShortIndices)152 TEST_P(LineLoopTest, LineLoopUShortIndices)
153 {
154 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
155 ignoreD3D11SDKLayersWarnings();
156
157 static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
158 runTest(GL_UNSIGNED_SHORT, 0, indices + 1);
159 }
160
TEST_P(LineLoopTest,LineLoopUIntIndices)161 TEST_P(LineLoopTest, LineLoopUIntIndices)
162 {
163 if (!IsGLExtensionEnabled("GL_OES_element_index_uint"))
164 {
165 return;
166 }
167
168 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
169 ignoreD3D11SDKLayersWarnings();
170
171 static const GLuint indices[] = {0, 7, 6, 9, 8, 0};
172 runTest(GL_UNSIGNED_INT, 0, indices + 1);
173 }
174
TEST_P(LineLoopTest,LineLoopUByteIndexBuffer)175 TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
176 {
177 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
178 ignoreD3D11SDKLayersWarnings();
179
180 static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
181
182 GLBuffer buf;
183 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
184 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
185
186 runTest(GL_UNSIGNED_BYTE, buf, reinterpret_cast<const void *>(sizeof(GLubyte)));
187 }
188
TEST_P(LineLoopTest,LineLoopUShortIndexBuffer)189 TEST_P(LineLoopTest, LineLoopUShortIndexBuffer)
190 {
191 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
192 ignoreD3D11SDKLayersWarnings();
193
194 static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
195
196 GLBuffer buf;
197 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
198 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
199
200 runTest(GL_UNSIGNED_SHORT, buf, reinterpret_cast<const void *>(sizeof(GLushort)));
201 }
202
TEST_P(LineLoopTest,LineLoopUIntIndexBuffer)203 TEST_P(LineLoopTest, LineLoopUIntIndexBuffer)
204 {
205 if (!IsGLExtensionEnabled("GL_OES_element_index_uint"))
206 {
207 return;
208 }
209
210 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
211 ignoreD3D11SDKLayersWarnings();
212
213 static const GLuint indices[] = {0, 7, 6, 9, 8, 0};
214
215 GLBuffer buf;
216 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
217 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
218
219 runTest(GL_UNSIGNED_INT, buf, reinterpret_cast<const void *>(sizeof(GLuint)));
220 }
221
222 class LineLoopTestES3 : public LineLoopTest
223 {};
224
225 // Test that uploading data to buffer that's in use then using it for line loop elements works.
TEST_P(LineLoopTestES3,UseAsUBOThenUpdateThenLineLoopUByteIndexBuffer)226 TEST_P(LineLoopTestES3, UseAsUBOThenUpdateThenLineLoopUByteIndexBuffer)
227 {
228 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
229 ignoreD3D11SDKLayersWarnings();
230
231 static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
232
233 GLFramebuffer framebuffer;
234 GLTexture texture;
235
236 GLBuffer buf;
237
238 preTestUpdateBuffer(framebuffer, texture, buf, sizeof(indices));
239
240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
241 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
242
243 runTest(GL_UNSIGNED_BYTE, buf, reinterpret_cast<const void *>(sizeof(GLubyte)));
244
245 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
246 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
247 }
248
249 // Test that uploading data to buffer that's in use then using it for line loop elements works.
TEST_P(LineLoopTestES3,UseAsUBOThenUpdateThenLineLoopUShortIndexBuffer)250 TEST_P(LineLoopTestES3, UseAsUBOThenUpdateThenLineLoopUShortIndexBuffer)
251 {
252 // http://anglebug.com/5833
253 ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm());
254
255 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
256 ignoreD3D11SDKLayersWarnings();
257
258 static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
259
260 GLFramebuffer framebuffer;
261 GLTexture texture;
262
263 GLBuffer buf;
264
265 preTestUpdateBuffer(framebuffer, texture, buf, sizeof(indices));
266
267 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
268 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
269
270 runTest(GL_UNSIGNED_SHORT, buf, reinterpret_cast<const void *>(sizeof(GLushort)));
271
272 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
273 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
274 }
275
276 // Test that uploading data to buffer that's in use then using it for line loop elements works.
TEST_P(LineLoopTestES3,UseAsUBOThenUpdateThenLineLoopUIntIndexBuffer)277 TEST_P(LineLoopTestES3, UseAsUBOThenUpdateThenLineLoopUIntIndexBuffer)
278 {
279 if (!IsGLExtensionEnabled("GL_OES_element_index_uint"))
280 {
281 return;
282 }
283
284 // http://anglebug.com/5833
285 ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm());
286
287 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
288 ignoreD3D11SDKLayersWarnings();
289
290 static const GLuint indices[] = {0, 7, 6, 9, 8, 0};
291
292 GLFramebuffer framebuffer;
293 GLTexture texture;
294
295 GLBuffer buf;
296
297 preTestUpdateBuffer(framebuffer, texture, buf, sizeof(indices));
298
299 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
300 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
301
302 runTest(GL_UNSIGNED_INT, buf, reinterpret_cast<const void *>(sizeof(GLuint)));
303
304 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
305 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
306 }
307
308 // Tests an edge case with a very large line loop element count.
309 // Disabled because it is slow and triggers an internal error.
TEST_P(LineLoopTest,DISABLED_DrawArraysWithLargeCount)310 TEST_P(LineLoopTest, DISABLED_DrawArraysWithLargeCount)
311 {
312 constexpr char kVS[] = "void main() { gl_Position = vec4(0); }";
313 constexpr char kFS[] = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }";
314
315 ANGLE_GL_PROGRAM(program, kVS, kFS);
316 glUseProgram(program);
317 glDrawArrays(GL_LINE_LOOP, 0, 0x3FFFFFFE);
318 EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
319
320 glDrawArrays(GL_LINE_LOOP, 0, 0x1FFFFFFE);
321 EXPECT_GL_NO_ERROR();
322 }
323
324 class LineLoopPrimitiveRestartTest : public ANGLETest
325 {
326 protected:
LineLoopPrimitiveRestartTest()327 LineLoopPrimitiveRestartTest()
328 {
329 setWindowWidth(64);
330 setWindowHeight(64);
331 setConfigRedBits(8);
332 setConfigGreenBits(8);
333 setConfigBlueBits(8);
334 setConfigAlphaBits(8);
335 }
336 };
337
TEST_P(LineLoopPrimitiveRestartTest,LineLoopWithPrimitiveRestart)338 TEST_P(LineLoopPrimitiveRestartTest, LineLoopWithPrimitiveRestart)
339 {
340 constexpr char kVS[] = R"(#version 300 es
341 in vec2 a_position;
342 // x,y = offset, z = scale
343 in vec3 a_transform;
344
345 invariant gl_Position;
346 void main()
347 {
348 vec2 v_position = a_transform.z * a_position + a_transform.xy;
349 gl_Position = vec4(v_position, 0.0, 1.0);
350 })";
351
352 constexpr char kFS[] = R"(#version 300 es
353 precision highp float;
354 layout (location=0) out vec4 fragColor;
355 void main()
356 {
357 fragColor = vec4(1.0, 0.0, 0.0, 1.0);
358 })";
359
360 ANGLE_GL_PROGRAM(program, kVS, kFS);
361 glBindAttribLocation(program, 0, "a_position");
362 glBindAttribLocation(program, 1, "a_transform");
363 glLinkProgram(program);
364 glUseProgram(program);
365 ASSERT_GL_NO_ERROR();
366
367 // clang-format off
368 constexpr GLfloat vertices[] = {
369 0.1, 0.1, -0.1, 0.1, -0.1, -0.1, 0.1, -0.1,
370 0.1, 0.1, -0.1, 0.1, -0.1, -0.1, 0.1, -0.1,
371 0.1, 0.1, -0.1, 0.1, -0.1, -0.1, 0.1, -0.1,
372 0.1, 0.1, -0.1, 0.1, -0.1, -0.1, 0.1, -0.1,
373 };
374
375 constexpr GLfloat transform[] = {
376 // first loop transform
377 0, 0, 9,
378 0, 0, 9,
379 0, 0, 9,
380 0, 0, 9,
381 // second loop transform
382 0.2, 0.1, 2,
383 0.2, 0.1, 2,
384 0.2, 0.1, 2,
385 0.2, 0.1, 2,
386 // third loop transform
387 0.5, -0.2, 3,
388 0.5, -0.2, 3,
389 0.5, -0.2, 3,
390 0.5, -0.2, 3,
391 // forth loop transform
392 -0.8, -0.5, 1,
393 -0.8, -0.5, 1,
394 -0.8, -0.5, 1,
395 -0.8, -0.5, 1,
396 };
397
398 constexpr GLushort lineloopAsStripIndices[] = {
399 // first strip
400 0, 1, 2, 3, 0,
401 // second strip
402 4, 5, 6, 7, 4,
403 // third strip
404 8, 9, 10, 11, 8,
405 // forth strip
406 12, 13, 14, 15, 12 };
407
408 constexpr GLushort lineloopWithRestartIndices[] = {
409 // first loop
410 0, 1, 2, 3, 0xffff,
411 // second loop
412 4, 5, 6, 7, 0xffff,
413 // third loop
414 8, 9, 10, 11, 0xffff,
415 // forth loop
416 12, 13, 14, 15,
417 };
418 // clang-format on
419
420 std::vector<GLColor> expectedPixels(getWindowWidth() * getWindowHeight());
421 std::vector<GLColor> renderedPixels(getWindowWidth() * getWindowHeight());
422
423 // Draw in non-primitive restart way
424 glClear(GL_COLOR_BUFFER_BIT);
425
426 glEnableVertexAttribArray(0);
427 glEnableVertexAttribArray(1);
428
429 glBindBuffer(GL_ARRAY_BUFFER, 0);
430 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
431
432 for (int loop = 0; loop < 4; ++loop)
433 {
434 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices + 8 * loop);
435 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, transform + 12 * loop);
436
437 glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, lineloopAsStripIndices);
438 }
439
440 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
441 expectedPixels.data());
442 ASSERT_GL_NO_ERROR();
443
444 // Draw line loop with primitive restart:
445 glClear(GL_COLOR_BUFFER_BIT);
446
447 GLBuffer vertexBuffer[2];
448 GLBuffer indexBuffer;
449
450 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
451 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineloopWithRestartIndices),
452 lineloopWithRestartIndices, GL_STATIC_DRAW);
453
454 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
455 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
456 glEnableVertexAttribArray(0);
457 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
458
459 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
460 glBufferData(GL_ARRAY_BUFFER, sizeof(transform), transform, GL_STATIC_DRAW);
461 glEnableVertexAttribArray(1);
462 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
463
464 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
465
466 glClear(GL_COLOR_BUFFER_BIT);
467 glDrawElements(GL_LINE_LOOP, ArraySize(lineloopWithRestartIndices), GL_UNSIGNED_SHORT, 0);
468
469 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
470 renderedPixels.data());
471
472 for (int y = 0; y < getWindowHeight(); ++y)
473 {
474 for (int x = 0; x < getWindowWidth(); ++x)
475 {
476 int idx = y * getWindowWidth() + x;
477 EXPECT_EQ(expectedPixels[idx], renderedPixels[idx])
478 << "Expected pixel at " << x << ", " << y << " to be " << expectedPixels[idx]
479 << std::endl;
480 }
481 }
482 }
483
484 class LineLoopIndirectTest : public LineLoopTest
485 {
486 protected:
runTest(GLenum indexType,const void * indices,GLuint indicesSize,GLuint firstIndex,bool useBuffersAsUboFirst)487 void runTest(GLenum indexType,
488 const void *indices,
489 GLuint indicesSize,
490 GLuint firstIndex,
491 bool useBuffersAsUboFirst)
492 {
493 struct DrawCommand
494 {
495 GLuint count;
496 GLuint primCount;
497 GLuint firstIndex;
498 GLint baseVertex;
499 GLuint reservedMustBeZero;
500 };
501
502 glClear(GL_COLOR_BUFFER_BIT);
503
504 static const GLfloat loopPositions[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
505 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f,
506 -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f};
507
508 static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f,
509 0.5f, 0.5f, 0.5f, -0.5f};
510 static const GLubyte stripIndices[] = {1, 0, 3, 2, 1};
511
512 glUseProgram(mProgram);
513
514 GLVertexArray vertexArray;
515
516 ASSERT_GL_NO_ERROR();
517
518 GLFramebuffer arrayUpdateFbo, elementUpdateFbo;
519 GLTexture arrayUpdateTex, elementUpdateTex;
520
521 GLBuffer vertBuffer;
522 GLBuffer buf;
523
524 if (useBuffersAsUboFirst)
525 {
526 preTestUpdateBuffer(arrayUpdateFbo, arrayUpdateTex, vertBuffer, sizeof(loopPositions));
527 preTestUpdateBuffer(elementUpdateFbo, elementUpdateTex, buf, indicesSize);
528 }
529
530 glBindVertexArray(vertexArray);
531 glBindBuffer(GL_ARRAY_BUFFER, vertBuffer);
532 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
533
534 if (useBuffersAsUboFirst)
535 {
536 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(loopPositions), loopPositions);
537 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indicesSize, indices);
538 }
539 else
540 {
541 glBufferData(GL_ARRAY_BUFFER, sizeof(loopPositions), loopPositions, GL_STATIC_DRAW);
542 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices, GL_STATIC_DRAW);
543 }
544 glEnableVertexAttribArray(mPositionLocation);
545 glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
546 glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
547
548 ASSERT_GL_NO_ERROR();
549
550 DrawCommand cmdBuffer = {};
551 cmdBuffer.count = 4;
552 cmdBuffer.firstIndex = firstIndex;
553 cmdBuffer.primCount = 1;
554 GLBuffer indirectBuf;
555 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
556 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand), &cmdBuffer, GL_STATIC_DRAW);
557
558 ASSERT_GL_NO_ERROR();
559
560 glEnable(GL_BLEND);
561 glDrawElementsIndirect(GL_LINE_LOOP, indexType, nullptr);
562 ASSERT_GL_NO_ERROR();
563
564 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
565
566 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
567
568 glBindVertexArray(0);
569
570 glBindBuffer(GL_ARRAY_BUFFER, 0);
571
572 glEnableVertexAttribArray(mPositionLocation);
573 glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions);
574 glUniform4f(mColorLocation, 0, 1, 0, 1);
575 glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices);
576
577 checkPixels();
578
579 if (useBuffersAsUboFirst)
580 {
581 glBindFramebuffer(GL_FRAMEBUFFER, arrayUpdateFbo);
582 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
583
584 glBindFramebuffer(GL_FRAMEBUFFER, elementUpdateFbo);
585 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
586 }
587 }
588 };
589
TEST_P(LineLoopIndirectTest,UByteIndexIndirectBuffer)590 TEST_P(LineLoopIndirectTest, UByteIndexIndirectBuffer)
591 {
592 // Old drivers buggy with optimized ConvertIndexIndirectLineLoop shader.
593 // http://anglebug.com/4720
594 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
595
596 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
597 ignoreD3D11SDKLayersWarnings();
598
599 static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
600
601 // Start at index 1.
602 runTest(GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(indices), sizeof(indices), 1, false);
603 }
604
TEST_P(LineLoopIndirectTest,UShortIndexIndirectBuffer)605 TEST_P(LineLoopIndirectTest, UShortIndexIndirectBuffer)
606 {
607 // Old drivers buggy with optimized ConvertIndexIndirectLineLoop shader.
608 // http://anglebug.com/4720
609 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
610
611 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
612 ignoreD3D11SDKLayersWarnings();
613
614 static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
615
616 // Start at index 1.
617 runTest(GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(indices), sizeof(indices), 1, false);
618 }
619
620 // Test that uploading data to buffer that's in use then using it for line loop elements works.
TEST_P(LineLoopIndirectTest,UseAsUBOThenUpdateThenUByteIndexIndirectBuffer)621 TEST_P(LineLoopIndirectTest, UseAsUBOThenUpdateThenUByteIndexIndirectBuffer)
622 {
623 // http://anglebug.com/5833
624 ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm());
625
626 // Old drivers buggy with optimized ConvertIndexIndirectLineLoop shader.
627 // http://anglebug.com/4720
628 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
629
630 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
631 ignoreD3D11SDKLayersWarnings();
632
633 static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
634
635 // Start at index 1.
636 runTest(GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(indices), sizeof(indices), 1, true);
637 }
638
639 // Test that uploading data to buffer that's in use then using it for line loop elements works.
TEST_P(LineLoopIndirectTest,UseAsUBOThenUpdateThenUShortIndexIndirectBuffer)640 TEST_P(LineLoopIndirectTest, UseAsUBOThenUpdateThenUShortIndexIndirectBuffer)
641 {
642 // http://anglebug.com/5833
643 ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm());
644
645 // Old drivers buggy with optimized ConvertIndexIndirectLineLoop shader.
646 // http://anglebug.com/4720
647 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
648
649 // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
650 ignoreD3D11SDKLayersWarnings();
651
652 static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
653
654 // Start at index 1.
655 runTest(GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(indices), sizeof(indices), 1, true);
656 }
657
658 ANGLE_INSTANTIATE_TEST_ES2(LineLoopTest);
659 ANGLE_INSTANTIATE_TEST_ES3_AND(LineLoopTestES3, WithDirectSPIRVGeneration(ES3_VULKAN()));
660
661 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LineLoopPrimitiveRestartTest);
662 ANGLE_INSTANTIATE_TEST_ES3_AND(
663 LineLoopPrimitiveRestartTest,
664 WithMetalForcedBufferGPUStorage(ES3_METAL()),
665 WithMetalMemoryBarrierAndCheapRenderPass(ES3_METAL(),
666 /* hasBarrier */ false,
667 /* cheapRenderPass */ false));
668
669 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LineLoopIndirectTest);
670 ANGLE_INSTANTIATE_TEST_ES31(LineLoopIndirectTest);
671