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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 GLubyte value = pixels[x + y * width]; 291 if (value < 190 || value > 194) 292 { 293 m_testCtx.getLog() << tcu::TestLog::Message << "First quad verification failed. " 294 << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value 295 << ", expected: <190-194>" << tcu::TestLog::EndMessage; 296 return false; 297 } 298 } 299 } 300 301 //Verify second quad 302 for (int y = 2; y < height - 2; ++y) 303 { 304 for (int x = width / 2 + 2; x < width - 2; ++x) 305 { 306 GLubyte value = pixels[x + y * width]; 307 if (value < 126 || value > 130) 308 { 309 m_testCtx.getLog() << tcu::TestLog::Message << "Second quad verification failed. " 310 << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value 311 << ", expected: <126-130>" << tcu::TestLog::EndMessage; 312 return false; 313 } 314 } 315 } 316 317 return verifyErrors(); 318 } 319 320 /** Constructor. 321 * 322 * @param context Rendering context 323 */ 324 MultiDrawArraysIndirectCountCase::MultiDrawArraysIndirectCountCase(deqp::Context& context) 325 : VertexArrayIndirectDrawingBaseCase(context, "MultiDrawArraysIndirectCount", 326 "Test verifies if MultiDrawArraysIndirectCountARB function works as expected.") 327 , m_vao(0) 328 , m_arrayBuffer(0) 329 , m_drawIndirectBuffer(0) 330 , m_parameterBuffer(0) 331 { 332 /* Left blank intentionally */ 333 } 334 335 /** Stub init method */ 336 void MultiDrawArraysIndirectCountCase::init() 337 { 338 glu::ContextType contextType = m_context.getRenderContext().getType(); 339 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) && 340 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters")) 341 return; 342 343 const Functions& gl = m_context.getRenderContext().getFunctions(); 344 345 const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 346 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f }; 347 348 const DrawArraysIndirectCommand indirect[] = { 349 { 4, 2, 0, 0 }, //4 vertices, 2 instanceCount, 0 first, 0 baseInstance 350 { 4, 1, 2, 0 } //4 vertices, 1 instanceCount, 2 first, 0 baseInstance 351 }; 352 353 const GLushort parameters[] = { 2, 1 }; 354 355 // Generate vertex array object 356 gl.genVertexArrays(1, &m_vao); 357 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays"); 358 359 gl.bindVertexArray(m_vao); 360 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray"); 361 362 // Setup vertex array buffer 363 gl.genBuffers(1, &m_arrayBuffer); 364 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 365 366 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer); 367 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 368 369 gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); 370 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 371 372 // Setup indirect command buffer 373 gl.genBuffers(1, &m_drawIndirectBuffer); 374 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 375 376 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer); 377 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 378 379 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 2 * sizeof(DrawArraysIndirectCommand), indirect, GL_STATIC_DRAW); 380 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 381 382 // Setup parameter buffer 383 gl.genBuffers(1, &m_parameterBuffer); 384 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 385 386 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer); 387 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 388 389 gl.bufferData(GL_PARAMETER_BUFFER_ARB, 100 * sizeof(GLushort), parameters, GL_STATIC_DRAW); 390 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 391 } 392 393 /** Stub deinit method */ 394 void MultiDrawArraysIndirectCountCase::deinit() 395 { 396 const Functions& gl = m_context.getRenderContext().getFunctions(); 397 398 if (m_vao) 399 gl.deleteVertexArrays(1, &m_vao); 400 if (m_arrayBuffer) 401 gl.deleteBuffers(1, &m_arrayBuffer); 402 if (m_drawIndirectBuffer) 403 gl.deleteBuffers(1, &m_drawIndirectBuffer); 404 if (m_parameterBuffer) 405 gl.deleteBuffers(1, &m_parameterBuffer); 406 } 407 408 /** Drawing quads method using drawArrays. 409 */ 410 bool MultiDrawArraysIndirectCountCase::draw() 411 { 412 const Functions& gl = m_context.getRenderContext().getFunctions(); 413 414 ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader); 415 ShaderProgram program(gl, sources); 416 417 if (!program.isOk()) 418 { 419 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n" 420 << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n" 421 << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n" 422 << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage; 423 return false; 424 } 425 426 gl.useProgram(program.getProgram()); 427 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); 428 429 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 430 gl.clear(GL_COLOR_BUFFER_BIT); 431 432 gl.enable(GL_BLEND); 433 gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 434 435 gl.enableVertexAttribArray(0); 436 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray"); 437 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 438 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer"); 439 440 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0); 441 GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawArraysIndirectCountARB"); 442 443 gl.disableVertexAttribArray(0); 444 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray"); 445 446 gl.disable(GL_BLEND); 447 448 return true; 449 } 450 451 /** Verify MultiDrawArrayIndirectCountARB errors 452 */ 453 bool MultiDrawArraysIndirectCountCase::verifyErrors() 454 { 455 const Functions& gl = m_context.getRenderContext().getFunctions(); 456 457 GLint errorCode; 458 459 bool result = true; 460 461 // INVALID_VALUE - drawcount offset not multiple of 4 462 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 2, 1, 0); 463 errorCode = gl.getError(); 464 if (errorCode != GL_INVALID_VALUE) 465 { 466 m_testCtx.getLog() << tcu::TestLog::Message 467 << "MultiDrawArraysIndirectCount error verifying failed (1). Expected code: " 468 << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage; 469 result = false; 470 } 471 472 // INVALID_OPERATION - maxdrawcount greater then parameter buffer size 473 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 4, 0); 474 errorCode = gl.getError(); 475 if (errorCode != GL_INVALID_OPERATION) 476 { 477 m_testCtx.getLog() << tcu::TestLog::Message 478 << "MultiDrawArraysIndirectCount error verifying failed (2). Expected code: " 479 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage; 480 result = false; 481 } 482 483 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0); 484 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 485 486 // INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound 487 gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0); 488 errorCode = gl.getError(); 489 if (errorCode != GL_INVALID_OPERATION) 490 { 491 m_testCtx.getLog() << tcu::TestLog::Message 492 << "MultiDrawArraysIndirectCount error verifying failed (3). Expected code: " 493 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage; 494 result = false; 495 } 496 497 return result; 498 } 499 500 /** Constructor. 501 * 502 * @param context Rendering context 503 */ 504 MultiDrawElementsIndirectCountCase::MultiDrawElementsIndirectCountCase(deqp::Context& context) 505 : VertexArrayIndirectDrawingBaseCase( 506 context, "MultiDrawElementsIndirectCount", 507 "Test verifies if MultiDrawElementsIndirectCountARB function works as expected.") 508 , m_vao(0) 509 , m_arrayBuffer(0) 510 , m_drawIndirectBuffer(0) 511 , m_parameterBuffer(0) 512 { 513 /* Left blank intentionally */ 514 } 515 516 /** Stub init method */ 517 void MultiDrawElementsIndirectCountCase::init() 518 { 519 glu::ContextType contextType = m_context.getRenderContext().getType(); 520 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) && 521 !m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters")) 522 return; 523 524 const Functions& gl = m_context.getRenderContext().getFunctions(); 525 526 const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 527 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f }; 528 529 const GLushort elements[] = { 0, 1, 2, 3, 4, 5 }; 530 531 const DrawElementsIndirectCommand indirect[] = { 532 { 4, 2, 0, 0, 0 }, //4 indices, 2 instanceCount, 0 firstIndex, 0 baseVertex, 0 baseInstance 533 { 4, 1, 2, 0, 0 } //4 indices, 1 instanceCount, 2 firstIndex, 0 baseVertex, 0 baseInstance 534 }; 535 536 const GLushort parameters[] = { 2, 1 }; 537 538 // Generate vertex array object 539 gl.genVertexArrays(1, &m_vao); 540 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays"); 541 542 gl.bindVertexArray(m_vao); 543 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray"); 544 545 // Setup vertex array buffer 546 gl.genBuffers(1, &m_arrayBuffer); 547 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 548 549 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer); 550 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 551 552 gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); 553 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 554 555 // Setup element array buffer 556 gl.genBuffers(1, &m_elementBuffer); 557 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 558 559 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer); 560 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 561 562 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), elements, GL_STATIC_DRAW); 563 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 564 565 // Setup indirect command buffer 566 gl.genBuffers(1, &m_drawIndirectBuffer); 567 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 568 569 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer); 570 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 571 572 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 3 * sizeof(DrawElementsIndirectCommand), indirect, GL_STATIC_DRAW); 573 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 574 575 // Setup parameters Re: buffer 576 gl.genBuffers(1, &m_parameterBuffer); 577 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 578 579 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer); 580 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 581 582 gl.bufferData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLushort), parameters, GL_STATIC_DRAW); 583 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 584 } 585 586 /** Stub deinit method */ 587 void MultiDrawElementsIndirectCountCase::deinit() 588 { 589 const Functions& gl = m_context.getRenderContext().getFunctions(); 590 591 if (m_vao) 592 gl.deleteVertexArrays(1, &m_vao); 593 if (m_arrayBuffer) 594 gl.deleteBuffers(1, &m_arrayBuffer); 595 if (m_elementBuffer) 596 gl.deleteBuffers(1, &m_elementBuffer); 597 if (m_drawIndirectBuffer) 598 gl.deleteBuffers(1, &m_drawIndirectBuffer); 599 if (m_parameterBuffer) 600 gl.deleteBuffers(1, &m_parameterBuffer); 601 } 602 603 /** Drawing quads method using drawArrays. 604 */ 605 bool MultiDrawElementsIndirectCountCase::draw() 606 { 607 const Functions& gl = m_context.getRenderContext().getFunctions(); 608 609 ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader); 610 ShaderProgram program(gl, sources); 611 612 if (!program.isOk()) 613 { 614 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n" 615 << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n" 616 << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n" 617 << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage; 618 return false; 619 } 620 621 gl.useProgram(program.getProgram()); 622 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); 623 624 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 625 gl.clear(GL_COLOR_BUFFER_BIT); 626 627 gl.enable(GL_BLEND); 628 gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 629 630 gl.enableVertexAttribArray(0); 631 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray"); 632 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 633 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer"); 634 635 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_SHORT, 0, 0, 2, 0); 636 GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawElementsIndirectCountARB"); 637 638 gl.disableVertexAttribArray(0); 639 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray"); 640 641 gl.disable(GL_BLEND); 642 643 return true; 644 } 645 646 /** Verify MultiDrawElementsIndirectCountARB errors 647 */ 648 bool MultiDrawElementsIndirectCountCase::verifyErrors() 649 { 650 const Functions& gl = m_context.getRenderContext().getFunctions(); 651 652 GLint errorCode; 653 654 bool result = true; 655 656 // INVALID_VALUE - drawcount offset not multiple of 4 657 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 2, 1, 0); 658 errorCode = gl.getError(); 659 if (errorCode != GL_INVALID_VALUE) 660 { 661 m_testCtx.getLog() << tcu::TestLog::Message 662 << "MultiDrawElementIndirectCount error verifying failed (1). Expected code: " 663 << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage; 664 result = false; 665 } 666 667 // INVALID_OPERATION - maxdrawcount greater then parameter buffer size 668 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 4, 0); 669 errorCode = gl.getError(); 670 if (errorCode != GL_INVALID_OPERATION) 671 { 672 m_testCtx.getLog() << tcu::TestLog::Message 673 << "MultiDrawElementIndirectCount error verifying failed (2). Expected code: " 674 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage; 675 result = false; 676 } 677 678 gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0); 679 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 680 681 // INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound 682 gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 3, 0); 683 errorCode = gl.getError(); 684 if (errorCode != GL_INVALID_OPERATION) 685 { 686 m_testCtx.getLog() << tcu::TestLog::Message 687 << "MultiDrawElementIndirectCount error verifying failed (3). Expected code: " 688 << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage; 689 result = false; 690 } 691 692 return result; 693 } 694 695 /** Constructor. 696 * 697 * @param context Rendering context. 698 */ 699 IndirectParametersTests::IndirectParametersTests(deqp::Context& context) 700 : TestCaseGroup(context, "indirect_parameters_tests", 701 "Verify conformance of CTS_ARB_indirect_parameters implementation") 702 { 703 } 704 705 /** Initializes the test group contents. */ 706 void IndirectParametersTests::init() 707 { 708 addChild(new ParameterBufferOperationsCase(m_context)); 709 addChild(new MultiDrawArraysIndirectCountCase(m_context)); 710 addChild(new MultiDrawElementsIndirectCountCase(m_context)); 711 } 712 713 } /* gl4cts namespace */ 714