ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / glsl-1.20 / recursion / recursion.c
blob7c3c4dc32f40056fb6617cd421200335e3729767
1 /*
2 * Copyright © 2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /**
25 * \file glsl-recursion.c
26 * Verify that shaders containing static recursion are rejected.
28 * From page 44 (page 50 of the PDF) of the GLSL 1.20 spec:
30 * "Recursion is not allowed, not even statically. Static recursion is
31 * present if the static function call graph of the program contains
32 * cycles."
34 * This langauge leaves a lot of questions unanswered.
36 * - Is the error generated at compile-time or link-time?
38 * - Is it an error to have a recursive function that is never statically
39 * called by main or any function called directly or indirectly by main?
40 * Technically speaking, such a function is not in the "static function
41 * call graph of the program" at all.
43 * This set of tests checks for a variety of forms of recursion in shaders.
44 * Logs are dumped at both compile-time and link-time. Errors are only
45 * checked at link time. However, a compile error will also generate a link
46 * error (linking an uncompiled shader).
48 * \author Ian Romanick <ian.d.romanick@intel.com>
50 #include "piglit-util-gl.h"
52 PIGLIT_GL_TEST_CONFIG_BEGIN
54 config.supports_gl_compat_version = 10;
56 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
58 PIGLIT_GL_TEST_CONFIG_END
60 static const char simple_text[] =
61 "#version 120\n"
62 "int A(void) { return A(); }\n"
63 "\n"
64 "void main() {\n"
65 " A();\n"
66 " gl_Position = gl_Vertex;\n"
67 "}"
70 static const char unreachable_text[] =
71 "#version 120\n"
72 "int A(void) { return A(); }\n"
73 "\n"
74 "void main() {\n"
75 " gl_Position = gl_Vertex;\n"
76 "}"
79 static const char unreachable_opt_text[] =
80 "#version 120\n"
81 "int A(void) { return A(); }\n"
82 "\n"
83 "void main() {\n"
84 " if (false) A();\n"
85 " gl_Position = gl_Vertex;\n"
86 "}"
89 static const char indirect_text[] =
90 "#version 120\n"
91 "int A(void);\n"
92 "int B(void) { return A(); }\n"
93 "int A(void) { return B(); }\n"
94 "\n"
95 "void main() {\n"
96 " A();\n"
97 " gl_Position = gl_Vertex;\n"
98 "}"
101 static const char indirect_sep1_text[] =
102 "#version 120\n"
103 "int B(void);\n"
104 "int A(void) { return B(); }\n"
105 "\n"
106 "void main() {\n"
107 " A();\n"
108 " gl_Position = gl_Vertex;\n"
112 static const char indirect_sep2_text[] =
113 "#version 120\n"
114 "int A(void);\n"
115 "int B(void) { return A(); }\n"
118 static const char indirect_complex_text[] =
119 "#version 120\n"
120 "int A(bool);\n"
121 "int B(bool from_a) { if (!from_a) return A(true); return 0; }\n"
122 "int A(bool from_b) { if (!from_b) return B(true); return 0; }\n"
123 "\n"
124 "void main() {\n"
125 " A(false);\n"
126 " B(false);\n"
127 " gl_Position = gl_Vertex;\n"
131 static const char indirect_complex1_text[] =
132 "#version 120\n"
133 "int B(bool);\n"
134 "int A(bool from_b) { if (!from_b) return B(true); return 0; }\n"
135 "\n"
136 "void main() {\n"
137 " A(false);\n"
138 " B(false);\n"
139 " gl_Position = gl_Vertex;\n"
143 static const char indirect_complex2_text[] =
144 "#version 120\n"
145 "int A(bool);\n"
146 "int B(bool from_a) { if (!from_a) return A(true); return 0; }\n"
149 struct test_vector {
150 const char *name;
151 const char *description;
152 const char *shader_source[4];
155 static const struct test_vector all_tests[] = {
157 "simple",
158 "Trivial test of recursion. main calls A, and A calls A.\n",
159 { simple_text, NULL }
162 "unreachable",
163 "Shader contains a function A that calls itself, but A is\n"
164 "trivially unreachable from main.\n",
165 { unreachable_text, NULL }
168 "unreachable-constant-folding",
169 "Shader contains a function A that calls itself, but A is\n"
170 "unreachable from main if a constant folding is performed\n"
171 "before the check for recursion.\n",
172 { unreachable_opt_text, NULL }
175 "indirect",
176 "Trivial test of indirect recursion. main calls A, A calls\n"
177 "B, and B calls A.\n",
178 { indirect_text, NULL }
181 "indirect-separate",
182 "Trivial test of indirect recursion. main calls A, A calls\n"
183 "B, and B calls A. A and B are in separate compilation\n"
184 "units.\n",
185 { indirect_sep1_text, indirect_sep2_text, NULL }
188 "indirect-complex",
189 "Two functions A and B are statically mutually recursive,\n"
190 "but the parameters passed to the functions ensure that no\n"
191 "recursion actually occurs. This is still an error.\n",
192 { indirect_complex_text, NULL }
195 "indirect-complex-separate",
196 "Two functions A and B are statically mutually recursive,\n"
197 "but the parameters passed to the functions ensure that no\n"
198 "recursion actually occurs. This is still an error. A and\n"
199 "B are in separate compilation units.\n",
200 { indirect_complex1_text, indirect_complex2_text, NULL }
204 enum piglit_result
205 piglit_display(void)
207 return PIGLIT_FAIL;
210 bool
211 do_named_test(const char *name)
213 bool pass = true;
214 unsigned i;
215 unsigned j;
217 for (i = 0; i < ARRAY_SIZE(all_tests); i++) {
218 GLint ok;
219 GLuint prog;
220 GLint size;
222 if (name != NULL && strcmp(name, all_tests[i].name) != 0)
223 continue;
225 printf("Starting test \"%s\":\n", all_tests[i].name);
227 prog = glCreateProgram();
229 for (j = 0; all_tests[i].shader_source[j] != NULL; j++) {
230 GLuint vs;
232 vs = glCreateShader(GL_VERTEX_SHADER);
233 glShaderSource(vs, 1,
234 (const GLchar **)
235 & all_tests[i].shader_source[j],
236 NULL);
237 glCompileShader(vs);
239 /* Some drivers return a size of 1 for an empty log.
240 * This is the size of a log that contains only a
241 * terminating NUL character.
243 printf("Compilation info log for shader %u:\n", j);
244 glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &size);
245 if (size > 1) {
246 GLchar *info = malloc(size);
248 glGetShaderInfoLog(vs, size, NULL, info);
249 printf("%s\n", info);
250 free(info);
251 } else {
252 printf("<empty log>\n\n");
255 glAttachShader(prog, vs);
256 glDeleteShader(vs);
259 glLinkProgram(prog);
261 /* Some drivers return a size of 1 for an empty log. This is
262 * the size of a log that contains only a terminating NUL
263 * character.
265 printf("Link info log:\n");
266 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
267 if (size > 1) {
268 GLchar *info = malloc(size);
269 glGetProgramInfoLog(prog, size, NULL, info);
270 printf("%s\n", info);
271 free(info);
272 } else {
273 printf("<empty log>\n\n");
276 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
277 if (ok) {
278 fprintf(stderr,
279 "Shader with recursion compiled and linked, "
280 "but it should have failed.\n");
281 pass = false;
283 printf("Done with test \"%s\".\n\n", all_tests[i].name);
285 glDeleteProgram(prog);
287 if (name != NULL)
288 break;
291 return pass;
294 void
295 piglit_init(int argc, char **argv)
297 bool pass = true;
298 const char *glsl_version_string;
300 piglit_require_vertex_shader();
302 glsl_version_string = (const char *)
303 glGetString(GL_SHADING_LANGUAGE_VERSION);
304 if (strtod(glsl_version_string, NULL) < 1.2) {
305 printf("Requires GLSL 1.20 (have version `%s')\n",
306 glsl_version_string);
307 piglit_report_result(PIGLIT_SKIP);
310 if (argc == 1) {
311 pass = do_named_test(NULL);
312 } else {
313 int i;
314 for (i = 1; i < argc; i++) {
315 pass = do_named_test(argv[i]) && pass;
319 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);