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 34namespace deqp 35{ 36namespace gles31 37{ 38namespace Functional 39{ 40namespace 41{ 42 43using namespace gls::StateQueryUtil; 44 45static 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 56static 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"; 63static 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"; 70static 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 82class ActiveProgramCase : public TestCase 83{ 84public: 85 ActiveProgramCase (Context& context, QueryType verifier, const char* name, const char* desc); 86 IterateResult iterate (void); 87 88private: 89 const QueryType m_verifier; 90}; 91 92ActiveProgramCase::ActiveProgramCase (Context& context, QueryType verifier, const char* name, const char* desc) 93 : TestCase (context, name, desc) 94 , m_verifier (verifier) 95{ 96} 97 98ActiveProgramCase::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 146class PipelineProgramCase : public TestCase 147{ 148public: 149 PipelineProgramCase (Context& context, QueryType verifier, const char* name, const char* desc, glw::GLenum stage); 150 IterateResult iterate (void); 151 152private: 153 const QueryType m_verifier; 154 const glw::GLenum m_targetStage; 155}; 156 157PipelineProgramCase::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 164PipelineProgramCase::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 221class ValidateStatusCase : public TestCase 222{ 223public: 224 ValidateStatusCase (Context& context, QueryType verifier, const char* name, const char* desc); 225 IterateResult iterate (void); 226 227private: 228 const QueryType m_verifier; 229}; 230 231ValidateStatusCase::ValidateStatusCase (Context& context, QueryType verifier, const char* name, const char* desc) 232 : TestCase (context, name, desc) 233 , m_verifier (verifier) 234{ 235} 236 237ValidateStatusCase::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 284class InfoLogCase : public TestCase 285{ 286public: 287 InfoLogCase (Context& context, const char* name, const char* desc); 288 IterateResult iterate (void); 289}; 290 291InfoLogCase::InfoLogCase (Context& context, const char* name, const char* desc) 292 : TestCase(context, name, desc) 293{ 294} 295 296InfoLogCase::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 378ProgramPipelineStateQueryTests::ProgramPipelineStateQueryTests (Context& context) 379 : TestCaseGroup(context, "program_pipeline", "Program Pipeline State Query tests") 380{ 381} 382 383ProgramPipelineStateQueryTests::~ProgramPipelineStateQueryTests (void) 384{ 385} 386 387void 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