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
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.
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
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
[] =
62 "int A(void) { return A(); }\n"
66 " gl_Position = gl_Vertex;\n"
70 static const char unreachable_text
[] =
72 "int A(void) { return A(); }\n"
75 " gl_Position = gl_Vertex;\n"
79 static const char unreachable_opt_text
[] =
81 "int A(void) { return A(); }\n"
85 " gl_Position = gl_Vertex;\n"
89 static const char indirect_text
[] =
92 "int B(void) { return A(); }\n"
93 "int A(void) { return B(); }\n"
97 " gl_Position = gl_Vertex;\n"
101 static const char indirect_sep1_text
[] =
104 "int A(void) { return B(); }\n"
108 " gl_Position = gl_Vertex;\n"
112 static const char indirect_sep2_text
[] =
115 "int B(void) { return A(); }\n"
118 static const char indirect_complex_text
[] =
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"
127 " gl_Position = gl_Vertex;\n"
131 static const char indirect_complex1_text
[] =
134 "int A(bool from_b) { if (!from_b) return B(true); return 0; }\n"
139 " gl_Position = gl_Vertex;\n"
143 static const char indirect_complex2_text
[] =
146 "int B(bool from_a) { if (!from_a) return A(true); return 0; }\n"
151 const char *description
;
152 const char *shader_source
[4];
155 static const struct test_vector all_tests
[] = {
158 "Trivial test of recursion. main calls A, and A calls A.\n",
159 { simple_text
, NULL
}
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
}
176 "Trivial test of indirect recursion. main calls A, A calls\n"
177 "B, and B calls A.\n",
178 { indirect_text
, NULL
}
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"
185 { indirect_sep1_text
, indirect_sep2_text
, NULL
}
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
}
211 do_named_test(const char *name
)
217 for (i
= 0; i
< ARRAY_SIZE(all_tests
); i
++) {
222 if (name
!= NULL
&& strcmp(name
, all_tests
[i
].name
) != 0)
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
++) {
232 vs
= glCreateShader(GL_VERTEX_SHADER
);
233 glShaderSource(vs
, 1,
235 & all_tests
[i
].shader_source
[j
],
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
);
246 GLchar
*info
= malloc(size
);
248 glGetShaderInfoLog(vs
, size
, NULL
, info
);
249 printf("%s\n", info
);
252 printf("<empty log>\n\n");
255 glAttachShader(prog
, vs
);
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
265 printf("Link info log:\n");
266 glGetProgramiv(prog
, GL_INFO_LOG_LENGTH
, &size
);
268 GLchar
*info
= malloc(size
);
269 glGetProgramInfoLog(prog
, size
, NULL
, info
);
270 printf("%s\n", info
);
273 printf("<empty log>\n\n");
276 glGetProgramiv(prog
, GL_LINK_STATUS
, &ok
);
279 "Shader with recursion compiled and linked, "
280 "but it should have failed.\n");
283 printf("Done with test \"%s\".\n\n", all_tests
[i
].name
);
285 glDeleteProgram(prog
);
295 piglit_init(int argc
, char **argv
)
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
);
311 pass
= do_named_test(NULL
);
314 for (i
= 1; i
< argc
; i
++) {
315 pass
= do_named_test(argv
[i
]) && pass
;
319 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);