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, ¶ms[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, ¶ms[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, ¶ms[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, ¶ms[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, ¶ms[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