es31fProgramStateQueryTests.cpp revision c423ce6164cdd88c8c3e47bec4ec34476743042a
1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2015 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 Program State Query tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fProgramStateQueryTests.hpp" 25#include "es31fInfoLogQueryShared.hpp" 26#include "glsStateQueryUtil.hpp" 27#include "gluRenderContext.hpp" 28#include "gluCallLogWrapper.hpp" 29#include "gluContextInfo.hpp" 30#include "gluObjectWrapper.hpp" 31#include "gluShaderProgram.hpp" 32#include "glwFunctions.hpp" 33#include "glwEnums.hpp" 34 35namespace deqp 36{ 37namespace gles31 38{ 39namespace Functional 40{ 41namespace 42{ 43 44using namespace gls::StateQueryUtil; 45 46static const char* getVerifierSuffix (QueryType type) 47{ 48 switch (type) 49 { 50 case QUERY_PROGRAM_INTEGER_VEC3: 51 case QUERY_PROGRAM_INTEGER: 52 return "get_programiv"; 53 54 default: 55 DE_ASSERT(DE_FALSE); 56 return DE_NULL; 57 } 58} 59 60class ProgramSeparableCase : public TestCase 61{ 62public: 63 ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc); 64 IterateResult iterate (void); 65 66private: 67 const QueryType m_verifier; 68}; 69 70ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc) 71 : TestCase (context, name, desc) 72 , m_verifier (verifier) 73{ 74} 75 76ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void) 77{ 78 static const char* const s_vertexSource = "#version 310 es\n" 79 "out highp vec4 v_color;\n" 80 "void main()\n" 81 "{\n" 82 " gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n" 83 " v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n" 84 "}\n"; 85 static const char* const s_fragmentSource = "#version 310 es\n" 86 "in highp vec4 v_color;\n" 87 "layout(location=0) out highp vec4 o_color;\n" 88 "void main()\n" 89 "{\n" 90 " o_color = v_color;\n" 91 "}\n"; 92 93 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 94 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 95 glu::Shader vtxShader (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX); 96 glu::Shader frgShader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT); 97 98 vtxShader.setSources(1, &s_vertexSource, DE_NULL); 99 frgShader.setSources(1, &s_fragmentSource, DE_NULL); 100 101 vtxShader.compile(); 102 frgShader.compile(); 103 104 { 105 const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader"); 106 m_testCtx.getLog() << vtxShader; 107 } 108 109 { 110 const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader"); 111 m_testCtx.getLog() << frgShader; 112 } 113 114 if (!vtxShader.getCompileStatus() || !frgShader.getCompileStatus()) 115 throw tcu::TestError("failed to build shaders"); 116 117 gl.enableLogging(true); 118 119 { 120 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial"); 121 glu::Program program (m_context.getRenderContext()); 122 123 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier); 124 } 125 126 { 127 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetFalse", "SetFalse"); 128 glu::Program program (m_context.getRenderContext()); 129 int linkStatus = 0; 130 131 gl.glAttachShader(program.getProgram(), vtxShader.getShader()); 132 gl.glAttachShader(program.getProgram(), frgShader.getShader()); 133 gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE); 134 gl.glLinkProgram(program.getProgram()); 135 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program"); 136 137 gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus); 138 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status"); 139 140 if (linkStatus == GL_FALSE) 141 throw tcu::TestError("failed to link program"); 142 143 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier); 144 } 145 146 { 147 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetTrue", "SetTrue"); 148 glu::Program program (m_context.getRenderContext()); 149 int linkStatus = 0; 150 151 gl.glAttachShader(program.getProgram(), vtxShader.getShader()); 152 gl.glAttachShader(program.getProgram(), frgShader.getShader()); 153 gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE); 154 gl.glLinkProgram(program.getProgram()); 155 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program"); 156 157 gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus); 158 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status"); 159 160 if (linkStatus == GL_FALSE) 161 throw tcu::TestError("failed to link program"); 162 163 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier); 164 } 165 166 result.setTestContextResult(m_testCtx); 167 return STOP; 168} 169 170class ComputeWorkGroupSizeCase : public TestCase 171{ 172public: 173 ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc); 174 IterateResult iterate (void); 175 176private: 177 const QueryType m_verifier; 178}; 179 180ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc) 181 : TestCase (context, name, desc) 182 , m_verifier (verifier) 183{ 184} 185 186ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void) 187{ 188 static const char* const s_computeSource1D = "#version 310 es\n" 189 "layout (local_size_x = 3) in;\n" 190 "layout(binding = 0) buffer Output\n" 191 "{\n" 192 " highp float val;\n" 193 "} sb_out;\n" 194 "\n" 195 "void main (void)\n" 196 "{\n" 197 " sb_out.val = 1.0;\n" 198 "}\n"; 199 static const char* const s_computeSource2D = "#version 310 es\n" 200 "layout (local_size_x = 3, local_size_y = 2) in;\n" 201 "layout(binding = 0) buffer Output\n" 202 "{\n" 203 " highp float val;\n" 204 "} sb_out;\n" 205 "\n" 206 "void main (void)\n" 207 "{\n" 208 " sb_out.val = 1.0;\n" 209 "}\n"; 210 static const char* const s_computeSource3D = "#version 310 es\n" 211 "layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n" 212 "layout(binding = 0) buffer Output\n" 213 "{\n" 214 " highp float val;\n" 215 "} sb_out;\n" 216 "\n" 217 "void main (void)\n" 218 "{\n" 219 " sb_out.val = 1.0;\n" 220 "}\n"; 221 222 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 223 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 224 225 gl.enableLogging(true); 226 227 { 228 const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneDimensional", "1D"); 229 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1D)); 230 231 m_testCtx.getLog() << program; 232 if (!program.isOk()) 233 throw tcu::TestError("failed to build program"); 234 235 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier); 236 } 237 238 { 239 const tcu::ScopedLogSection section (m_testCtx.getLog(), "TwoDimensional", "2D"); 240 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource2D)); 241 242 m_testCtx.getLog() << program; 243 if (!program.isOk()) 244 throw tcu::TestError("failed to build program"); 245 246 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier); 247 } 248 249 { 250 const tcu::ScopedLogSection section (m_testCtx.getLog(), "TreeDimensional", "3D"); 251 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource3D)); 252 253 m_testCtx.getLog() << program; 254 if (!program.isOk()) 255 throw tcu::TestError("failed to build program"); 256 257 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier); 258 } 259 260 result.setTestContextResult(m_testCtx); 261 return STOP; 262} 263 264class ActiveAtomicCounterBuffersCase : public TestCase 265{ 266public: 267 ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc); 268 IterateResult iterate (void); 269 270private: 271 const QueryType m_verifier; 272}; 273 274ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc) 275 : TestCase (context, name, desc) 276 , m_verifier (verifier) 277{ 278} 279 280ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void) 281{ 282 static const char* const s_computeSource0 = "#version 310 es\n" 283 "layout (local_size_x = 3) in;\n" 284 "layout(binding = 0) buffer Output\n" 285 "{\n" 286 " highp float val;\n" 287 "} sb_out;\n" 288 "\n" 289 "void main (void)\n" 290 "{\n" 291 " sb_out.val = 1.0;\n" 292 "}\n"; 293 static const char* const s_computeSource1 = "#version 310 es\n" 294 "layout (local_size_x = 3) in;\n" 295 "layout(binding = 0) uniform highp atomic_uint u_counters[2];\n" 296 "layout(binding = 0) buffer Output\n" 297 "{\n" 298 " highp float val;\n" 299 "} sb_out;\n" 300 "\n" 301 "void main (void)\n" 302 "{\n" 303 " sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n" 304 "}\n"; 305 306 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 307 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 308 309 gl.enableLogging(true); 310 311 { 312 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial"); 313 glu::Program program (m_context.getRenderContext()); 314 315 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier); 316 } 317 318 { 319 const tcu::ScopedLogSection section (m_testCtx.getLog(), "NoBuffers", "No buffers"); 320 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource0)); 321 322 m_testCtx.getLog() << program; 323 if (!program.isOk()) 324 throw tcu::TestError("failed to build program"); 325 326 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier); 327 } 328 329 { 330 const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneBuffer", "One buffer"); 331 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1)); 332 333 m_testCtx.getLog() << program; 334 if (!program.isOk()) 335 throw tcu::TestError("failed to build program"); 336 337 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier); 338 } 339 340 result.setTestContextResult(m_testCtx); 341 return STOP; 342} 343 344class ProgramLogCase : public TestCase 345{ 346public: 347 enum BuildErrorType 348 { 349 BUILDERROR_VERTEX_FRAGMENT = 0, 350 BUILDERROR_COMPUTE, 351 BUILDERROR_GEOMETRY, 352 BUILDERROR_TESSELLATION, 353 }; 354 355 ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType); 356 357private: 358 void init (void); 359 IterateResult iterate (void); 360 glu::ProgramSources getProgramSources (void) const; 361 362 const BuildErrorType m_buildErrorType; 363}; 364 365ProgramLogCase::ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType) 366 : TestCase (ctx, name, desc) 367 , m_buildErrorType (errorType) 368{ 369} 370 371void ProgramLogCase::init (void) 372{ 373 switch (m_buildErrorType) 374 { 375 case BUILDERROR_VERTEX_FRAGMENT: 376 case BUILDERROR_COMPUTE: 377 break; 378 379 case BUILDERROR_GEOMETRY: 380 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 381 throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension"); 382 break; 383 384 case BUILDERROR_TESSELLATION: 385 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")) 386 throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension"); 387 break; 388 389 default: 390 DE_ASSERT(false); 391 break; 392 } 393} 394 395ProgramLogCase::IterateResult ProgramLogCase::iterate (void) 396{ 397 using gls::StateQueryUtil::StateQueryMemoryWriteGuard; 398 399 tcu::ResultCollector result (m_testCtx.getLog()); 400 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 401 glu::ShaderProgram program (m_context.getRenderContext(), getProgramSources()); 402 StateQueryMemoryWriteGuard<glw::GLint> logLen; 403 404 gl.enableLogging(true); 405 406 m_testCtx.getLog() << tcu::TestLog::Message << "Trying to link a broken program." << tcu::TestLog::EndMessage; 407 408 gl.glGetProgramiv(program.getProgram(), GL_INFO_LOG_LENGTH, &logLen); 409 logLen.verifyValidity(result); 410 411 if (logLen.verifyValidity(result)) 412 verifyInfoLogQuery(result, gl, logLen, program.getProgram(), &glu::CallLogWrapper::glGetProgramInfoLog, "glGetProgramInfoLog"); 413 414 result.setTestContextResult(m_testCtx); 415 return STOP; 416} 417 418glu::ProgramSources ProgramLogCase::getProgramSources (void) const 419{ 420 switch (m_buildErrorType) 421 { 422 case BUILDERROR_VERTEX_FRAGMENT: 423 return glu::ProgramSources() 424 << glu::VertexSource("#version 310 es\n" 425 "in highp vec4 a_pos;\n" 426 "uniform highp vec4 u_uniform;\n" 427 "void main()\n" 428 "{\n" 429 " gl_Position = a_pos + u_uniform;\n" 430 "}\n") 431 << glu::FragmentSource("#version 310 es\n" 432 "in highp vec4 v_missingVar;\n" 433 "uniform highp int u_uniform;\n" 434 "layout(location = 0) out mediump vec4 fragColor;\n" 435 "void main()\n" 436 "{\n" 437 " fragColor = v_missingVar + vec4(float(u_uniform));\n" 438 "}\n"); 439 440 case BUILDERROR_COMPUTE: 441 return glu::ProgramSources() 442 << glu::ComputeSource("#version 310 es\n" 443 "layout (binding = 0) buffer IOBuffer { highp float buf_var; };\n" 444 "uniform highp vec4 u_uniform;\n" 445 "void main()\n" 446 "{\n" 447 " buf_var = u_uniform.x;\n" 448 "}\n"); 449 450 case BUILDERROR_GEOMETRY: 451 return glu::ProgramSources() 452 << glu::VertexSource("#version 310 es\n" 453 "in highp vec4 a_pos;\n" 454 "uniform highp vec4 u_uniform;\n" 455 "void main()\n" 456 "{\n" 457 " gl_Position = a_pos + u_uniform;\n" 458 "}\n") 459 << glu::GeometrySource("#version 310 es\n" 460 "#extension GL_EXT_geometry_shader : require\n" 461 "layout(triangles) in;\n" 462 "layout(max_vertices=1, points) out;\n" 463 "in highp vec4 v_missingVar[];\n" 464 "uniform highp int u_uniform;\n" 465 "void main()\n" 466 "{\n" 467 " gl_Position = gl_in[0].gl_Position + v_missingVar[2] + vec4(float(u_uniform));\n" 468 " EmitVertex();\n" 469 "}\n") 470 << glu::FragmentSource("#version 310 es\n" 471 "layout(location = 0) out mediump vec4 fragColor;\n" 472 "void main()\n" 473 "{\n" 474 " fragColor = vec4(1.0);\n" 475 "}\n"); 476 477 case BUILDERROR_TESSELLATION: 478 return glu::ProgramSources() 479 << glu::VertexSource("#version 310 es\n" 480 "in highp vec4 a_pos;\n" 481 "void main()\n" 482 "{\n" 483 " gl_Position = a_pos;\n" 484 "}\n") 485 << glu::TessellationControlSource("#version 310 es\n" 486 "#extension GL_EXT_tessellation_shader : require\n" 487 "layout(vertices=2) out;" 488 "patch out highp vec2 vp_var;\n" 489 "void main()\n" 490 "{\n" 491 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position\n" 492 " gl_TessLevelOuter[0] = 0.8;\n" 493 " gl_TessLevelOuter[1] = 0.8;\n" 494 " if (gl_InvocationID == 0)\n" 495 " vp_var = gl_in[gl_InvocationID].gl_Position.xy;\n" 496 "}\n") 497 << glu::TessellationEvaluationSource("#version 310 es\n" 498 "#extension GL_EXT_tessellation_shader : require\n" 499 "layout(isolines) in;" 500 "in highp float vp_var[];\n" 501 "void main()\n" 502 "{\n" 503 " gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(vp_var[1]);\n" 504 "}\n") 505 << glu::FragmentSource("#version 310 es\n" 506 "layout(location = 0) out mediump vec4 fragColor;\n" 507 "void main()\n" 508 "{\n" 509 " fragColor = vec4(1.0);\n" 510 "}\n"); 511 512 default: 513 DE_ASSERT(false); 514 return glu::ProgramSources(); 515 } 516} 517 518} // anonymous 519 520ProgramStateQueryTests::ProgramStateQueryTests (Context& context) 521 : TestCaseGroup(context, "program", "Program State Query tests") 522{ 523} 524 525ProgramStateQueryTests::~ProgramStateQueryTests (void) 526{ 527} 528 529void ProgramStateQueryTests::init (void) 530{ 531 static const QueryType intVerifiers[] = 532 { 533 QUERY_PROGRAM_INTEGER, 534 }; 535 static const QueryType intVec3Verifiers[] = 536 { 537 QUERY_PROGRAM_INTEGER_VEC3, 538 }; 539 540#define FOR_EACH_INT_VERIFIER(X) \ 541 for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx) \ 542 { \ 543 const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]); \ 544 const QueryType verifier = intVerifiers[verifierNdx]; \ 545 this->addChild(X); \ 546 } 547 548#define FOR_EACH_VEC_VERIFIER(X) \ 549 for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx) \ 550 { \ 551 const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]); \ 552 const QueryType verifier = intVec3Verifiers[verifierNdx]; \ 553 this->addChild(X); \ 554 } 555 556 FOR_EACH_INT_VERIFIER(new ProgramSeparableCase (m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(), "Test PROGRAM_SEPARABLE")); 557 FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase (m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(), "Test COMPUTE_WORK_GROUP_SIZE")); 558 FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase (m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(), "Test ACTIVE_ATOMIC_COUNTER_BUFFERS")); 559 560#undef FOR_EACH_INT_VERIFIER 561#undef FOR_EACH_VEC_VERIFIER 562 563 // program info log tests 564 // \note, there exists similar tests in gles3 module. However, the gles31 could use a different 565 // shader compiler with different INFO_LOG bugs. 566 { 567 static const struct 568 { 569 const char* caseName; 570 ProgramLogCase::BuildErrorType caseType; 571 } shaderTypes[] = 572 { 573 { "info_log_vertex_fragment_link_fail", ProgramLogCase::BUILDERROR_VERTEX_FRAGMENT }, 574 { "info_log_compute_link_fail", ProgramLogCase::BUILDERROR_COMPUTE }, 575 { "info_log_geometry_link_fail", ProgramLogCase::BUILDERROR_GEOMETRY }, 576 { "info_log_tessellation_link_fail", ProgramLogCase::BUILDERROR_TESSELLATION }, 577 }; 578 579 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx) 580 addChild(new ProgramLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType)); 581 } 582} 583 584} // Functional 585} // gles31 586} // deqp 587