Fix missing dependency on sparse binds
[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                                                                                                 "${GLSL_PER_VERTEX_OUT}\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                                                                                                 "${GLSL_PER_VERTEX_IN_ARR}\n"
66                                                                                                 "${GLSL_PER_VERTEX_OUT_ARR}\n"
67                                                                                                 "layout (vertices=3) out;\n"
68                                                                                                 "\n"
69                                                                                                 "void main()\n"
70                                                                                                 "{\n"
71                                                                                                 "       gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
72                                                                                                 "}\n";
73
74 static const char* tessEvalShaderSource         =       "${GLSL_VERSION_STRING}\n"
75                                                                                                 "${GLSL_TESS_EXTENSION_STRING}\n"
76                                                                                                 "${GLSL_PER_VERTEX_IN_ARR}\n"
77                                                                                                 "${GLSL_PER_VERTEX_OUT}\n"
78                                                                                                 "layout(triangles) in;\n"
79                                                                                                 "\n"
80                                                                                                 "void main()\n"
81                                                                                                 "{\n"
82                                                                                                 "       gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;\n"
83                                                                                                 "}\n";
84
85 static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
86 {
87         if (!ctx.getContextInfo().isExtensionSupported(extName))
88                 throw tcu::NotSupportedError(string(extName) + " not supported");
89 }
90
91 static void checkTessellationSupport (NegativeTestContext& ctx)
92 {
93         if (glu::isContextTypeES(ctx.getRenderContext().getType()))
94                 checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
95 }
96
97 // Helper for constructing tessellation pipeline sources.
98 static glu::ProgramSources makeTessPipelineSources (const std::string& vertexSrc, const std::string& fragmentSrc, const std::string& tessCtrlSrc, const std::string& tessEvalSrc)
99 {
100         glu::ProgramSources sources;
101         sources.sources[glu::SHADERTYPE_VERTEX].push_back(vertexSrc);
102         sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
103
104         if (!tessCtrlSrc.empty())
105                 sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(tessCtrlSrc);
106
107         if (!tessEvalSrc.empty())
108                 sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(tessEvalSrc);
109
110         return sources;
111 }
112
113 map<string, string> constructSpecializationMap(NegativeTestContext& ctx)
114 {
115         glu::GLSLVersion        glslVersion = glu::getContextTypeGLSLVersion(ctx.getRenderContext().getType());
116         bool                            isES31          = (glslVersion == glu::GLSL_VERSION_310_ES);
117         string                          ext                     = isES31 ? "#extension GL_EXT_tessellation_shader : require" : "";
118         return
119         {
120                 { "GLSL_VERSION_STRING",                getGLSLVersionDeclaration(glslVersion) },
121                 { "GLSL_TESS_EXTENSION_STRING", ext },
122                 { "GLSL_PER_VERTEX_OUT",                "" },           // needed for GL4.5
123                 { "GLSL_PER_VERTEX_IN_ARR",             "" },
124                 { "GLSL_PER_VERTEX_OUT_ARR",    "" }
125         };
126 }
127
128 // Incomplete active tess shaders
129 void single_tessellation_stage (NegativeTestContext& ctx)
130 {
131         // this case does not apply to GL4.5
132         if (!glu::isContextTypeES(ctx.getRenderContext().getType()))
133                 return;
134
135         const bool                      requireTES      = !ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5");
136         map<string, string>     args            = constructSpecializationMap(ctx);
137
138         checkTessellationSupport(ctx);
139
140         {
141                 glu::ShaderProgram program(ctx.getRenderContext(),
142                                                                    makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
143                                                                                                                    tcu::StringTemplate(fragmentShaderSource).specialize(args),
144                                                                                                                    tcu::StringTemplate(tessControlShaderSource).specialize(args),
145                                                                                                                    "")); // missing tessEvalShaderSource
146                 tcu::TestLog& log = ctx.getLog();
147                 log << program;
148
149                 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.");
150
151                 if (requireTES && program.isOk())
152                         ctx.fail("Program was not expected to link");
153                 else if (!requireTES && !program.isOk())
154                         ctx.fail("Program was expected to link");
155
156                 ctx.endSection();
157         }
158
159         {
160                 glu::ShaderProgram program(ctx.getRenderContext(),
161                                                                    makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
162                                                                                                                    tcu::StringTemplate(fragmentShaderSource).specialize(args),
163                                                                                                                    tcu::StringTemplate(tessControlShaderSource).specialize(args),
164                                                                                                                    "") // missing tessEvalShaderSource
165                                                                    << glu::ProgramSeparable(true));
166                 tcu::TestLog& log = ctx.getLog();
167                 log << program;
168
169                 if (!program.isOk())
170                         TCU_THROW(TestError, "failed to build program");
171
172                 ctx.glUseProgram(program.getProgram());
173                 ctx.expectError(GL_NO_ERROR);
174
175                 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.");
176                 ctx.glDrawArrays(GL_PATCHES, 0, 3);
177                 ctx.expectError(requireTES ? GL_INVALID_OPERATION : GL_NO_ERROR);
178                 ctx.endSection();
179
180                 ctx.glUseProgram(0);
181         }
182
183         {
184                 glu::ShaderProgram program(ctx.getRenderContext(),
185                                                                    makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
186                                                                                                                    tcu::StringTemplate(fragmentShaderSource).specialize(args),
187                                                                                                                    "", // missing tessControlShaderSource
188                                                                                                                    tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
189                 tcu::TestLog& log = ctx.getLog();
190                 log << program;
191
192                 ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
193
194                 if (program.isOk())
195                         ctx.fail("Program was not expected to link");
196
197                 ctx.endSection();
198         }
199
200         {
201                 glu::ShaderProgram program(ctx.getRenderContext(),
202                                                                    makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
203                                                                                                                    tcu::StringTemplate(fragmentShaderSource).specialize(args),
204                                                                                                                    "", // missing tessControlShaderSource
205                                                                                                                    tcu::StringTemplate(tessEvalShaderSource).specialize(args))
206                                                                         << glu::ProgramSeparable(true));
207                 tcu::TestLog& log = ctx.getLog();
208                 log << program;
209
210                 if (!program.isOk())
211                         TCU_THROW(TestError, "failed to build program");
212
213                 ctx.glUseProgram(program.getProgram());
214                 ctx.expectError(GL_NO_ERROR);
215
216                 ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation evaluation shader but no tessellation control shader.");
217                 ctx.glDrawArrays(GL_PATCHES, 0, 3);
218                 ctx.expectError(GL_INVALID_OPERATION);
219                 ctx.endSection();
220
221                 ctx.glUseProgram(0);
222         }
223 }
224
225 // Complete active tess shaders invalid primitive mode
226 void invalid_primitive_mode (NegativeTestContext& ctx)
227 {
228         checkTessellationSupport(ctx);
229
230         map<string, string> args = constructSpecializationMap(ctx);
231         glu::ShaderProgram program(ctx.getRenderContext(),
232                                                            makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
233                                                                                                            tcu::StringTemplate(fragmentShaderSource).specialize(args),
234                                                                                                            tcu::StringTemplate(tessControlShaderSource).specialize(args),
235                                                                                                            tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
236         tcu::TestLog& log = ctx.getLog();
237         log << program;
238
239         ctx.glUseProgram(program.getProgram());
240         ctx.expectError(GL_NO_ERROR);
241
242         ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and primitive mode is not GL_PATCHES.");
243         ctx.glDrawArrays(GL_TRIANGLES, 0, 3);
244         ctx.expectError(GL_INVALID_OPERATION);
245         ctx.endSection();
246
247         ctx.glUseProgram(0);
248 }
249
250 void tessellation_not_active (NegativeTestContext& ctx)
251 {
252         checkTessellationSupport(ctx);
253
254         const glw::GLenum tessErr = ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5") ? GL_NO_ERROR : GL_INVALID_OPERATION;
255         map<string, string> args = constructSpecializationMap(ctx);
256         glu::ShaderProgram program(ctx.getRenderContext(),
257                                                            makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
258                                                                                                            tcu::StringTemplate(fragmentShaderSource).specialize(args),
259                                                                                                            "",          // missing tessControlShaderSource
260                                                                                                            ""));        // missing tessEvalShaderSource
261         tcu::TestLog& log = ctx.getLog();
262         log << program;
263
264         GLuint vao = 0;
265         if (!glu::isContextTypeES(ctx.getRenderContext().getType()))
266         {
267                 ctx.glGenVertexArrays(1, &vao);
268                 ctx.glBindVertexArray(vao);
269         }
270
271         ctx.glUseProgram(program.getProgram());
272         ctx.expectError(GL_NO_ERROR);
273
274         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.");
275         ctx.glDrawArrays(GL_PATCHES, 0, 3);
276         ctx.expectError(tessErr);
277         ctx.endSection();
278
279         ctx.glUseProgram(0);
280
281         if (vao)
282                 ctx.glDeleteVertexArrays(1, &vao);
283 }
284
285 void invalid_program_state (NegativeTestContext& ctx)
286 {
287         checkTessellationSupport(ctx);
288
289         const glu::RenderContext&       rc              = ctx.getRenderContext();
290         map<string, string>                     args    = constructSpecializationMap(ctx);
291
292         // for gl4.5 we need to add per vertex sections
293         if (!glu::isContextTypeES(rc.getType()))
294         {
295                 args["GLSL_PER_VERTEX_OUT"]             = "out gl_PerVertex { vec4 gl_Position; };\n";
296                 args["GLSL_PER_VERTEX_IN_ARR"]  = "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
297                 args["GLSL_PER_VERTEX_OUT_ARR"] = "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
298         }
299
300         glu::FragmentSource frgSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
301         glu::TessellationControlSource tessCtrlSource(tcu::StringTemplate(tessControlShaderSource).specialize(args));
302         glu::TessellationEvaluationSource tessEvalSource(tcu::StringTemplate(tessEvalShaderSource).specialize(args));
303
304         glu::ProgramPipeline pipeline(rc);
305
306         glu::ShaderProgram      fragProgram     (rc, glu::ProgramSources() << glu::ProgramSeparable(true) << frgSource);
307         glu::ShaderProgram      tessCtrlProgram (rc, glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
308         glu::ShaderProgram      tessEvalProgram (rc, glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
309
310         tcu::TestLog& log = ctx.getLog();
311         log << fragProgram << tessCtrlProgram << tessEvalProgram;
312
313         if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
314                 throw tcu::TestError("failed to build program");
315
316         ctx.glBindProgramPipeline(pipeline.getPipeline());
317         ctx.expectError(GL_NO_ERROR);
318
319         ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
320         ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_CONTROL_SHADER_BIT, tessCtrlProgram.getProgram());
321         ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_EVALUATION_SHADER_BIT, tessEvalProgram.getProgram());
322         ctx.expectError(GL_NO_ERROR);
323
324         ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and vertex shader is missing.");
325         ctx.glDrawArrays(GL_PATCHES, 0, 3);
326         ctx.expectError(GL_INVALID_OPERATION);
327         ctx.endSection();
328
329         ctx.glBindProgramPipeline(0);
330         ctx.expectError(GL_NO_ERROR);
331 }
332
333 void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
334 {
335         checkTessellationSupport(ctx);
336
337         const char* const tessControlVertLimitSource    =       "${GLSL_VERSION_STRING}\n"
338                                                                                                                 "${GLSL_TESS_EXTENSION_STRING}\n"
339                                                                                                                 "layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
340                                                                                                                 "void main()\n"
341                                                                                                                 "{\n"
342                                                                                                                 "       gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
343                                                                                                                 "}\n";
344
345         map<string, string> args = constructSpecializationMap(ctx);
346         int maxPatchVertices= 0;
347
348         ctx.beginSection("Output vertex count exceeds GL_MAX_PATCH_VERTICES.");
349         ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
350         ctx.expectError(GL_NO_ERROR);
351
352         std::ostringstream                              oss;
353         oss << (maxPatchVertices + 1);
354         args["GL_MAX_PATCH_LIMIT"] =    oss.str();
355
356
357         glu::ShaderProgram program(ctx.getRenderContext(),
358                                                            makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
359                                                                                                            tcu::StringTemplate(fragmentShaderSource).specialize(args),
360                                                                                                            tcu::StringTemplate(tessControlVertLimitSource).specialize(args),
361                                                                                                            tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
362         tcu::TestLog& log = ctx.getLog();
363         log << program;
364
365         bool testFailed = program.getProgramInfo().linkOk;
366
367         if (testFailed)
368                 ctx.fail("Program was not expected to link");
369
370         ctx.endSection();
371 }
372
373 void invalid_get_programiv (NegativeTestContext& ctx)
374 {
375         checkTessellationSupport(ctx);
376
377         GLuint  program         = ctx.glCreateProgram();
378         GLint   params[1]       = { 0 };
379
380         ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has not been linked properly.");
381         ctx.glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES, &params[0]);
382         ctx.expectError(GL_INVALID_OPERATION);
383         ctx.endSection();
384
385         ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_MODE is queried for a program which has not been linked properly.");
386         ctx.glGetProgramiv(program, GL_TESS_GEN_MODE, &params[0]);
387         ctx.expectError(GL_INVALID_OPERATION);
388         ctx.endSection();
389
390         ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_SPACING is queried for a program which has not been linked properly.");
391         ctx.glGetProgramiv(program, GL_TESS_GEN_SPACING, &params[0]);
392         ctx.expectError(GL_INVALID_OPERATION);
393         ctx.endSection();
394
395         ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_VERTEX_ORDER is queried for a program which has not been linked properly.");
396         ctx.glGetProgramiv(program, GL_TESS_GEN_VERTEX_ORDER, &params[0]);
397         ctx.expectError(GL_INVALID_OPERATION);
398         ctx.endSection();
399
400         ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_POINT_MODE is queried for a program which has not been linked properly.");
401         ctx.glGetProgramiv(program, GL_TESS_GEN_POINT_MODE, &params[0]);
402         ctx.expectError(GL_INVALID_OPERATION);
403         ctx.endSection();
404
405         ctx.glDeleteProgram(program);
406 }
407
408 void invalid_patch_parameteri (NegativeTestContext& ctx)
409 {
410         checkTessellationSupport(ctx);
411
412         ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_PATCH_VERTICES.");
413         ctx.glPatchParameteri(-1, 1);
414         ctx.expectError(GL_INVALID_ENUM);
415         ctx.endSection();
416
417         ctx.beginSection("GL_INVALID_VALUE is generated if value is less than or equal to zero.");
418         ctx.glPatchParameteri(GL_PATCH_VERTICES, 0);
419         ctx.expectError(GL_INVALID_VALUE);
420         ctx.endSection();
421
422         int maxPatchVertices= 0;
423         ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
424         ctx.expectError(GL_NO_ERROR);
425
426         ctx.beginSection("GL_INVALID_VALUE is generated if value is greater than GL_MAX_PATCH_VERTICES.");
427         ctx.glPatchParameteri(GL_PATCH_VERTICES, maxPatchVertices + 1);
428         ctx.expectError(GL_INVALID_VALUE);
429         ctx.endSection();
430 }
431
432 std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
433 {
434         const FunctionContainer funcs[] =
435         {
436                 { single_tessellation_stage,                                    "single_tessellation_stage",                                    "Invalid program state with single tessellation stage"                                                  },
437                 { invalid_primitive_mode,                                               "invalid_primitive_mode",                                               "Invalid primitive mode when tessellation is active"                                                    },
438                 { tessellation_not_active,                                              "tessellation_not_active",                                              "Use of GL_PATCHES when tessellation is not active"                                                             },
439                 { invalid_program_state,                                                "invalid_program_state",                                                "Invalid program state when tessellation active but no vertex shader present"   },
440                 { invalid_get_programiv,                                                "get_programiv",                                                                "Invalid glGetProgramiv() usage"                                                                                                },
441                 { invalid_patch_parameteri,                                             "invalid_program_queries",                                              "Invalid glPatchParameteri() usage"                                                                                             },
442                 { tessellation_control_invalid_vertex_count,    "tessellation_control_invalid_vertex_count",    "Exceed vertex count limit in tessellation control shader"                                              },
443         };
444
445         return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
446 }
447
448 } // NegativeTestShared
449 } // Functional
450 } // gles31
451 } // deqp