Modify single_tessellation_stage 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         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