framework/replay: disable AA accounting when comparing with no tolerance
[piglit.git] / tests / glslparsertest / glslparsertest.c
blobdd441677ae39e1d97af4d60b6007a5405635f8e9
1 /*
2 * Copyright © 2009 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 DEALINGS
21 * IN THE SOFTWARE.
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
28 /** @file glslparsertest.c
30 * Tests that compiling (but not linking or drawing with) a given
31 * shader either succeeds or fails as expected.
34 #include <errno.h>
36 #include "piglit-util-gl.h"
38 #define COMPAT_FLAG (1u << 31)
40 static unsigned parse_glsl_version_number(const char *str);
41 static int process_options(int argc, char **argv);
43 PIGLIT_GL_TEST_CONFIG_BEGIN
45 argc = process_options(argc, argv);
46 if (argc > 3) {
47 const unsigned int version
48 = parse_glsl_version_number(argv[3]);
49 const bool compat = !!(version & COMPAT_FLAG);
50 const unsigned int int_version = version & ~COMPAT_FLAG;
51 switch (int_version) {
52 /* This is a hack to support es
54 * This works because version 1.00, 3.00, 3.10, 3.20 (even
55 * though 3.x should include "es") are unique to GLES, there is
56 * no desktop OpenGL shader language 1.00, 3.00, 3.10, or 3.20
58 case 100:
59 config.supports_gl_compat_version = 10;
60 config.supports_gl_es_version = 20;
61 break;
62 case 300:
63 config.supports_gl_compat_version = 10;
64 config.supports_gl_es_version = 30;
65 break;
66 case 310:
67 config.supports_gl_compat_version = 10;
68 config.supports_gl_es_version = 31;
69 break;
70 case 320:
71 config.supports_gl_compat_version = 10;
72 config.supports_gl_es_version = 32;
73 break;
74 default: {
75 const unsigned int gl_version
76 = required_gl_version_from_glsl_version(int_version);
77 config.supports_gl_compat_version = gl_version;
78 if (gl_version < 31 || compat)
79 config.supports_gl_core_version = 0;
80 else
81 config.supports_gl_core_version = gl_version;
83 break;
85 } else {
86 config.supports_gl_compat_version = 10;
87 config.supports_gl_es_version = 20;
90 config.window_width = 200;
91 config.window_height = 100;
92 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
94 PIGLIT_GL_TEST_CONFIG_END
96 static char *filename;
97 static int expected_pass;
98 static int gl_version_times_10 = 0;
99 static int check_link = 0;
100 static unsigned requested_version = 110;
101 static bool test_requires_geometry_shader4 = false;
102 static bool dummy_shader_include = false;
103 static char *shader_include_path = NULL;
105 static GLint
106 get_shader_compile_status(GLuint shader)
108 GLint status;
110 #if defined PIGLIT_USE_OPENGL
111 if (gl_version_times_10 >= 20) {
112 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
113 } else {
114 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
116 #elif defined PIGLIT_USE_OPENGL_ES2
117 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
118 #else
119 # error
120 #endif
122 return status;
125 static GLsizei
126 get_shader_info_log_length(GLuint shader)
128 GLsizei length;
130 #if defined PIGLIT_USE_OPENGL
131 if (gl_version_times_10 >= 20) {
132 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
133 } else {
134 glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
136 #elif defined PIGLIT_USE_OPENGL_ES2
137 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
138 #else
139 # error
140 #endif
142 return length;
145 static char*
146 get_shader_name(GLenum type)
148 switch(type) {
149 case GL_VERTEX_SHADER:
150 return "vertex";
151 case GL_TESS_CONTROL_SHADER:
152 return "tessellation control";
153 case GL_TESS_EVALUATION_SHADER:
154 return "tessellation evaluation";
155 case GL_GEOMETRY_SHADER:
156 return "geometry";
157 case GL_FRAGMENT_SHADER:
158 return "fragment";
159 case GL_COMPUTE_SHADER:
160 return "compute";
161 default:
162 fprintf(stderr, "Unexpected type in get_shader_name()\n");
163 piglit_report_result(PIGLIT_FAIL);
165 return NULL;
168 static bool
169 glsl_is_es(int version)
171 if (version == 100 || version == 300 || version == 310 || version == 320) {
172 return true;
174 return false;
178 * Attach a dumy shader of the given type.
180 static void
181 attach_dummy_shader(GLuint shader_prog, GLenum type)
183 const char *shader_template;
184 char shader_text[4096];
185 GLint shader;
186 /* this sets the 'es' string at the end of the version, 1.00 doesn't have that */
187 bool es_flag = (glsl_is_es(requested_version) && requested_version != 100);
189 switch (type) {
190 case GL_VERTEX_SHADER:
191 shader_template =
192 "#version %d %s\n"
193 "void main() { gl_Position = vec4(0.0); }";
194 break;
195 case GL_TESS_EVALUATION_SHADER:
196 shader_template =
197 "#version %d %s\n"
198 "#extension GL_ARB_tessellation_shader : require\n"
199 "layout(quads, equal_spacing) in;\n"
200 "void main() { gl_Position = vec4(0.0); }";
201 break;
202 case GL_FRAGMENT_SHADER:
203 shader_template =
204 "#version %d %s\n"
205 "void main() { }";
206 break;
207 default:
208 shader_template = NULL;
209 printf("No dummy shader available for this shader type\n");
210 piglit_report_result(PIGLIT_FAIL);
211 break;
214 snprintf(shader_text, sizeof(shader_text),
215 shader_template,
216 requested_version,
217 es_flag ? "es" : "");
218 shader = piglit_compile_shader_text(type, shader_text);
219 glAttachShader(shader_prog, shader);
224 * GLES requires both vertex and fragment shaders to be present in
225 * order to link. From section 2.10.3 (Program Objects) of the GLES 2.0 spec:
227 * "Linking will also fail ... if program does not contain both a
228 * vertex shader and a fragment shader ..."
230 * So compile a dummy shader of type complementary to "type" and
231 * attach it to shader_prog.
233 static void
234 attach_complementary_shader(GLuint shader_prog, GLenum type)
236 if (type == GL_FRAGMENT_SHADER)
237 attach_dummy_shader(shader_prog, GL_VERTEX_SHADER);
238 else if (type == GL_VERTEX_SHADER)
239 attach_dummy_shader(shader_prog, GL_FRAGMENT_SHADER);
242 static void
243 require_feature(int gl_ver, const char *gl_ext, int es_ver, const char *es_ext)
245 const int required_ver = piglit_is_gles() ? es_ver : gl_ver;
246 const char *required_ext = piglit_is_gles() ? es_ext : gl_ext;
248 if (piglit_get_gl_version() < required_ver &&
249 !piglit_is_extension_supported(required_ext)) {
250 printf("Test requires version %g or %s\n",
251 required_ver / 10.0, required_ext);
252 piglit_report_result(PIGLIT_SKIP);
256 static void
257 test(void)
259 GLint prog;
260 GLint ok;
261 GLchar *prog_string;
262 FILE *out;
263 GLboolean pass;
264 GLchar *info;
265 GLint size;
266 GLenum type;
267 char *failing_stage = NULL;
269 if (strcmp(filename + strlen(filename) - 4, "frag") == 0)
270 type = GL_FRAGMENT_SHADER;
271 else if (strcmp(filename + strlen(filename) - 4, "vert") == 0)
272 type = GL_VERTEX_SHADER;
273 else if (strcmp(filename + strlen(filename) - 4, "tesc") == 0)
274 type = GL_TESS_CONTROL_SHADER;
275 else if (strcmp(filename + strlen(filename) - 4, "tese") == 0)
276 type = GL_TESS_EVALUATION_SHADER;
277 else if (strcmp(filename + strlen(filename) - 4, "geom") == 0)
278 type = GL_GEOMETRY_SHADER;
279 else if (strcmp(filename + strlen(filename) - 4, "comp") == 0)
280 type = GL_COMPUTE_SHADER;
281 else {
282 type = GL_NONE;
283 fprintf(stderr, "Couldn't determine type of program %s\n",
284 filename);
285 piglit_report_result(PIGLIT_FAIL);
288 piglit_require_vertex_shader();
289 piglit_require_fragment_shader();
291 if (type == GL_TESS_CONTROL_SHADER || type == GL_TESS_EVALUATION_SHADER) {
292 require_feature(40, "GL_ARB_tessellation_shader",
293 32, "GL_OES_tessellation_shader");
296 if (type == GL_COMPUTE_SHADER) {
297 require_feature(43, "GL_ARB_compute_shader", 31, NULL);
300 prog_string = piglit_load_text_file(filename, NULL);
301 if (prog_string == NULL) {
302 fprintf(stderr, "Couldn't open program %s: %s\n",
303 filename, strerror(errno));
304 exit(1);
307 if (dummy_shader_include) {
308 glNamedStringARB(GL_SHADER_INCLUDE_ARB, -1, "/dummy/path_to/shader_include",
309 -1, "");
312 prog = glCreateShader(type);
313 glShaderSource(prog, 1, (const GLchar **)&prog_string, NULL);
315 if (shader_include_path)
316 glCompileShaderIncludeARB(prog, 1, (const char * const *) &shader_include_path, NULL);
317 else
318 glCompileShader(prog);
320 ok = get_shader_compile_status(prog);
322 size = get_shader_info_log_length(prog);
323 if (size != 0) {
324 info = malloc(size);
325 glGetShaderInfoLog(prog, size, NULL, info);
326 } else {
327 info = "(no compiler output)";
330 if (!ok) {
331 failing_stage = "compile";
332 } else {
333 /* Try linking the shader if it compiled. We do this
334 * even if --check-link wasn't specified, to increase
335 * coverage of linker code.
337 GLuint shader_prog;
339 shader_prog = glCreateProgram();
340 glAttachShader(shader_prog, prog);
341 if (glsl_is_es(requested_version)) {
342 attach_complementary_shader(shader_prog, type);
344 #if PIGLIT_USE_OPENGL
345 if (type == GL_GEOMETRY_SHADER ||
346 type == GL_TESS_CONTROL_SHADER ||
347 type == GL_TESS_EVALUATION_SHADER)
348 attach_dummy_shader(shader_prog, GL_VERTEX_SHADER);
349 if (type == GL_TESS_CONTROL_SHADER)
350 attach_dummy_shader(shader_prog, GL_TESS_EVALUATION_SHADER);
351 if (test_requires_geometry_shader4) {
352 /* The default value of
353 * GL_GEOMETRY_VERTICES_OUT_ARB is zero, which
354 * is useless for testing. Use a value of 3.
356 glProgramParameteriARB(shader_prog,
357 GL_GEOMETRY_VERTICES_OUT_ARB,
360 #endif
361 glLinkProgram(shader_prog);
362 if (check_link) {
363 ok = piglit_link_check_status_quiet(shader_prog);
364 if (!ok) {
365 failing_stage = "link";
368 glDeleteProgram(shader_prog);
371 pass = (expected_pass == ok);
373 if (pass)
374 out = stdout;
375 else
376 out = stderr;
378 if (!ok) {
379 fprintf(out, "Failed to %s %s shader %s: %s\n",
380 failing_stage,
381 get_shader_name(type),
382 filename, info);
383 if (expected_pass) {
384 printf("Shader source:\n");
385 printf("%s\n", prog_string);
387 } else {
388 fprintf(out, "Successfully %s %s shader %s: %s\n",
389 check_link ? "compiled and linked" : "compiled",
390 get_shader_name(type),
391 filename, info);
392 if (!expected_pass) {
393 printf("Shader source:\n");
394 printf("%s\n", prog_string);
398 if (size != 0)
399 free(info);
400 free(prog_string);
401 glDeleteShader(prog);
402 piglit_report_result (pass ? PIGLIT_PASS : PIGLIT_FAIL);
405 static void usage(char *name)
407 printf("%s {options} <filename.frag|filename.vert> <pass|fail> "
408 "{requested GLSL version} {list of required GL extensions}\n", name);
409 printf("\nSupported options:\n");
410 printf(" --check-link: also detect link failures\n");
411 exit(1);
415 * Process any options and remove them from the argv array. Return
416 * the new argc.
418 static int
419 process_options(int argc, char **argv)
421 int i = 1;
422 int new_argc = 1;
423 while (i < argc) {
424 if (argv[i][0] == '-' && strcmp(argv[i], "-compat") != 0) {
425 if (strcmp(argv[i], "--check-link") == 0)
426 check_link = 1;
427 else if (strcmp(argv[i], "--dummy-shader-include") == 0)
428 dummy_shader_include = true;
429 else if (strncmp(argv[i], "--shader-include-path=", 22) == 0)
430 shader_include_path = argv[i] + 22;
431 else
432 usage(argv[0]);
433 /* do not retain the option; we've processed it */
434 i++;
435 } else {
436 /* retain the option in the argv array */
437 argv[new_argc++] = argv[i++];
440 return new_argc;
443 static unsigned
444 parse_glsl_version_number(const char *str)
446 unsigned major = 0;
447 unsigned minor = 0;
448 unsigned flags = 0;
450 /* Accept a return value of either 1 or 2 from sscanf(), so
451 * that the version number may be supplied as either "<int>"
452 * or "<int>.<int>".
454 if (sscanf(str, "%u.%u", &major, &minor) == 0) {
455 printf("Ill-formed GLSL version number: %s\n", str);
456 piglit_report_result(PIGLIT_FAIL);
459 if (strstr(str, "compatibility"))
460 flags |= COMPAT_FLAG;
462 return ((major * 100) + minor) | flags;
466 static unsigned
467 parse_glsl_version_string(const char *str)
469 if (piglit_is_gles()) {
470 /* In GLSL ES, the string returned by
471 * glGetString(GL_SHADING_LANGUAGE_VERSION) is
472 * prefixed by some text. Verify that the expected
473 * text is there and skip it before calling
474 * parse_glsl_version_number().
476 const char *expected_prefix = "OpenGL ES GLSL ES ";
477 if (strncmp(str, expected_prefix,
478 strlen(expected_prefix)) != 0) {
479 printf("Ill-formed GLSL version string: %s\n", str);
480 piglit_report_result(PIGLIT_FAIL);
482 str += strlen(expected_prefix);
484 return parse_glsl_version_number(str);
488 static void
489 check_version(unsigned glsl_version)
491 if (!piglit_is_gles()) {
492 if (requested_version == 100) {
493 piglit_require_extension("GL_ARB_ES2_compatibility");
494 return;
495 } else if (requested_version == 300) {
496 piglit_require_extension("GL_ARB_ES3_compatibility");
497 return;
498 } else if (requested_version == 310) {
499 piglit_require_extension("GL_ARB_ES3_1_compatibility");
500 return;
501 } else if (requested_version == 320) {
502 piglit_require_extension("GL_ARB_ES3_2_compatibility");
503 return;
507 if (glsl_version < requested_version) {
508 fprintf(stderr,
509 "GLSL version is %u.%u, but requested version %u.%u is required\n",
510 glsl_version / 100, glsl_version % 100,
511 requested_version / 100, requested_version % 100);
512 piglit_report_result(PIGLIT_SKIP);
517 void
518 piglit_init(int argc, char**argv)
520 const char *glsl_version_string;
521 unsigned glsl_version = 0;
522 int i;
524 if (argc < 3)
525 usage(argv[0]);
527 if (strlen(argv[1]) < 5)
528 usage(argv[0]);
529 filename = argv[1];
531 if (strcmp(argv[2], "pass") == 0)
532 expected_pass = 1;
533 else if (strcmp(argv[2], "fail") == 0)
534 expected_pass = 0;
535 else
536 usage(argv[0]);
538 if (argc > 3)
539 requested_version = parse_glsl_version_number(argv[3]) & ~COMPAT_FLAG;
541 gl_version_times_10 = piglit_get_gl_version();
543 if (gl_version_times_10 < 20
544 && !piglit_is_extension_supported("GL_ARB_shader_objects")) {
545 printf("Requires OpenGL 2.0\n");
546 piglit_report_result(PIGLIT_SKIP);
549 glsl_version_string = (char *)
550 glGetString(GL_SHADING_LANGUAGE_VERSION);
552 if (glsl_version_string != NULL)
553 glsl_version = parse_glsl_version_string(glsl_version_string);
555 check_version(glsl_version);
557 for (i = 4; i < argc; i++) {
558 if (argv[i][0] == '!') {
559 piglit_require_not_extension(argv[i] + 1);
560 } else {
561 piglit_require_extension(argv[i]);
562 if (strstr(argv[i], "geometry_shader4") != NULL)
563 test_requires_geometry_shader4 = true;
567 test();
570 enum piglit_result
571 piglit_display(void)
573 /* Should never be reached */
574 return PIGLIT_FAIL;