xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cIndirectParametersTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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, &paramBuffer);
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, &paramBinding);
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, &paramBuffer);
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 } // namespace gl4cts
717