• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 } /* gl4cts namespace */
717