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 Pipeline State Query tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fProgramPipelineStateQueryTests.hpp" 25 #include "es31fInfoLogQueryShared.hpp" 26 #include "glsStateQueryUtil.hpp" 27 #include "gluRenderContext.hpp" 28 #include "gluCallLogWrapper.hpp" 29 #include "gluObjectWrapper.hpp" 30 #include "gluShaderProgram.hpp" 31 #include "glwFunctions.hpp" 32 #include "glwEnums.hpp" 33 34 namespace deqp 35 { 36 namespace gles31 37 { 38 namespace Functional 39 { 40 namespace 41 { 42 43 using namespace gls::StateQueryUtil; 44 45 static const char* getVerifierSuffix (QueryType type) 46 { 47 switch (type) 48 { 49 case QUERY_PIPELINE_INTEGER: return "get_program_pipelineiv"; 50 default: 51 DE_ASSERT(DE_FALSE); 52 return DE_NULL; 53 } 54 } 55 56 static const char* const s_vertexSource = "#version 310 es\n" 57 "out highp vec4 v_color;\n" 58 "void main()\n" 59 "{\n" 60 " gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n" 61 " v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n" 62 "}\n"; 63 static const char* const s_fragmentSource = "#version 310 es\n" 64 "in highp vec4 v_color;\n" 65 "layout(location=0) out highp vec4 o_color;\n" 66 "void main()\n" 67 "{\n" 68 " o_color = v_color;\n" 69 "}\n"; 70 static const char* const s_computeSource = "#version 310 es\n" 71 "layout (local_size_x = 1, local_size_y = 1) in;\n" 72 "layout(binding = 0) buffer Output\n" 73 "{\n" 74 " highp float val;\n" 75 "} sb_out;\n" 76 "\n" 77 "void main (void)\n" 78 "{\n" 79 " sb_out.val = 1.0;\n" 80 "}\n"; 81 82 class ActiveProgramCase : public TestCase 83 { 84 public: 85 ActiveProgramCase (Context& context, QueryType verifier, const char* name, const char* desc); 86 IterateResult iterate (void); 87 88 private: 89 const QueryType m_verifier; 90 }; 91 92 ActiveProgramCase::ActiveProgramCase (Context& context, QueryType verifier, const char* name, const char* desc) 93 : TestCase (context, name, desc) 94 , m_verifier (verifier) 95 { 96 } 97 98 ActiveProgramCase::IterateResult ActiveProgramCase::iterate (void) 99 { 100 const glu::ShaderProgram vtxProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource)); 101 const glu::ShaderProgram frgProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource)); 102 const glu::ProgramPipeline pipeline (m_context.getRenderContext()); 103 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 104 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 105 106 { 107 const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program"); 108 m_testCtx.getLog() << vtxProgram; 109 } 110 111 { 112 const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program"); 113 m_testCtx.getLog() << frgProgram; 114 } 115 116 if (!vtxProgram.isOk() || !frgProgram.isOk()) 117 throw tcu::TestError("failed to build program"); 118 119 gl.enableLogging(true); 120 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 121 122 gl.glBindProgramPipeline(pipeline.getPipeline()); 123 gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram()); 124 gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram()); 125 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 126 gl.glBindProgramPipeline(0); 127 GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline"); 128 129 { 130 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 131 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, 0, m_verifier); 132 } 133 134 { 135 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set"); 136 137 gl.glActiveShaderProgram(pipeline.getPipeline(), frgProgram.getProgram()); 138 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 139 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, (int)frgProgram.getProgram(), m_verifier); 140 } 141 142 result.setTestContextResult(m_testCtx); 143 return STOP; 144 } 145 146 class PipelineProgramCase : public TestCase 147 { 148 public: 149 PipelineProgramCase (Context& context, QueryType verifier, const char* name, const char* desc, glw::GLenum stage); 150 IterateResult iterate (void); 151 152 private: 153 const QueryType m_verifier; 154 const glw::GLenum m_targetStage; 155 }; 156 157 PipelineProgramCase::PipelineProgramCase (Context& context, QueryType verifier, const char* name, const char* desc, glw::GLenum stage) 158 : TestCase (context, name, desc) 159 , m_verifier (verifier) 160 , m_targetStage (stage) 161 { 162 } 163 164 PipelineProgramCase::IterateResult PipelineProgramCase::iterate (void) 165 { 166 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 167 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 168 const int stageBit = (m_targetStage == GL_VERTEX_SHADER) ? (GL_VERTEX_SHADER_BIT) 169 : (m_targetStage == GL_FRAGMENT_SHADER) ? (GL_FRAGMENT_SHADER_BIT) 170 : (GL_COMPUTE_SHADER_BIT); 171 glu::ProgramSources sources; 172 173 if (m_targetStage == GL_VERTEX_SHADER) 174 sources << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource); 175 else if (m_targetStage == GL_FRAGMENT_SHADER) 176 sources << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource); 177 else if (m_targetStage == GL_COMPUTE_SHADER) 178 sources << glu::ProgramSeparable(true) << glu::ComputeSource(s_computeSource); 179 else 180 DE_ASSERT(false); 181 182 gl.enableLogging(true); 183 184 { 185 glu::ShaderProgram program(m_context.getRenderContext(), sources); 186 187 { 188 const tcu::ScopedLogSection section(m_testCtx.getLog(), "program", "Program"); 189 m_testCtx.getLog() << program; 190 } 191 192 if (!program.isOk()) 193 throw tcu::TestError("failed to build program"); 194 195 { 196 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial"); 197 glu::ProgramPipeline pipeline (m_context.getRenderContext()); 198 199 gl.glBindProgramPipeline(pipeline.getPipeline()); 200 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline"); 201 202 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, 0, m_verifier); 203 } 204 205 { 206 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Set", "Set"); 207 glu::ProgramPipeline pipeline (m_context.getRenderContext()); 208 209 gl.glBindProgramPipeline(pipeline.getPipeline()); 210 gl.glUseProgramStages(pipeline.getPipeline(), stageBit, program.getProgram()); 211 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline"); 212 213 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, program.getProgram(), m_verifier); 214 } 215 } 216 217 result.setTestContextResult(m_testCtx); 218 return STOP; 219 } 220 221 class ValidateStatusCase : public TestCase 222 { 223 public: 224 ValidateStatusCase (Context& context, QueryType verifier, const char* name, const char* desc); 225 IterateResult iterate (void); 226 227 private: 228 const QueryType m_verifier; 229 }; 230 231 ValidateStatusCase::ValidateStatusCase (Context& context, QueryType verifier, const char* name, const char* desc) 232 : TestCase (context, name, desc) 233 , m_verifier (verifier) 234 { 235 } 236 237 ValidateStatusCase::IterateResult ValidateStatusCase::iterate (void) 238 { 239 glu::ShaderProgram vtxProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource)); 240 glu::ShaderProgram frgProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource)); 241 glu::ProgramPipeline pipeline (m_context.getRenderContext()); 242 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 243 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 244 245 { 246 const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program"); 247 m_testCtx.getLog() << vtxProgram; 248 } 249 250 { 251 const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program"); 252 m_testCtx.getLog() << frgProgram; 253 } 254 255 if (!vtxProgram.isOk() || !frgProgram.isOk()) 256 throw tcu::TestError("failed to build program"); 257 258 gl.enableLogging(true); 259 260 gl.glBindProgramPipeline(pipeline.getPipeline()); 261 gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram()); 262 gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram()); 263 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 264 gl.glBindProgramPipeline(0); 265 GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline"); 266 267 { 268 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 269 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, 0, m_verifier); 270 } 271 272 { 273 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Validate"); 274 275 gl.glValidateProgramPipeline(pipeline.getPipeline()); 276 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 277 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, GL_TRUE, m_verifier); 278 } 279 280 result.setTestContextResult(m_testCtx); 281 return STOP; 282 } 283 284 class InfoLogCase : public TestCase 285 { 286 public: 287 InfoLogCase (Context& context, const char* name, const char* desc); 288 IterateResult iterate (void); 289 }; 290 291 InfoLogCase::InfoLogCase (Context& context, const char* name, const char* desc) 292 : TestCase(context, name, desc) 293 { 294 } 295 296 InfoLogCase::IterateResult InfoLogCase::iterate (void) 297 { 298 using gls::StateQueryUtil::StateQueryMemoryWriteGuard; 299 300 static const char* const s_incompatibleFragmentSource = "#version 310 es\n" 301 "in mediump vec2 v_colorB;\n" 302 "in mediump vec2 v_colorC;\n" 303 "layout(location=0) out highp vec4 o_color;\n" 304 "void main()\n" 305 "{\n" 306 " o_color = v_colorB.xxyy + v_colorC.yyxy;\n" 307 "}\n"; 308 309 glu::ShaderProgram vtxProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource)); 310 glu::ShaderProgram frgProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_incompatibleFragmentSource)); 311 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 312 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 313 314 { 315 const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program"); 316 m_testCtx.getLog() << vtxProgram; 317 } 318 319 { 320 const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program"); 321 m_testCtx.getLog() << frgProgram; 322 } 323 324 if (!vtxProgram.isOk() || !frgProgram.isOk()) 325 throw tcu::TestError("failed to build program"); 326 327 gl.enableLogging(true); 328 329 { 330 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial"); 331 glu::ProgramPipeline pipeline (m_context.getRenderContext()); 332 std::string buf (3, 'X'); 333 int written = -1; 334 335 verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_INFO_LOG_LENGTH, 0, QUERY_PIPELINE_INTEGER); 336 337 gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 2, &written, &buf[0]); 338 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query log"); 339 340 if (written == -1) 341 result.fail("'length' was not written to"); 342 else if (written != 0) 343 result.fail("'length' was not 0"); 344 else if (buf[0] != '\0') 345 result.fail("log was not 0-sized null-terminated string"); 346 else if (buf[1] != 'X' || buf[2] != 'X') 347 result.fail("buffer after returned length modified"); 348 } 349 350 { 351 const tcu::ScopedLogSection superSection (m_testCtx.getLog(), "ValidationFail", "Failed validation"); 352 glu::ProgramPipeline pipeline (m_context.getRenderContext()); 353 StateQueryMemoryWriteGuard<glw::GLint> logLen; 354 355 gl.glBindProgramPipeline(pipeline.getPipeline()); 356 gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram()); 357 gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram()); 358 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 359 360 gl.glBindProgramPipeline(0); 361 GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline"); 362 gl.glValidateProgramPipeline(pipeline.getPipeline()); 363 GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline"); 364 365 gl.glGetProgramPipelineiv(pipeline.getPipeline(), GL_INFO_LOG_LENGTH, &logLen); 366 GLU_EXPECT_NO_ERROR(gl.glGetError(), "get INFO_LOG_LENGTH"); 367 368 if (logLen.verifyValidity(result)) 369 verifyInfoLogQuery(result, gl, logLen, pipeline.getPipeline(), &glu::CallLogWrapper::glGetProgramPipelineInfoLog, "glGetProgramPipelineInfoLog"); 370 } 371 372 result.setTestContextResult(m_testCtx); 373 return STOP; 374 } 375 376 } // anonymous 377 378 ProgramPipelineStateQueryTests::ProgramPipelineStateQueryTests (Context& context) 379 : TestCaseGroup(context, "program_pipeline", "Program Pipeline State Query tests") 380 { 381 } 382 383 ProgramPipelineStateQueryTests::~ProgramPipelineStateQueryTests (void) 384 { 385 } 386 387 void ProgramPipelineStateQueryTests::init (void) 388 { 389 static const QueryType verifiers[] = 390 { 391 QUERY_PIPELINE_INTEGER, 392 }; 393 394 #define FOR_EACH_VERIFIER(X) \ 395 for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx) \ 396 { \ 397 const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]); \ 398 const QueryType verifier = verifiers[verifierNdx]; \ 399 this->addChild(X); \ 400 } 401 402 FOR_EACH_VERIFIER(new ActiveProgramCase(m_context, verifier, (std::string("active_program_") + verifierSuffix).c_str(), "Test ACTIVE_PROGRAM")); 403 FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("vertex_shader_") + verifierSuffix).c_str(), "Test VERTEX_SHADER", GL_VERTEX_SHADER)); 404 FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("fragment_shader_") + verifierSuffix).c_str(), "Test FRAGMENT_SHADER", GL_FRAGMENT_SHADER)); 405 FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("compute_shader_") + verifierSuffix).c_str(), "Test COMPUTE_SHADER", GL_COMPUTE_SHADER)); 406 FOR_EACH_VERIFIER(new ValidateStatusCase(m_context, verifier, (std::string("validate_status_") + verifierSuffix).c_str(), "Test VALIDATE_STATUS")); 407 408 #undef FOR_EACH_VERIFIER 409 410 this->addChild(new InfoLogCase(m_context, "info_log", "Test info log")); 411 } 412 413 } // Functional 414 } // gles31 415 } // deqp 416