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
checkExtensionSupport(NegativeTestContext & ctx,const char * extName)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
checkTessellationSupport(NegativeTestContext & ctx)87 static void checkTessellationSupport (NegativeTestContext& ctx)
88 {
89 checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
90 }
91
92 // Helper for constructing tessellation pipeline sources.
makeTessPipelineSources(const std::string & vertexSrc,const std::string & fragmentSrc,const std::string & tessCtrlSrc,const std::string & tessEvalSrc)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
single_tessellation_stage(NegativeTestContext & ctx)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
invalid_primitive_mode(NegativeTestContext & ctx)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
tessellation_not_active(NegativeTestContext & ctx)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
invalid_program_state(NegativeTestContext & ctx)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
tessellation_control_invalid_vertex_count(NegativeTestContext & ctx)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
invalid_get_programiv(NegativeTestContext & ctx)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
invalid_patch_parameteri(NegativeTestContext & ctx)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
getNegativeTessellationTestFunctions(void)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