Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2016 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 Tessellation tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fNegativeTessellationTests.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 
     44 using tcu::TestLog;
     45 using namespace glw;
     46 
     47 static const char* vertexShaderSource		=	"${GLSL_VERSION_STRING}\n"
     48 												"\n"
     49 												"void main (void)\n"
     50 												"{\n"
     51 												"	gl_Position = vec4(0.0);\n"
     52 												"}\n";
     53 
     54 static const char* fragmentShaderSource		=	"${GLSL_VERSION_STRING}\n"
     55 												"precision mediump float;\n"
     56 												"layout(location = 0) out mediump vec4 fragColor;\n"
     57 												"\n"
     58 												"void main (void)\n"
     59 												"{\n"
     60 												"	fragColor = vec4(1.0);\n"
     61 												"}\n";
     62 
     63 static const char* tessControlShaderSource	=	"${GLSL_VERSION_STRING}\n"
     64 												"${GLSL_TESS_EXTENSION_STRING}\n"
     65 												"layout (vertices=3) out;\n"
     66 												"\n"
     67 												"void main()\n"
     68 												"{\n"
     69 												"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
     70 												"}\n";
     71 
     72 static const char* tessEvalShaderSource		=	"${GLSL_VERSION_STRING}\n"
     73 												"${GLSL_TESS_EXTENSION_STRING}\n"
     74 												"layout(triangles) in;\n"
     75 												"\n"
     76 												"void main()\n"
     77 												"{\n"
     78 												"	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;\n"
     79 												"}\n";
     80 
     81 static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
     82 {
     83 	if (!ctx.getContextInfo().isExtensionSupported(extName))
     84 		throw tcu::NotSupportedError(string(extName) + " not supported");
     85 }
     86 
     87 static void checkTessellationSupport (NegativeTestContext& ctx)
     88 {
     89 	checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
     90 }
     91 
     92 // Helper for constructing tessellation pipeline sources.
     93 static glu::ProgramSources makeTessPipelineSources (const std::string& vertexSrc, const std::string& fragmentSrc, const std::string& tessCtrlSrc, const std::string& tessEvalSrc)
     94 {
     95 	glu::ProgramSources sources;
     96 	sources.sources[glu::SHADERTYPE_VERTEX].push_back(vertexSrc);
     97 	sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
     98 
     99 	if (!tessCtrlSrc.empty())
    100 		sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(tessCtrlSrc);
    101 
    102 	if (!tessEvalSrc.empty())
    103 		sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(tessEvalSrc);
    104 
    105 	return sources;
    106 }
    107 
    108 // Incomplete active tess shaders
    109 void single_tessellation_stage (NegativeTestContext& ctx)
    110 {
    111 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    112 	const bool					requireTES = !ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5");
    113 	map<string, string>			args;
    114 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    115 	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    116 
    117 	checkTessellationSupport(ctx);
    118 
    119 	{
    120 		glu::ShaderProgram program(ctx.getRenderContext(),
    121 								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    122 														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    123 														   tcu::StringTemplate(tessControlShaderSource).specialize(args),
    124 														   "")); // missing tessEvalShaderSource
    125 		tcu::TestLog& log = ctx.getLog();
    126 		log << program;
    127 
    128 		ctx.beginSection("A link error is generated if a non-separable program has a tessellation control shader but no tessellation evaluation shader, unless GL_NV_gpu_shader5 is supported.");
    129 
    130 		if (requireTES && program.isOk())
    131 			ctx.fail("Program was not expected to link");
    132 		else if (!requireTES && !program.isOk())
    133 			ctx.fail("Program was expected to link");
    134 
    135 		ctx.endSection();
    136 	}
    137 
    138 	{
    139 		glu::ShaderProgram program(ctx.getRenderContext(),
    140 								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    141 														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    142 														   tcu::StringTemplate(tessControlShaderSource).specialize(args),
    143 														   "") // missing tessEvalShaderSource
    144 								   << glu::ProgramSeparable(true));
    145 		tcu::TestLog& log = ctx.getLog();
    146 		log << program;
    147 
    148 		if (!program.isOk())
    149 			TCU_THROW(TestError, "failed to build program");
    150 
    151 		ctx.glUseProgram(program.getProgram());
    152 		ctx.expectError(GL_NO_ERROR);
    153 
    154 		ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation control shader but no tessellation evaluation shader, unless GL_NV_gpu_shader5 is supported.");
    155 		ctx.glDrawArrays(GL_PATCHES, 0, 3);
    156 		ctx.expectError(requireTES ? GL_INVALID_OPERATION : GL_NO_ERROR);
    157 		ctx.endSection();
    158 
    159 		ctx.glUseProgram(0);
    160 	}
    161 
    162 	{
    163 		glu::ShaderProgram program(ctx.getRenderContext(),
    164 								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    165 														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    166 														   "", // missing tessControlShaderSource
    167 														   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
    168 		tcu::TestLog& log = ctx.getLog();
    169 		log << program;
    170 
    171 		ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
    172 
    173 		if (program.isOk())
    174 			ctx.fail("Program was not expected to link");
    175 
    176 		ctx.endSection();
    177 	}
    178 
    179 	{
    180 		glu::ShaderProgram program(ctx.getRenderContext(),
    181 								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    182 														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    183 														   "", // missing tessControlShaderSource
    184 														   tcu::StringTemplate(tessEvalShaderSource).specialize(args))
    185 									<< glu::ProgramSeparable(true));
    186 		tcu::TestLog& log = ctx.getLog();
    187 		log << program;
    188 
    189 		if (!program.isOk())
    190 			TCU_THROW(TestError, "failed to build program");
    191 
    192 		ctx.glUseProgram(program.getProgram());
    193 		ctx.expectError(GL_NO_ERROR);
    194 
    195 		ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation evaluation shader but no tessellation control shader.");
    196 		ctx.glDrawArrays(GL_PATCHES, 0, 3);
    197 		ctx.expectError(GL_INVALID_OPERATION);
    198 		ctx.endSection();
    199 
    200 		ctx.glUseProgram(0);
    201 	}
    202 }
    203 
    204 // Complete active tess shaders invalid primitive mode
    205 void invalid_primitive_mode (NegativeTestContext& ctx)
    206 {
    207 	checkTessellationSupport(ctx);
    208 
    209 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    210 	map<string, string>			args;
    211 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    212 	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    213 
    214 	glu::ShaderProgram program(ctx.getRenderContext(),
    215 							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    216 													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    217 													   tcu::StringTemplate(tessControlShaderSource).specialize(args),
    218 													   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
    219 	tcu::TestLog& log = ctx.getLog();
    220 	log << program;
    221 
    222 	ctx.glUseProgram(program.getProgram());
    223 	ctx.expectError(GL_NO_ERROR);
    224 
    225 	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and primitive mode is not GL_PATCHES.");
    226 	ctx.glDrawArrays(GL_TRIANGLES, 0, 3);
    227 	ctx.expectError(GL_INVALID_OPERATION);
    228 	ctx.endSection();
    229 
    230 	ctx.glUseProgram(0);
    231 }
    232 
    233 void tessellation_not_active (NegativeTestContext& ctx)
    234 {
    235 	checkTessellationSupport(ctx);
    236 
    237 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    238 	const glw::GLenum			tessErr = ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5") ? GL_NO_ERROR : GL_INVALID_OPERATION;
    239 	map<string, string>			args;
    240 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    241 	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    242 
    243 	glu::ShaderProgram program(ctx.getRenderContext(),
    244 							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    245 													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    246 													   "",		// missing tessControlShaderSource
    247 													   ""));	// missing tessEvalShaderSource
    248 	tcu::TestLog& log = ctx.getLog();
    249 	log << program;
    250 
    251 	ctx.glUseProgram(program.getProgram());
    252 	ctx.expectError(GL_NO_ERROR);
    253 
    254 	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is not active and primitive mode is GL_PATCHES, unless GL_NV_gpu_shader5 is supported.");
    255 	ctx.glDrawArrays(GL_PATCHES, 0, 3);
    256 	ctx.expectError(tessErr);
    257 	ctx.endSection();
    258 
    259 	ctx.glUseProgram(0);
    260 }
    261 
    262 void invalid_program_state (NegativeTestContext& ctx)
    263 {
    264 	checkTessellationSupport(ctx);
    265 
    266 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    267 	map<string, string>			args;
    268 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    269 	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    270 
    271 	glu::FragmentSource frgSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
    272 	glu::TessellationControlSource tessCtrlSource(tcu::StringTemplate(tessControlShaderSource).specialize(args));
    273 	glu::TessellationEvaluationSource tessEvalSource(tcu::StringTemplate(tessEvalShaderSource).specialize(args));
    274 
    275 	glu::ProgramPipeline pipeline(ctx.getRenderContext());
    276 
    277 	glu::ShaderProgram	fragProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << frgSource);
    278 	glu::ShaderProgram	tessCtrlProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
    279 	glu::ShaderProgram	tessEvalProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
    280 
    281 	tcu::TestLog& log = ctx.getLog();
    282 	log << fragProgram << tessCtrlProgram << tessEvalProgram;
    283 
    284 	if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
    285 		throw tcu::TestError("failed to build program");
    286 
    287 	ctx.glBindProgramPipeline(pipeline.getPipeline());
    288 	ctx.expectError(GL_NO_ERROR);
    289 
    290 	ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
    291 	ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_CONTROL_SHADER_BIT, tessCtrlProgram.getProgram());
    292 	ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_EVALUATION_SHADER_BIT, tessEvalProgram.getProgram());
    293 	ctx.expectError(GL_NO_ERROR);
    294 
    295 	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and vertex shader is missing.");
    296 	ctx.glDrawArrays(GL_PATCHES, 0, 3);
    297 	ctx.expectError(GL_INVALID_OPERATION);
    298 	ctx.endSection();
    299 
    300 	ctx.glBindProgramPipeline(0);
    301 	ctx.expectError(GL_NO_ERROR);
    302 }
    303 
    304 void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
    305 {
    306 	checkTessellationSupport(ctx);
    307 
    308 	const char* const tessControlVertLimitSource	=	"${GLSL_VERSION_STRING}\n"
    309 														"${GLSL_TESS_EXTENSION_STRING}\n"
    310 														"layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
    311 														"void main()\n"
    312 														"{\n"
    313 														"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
    314 														"}\n";
    315 
    316 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    317 	map<string, string>			args;
    318 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    319 	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    320 
    321 	int maxPatchVertices= 0;
    322 
    323 	ctx.beginSection("Output vertex count exceeds GL_MAX_PATCH_VERTICES.");
    324 	ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
    325 	ctx.expectError(GL_NO_ERROR);
    326 
    327 	std::ostringstream				oss;
    328 	oss << (maxPatchVertices + 1);
    329 	args["GL_MAX_PATCH_LIMIT"] =	oss.str();
    330 
    331 
    332 	glu::ShaderProgram program(ctx.getRenderContext(),
    333 							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
    334 													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
    335 													   tcu::StringTemplate(tessControlVertLimitSource).specialize(args),
    336 													   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
    337 	tcu::TestLog& log = ctx.getLog();
    338 	log << program;
    339 
    340 	bool testFailed = program.getProgramInfo().linkOk;
    341 
    342 	if (testFailed)
    343 		ctx.fail("Program was not expected to link");
    344 
    345 	ctx.endSection();
    346 }
    347 
    348 void invalid_get_programiv (NegativeTestContext& ctx)
    349 {
    350 	checkTessellationSupport(ctx);
    351 
    352 	GLuint	program		= ctx.glCreateProgram();
    353 	GLint	params[1]	= { 0 };
    354 
    355 	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has not been linked properly.");
    356 	ctx.glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES, &params[0]);
    357 	ctx.expectError(GL_INVALID_OPERATION);
    358 	ctx.endSection();
    359 
    360 	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_MODE is queried for a program which has not been linked properly.");
    361 	ctx.glGetProgramiv(program, GL_TESS_GEN_MODE, &params[0]);
    362 	ctx.expectError(GL_INVALID_OPERATION);
    363 	ctx.endSection();
    364 
    365 	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_SPACING is queried for a program which has not been linked properly.");
    366 	ctx.glGetProgramiv(program, GL_TESS_GEN_SPACING, &params[0]);
    367 	ctx.expectError(GL_INVALID_OPERATION);
    368 	ctx.endSection();
    369 
    370 	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_VERTEX_ORDER is queried for a program which has not been linked properly.");
    371 	ctx.glGetProgramiv(program, GL_TESS_GEN_VERTEX_ORDER, &params[0]);
    372 	ctx.expectError(GL_INVALID_OPERATION);
    373 	ctx.endSection();
    374 
    375 	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_POINT_MODE is queried for a program which has not been linked properly.");
    376 	ctx.glGetProgramiv(program, GL_TESS_GEN_POINT_MODE, &params[0]);
    377 	ctx.expectError(GL_INVALID_OPERATION);
    378 	ctx.endSection();
    379 
    380 	ctx.glDeleteProgram(program);
    381 }
    382 
    383 void invalid_patch_parameteri (NegativeTestContext& ctx)
    384 {
    385 	checkTessellationSupport(ctx);
    386 
    387 	ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_PATCH_VERTICES.");
    388 	ctx.glPatchParameteri(-1, 1);
    389 	ctx.expectError(GL_INVALID_ENUM);
    390 	ctx.endSection();
    391 
    392 	ctx.beginSection("GL_INVALID_VALUE is generated if value is less than or equal to zero.");
    393 	ctx.glPatchParameteri(GL_PATCH_VERTICES, 0);
    394 	ctx.expectError(GL_INVALID_VALUE);
    395 	ctx.endSection();
    396 
    397 	int maxPatchVertices= 0;
    398 	ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
    399 	ctx.expectError(GL_NO_ERROR);
    400 
    401 	ctx.beginSection("GL_INVALID_VALUE is generated if value is greater than GL_MAX_PATCH_VERTICES.");
    402 	ctx.glPatchParameteri(GL_PATCH_VERTICES, maxPatchVertices + 1);
    403 	ctx.expectError(GL_INVALID_VALUE);
    404 	ctx.endSection();
    405 }
    406 
    407 std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
    408 {
    409 	const FunctionContainer funcs[] =
    410 	{
    411 		{ single_tessellation_stage,					"single_tessellation_stage",					"Invalid program state with single tessellation stage"							},
    412 		{ invalid_primitive_mode,						"invalid_primitive_mode",						"Invalid primitive mode when tessellation is active"							},
    413 		{ tessellation_not_active,						"tessellation_not_active",						"Use of GL_PATCHES when tessellation is not active"								},
    414 		{ invalid_program_state,						"invalid_program_state",						"Invalid program state when tessellation active but no vertex shader present"	},
    415 		{ invalid_get_programiv,						"get_programiv",								"Invalid glGetProgramiv() usage"												},
    416 		{ invalid_patch_parameteri,						"invalid_program_queries",						"Invalid glPatchParameteri() usage"												},
    417 		{ tessellation_control_invalid_vertex_count,	"tessellation_control_invalid_vertex_count",	"Exceed vertex count limit in tessellation control shader"						},
    418 	};
    419 
    420 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    421 }
    422 
    423 } // NegativeTestShared
    424 } // Functional
    425 } // gles31
    426 } // deqp
    427