Home | History | Annotate | Download | only in functional
      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