1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 /**
25 */ /*!
26 * \file gl4cIndirectParametersTests.cpp
27 * \brief Conformance tests for the GL_ARB_indirect_parameters functionality.
28 */ /*-------------------------------------------------------------------*/
29
30 #include "gl4cIndirectParametersTests.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluDrawUtil.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37 #include "tcuRenderTarget.hpp"
38 #include "tcuTestLog.hpp"
39
40 using namespace glw;
41 using namespace glu;
42
43 namespace gl4cts
44 {
45
46 static const char* c_vertShader = "#version 430\n"
47 "\n"
48 "in vec3 vertex;\n"
49 "\n"
50 "void main()\n"
51 "{\n"
52 " gl_Position = vec4(vertex, 1);\n"
53 "}\n";
54
55 static const char* c_fragShader = "#version 430\n"
56 "\n"
57 "out vec4 fragColor;\n"
58 "\n"
59 "void main()\n"
60 "{\n"
61 " fragColor = vec4(1, 1, 1, 0.5);\n"
62 "}\n";
63
64 /** Constructor.
65 *
66 * @param context Rendering context
67 */
ParameterBufferOperationsCase(deqp::Context & context)68 ParameterBufferOperationsCase::ParameterBufferOperationsCase(deqp::Context& context)
69 : TestCase(context, "ParameterBufferOperations",
70 "Verifies if operations on new buffer object PARAMETER_BUFFER_ARB works as expected.")
71 {
72 /* Left blank intentionally */
73 }
74
75 /** Stub init method */
init()76 void ParameterBufferOperationsCase::init()
77 {
78 }
79
80 /** Executes test iteration.
81 *
82 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
83 */
iterate()84 tcu::TestNode::IterateResult ParameterBufferOperationsCase::iterate()
85 {
86 glu::ContextType contextType = m_context.getRenderContext().getType();
87 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
88 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
89 {
90 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
91 return STOP;
92 }
93
94 const Functions& gl = m_context.getRenderContext().getFunctions();
95
96 GLuint paramBuffer;
97
98 GLint data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
99 GLint subData[] = { 10, 11, 12, 13, 14 };
100 GLint expData[] = { 0, 1, 10, 11, 12, 13, 14, 7, 8, 9 };
101
102 bool result = true;
103
104 // Test buffer generating and binding
105 gl.genBuffers(1, ¶mBuffer);
106 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
107
108 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, paramBuffer);
109 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
110
111 GLint paramBinding;
112 gl.getIntegerv(GL_PARAMETER_BUFFER_BINDING_ARB, ¶mBinding);
113 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
114
115 if ((GLuint)paramBinding != paramBuffer)
116 {
117 result = false;
118 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer binding mismatch" << tcu::TestLog::EndMessage;
119 }
120 else
121 {
122 // Test filling buffer with data
123 gl.bufferData(GL_PARAMETER_BUFFER_ARB, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
124 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
125
126 gl.bufferSubData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLint), 5 * sizeof(GLint), subData);
127 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
128
129 // Test buffer mapping
130 GLvoid* buffer = gl.mapBuffer(GL_PARAMETER_BUFFER_ARB, GL_READ_ONLY);
131 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer");
132
133 if (memcmp(buffer, expData, 10 * sizeof(GLint)) != 0)
134 {
135 result = false;
136 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer data mismatch" << tcu::TestLog::EndMessage;
137 }
138 else
139 {
140 GLvoid* bufferPointer;
141 gl.getBufferPointerv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_MAP_POINTER, &bufferPointer);
142 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferPointerv");
143
144 if (buffer != bufferPointer)
145 {
146 result = false;
147 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer pointer mismatch" << tcu::TestLog::EndMessage;
148 }
149 else
150 {
151 GLint bufferSize;
152 GLint bufferUsage;
153 gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_SIZE, &bufferSize);
154 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
155 gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_USAGE, &bufferUsage);
156 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
157
158 if (bufferSize != 10 * sizeof(GLint))
159 {
160 result = false;
161 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size mismatch" << tcu::TestLog::EndMessage;
162 }
163 else if (bufferUsage != GL_DYNAMIC_DRAW)
164 {
165 result = false;
166 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer usage mismatch" << tcu::TestLog::EndMessage;
167 }
168 }
169 }
170
171 gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
172 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
173
174 // Test buffer ranged mapping
175 buffer =
176 gl.mapBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
177 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");
178
179 // Test buffer flushing
180 GLint* bufferInt = (GLint*)buffer;
181
182 bufferInt[0] = 100;
183 gl.flushMappedBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint));
184 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
185
186 gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
187 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
188
189 // Test buffers data copying
190 GLuint arrayBuffer;
191 gl.genBuffers(1, &arrayBuffer);
192 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
193
194 gl.bindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
195 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
196
197 gl.bufferData(GL_ARRAY_BUFFER, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
198 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
199
200 gl.copyBufferSubData(GL_PARAMETER_BUFFER_ARB, GL_ARRAY_BUFFER, 0, 0, sizeof(GLint));
201 GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyBufferSubData");
202
203 gl.mapBufferRange(GL_ARRAY_BUFFER, 0, 1, GL_MAP_READ_BIT);
204 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");
205
206 bufferInt = (GLint*)buffer;
207 if (bufferInt[0] != 100)
208 {
209 result = false;
210 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer copy operation failed" << tcu::TestLog::EndMessage;
211 }
212
213 gl.unmapBuffer(GL_ARRAY_BUFFER);
214 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
215
216 // Release array buffer
217 gl.deleteBuffers(1, &arrayBuffer);
218 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
219 }
220
221 // Release parameter buffer
222 gl.deleteBuffers(1, ¶mBuffer);
223 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
224
225 if (result)
226 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
227 else
228 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
229
230 return STOP;
231 }
232
233 /** Constructor.
234 *
235 * @param context Rendering context
236 */
VertexArrayIndirectDrawingBaseCase(deqp::Context & context,const char * name,const char * description)237 VertexArrayIndirectDrawingBaseCase::VertexArrayIndirectDrawingBaseCase(deqp::Context& context, const char* name,
238 const char* description)
239 : TestCase(context, name, description)
240 {
241 /* Left blank intentionally */
242 }
243
244 /** Executes test iteration.
245 *
246 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
247 */
iterate()248 tcu::TestNode::IterateResult VertexArrayIndirectDrawingBaseCase::iterate()
249 {
250 glu::ContextType contextType = m_context.getRenderContext().getType();
251 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
252 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
253 {
254 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
255 return STOP;
256 }
257
258 if (draw() && verify())
259 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
260 else
261 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
262
263 return STOP;
264 }
265
266 /** This method verifies if drawn quads are as expected.
267 *
268 * @return Returns true if quads are drawn properly, false otherwise.
269 */
verify()270 bool VertexArrayIndirectDrawingBaseCase::verify()
271 {
272 const Functions& gl = m_context.getRenderContext().getFunctions();
273 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
274
275 const int width = rt.getWidth();
276 const int height = rt.getHeight();
277
278 std::vector<GLubyte> pixels;
279 pixels.resize(width * height);
280
281 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
282 gl.readPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, pixels.data());
283 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
284
285 //Verify first quad
286 for (int y = 2; y < height - 2; ++y)
287 {
288 for (int x = 2; x < width / 2 - 2; ++x)
289 {
290 int value = pixels[x + y * width];
291 // Support 5-bit precision for the framebuffer, re-quantized to 8-bits from glReadPixels.
292 if (value < 189 || value > 197)
293 {
294 m_testCtx.getLog() << tcu::TestLog::Message << "First quad verification failed. "
295 << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
296 << ", expected: <189-197>" << tcu::TestLog::EndMessage;
297 return false;
298 }
299 }
300 }
301
302 //Verify second quad
303 for (int y = 2; y < height - 2; ++y)
304 {
305 for (int x = width / 2 + 2; x < width - 2; ++x)
306 {
307 int value = pixels[x + y * width];
308 // Support 5-bit precision for the framebuffer, re-quantized to 8-bits from glReadPixels.
309 if (value < 123 || value > 132)
310 {
311 m_testCtx.getLog() << tcu::TestLog::Message << "Second quad verification failed. "
312 << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
313 << ", expected: <123-132>" << tcu::TestLog::EndMessage;
314 return false;
315 }
316 }
317 }
318
319 return verifyErrors();
320 }
321
322 /** Constructor.
323 *
324 * @param context Rendering context
325 */
MultiDrawArraysIndirectCountCase(deqp::Context & context)326 MultiDrawArraysIndirectCountCase::MultiDrawArraysIndirectCountCase(deqp::Context& context)
327 : VertexArrayIndirectDrawingBaseCase(context, "MultiDrawArraysIndirectCount",
328 "Test verifies if MultiDrawArraysIndirectCountARB function works as expected.")
329 , m_vao(0)
330 , m_arrayBuffer(0)
331 , m_drawIndirectBuffer(0)
332 , m_parameterBuffer(0)
333 {
334 /* Left blank intentionally */
335 }
336
337 /** Stub init method */
init()338 void MultiDrawArraysIndirectCountCase::init()
339 {
340 glu::ContextType contextType = m_context.getRenderContext().getType();
341 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
342 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
343 return;
344
345 const Functions& gl = m_context.getRenderContext().getFunctions();
346
347 const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
348 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f };
349
350 const DrawArraysIndirectCommand indirect[] = {
351 { 4, 2, 0, 0 }, //4 vertices, 2 instanceCount, 0 first, 0 baseInstance
352 { 4, 1, 2, 0 } //4 vertices, 1 instanceCount, 2 first, 0 baseInstance
353 };
354
355 const GLushort parameters[] = { 2, 1 };
356
357 // Generate vertex array object
358 gl.genVertexArrays(1, &m_vao);
359 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
360
361 gl.bindVertexArray(m_vao);
362 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
363
364 // Setup vertex array buffer
365 gl.genBuffers(1, &m_arrayBuffer);
366 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
367
368 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
369 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
370
371 gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
373
374 // Setup indirect command buffer
375 gl.genBuffers(1, &m_drawIndirectBuffer);
376 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
377
378 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
379 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
380
381 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 2 * sizeof(DrawArraysIndirectCommand), indirect, GL_STATIC_DRAW);
382 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
383
384 // Setup parameter buffer
385 gl.genBuffers(1, &m_parameterBuffer);
386 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
387
388 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
389 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
390
391 gl.bufferData(GL_PARAMETER_BUFFER_ARB, 100 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
392 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
393 }
394
395 /** Stub deinit method */
deinit()396 void MultiDrawArraysIndirectCountCase::deinit()
397 {
398 const Functions& gl = m_context.getRenderContext().getFunctions();
399
400 if (m_vao)
401 gl.deleteVertexArrays(1, &m_vao);
402 if (m_arrayBuffer)
403 gl.deleteBuffers(1, &m_arrayBuffer);
404 if (m_drawIndirectBuffer)
405 gl.deleteBuffers(1, &m_drawIndirectBuffer);
406 if (m_parameterBuffer)
407 gl.deleteBuffers(1, &m_parameterBuffer);
408 }
409
410 /** Drawing quads method using drawArrays.
411 */
draw()412 bool MultiDrawArraysIndirectCountCase::draw()
413 {
414 const Functions& gl = m_context.getRenderContext().getFunctions();
415
416 ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
417 ShaderProgram program(gl, sources);
418
419 if (!program.isOk())
420 {
421 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
422 << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
423 << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
424 << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
425 return false;
426 }
427
428 gl.useProgram(program.getProgram());
429 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
430
431 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
432 gl.clear(GL_COLOR_BUFFER_BIT);
433
434 gl.enable(GL_BLEND);
435 gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
436
437 gl.enableVertexAttribArray(0);
438 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
439 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
440 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
441
442 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
443 GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawArraysIndirectCountARB");
444
445 gl.disableVertexAttribArray(0);
446 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
447
448 gl.disable(GL_BLEND);
449
450 return true;
451 }
452
453 /** Verify MultiDrawArrayIndirectCountARB errors
454 */
verifyErrors()455 bool MultiDrawArraysIndirectCountCase::verifyErrors()
456 {
457 const Functions& gl = m_context.getRenderContext().getFunctions();
458
459 GLint errorCode;
460
461 bool result = true;
462
463 // INVALID_VALUE - drawcount offset not multiple of 4
464 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 2, 1, 0);
465 errorCode = gl.getError();
466 if (errorCode != GL_INVALID_VALUE)
467 {
468 m_testCtx.getLog() << tcu::TestLog::Message
469 << "MultiDrawArraysIndirectCount error verifying failed (1). Expected code: "
470 << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
471 result = false;
472 }
473
474 // INVALID_OPERATION - maxdrawcount greater then parameter buffer size
475 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 4, 0);
476 errorCode = gl.getError();
477 if (errorCode != GL_INVALID_OPERATION)
478 {
479 m_testCtx.getLog() << tcu::TestLog::Message
480 << "MultiDrawArraysIndirectCount error verifying failed (2). Expected code: "
481 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
482 result = false;
483 }
484
485 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
486 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
487
488 // INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
489 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
490 errorCode = gl.getError();
491 if (errorCode != GL_INVALID_OPERATION)
492 {
493 m_testCtx.getLog() << tcu::TestLog::Message
494 << "MultiDrawArraysIndirectCount error verifying failed (3). Expected code: "
495 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
496 result = false;
497 }
498
499 return result;
500 }
501
502 /** Constructor.
503 *
504 * @param context Rendering context
505 */
MultiDrawElementsIndirectCountCase(deqp::Context & context)506 MultiDrawElementsIndirectCountCase::MultiDrawElementsIndirectCountCase(deqp::Context& context)
507 : VertexArrayIndirectDrawingBaseCase(
508 context, "MultiDrawElementsIndirectCount",
509 "Test verifies if MultiDrawElementsIndirectCountARB function works as expected.")
510 , m_vao(0)
511 , m_arrayBuffer(0)
512 , m_elementBuffer(0)
513 , m_drawIndirectBuffer(0)
514 , m_parameterBuffer(0)
515 {
516 /* Left blank intentionally */
517 }
518
519 /** Stub init method */
init()520 void MultiDrawElementsIndirectCountCase::init()
521 {
522 glu::ContextType contextType = m_context.getRenderContext().getType();
523 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
524 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
525 return;
526
527 const Functions& gl = m_context.getRenderContext().getFunctions();
528
529 const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
530 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f };
531
532 const GLushort elements[] = { 0, 1, 2, 3, 4, 5 };
533
534 const DrawElementsIndirectCommand indirect[] = {
535 { 4, 2, 0, 0, 0 }, //4 indices, 2 instanceCount, 0 firstIndex, 0 baseVertex, 0 baseInstance
536 { 4, 1, 2, 0, 0 } //4 indices, 1 instanceCount, 2 firstIndex, 0 baseVertex, 0 baseInstance
537 };
538
539 const GLushort parameters[] = { 2, 1 };
540
541 // Generate vertex array object
542 gl.genVertexArrays(1, &m_vao);
543 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
544
545 gl.bindVertexArray(m_vao);
546 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
547
548 // Setup vertex array buffer
549 gl.genBuffers(1, &m_arrayBuffer);
550 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
551
552 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
553 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
554
555 gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
556 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
557
558 // Setup element array buffer
559 gl.genBuffers(1, &m_elementBuffer);
560 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
561
562 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
563 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
564
565 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), elements, GL_STATIC_DRAW);
566 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
567
568 // Setup indirect command buffer
569 gl.genBuffers(1, &m_drawIndirectBuffer);
570 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
571
572 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
573 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
574
575 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 3 * sizeof(DrawElementsIndirectCommand), indirect, GL_STATIC_DRAW);
576 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
577
578 // Setup parameters Re: buffer
579 gl.genBuffers(1, &m_parameterBuffer);
580 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
581
582 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
583 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
584
585 gl.bufferData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
586 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
587 }
588
589 /** Stub deinit method */
deinit()590 void MultiDrawElementsIndirectCountCase::deinit()
591 {
592 const Functions& gl = m_context.getRenderContext().getFunctions();
593
594 if (m_vao)
595 gl.deleteVertexArrays(1, &m_vao);
596 if (m_arrayBuffer)
597 gl.deleteBuffers(1, &m_arrayBuffer);
598 if (m_elementBuffer)
599 gl.deleteBuffers(1, &m_elementBuffer);
600 if (m_drawIndirectBuffer)
601 gl.deleteBuffers(1, &m_drawIndirectBuffer);
602 if (m_parameterBuffer)
603 gl.deleteBuffers(1, &m_parameterBuffer);
604 }
605
606 /** Drawing quads method using drawArrays.
607 */
draw()608 bool MultiDrawElementsIndirectCountCase::draw()
609 {
610 const Functions& gl = m_context.getRenderContext().getFunctions();
611
612 ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
613 ShaderProgram program(gl, sources);
614
615 if (!program.isOk())
616 {
617 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
618 << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
619 << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
620 << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
621 return false;
622 }
623
624 gl.useProgram(program.getProgram());
625 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
626
627 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
628 gl.clear(GL_COLOR_BUFFER_BIT);
629
630 gl.enable(GL_BLEND);
631 gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
632
633 gl.enableVertexAttribArray(0);
634 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
635 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
636 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
637
638 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_SHORT, 0, 0, 2, 0);
639 GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawElementsIndirectCountARB");
640
641 gl.disableVertexAttribArray(0);
642 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
643
644 gl.disable(GL_BLEND);
645
646 return true;
647 }
648
649 /** Verify MultiDrawElementsIndirectCountARB errors
650 */
verifyErrors()651 bool MultiDrawElementsIndirectCountCase::verifyErrors()
652 {
653 const Functions& gl = m_context.getRenderContext().getFunctions();
654
655 GLint errorCode;
656
657 bool result = true;
658
659 // INVALID_VALUE - drawcount offset not multiple of 4
660 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 2, 1, 0);
661 errorCode = gl.getError();
662 if (errorCode != GL_INVALID_VALUE)
663 {
664 m_testCtx.getLog() << tcu::TestLog::Message
665 << "MultiDrawElementIndirectCount error verifying failed (1). Expected code: "
666 << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
667 result = false;
668 }
669
670 // INVALID_OPERATION - maxdrawcount greater then parameter buffer size
671 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 4, 0);
672 errorCode = gl.getError();
673 if (errorCode != GL_INVALID_OPERATION)
674 {
675 m_testCtx.getLog() << tcu::TestLog::Message
676 << "MultiDrawElementIndirectCount error verifying failed (2). Expected code: "
677 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
678 result = false;
679 }
680
681 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
682 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
683
684 // INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
685 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 3, 0);
686 errorCode = gl.getError();
687 if (errorCode != GL_INVALID_OPERATION)
688 {
689 m_testCtx.getLog() << tcu::TestLog::Message
690 << "MultiDrawElementIndirectCount error verifying failed (3). Expected code: "
691 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
692 result = false;
693 }
694
695 return result;
696 }
697
698 /** Constructor.
699 *
700 * @param context Rendering context.
701 */
IndirectParametersTests(deqp::Context & context)702 IndirectParametersTests::IndirectParametersTests(deqp::Context& context)
703 : TestCaseGroup(context, "indirect_parameters_tests",
704 "Verify conformance of CTS_ARB_indirect_parameters implementation")
705 {
706 }
707
708 /** Initializes the test group contents. */
init()709 void IndirectParametersTests::init()
710 {
711 addChild(new ParameterBufferOperationsCase(m_context));
712 addChild(new MultiDrawArraysIndirectCountCase(m_context));
713 addChild(new MultiDrawElementsIndirectCountCase(m_context));
714 }
715
716 } /* gl4cts namespace */
717