1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2017 The Android Open Source Project 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 Negative Compute tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fNegativeComputeTests.hpp" 25 #include "gluContextInfo.hpp" 26 #include "gluShaderProgram.hpp" 27 #include "glwDefs.hpp" 28 #include "glwEnums.hpp" 29 #include "tcuStringTemplate.hpp" 30 31 namespace deqp 32 { 33 34 using std::string; 35 using std::map; 36 37 namespace gles31 38 { 39 namespace Functional 40 { 41 namespace NegativeTestShared 42 { 43 namespace 44 { 45 46 using tcu::TestLog; 47 using namespace glw; 48 49 static const char* const vertexShaderSource = "${GLSL_VERSION_STRING}\n" 50 "\n" 51 "void main (void)\n" 52 "{\n" 53 " gl_Position = vec4(0.0);\n" 54 "}\n"; 55 56 static const char* const fragmentShaderSource = "${GLSL_VERSION_STRING}\n" 57 "precision mediump float;\n" 58 "layout(location = 0) out mediump vec4 fragColor;\n" 59 "\n" 60 "void main (void)\n" 61 "{\n" 62 " fragColor = vec4(1.0);\n" 63 "}\n"; 64 65 static const char* const computeShaderSource = "${GLSL_VERSION_STRING}\n" 66 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 67 "void main (void)\n" 68 "{\n" 69 "}\n"; 70 71 static const char* const invalidComputeShaderSource = "${GLSL_VERSION_STRING}\n" 72 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 73 "void main (void)\n" 74 "{\n" 75 " highp uint var = -1;\n" // error 76 "}\n"; 77 78 int getResourceLimit (NegativeTestContext& ctx, GLenum resource) 79 { 80 int limit = 0; 81 ctx.glGetIntegerv(resource, &limit); 82 83 return limit; 84 } 85 86 void verifyLinkError (NegativeTestContext& ctx, const glu::ShaderProgram& program) 87 { 88 bool testFailed = false; 89 90 tcu::TestLog& log = ctx.getLog(); 91 log << program; 92 93 testFailed = program.getProgramInfo().linkOk; 94 95 if (testFailed) 96 { 97 const char* const message("Program was not expected to link."); 98 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage; 99 ctx.fail(message); 100 } 101 } 102 103 void verifyCompileError (NegativeTestContext& ctx, const glu::ShaderProgram& program, glu::ShaderType shaderType) 104 { 105 bool testFailed = false; 106 107 tcu::TestLog& log = ctx.getLog(); 108 log << program; 109 110 testFailed = program.getShaderInfo(shaderType).compileOk; 111 112 if (testFailed) 113 { 114 const char* const message("Program was not expected to compile."); 115 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage; 116 ctx.fail(message); 117 } 118 } 119 120 string generateComputeShader (NegativeTestContext& ctx, const string& shaderDeclarations, const string& shaderBody) 121 { 122 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 123 const char* const shaderVersion = isES32 124 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) 125 : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 126 127 std::ostringstream compShaderSource; 128 129 compShaderSource << shaderVersion << "\n" 130 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 131 << shaderDeclarations << "\n" 132 << "void main (void)\n" 133 << "{\n" 134 << shaderBody 135 << "}\n"; 136 137 return compShaderSource.str(); 138 } 139 140 string genBuiltInSource (glu::ShaderType shaderType) 141 { 142 std::ostringstream source; 143 source << "${GLSL_VERSION_STRING}\n"; 144 145 switch (shaderType) 146 { 147 case glu::SHADERTYPE_VERTEX: 148 case glu::SHADERTYPE_FRAGMENT: 149 break; 150 151 case glu::SHADERTYPE_COMPUTE: 152 source << "layout (local_size_x = 1) in;\n"; 153 break; 154 155 case glu::SHADERTYPE_GEOMETRY: 156 source << "layout(points) in;\n" 157 << "layout(line_strip, max_vertices = 3) out;\n"; 158 break; 159 160 case glu::SHADERTYPE_TESSELLATION_CONTROL: 161 source << "${GLSL_TESS_EXTENSION_STRING}\n" 162 << "layout(vertices = 10) out;\n"; 163 break; 164 165 case glu::SHADERTYPE_TESSELLATION_EVALUATION: 166 source << "${GLSL_TESS_EXTENSION_STRING}\n" 167 << "layout(triangles) in;\n"; 168 break; 169 170 default: 171 DE_FATAL("Unknown shader type"); 172 break; 173 } 174 175 source << "\n" 176 << "void main(void)\n" 177 << "{\n" 178 << "${COMPUTE_BUILT_IN_CONSTANTS_STRING}" 179 << "}\n"; 180 181 return source.str(); 182 } 183 184 void exceed_uniform_block_limit (NegativeTestContext& ctx) 185 { 186 std::ostringstream shaderDecl; 187 std::ostringstream shaderBody; 188 189 shaderDecl << "layout(std140, binding = 0) uniform Block\n" 190 << "{\n" 191 << " highp vec4 val;\n" 192 << "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_BLOCKS) + 1 << "];\n"; 193 194 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 195 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 196 197 ctx.beginSection("Link error is generated if a compute shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS."); 198 verifyLinkError(ctx, program); 199 ctx.endSection(); 200 } 201 202 void exceed_shader_storage_block_limit (NegativeTestContext& ctx) 203 { 204 std::ostringstream shaderDecl; 205 std::ostringstream shaderBody; 206 207 shaderDecl << "layout(std140, binding = 0) buffer Block\n" 208 << "{\n" 209 << " highp vec4 val;\n" 210 << "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS) + 1 << "];\n"; 211 212 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 213 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 214 215 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS."); 216 verifyLinkError(ctx, program); 217 ctx.endSection(); 218 } 219 220 void exceed_texture_image_units_limit (NegativeTestContext& ctx) 221 { 222 const int limit = getResourceLimit(ctx, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS) + 1; 223 std::ostringstream shaderDecl; 224 std::ostringstream shaderBody; 225 226 shaderDecl << "layout(binding = 0) " 227 << "uniform highp sampler2D u_sampler[" << limit + 1 << "];\n" 228 << "\n" 229 << "layout(binding = 0) buffer Output {\n" 230 << " vec4 values[ " << limit + 1 << " ];\n" 231 << "} sb_out;\n"; 232 233 for (int i = 0; i < limit + 1; ++i) 234 shaderBody << " sb_out.values[" << i << "] = texture(u_sampler[" << i << "], vec2(1.0f));\n"; 235 236 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 237 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 238 239 tcu::TestLog& log = ctx.getLog(); 240 log << tcu::TestLog::Message << "Possible link error is generated if compute shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS." << tcu::TestLog::EndMessage; 241 log << program; 242 243 if (program.getProgramInfo().linkOk) 244 { 245 log << tcu::TestLog::Message << "Quality Warning: program was not expected to link." << tcu::TestLog::EndMessage; 246 ctx.glUseProgram(program.getProgram()); 247 ctx.expectError(GL_NO_ERROR); 248 249 ctx.beginSection("GL_INVALID_OPERATION error is generated if the sum of the number of active samplers for each active program exceeds the maximum number of texture image units allowed"); 250 ctx.glDispatchCompute(1, 1, 1); 251 ctx.expectError(GL_INVALID_OPERATION); 252 ctx.endSection(); 253 } 254 } 255 256 void exceed_image_uniforms_limit (NegativeTestContext& ctx) 257 { 258 const int limit = getResourceLimit(ctx, GL_MAX_COMPUTE_IMAGE_UNIFORMS); 259 std::ostringstream shaderDecl; 260 std::ostringstream shaderBody; 261 262 shaderDecl << "layout(rgba8, binding = 0) " 263 << "uniform readonly highp image2D u_image[" << limit + 1 << "];\n" 264 << "\n" 265 << "layout(binding = 0) buffer Output {\n" 266 << " float values[" << limit + 1 << "];\n" 267 << "} sb_out;\n"; 268 269 for (int i = 0; i < limit + 1; ++i) 270 shaderBody << " sb_out.values[" << i << "]" << " = imageLoad(u_image[" << i << "], ivec2(gl_GlobalInvocationID.xy)).x;\n"; 271 272 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 273 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 274 275 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS."); 276 verifyLinkError(ctx, program); 277 ctx.endSection(); 278 } 279 280 void exceed_shared_memory_size_limit (NegativeTestContext& ctx) 281 { 282 const int limit = getResourceLimit(ctx, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE); 283 const long numberOfElements = limit / sizeof(GLuint); 284 std::ostringstream shaderDecl; 285 std::ostringstream shaderBody; 286 287 shaderDecl << "shared uint values[" << numberOfElements + 1 << "];\n" 288 << "\n" 289 << "layout(binding = 0) buffer Output {\n" 290 << " uint values;\n" 291 << "} sb_out;\n"; 292 293 shaderBody << " sb_out.values = values[" << numberOfElements << "];\n"; 294 295 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 296 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 297 298 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE."); 299 verifyLinkError(ctx, program); 300 ctx.endSection(); 301 } 302 303 void exceed_uniform_components_limit (NegativeTestContext& ctx) 304 { 305 const int limit = getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_COMPONENTS); 306 std::ostringstream shaderDecl; 307 std::ostringstream shaderBody; 308 309 shaderDecl << "uniform highp uint u_value[" << limit + 1 << "];\n" 310 << "\n" 311 << "layout(binding = 0) buffer Output {\n" 312 << " uint values[2];\n" 313 << "} sb_out;\n"; 314 315 shaderBody << " sb_out.values[0] = u_value[" << limit << "];\n"; 316 shaderBody << " sb_out.values[1] = u_value[0];\n"; 317 318 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 319 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 320 321 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS."); 322 verifyLinkError(ctx, program); 323 ctx.endSection(); 324 } 325 326 void exceed_atomic_counter_buffer_limit (NegativeTestContext& ctx) 327 { 328 const int limit = getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS); 329 std::ostringstream shaderDecl; 330 std::ostringstream shaderBody; 331 332 for (int i = 0; i < limit + 1; ++i) 333 { 334 shaderDecl << "layout(binding = " << i << ") " 335 << "uniform atomic_uint u_atomic" << i << ";\n"; 336 337 if (i == 0) 338 shaderBody << " uint oldVal = atomicCounterIncrement(u_atomic" << i << ");\n"; 339 else 340 shaderBody << " oldVal = atomicCounterIncrement(u_atomic" << i << ");\n"; 341 } 342 343 shaderBody << " sb_out.value = oldVal;\n"; 344 345 shaderDecl << "\n" 346 << "layout(binding = 0) buffer Output {\n" 347 << " uint value;\n" 348 << "} sb_out;\n"; 349 350 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 351 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 352 353 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS."); 354 verifyLinkError(ctx, program); 355 ctx.endSection(); 356 } 357 358 void exceed_atomic_counters_limit (NegativeTestContext& ctx) 359 { 360 std::ostringstream shaderDecl; 361 std::ostringstream shaderBody; 362 363 shaderDecl << "layout(binding = 0, offset = 0) uniform atomic_uint u_atomic0;\n" 364 << "layout(binding = " << sizeof(GLuint) * getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTERS) << ", offset = 0) uniform atomic_uint u_atomic1;\n" 365 << "\n" 366 << "layout(binding = 0) buffer Output {\n" 367 << " uint value;\n" 368 << "} sb_out;\n"; 369 370 shaderBody << " uint oldVal = 0u;\n" 371 << " oldVal = atomicCounterIncrement(u_atomic0);\n" 372 << " oldVal = atomicCounterIncrement(u_atomic1);\n" 373 << " sb_out.value = oldVal;\n"; 374 375 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() 376 << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str()))); 377 378 ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS."); 379 verifyLinkError(ctx, program); 380 ctx.endSection(); 381 } 382 383 void program_not_active (NegativeTestContext& ctx) 384 { 385 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 386 map<string, string> args; 387 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 388 389 const glu::VertexSource vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args)); 390 const glu::FragmentSource fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args)); 391 392 glu::ProgramPipeline pipeline(ctx.getRenderContext()); 393 394 glu::ShaderProgram vertProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource); 395 glu::ShaderProgram fragProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource); 396 397 tcu::TestLog& log = ctx.getLog(); 398 log << vertProgram << fragProgram; 399 400 if (!vertProgram.isOk() || !fragProgram.isOk()) 401 TCU_THROW(InternalError, "failed to build program"); 402 403 ctx.glBindProgramPipeline(pipeline.getPipeline()); 404 ctx.expectError(GL_NO_ERROR); 405 406 ctx.beginSection("Program not set at all"); 407 { 408 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage."); 409 ctx.glDispatchCompute(1, 1, 1); 410 ctx.expectError(GL_INVALID_OPERATION); 411 ctx.endSection(); 412 413 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage."); 414 GLintptr indirect = 0; 415 ctx.glDispatchComputeIndirect(indirect); 416 ctx.expectError(GL_INVALID_OPERATION); 417 ctx.endSection(); 418 } 419 ctx.endSection(); 420 421 ctx.beginSection("Program contains graphic pipeline stages"); 422 { 423 ctx.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vertProgram.getProgram()); 424 ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram()); 425 ctx.expectError(GL_NO_ERROR); 426 427 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage."); 428 ctx.glDispatchCompute(1, 1, 1); 429 ctx.expectError(GL_INVALID_OPERATION); 430 ctx.endSection(); 431 432 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage."); 433 GLintptr indirect = 0; 434 ctx.glDispatchComputeIndirect(indirect); 435 ctx.expectError(GL_INVALID_OPERATION); 436 ctx.endSection(); 437 } 438 ctx.endSection(); 439 440 ctx.glBindProgramPipeline(0); 441 ctx.expectError(GL_NO_ERROR); 442 } 443 444 void invalid_program_query (NegativeTestContext& ctx) 445 { 446 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 447 map<string, string> args; 448 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 449 450 GLint data[3] = { 0, 0, 0 }; 451 452 ctx.beginSection("Compute shader that does not link"); 453 { 454 const glu::ComputeSource compSource(tcu::StringTemplate(invalidComputeShaderSource).specialize(args)); 455 glu::ShaderProgram invalidComputeProgram (ctx.getRenderContext(), glu::ProgramSources() << compSource); 456 457 tcu::TestLog& log = ctx.getLog(); 458 log << invalidComputeProgram; 459 460 if (invalidComputeProgram.isOk()) 461 TCU_THROW(InternalError, "program should not of built"); 462 463 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly."); 464 ctx.glGetProgramiv(invalidComputeProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]); 465 ctx.expectError(GL_INVALID_OPERATION); 466 ctx.endSection(); 467 468 ctx.glUseProgram(0); 469 } 470 ctx.endSection(); 471 472 ctx.beginSection("Compute shader not present"); 473 { 474 const glu::VertexSource vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args)); 475 const glu::FragmentSource fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args)); 476 glu::ShaderProgram graphicsPipelineProgram (ctx.getRenderContext(), glu::ProgramSources() << vertSource << fragSource); 477 478 tcu::TestLog& log = ctx.getLog(); 479 log << graphicsPipelineProgram; 480 481 if (!graphicsPipelineProgram.isOk()) 482 TCU_THROW(InternalError, "failed to build program"); 483 484 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly."); 485 ctx.glGetProgramiv(graphicsPipelineProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]); 486 ctx.expectError(GL_INVALID_OPERATION); 487 ctx.endSection(); 488 489 ctx.glUseProgram(0); 490 } 491 ctx.endSection(); 492 } 493 494 void invalid_dispatch_compute_indirect (NegativeTestContext& ctx) 495 { 496 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 497 map<string, string> args; 498 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 499 500 const glu::ComputeSource compSource(tcu::StringTemplate(computeShaderSource).specialize(args)); 501 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 502 503 tcu::TestLog& log = ctx.getLog(); 504 log << program; 505 506 if (!program.isOk()) 507 TCU_THROW(InternalError, "failed to build program"); 508 509 ctx.glUseProgram(program.getProgram()); 510 ctx.expectError(GL_NO_ERROR); 511 512 static const struct 513 { 514 GLuint numGroupsX; 515 GLuint numGroupsY; 516 GLuint numGroupsZ; 517 } data = {0, 0, 0}; 518 519 { 520 GLuint buffer; 521 ctx.glGenBuffers(1, &buffer); 522 ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0); 523 ctx.expectError(GL_NO_ERROR); 524 525 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if zero is bound to GL_DISPATCH_INDIRECT_BUFFER."); 526 GLintptr indirect = 0; 527 ctx.glDispatchComputeIndirect(indirect); 528 ctx.expectError(GL_INVALID_OPERATION); 529 ctx.endSection(); 530 531 ctx.glDeleteBuffers(1, &buffer); 532 } 533 534 { 535 GLuint buffer; 536 ctx.glGenBuffers(1, &buffer); 537 ctx.expectError(GL_NO_ERROR); 538 539 ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer); 540 ctx.expectError(GL_NO_ERROR); 541 542 ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW); 543 ctx.expectError(GL_NO_ERROR); 544 545 ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if data is sourced beyond the end of the buffer object."); 546 GLintptr indirect = 1 << 10; 547 ctx.glDispatchComputeIndirect(indirect); 548 ctx.expectError(GL_INVALID_OPERATION); 549 ctx.endSection(); 550 551 ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0); 552 ctx.glDeleteBuffers(1, &buffer); 553 } 554 555 { 556 ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if the value of indirect is less than zero."); 557 GLintptr indirect = -1; 558 ctx.glDispatchComputeIndirect(indirect); 559 ctx.expectError(GL_INVALID_VALUE); 560 ctx.endSection(); 561 } 562 563 { 564 GLuint buffer; 565 ctx.glGenBuffers(1, &buffer); 566 ctx.expectError(GL_NO_ERROR); 567 568 ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer); 569 ctx.expectError(GL_NO_ERROR); 570 571 ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW); 572 ctx.expectError(GL_NO_ERROR); 573 574 ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if indirect is not a multiple of the size, in basic machine units, of uint."); 575 GLintptr indirect = sizeof(data) + 1; 576 ctx.glDispatchComputeIndirect(indirect); 577 ctx.expectError(GL_INVALID_VALUE); 578 ctx.endSection(); 579 580 ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0); 581 ctx.glDeleteBuffers(1, &buffer); 582 } 583 } 584 585 void invalid_maximum_work_group_counts (NegativeTestContext& ctx) 586 { 587 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 588 map<string, string> args; 589 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 590 591 const glu::ComputeSource compSource(tcu::StringTemplate(computeShaderSource).specialize(args)); 592 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 593 594 tcu::TestLog& log = ctx.getLog(); 595 log << program; 596 597 if (!program.isOk()) 598 TCU_THROW(InternalError, "failed to build program"); 599 600 ctx.glUseProgram(program.getProgram()); 601 ctx.expectError(GL_NO_ERROR); 602 603 GLint workGroupCountX; 604 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)0, &workGroupCountX); 605 ctx.expectError(GL_NO_ERROR); 606 607 ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsX> array is larger than the maximum work group count for the x dimension."); 608 ctx.glDispatchCompute(workGroupCountX+1, 1, 1); 609 ctx.expectError(GL_INVALID_VALUE); 610 ctx.endSection(); 611 612 GLint workGroupCountY; 613 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)1, &workGroupCountY); 614 ctx.expectError(GL_NO_ERROR); 615 616 ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsY> array is larger than the maximum work group count for the y dimension."); 617 ctx.glDispatchCompute(1, workGroupCountY+1, 1); 618 ctx.expectError(GL_INVALID_VALUE); 619 ctx.endSection(); 620 621 GLint workGroupCountZ; 622 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)2, &workGroupCountZ); 623 ctx.expectError(GL_NO_ERROR); 624 625 ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsZ> array is larger than the maximum work group count for the z dimension."); 626 ctx.glDispatchCompute(1, 1, workGroupCountZ+1); 627 ctx.expectError(GL_INVALID_VALUE); 628 ctx.endSection(); 629 } 630 631 void invalid_maximum_work_group_sizes (NegativeTestContext& ctx) 632 { 633 GLint maxWorkGroupSizeX; 634 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)0, &maxWorkGroupSizeX); 635 ctx.expectError(GL_NO_ERROR); 636 637 GLint maxWorkGroupSizeY; 638 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)1, &maxWorkGroupSizeY); 639 ctx.expectError(GL_NO_ERROR); 640 641 GLint maxWorkGroupSizeZ; 642 ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)2, &maxWorkGroupSizeZ); 643 ctx.expectError(GL_NO_ERROR); 644 645 GLint maxWorkGroupInvocations; 646 ctx.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &maxWorkGroupInvocations); 647 ctx.expectError(GL_NO_ERROR); 648 649 DE_ASSERT((maxWorkGroupSizeX * maxWorkGroupSizeY * maxWorkGroupSizeZ) > maxWorkGroupInvocations ); 650 651 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 652 const char* const shaderVersion = isES32 653 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) 654 : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 655 656 static const struct 657 { 658 GLint x; 659 GLint y; 660 GLint z; 661 } localWorkGroupSizeCases[] = 662 { 663 { maxWorkGroupSizeX+1, 1, 1 }, 664 { 1, maxWorkGroupSizeY+1, 1 }, 665 { 1, 1, maxWorkGroupSizeZ+1 }, 666 { maxWorkGroupSizeX, maxWorkGroupSizeY, maxWorkGroupSizeZ }, 667 }; 668 669 for (int testCase = 0; testCase < DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases); ++testCase) 670 { 671 std::ostringstream compShaderSource; 672 673 compShaderSource << shaderVersion << "\n" 674 << "layout(local_size_x = " << localWorkGroupSizeCases[testCase].x << ", local_size_y = " << localWorkGroupSizeCases[testCase].y << ", local_size_z = " << localWorkGroupSizeCases[testCase].z << ") in;\n" 675 << "void main (void)\n" 676 << "{\n" 677 << "}\n"; 678 679 const glu::ComputeSource compSource(compShaderSource.str()); 680 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 681 682 if (testCase == DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases)-1) 683 { 684 bool testFailed = false; 685 ctx.beginSection("A compile time or link error is generated if the maximum number of invocations in a single local work group (product of the three dimensions) is greater than GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS."); 686 687 ctx.getLog() << program; 688 testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk); 689 690 if (testFailed) 691 { 692 const char* const message("Program was not expected to compile or link."); 693 ctx.getLog() << tcu::TestLog::Message << message << tcu::TestLog::EndMessage; 694 ctx.fail(message); 695 } 696 } 697 else 698 { 699 ctx.beginSection("A compile time error is generated if the fixed local group size of the shader in any dimension is greater than the maximum supported."); 700 verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE); 701 } 702 703 ctx.endSection(); 704 } 705 } 706 707 void invalid_layout_qualifiers (NegativeTestContext& ctx) 708 { 709 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 710 const char* const shaderVersion = isES32 711 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) 712 : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 713 714 { 715 std::ostringstream compShaderSource; 716 compShaderSource << shaderVersion << "\n" 717 << "void main (void)\n" 718 << "{\n" 719 << "}\n"; 720 721 const glu::ComputeSource compSource(compShaderSource.str()); 722 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 723 724 ctx.beginSection("A link error is generated if the compute shader program does not contain an input layout qualifier specifying a fixed local group size."); 725 verifyLinkError(ctx, program); 726 ctx.endSection(); 727 } 728 729 { 730 std::ostringstream compShaderSource; 731 compShaderSource << shaderVersion << "\n" 732 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 733 << "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n" 734 << "void main (void)\n" 735 << "{\n" 736 << "}\n"; 737 738 const glu::ComputeSource compSource(compShaderSource.str()); 739 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 740 741 ctx.beginSection("A compile-time error is generated if a local work group size qualifier is declared more than once in the same shader."); 742 verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE); 743 ctx.endSection(); 744 } 745 746 { 747 std::ostringstream compShaderSource; 748 compShaderSource << shaderVersion << "\n" 749 << "out mediump vec4 fragColor;\n" 750 << "\n" 751 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 752 << "void main (void)\n" 753 << "{\n" 754 << "}\n"; 755 756 const glu::ComputeSource compSource(compShaderSource.str()); 757 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 758 759 ctx.beginSection("A compile-time error is generated if a user defined output variable is declared in a compute shader."); 760 verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE); 761 ctx.endSection(); 762 } 763 764 { 765 std::ostringstream compShaderSource; 766 compShaderSource << shaderVersion << "\n" 767 << "uvec3 gl_NumWorkGroups;\n" 768 << "uvec3 gl_WorkGroupSize;\n" 769 << "uvec3 gl_WorkGroupID;\n" 770 << "uvec3 gl_LocalInvocationID;\n" 771 << "uvec3 gl_GlobalInvocationID;\n" 772 << "uvec3 gl_LocalInvocationIndex;\n" 773 << "\n" 774 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 775 << "void main (void)\n" 776 << "{\n" 777 << "}\n"; 778 779 const glu::ComputeSource compSource(compShaderSource.str()); 780 glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << compSource); 781 782 ctx.beginSection("A compile time or link error is generated if compute shader built-in variables are redeclared."); 783 bool testFailed = false; 784 785 tcu::TestLog& log = ctx.getLog(); 786 log << program; 787 788 testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk); 789 790 if (testFailed) 791 { 792 const char* const message("Program was not expected to compile or link."); 793 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage; 794 ctx.fail(message); 795 } 796 797 ctx.endSection(); 798 } 799 } 800 801 void invalid_write_built_in_constants (NegativeTestContext& ctx) 802 { 803 if ((!ctx.isExtensionSupported("GL_EXT_tessellation_shader") && !ctx.isExtensionSupported("GL_OES_tessellation_shader")) || 804 (!ctx.isExtensionSupported("GL_EXT_geometry_shader") && !ctx.isExtensionSupported("GL_OES_geometry_shader"))) 805 { 806 TCU_THROW(NotSupportedError, "tessellation and geometry shader extensions not supported"); 807 } 808 809 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 810 map<string, string> args; 811 812 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 813 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require"; 814 args["COMPUTE_BUILT_IN_CONSTANTS_STRING"] = " gl_MaxComputeWorkGroupCount = ivec3(65535, 65535, 65535);\n" 815 " gl_MaxComputeWorkGroupCount = ivec3(1024, 1024, 64);\n" 816 " gl_MaxComputeWorkGroupSize = ivec3(512);\n" 817 " gl_MaxComputeUniformComponents = 512;\n" 818 " gl_MaxComputeTextureImageUnits = 16;\n" 819 " gl_MaxComputeImageUniforms = 8;\n" 820 " gl_MaxComputeAtomicCounters = 8;\n" 821 " gl_MaxComputeAtomicCounterBuffers = 1;\n"; 822 823 const glu::VertexSource vertSource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_VERTEX)).specialize(args)); 824 const glu::FragmentSource fragSource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_FRAGMENT)).specialize(args)); 825 const glu::TessellationControlSource tessCtrlSource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_CONTROL)).specialize(args)); 826 const glu::TessellationEvaluationSource tessEvalSource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_EVALUATION)).specialize(args)); 827 const glu::GeometrySource geometrySource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_GEOMETRY)).specialize(args)); 828 const glu::ComputeSource computeSource (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_COMPUTE)).specialize(args)); 829 830 glu::ShaderProgram vertProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource); 831 glu::ShaderProgram fragProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource); 832 glu::ShaderProgram tessCtrlProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource); 833 glu::ShaderProgram tessEvalProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource); 834 glu::ShaderProgram geometryProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << geometrySource); 835 glu::ShaderProgram computeProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << computeSource); 836 837 ctx.beginSection("A compile time is generated if compute built-in constants provided in all shaders are written to."); 838 verifyCompileError(ctx, vertProgram, glu::SHADERTYPE_VERTEX); 839 verifyCompileError(ctx, fragProgram, glu::SHADERTYPE_FRAGMENT); 840 verifyCompileError(ctx, tessCtrlProgram, glu::SHADERTYPE_TESSELLATION_CONTROL); 841 verifyCompileError(ctx, tessEvalProgram, glu::SHADERTYPE_TESSELLATION_EVALUATION); 842 verifyCompileError(ctx, geometryProgram, glu::SHADERTYPE_GEOMETRY); 843 verifyCompileError(ctx, computeProgram, glu::SHADERTYPE_COMPUTE); 844 ctx.endSection(); 845 } 846 847 } // anonymous 848 849 std::vector<FunctionContainer> getNegativeComputeTestFunctions (void) 850 { 851 const FunctionContainer funcs[] = 852 { 853 { program_not_active, "program_not_active", "Use dispatch commands with no active program" }, 854 { invalid_program_query, "invalid_program_query", "Querying GL_COMPUTE_WORK_GROUP_SIZE with glGetProgramiv() on invalid programs" }, 855 { invalid_dispatch_compute_indirect, "invalid_dispatch_compute_indirect", "Invalid glDispatchComputeIndirect usage" }, 856 { invalid_maximum_work_group_counts, "invalid_maximum_work_group_counts", "Maximum workgroup counts for dispatch commands" }, 857 { invalid_maximum_work_group_sizes, "invalid_maximum_work_group_sizes", "Maximum local workgroup sizes declared in compute shaders" }, 858 { invalid_layout_qualifiers, "invalid_layout_qualifiers", "Invalid layout qualifiers in compute shaders" }, 859 { invalid_write_built_in_constants, "invalid_write_built_in_constants", "Invalid writes to built-in compute shader constants" }, 860 { exceed_uniform_block_limit, "exceed_uniform_block_limit", "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS" }, 861 { exceed_shader_storage_block_limit, "exceed_shader_storage_block_limit", "Link error when shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS" }, 862 { exceed_texture_image_units_limit, "exceed_texture_image_units_limit", "Link error when shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS" }, 863 { exceed_image_uniforms_limit, "exceed_image_uniforms_limit", "Link error when shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS" }, 864 { exceed_shared_memory_size_limit, "exceed_shared_memory_size_limit", "Link error when shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE" }, 865 { exceed_uniform_components_limit, "exceed_uniform_components_limit", "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS" }, 866 { exceed_atomic_counter_buffer_limit, "exceed_atomic_counter_buffer_limit", "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS" }, 867 { exceed_atomic_counters_limit, "exceed_atomic_counters_limit", "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS" }, 868 }; 869 870 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); 871 } 872 873 } // NegativeTestShared 874 } // Functional 875 } // gles31 876 } // deqp 877