Modify tessellation_not_active to check for GL_NV_gpu_shader5
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fNegativeTessellationTests.cpp
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         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";
115
116         checkTessellationSupport(ctx);
117
118         {
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();
125                 log << program;
126
127                 ctx.beginSection("A link error is generated if a non-separable program has a tessellation control shader but no tessellation evaluation shader.");
128
129                 if (program.isOk())
130                         ctx.fail("Program was not expected to link");
131
132                 ctx.endSection();
133         }
134
135         {
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();
143                 log << program;
144
145                 if (!program.isOk())
146                         TCU_THROW(TestError, "failed to build program");
147
148                 ctx.glUseProgram(program.getProgram());
149                 ctx.expectError(GL_NO_ERROR);
150
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);
154                 ctx.endSection();
155
156                 ctx.glUseProgram(0);
157         }
158
159         {
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();
166                 log << program;
167
168                 ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
169
170                 if (program.isOk())
171                         ctx.fail("Program was not expected to link");
172
173                 ctx.endSection();
174         }
175
176         {
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();
184                 log << program;
185
186                 if (!program.isOk())
187                         TCU_THROW(TestError, "failed to build program");
188
189                 ctx.glUseProgram(program.getProgram());
190                 ctx.expectError(GL_NO_ERROR);
191
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);
195                 ctx.endSection();
196
197                 ctx.glUseProgram(0);
198         }
199 }
200
201 // Complete active tess shaders invalid primitive mode
202 void invalid_primitive_mode (NegativeTestContext& ctx)
203 {
204         checkTessellationSupport(ctx);
205
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";
210
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();
217         log << program;
218
219         ctx.glUseProgram(program.getProgram());
220         ctx.expectError(GL_NO_ERROR);
221
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);
225         ctx.endSection();
226
227         ctx.glUseProgram(0);
228 }
229
230 void tessellation_not_active (NegativeTestContext& ctx)
231 {
232         checkTessellationSupport(ctx);
233
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";
239
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();
246         log << program;
247
248         ctx.glUseProgram(program.getProgram());
249         ctx.expectError(GL_NO_ERROR);
250
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);
254         ctx.endSection();
255
256         ctx.glUseProgram(0);
257 }
258
259 void invalid_program_state (NegativeTestContext& ctx)
260 {
261         checkTessellationSupport(ctx);
262
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";
267
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));
271
272         glu::ProgramPipeline pipeline(ctx.getRenderContext());
273
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);
277
278         tcu::TestLog& log = ctx.getLog();
279         log << fragProgram << tessCtrlProgram << tessEvalProgram;
280
281         if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
282                 throw tcu::TestError("failed to build program");
283
284         ctx.glBindProgramPipeline(pipeline.getPipeline());
285         ctx.expectError(GL_NO_ERROR);
286
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);
291
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);
295         ctx.endSection();
296
297         ctx.glBindProgramPipeline(0);
298         ctx.expectError(GL_NO_ERROR);
299 }
300
301 void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
302 {
303         checkTessellationSupport(ctx);
304
305         const char* const tessControlVertLimitSource    =       "${GLSL_VERSION_STRING}\n"
306                                                                                                                 "${GLSL_TESS_EXTENSION_STRING}\n"
307                                                                                                                 "layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
308                                                                                                                 "void main()\n"
309                                                                                                                 "{\n"
310                                                                                                                 "       gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
311                                                                                                                 "}\n";
312
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";
317
318         int maxPatchVertices= 0;
319
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);
323
324         std::ostringstream                              oss;
325         oss << (maxPatchVertices + 1);
326         args["GL_MAX_PATCH_LIMIT"] =    oss.str();
327
328
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();
335         log << program;
336
337         bool testFailed = program.getProgramInfo().linkOk;
338
339         if (testFailed)
340                 ctx.fail("Program was not expected to link");
341
342         ctx.endSection();
343 }
344
345 void invalid_get_programiv (NegativeTestContext& ctx)
346 {
347         checkTessellationSupport(ctx);
348
349         GLuint  program         = ctx.glCreateProgram();
350         GLint   params[1]       = { 0 };
351
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, &params[0]);
354         ctx.expectError(GL_INVALID_OPERATION);
355         ctx.endSection();
356
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, &params[0]);
359         ctx.expectError(GL_INVALID_OPERATION);
360         ctx.endSection();
361
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, &params[0]);
364         ctx.expectError(GL_INVALID_OPERATION);
365         ctx.endSection();
366
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, &params[0]);
369         ctx.expectError(GL_INVALID_OPERATION);
370         ctx.endSection();
371
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, &params[0]);
374         ctx.expectError(GL_INVALID_OPERATION);
375         ctx.endSection();
376
377         ctx.glDeleteProgram(program);
378 }
379
380 void invalid_patch_parameteri (NegativeTestContext& ctx)
381 {
382         checkTessellationSupport(ctx);
383
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);
387         ctx.endSection();
388
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);
392         ctx.endSection();
393
394         int maxPatchVertices= 0;
395         ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
396         ctx.expectError(GL_NO_ERROR);
397
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);
401         ctx.endSection();
402 }
403
404 std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
405 {
406         const FunctionContainer funcs[] =
407         {
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"                                              },
415         };
416
417         return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
418 }
419
420 } // NegativeTestShared
421 } // Functional
422 } // gles31
423 } // deqp