1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2016 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Negative Tessellation tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es31fNegativeTessellationTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "glwDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "tcuStringTemplate.hpp"
41 namespace NegativeTestShared
47 static const char* vertexShaderSource = "${GLSL_VERSION_STRING}\n"
51 " gl_Position = vec4(0.0);\n"
54 static const char* fragmentShaderSource = "${GLSL_VERSION_STRING}\n"
55 "precision mediump float;\n"
56 "layout(location = 0) out mediump vec4 fragColor;\n"
60 " fragColor = vec4(1.0);\n"
63 static const char* tessControlShaderSource = "${GLSL_VERSION_STRING}\n"
64 "${GLSL_TESS_EXTENSION_STRING}\n"
65 "layout (vertices=3) out;\n"
69 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
72 static const char* tessEvalShaderSource = "${GLSL_VERSION_STRING}\n"
73 "${GLSL_TESS_EXTENSION_STRING}\n"
74 "layout(triangles) in;\n"
78 " gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;\n"
81 static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
83 if (!ctx.getContextInfo().isExtensionSupported(extName))
84 throw tcu::NotSupportedError(string(extName) + " not supported");
87 static void checkTessellationSupport (NegativeTestContext& ctx)
89 checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
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)
95 glu::ProgramSources sources;
96 sources.sources[glu::SHADERTYPE_VERTEX].push_back(vertexSrc);
97 sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
99 if (!tessCtrlSrc.empty())
100 sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(tessCtrlSrc);
102 if (!tessEvalSrc.empty())
103 sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(tessEvalSrc);
108 // Incomplete active tess shaders
109 void single_tessellation_stage (NegativeTestContext& ctx)
111 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
112 map<string, string> args;
113 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
114 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
116 checkTessellationSupport(ctx);
119 glu::ShaderProgram program(ctx.getRenderContext(),
120 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
121 tcu::StringTemplate(fragmentShaderSource).specialize(args),
122 tcu::StringTemplate(tessControlShaderSource).specialize(args),
123 "")); // missing tessEvalShaderSource
124 tcu::TestLog& log = ctx.getLog();
127 ctx.beginSection("A link error is generated if a non-separable program has a tessellation control shader but no tessellation evaluation shader.");
130 ctx.fail("Program was not expected to link");
136 glu::ShaderProgram program(ctx.getRenderContext(),
137 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
138 tcu::StringTemplate(fragmentShaderSource).specialize(args),
139 tcu::StringTemplate(tessControlShaderSource).specialize(args),
140 "") // missing tessEvalShaderSource
141 << glu::ProgramSeparable(true));
142 tcu::TestLog& log = ctx.getLog();
146 TCU_THROW(TestError, "failed to build program");
148 ctx.glUseProgram(program.getProgram());
149 ctx.expectError(GL_NO_ERROR);
151 ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation control shader but no tessellation evaluation shader.");
152 ctx.glDrawArrays(GL_PATCHES, 0, 3);
153 ctx.expectError(GL_INVALID_OPERATION);
160 glu::ShaderProgram program(ctx.getRenderContext(),
161 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
162 tcu::StringTemplate(fragmentShaderSource).specialize(args),
163 "", // missing tessControlShaderSource
164 tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
165 tcu::TestLog& log = ctx.getLog();
168 ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
171 ctx.fail("Program was not expected to link");
177 glu::ShaderProgram program(ctx.getRenderContext(),
178 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
179 tcu::StringTemplate(fragmentShaderSource).specialize(args),
180 "", // missing tessControlShaderSource
181 tcu::StringTemplate(tessEvalShaderSource).specialize(args))
182 << glu::ProgramSeparable(true));
183 tcu::TestLog& log = ctx.getLog();
187 TCU_THROW(TestError, "failed to build program");
189 ctx.glUseProgram(program.getProgram());
190 ctx.expectError(GL_NO_ERROR);
192 ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation evaluation shader but no tessellation control shader.");
193 ctx.glDrawArrays(GL_PATCHES, 0, 3);
194 ctx.expectError(GL_INVALID_OPERATION);
201 // Complete active tess shaders invalid primitive mode
202 void invalid_primitive_mode (NegativeTestContext& ctx)
204 checkTessellationSupport(ctx);
206 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
207 map<string, string> args;
208 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
209 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
211 glu::ShaderProgram program(ctx.getRenderContext(),
212 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
213 tcu::StringTemplate(fragmentShaderSource).specialize(args),
214 tcu::StringTemplate(tessControlShaderSource).specialize(args),
215 tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
216 tcu::TestLog& log = ctx.getLog();
219 ctx.glUseProgram(program.getProgram());
220 ctx.expectError(GL_NO_ERROR);
222 ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and primitive mode is not GL_PATCHES.");
223 ctx.glDrawArrays(GL_TRIANGLES, 0, 3);
224 ctx.expectError(GL_INVALID_OPERATION);
230 void tessellation_not_active (NegativeTestContext& ctx)
232 checkTessellationSupport(ctx);
234 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
235 const glw::GLenum tessErr = ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5") ? GL_NO_ERROR : GL_INVALID_OPERATION;
236 map<string, string> args;
237 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
238 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
240 glu::ShaderProgram program(ctx.getRenderContext(),
241 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
242 tcu::StringTemplate(fragmentShaderSource).specialize(args),
243 "", // missing tessControlShaderSource
244 "")); // missing tessEvalShaderSource
245 tcu::TestLog& log = ctx.getLog();
248 ctx.glUseProgram(program.getProgram());
249 ctx.expectError(GL_NO_ERROR);
251 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.");
252 ctx.glDrawArrays(GL_PATCHES, 0, 3);
253 ctx.expectError(tessErr);
259 void invalid_program_state (NegativeTestContext& ctx)
261 checkTessellationSupport(ctx);
263 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
264 map<string, string> args;
265 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
266 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
268 glu::FragmentSource frgSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
269 glu::TessellationControlSource tessCtrlSource(tcu::StringTemplate(tessControlShaderSource).specialize(args));
270 glu::TessellationEvaluationSource tessEvalSource(tcu::StringTemplate(tessEvalShaderSource).specialize(args));
272 glu::ProgramPipeline pipeline(ctx.getRenderContext());
274 glu::ShaderProgram fragProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << frgSource);
275 glu::ShaderProgram tessCtrlProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
276 glu::ShaderProgram tessEvalProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
278 tcu::TestLog& log = ctx.getLog();
279 log << fragProgram << tessCtrlProgram << tessEvalProgram;
281 if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
282 throw tcu::TestError("failed to build program");
284 ctx.glBindProgramPipeline(pipeline.getPipeline());
285 ctx.expectError(GL_NO_ERROR);
287 ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
288 ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_CONTROL_SHADER_BIT, tessCtrlProgram.getProgram());
289 ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_EVALUATION_SHADER_BIT, tessEvalProgram.getProgram());
290 ctx.expectError(GL_NO_ERROR);
292 ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and vertex shader is missing.");
293 ctx.glDrawArrays(GL_PATCHES, 0, 3);
294 ctx.expectError(GL_INVALID_OPERATION);
297 ctx.glBindProgramPipeline(0);
298 ctx.expectError(GL_NO_ERROR);
301 void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
303 checkTessellationSupport(ctx);
305 const char* const tessControlVertLimitSource = "${GLSL_VERSION_STRING}\n"
306 "${GLSL_TESS_EXTENSION_STRING}\n"
307 "layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
310 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
313 const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
314 map<string, string> args;
315 args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
316 args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
318 int maxPatchVertices= 0;
320 ctx.beginSection("Output vertex count exceeds GL_MAX_PATCH_VERTICES.");
321 ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
322 ctx.expectError(GL_NO_ERROR);
324 std::ostringstream oss;
325 oss << (maxPatchVertices + 1);
326 args["GL_MAX_PATCH_LIMIT"] = oss.str();
329 glu::ShaderProgram program(ctx.getRenderContext(),
330 makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
331 tcu::StringTemplate(fragmentShaderSource).specialize(args),
332 tcu::StringTemplate(tessControlVertLimitSource).specialize(args),
333 tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
334 tcu::TestLog& log = ctx.getLog();
337 bool testFailed = program.getProgramInfo().linkOk;
340 ctx.fail("Program was not expected to link");
345 void invalid_get_programiv (NegativeTestContext& ctx)
347 checkTessellationSupport(ctx);
349 GLuint program = ctx.glCreateProgram();
350 GLint params[1] = { 0 };
352 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has not been linked properly.");
353 ctx.glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES, ¶ms[0]);
354 ctx.expectError(GL_INVALID_OPERATION);
357 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_MODE is queried for a program which has not been linked properly.");
358 ctx.glGetProgramiv(program, GL_TESS_GEN_MODE, ¶ms[0]);
359 ctx.expectError(GL_INVALID_OPERATION);
362 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_SPACING is queried for a program which has not been linked properly.");
363 ctx.glGetProgramiv(program, GL_TESS_GEN_SPACING, ¶ms[0]);
364 ctx.expectError(GL_INVALID_OPERATION);
367 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_VERTEX_ORDER is queried for a program which has not been linked properly.");
368 ctx.glGetProgramiv(program, GL_TESS_GEN_VERTEX_ORDER, ¶ms[0]);
369 ctx.expectError(GL_INVALID_OPERATION);
372 ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_POINT_MODE is queried for a program which has not been linked properly.");
373 ctx.glGetProgramiv(program, GL_TESS_GEN_POINT_MODE, ¶ms[0]);
374 ctx.expectError(GL_INVALID_OPERATION);
377 ctx.glDeleteProgram(program);
380 void invalid_patch_parameteri (NegativeTestContext& ctx)
382 checkTessellationSupport(ctx);
384 ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_PATCH_VERTICES.");
385 ctx.glPatchParameteri(-1, 1);
386 ctx.expectError(GL_INVALID_ENUM);
389 ctx.beginSection("GL_INVALID_VALUE is generated if value is less than or equal to zero.");
390 ctx.glPatchParameteri(GL_PATCH_VERTICES, 0);
391 ctx.expectError(GL_INVALID_VALUE);
394 int maxPatchVertices= 0;
395 ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
396 ctx.expectError(GL_NO_ERROR);
398 ctx.beginSection("GL_INVALID_VALUE is generated if value is greater than GL_MAX_PATCH_VERTICES.");
399 ctx.glPatchParameteri(GL_PATCH_VERTICES, maxPatchVertices + 1);
400 ctx.expectError(GL_INVALID_VALUE);
404 std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
406 const FunctionContainer funcs[] =
408 { single_tessellation_stage, "single_tessellation_stage", "Invalid program state with single tessellation stage" },
409 { invalid_primitive_mode, "invalid_primitive_mode", "Invalid primitive mode when tessellation is active" },
410 { tessellation_not_active, "tessellation_not_active", "Use of GL_PATCHES when tessellation is not active" },
411 { invalid_program_state, "invalid_program_state", "Invalid program state when tessellation active but no vertex shader present" },
412 { invalid_get_programiv, "get_programiv", "Invalid glGetProgramiv() usage" },
413 { invalid_patch_parameteri, "invalid_program_queries", "Invalid glPatchParameteri() usage" },
414 { tessellation_control_invalid_vertex_count, "tessellation_control_invalid_vertex_count", "Exceed vertex count limit in tessellation control shader" },
417 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
420 } // NegativeTestShared