glsl-array-bounds: set out-of-bounds array index inside shader
[piglit.git] / tests / shaders / built-in-constants.c
blobdf5fa2a84c8e023cf9a80d87347d6b6750a9d0c8
1 /*
2 * Copyright © 2013 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.
23 #include <stdbool.h>
24 #include <string.h>
26 #include "piglit-util-gl.h"
27 #include "parser_utils.h"
29 static void parse_file(const char *filename);
31 struct test_vector {
32 const char *name;
33 int minimum;
36 struct test_vector tests[500];
37 unsigned num_tests = 0;
39 int required_glsl_version = 0;
40 char required_glsl_version_string[128];
41 bool es_shader = false;
42 bool compat_shader = false;
43 GLenum shader_type = 0;
45 /**
46 * List of extensions required by the current test set.
48 char *required_extensions[32];
49 unsigned num_required_extensions = 0;
51 /**
52 * Array of extension enables for the shader code
54 * For each used entry in \c required_extensions, there is text in
55 * this string of the form "#extension ...: require\n".
57 #define MAX_EXTENSION_ENABLE_LINE_LEN 80
58 char extension_enables[ARRAY_SIZE(required_extensions)
59 * MAX_EXTENSION_ENABLE_LINE_LEN];
60 unsigned extension_enables_len = 0;
62 static const char *const uniform_template =
63 "uniform float f[%s %s %d ? 1 : -1];\n"
66 static const char *const passthrough_uniform =
67 "uniform float f[1];\n"
70 static const char *const vertex_shader_body =
71 "void main() { gl_Position = vec4(f[0]); }\n"
74 static const char *const tessellation_control_shader_body =
75 "layout(vertices = 1) out;\n"
76 "void main() { gl_TessLevelInner[0] = f[0]; }\n"
79 static const char *const tessellation_evaluation_shader_body =
80 "void main() { gl_Position = vec4(f[0]); }\n"
83 static const char *const geometry_shader_body =
84 "layout(points) in;\n"
85 "layout(points, max_vertices = 1) out;\n"
86 "void main() { gl_Position = vec4(f[0]); EmitVertex(); }\n"
89 static const char *const compute_shader_body =
90 "layout(local_size_x = 1) in;\n"
91 "void main() { }\n"
94 /* The __VERSION__ stuff is to work-around gl_FragColor not existing in GLSL
95 * ES 3.00.
97 static const char *const fragment_shader_body =
98 "#if __VERSION__ >= 300\n"
99 "out vec4 color;\n"
100 "#define gl_FragColor color\n"
101 "#endif\n"
102 "void main() { gl_FragColor = vec4(f[0]); }\n"
106 PIGLIT_GL_TEST_CONFIG_BEGIN
108 parse_file(argv[1]);
110 switch (required_glsl_version) {
111 case 100:
112 config.supports_gl_compat_version = 10;
113 config.supports_gl_es_version = 20;
114 break;
115 case 300:
116 config.supports_gl_compat_version = 10;
117 config.supports_gl_es_version = 30;
118 break;
119 case 310:
120 config.supports_gl_es_version = 31;
122 /* It seems impossible that a desktop OpenGL implementation
123 * would support GL_ARB_ES3_1_compatibility and not support at
124 * least OpenGL 3.2. Realistically, the compute shader
125 * requirement means that nearly all
126 * GL_ARB_ES3_1_compatibility implementations will be OpenGL
127 * 4.2 or later.
129 if (!compat_shader) {
130 config.supports_gl_core_version = 32;
131 break;
133 default: {
134 const unsigned int gl_version
135 = required_gl_version_from_glsl_version(required_glsl_version);
136 config.supports_gl_compat_version = gl_version;
137 if (gl_version < 31 || compat_shader)
138 config.supports_gl_core_version = 0;
139 else
140 config.supports_gl_core_version = gl_version;
141 break;
145 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
147 PIGLIT_GL_TEST_CONFIG_END
149 enum piglit_result
150 piglit_display(void)
152 /* UNREACHED */
153 return PIGLIT_FAIL;
158 * Comparison function for qsort of test_vector list
160 static int
161 compar(const void *_a, const void *_b)
163 const struct test_vector *a = (const struct test_vector *) _a;
164 const struct test_vector *b = (const struct test_vector *) _b;
166 return strcmp(a->name, b->name);
169 static GLenum
170 parse_shader_type(const char *line, ptrdiff_t len)
172 int i;
173 static struct {
174 const char *name;
175 GLenum type;
176 } shader_types[] = {
177 { "GL_VERTEX_SHADER", GL_VERTEX_SHADER },
178 { "GL_TESS_CONTROL_SHADER", GL_TESS_CONTROL_SHADER },
179 { "GL_TESS_EVALUATION_SHADER", GL_TESS_EVALUATION_SHADER },
180 { "GL_GEOMETRY_SHADER", GL_GEOMETRY_SHADER },
181 { "GL_FRAGMENT_SHADER", GL_FRAGMENT_SHADER },
182 { "GL_COMPUTE_SHADER", GL_COMPUTE_SHADER },
185 for (i = 0; i < ARRAY_SIZE(shader_types); i++) {
186 if (len == strlen(shader_types[i].name) &&
187 strncmp(shader_types[i].name, line, 3) == 0) {
188 return shader_types[i].type;
192 return 0;
196 * Parse the file of values to test, fill in test vector list.
198 void
199 parse_file(const char *filename)
201 unsigned text_size;
202 char *text = piglit_load_text_file(filename, &text_size);
203 char *line = text;
204 char *end_of_line;
205 ptrdiff_t len;
206 char *endptr;
208 if (line == NULL) {
209 fprintf(stderr, "could not read file \"%s\"\n", filename);
210 piglit_report_result(PIGLIT_FAIL);
213 /* The format of the test file is:
215 * version [es|core|compatibility]
216 * GL_VERTEX_SHADER|GL_GEOMETRY_SHADER|GL_FRAGMENT_SHADER|GL_COMPUTE_SHADER
217 * GL_ARB_some_extension
218 * gl_MaxFoo 8
219 * gl_MaxBar 16
220 * gl_MinAsdf -2
223 /* Process the version requirement.
225 end_of_line = strchrnul(line, '\n');
226 len = end_of_line - line;
228 if (len + 1 >= ARRAY_SIZE(required_glsl_version_string)) {
229 fprintf(stderr, "Version line too long.\n");
230 piglit_report_result(PIGLIT_FAIL);
233 memcpy(required_glsl_version_string, line, len);
234 required_glsl_version_string[len] = '\0';
236 required_glsl_version = strtol(line, &endptr, 10);
237 parse_whitespace(endptr, (const char **)&line);
238 es_shader = strncmp("es\n", line, 3) == 0;
239 compat_shader = strncmp("compatibility\n", line, 7) == 0;
241 if (required_glsl_version <= 0 ||
242 (line != end_of_line &&
243 strncmp("es\n", line, 3) != 0 &&
244 strncmp("core\n", line, 5) != 0 &&
245 strncmp("compatibility\n", line, 7) != 0)) {
246 fprintf(stderr, "Parse error in version line.\n");
247 piglit_report_result(PIGLIT_FAIL);
250 /* Skip to the next line.
252 line = strchrnul(line, '\n');
253 if (line[0] != '\0')
254 line++;
256 end_of_line = strchrnul(line, '\n');
257 len = end_of_line - line;
258 assert(end_of_line[0] == '\n' || end_of_line[0] == '\0');
260 /* Process the shader type.
262 shader_type = parse_shader_type(line, len);
263 if (shader_type != 0) {
264 /* Advance to the next input line.
266 line = end_of_line;
267 if (line[0] == '\n')
268 line++;
271 /* Process the list of required extensions.
273 while (strncmp("GL_", line, 3) == 0) {
274 end_of_line = strchrnul(line, '\n');
275 len = end_of_line - line;
277 assert(end_of_line[0] == '\n' || end_of_line[0] == '\0');
279 if (num_required_extensions >= ARRAY_SIZE(required_extensions)) {
280 fprintf(stderr, "Too many required extensions!\n");
281 piglit_report_result(PIGLIT_FAIL);
284 /* Copy the new extension to the list.
286 required_extensions[num_required_extensions] =
287 strndup(line, len);
288 num_required_extensions++;
290 /* Advance to the next input line.
292 line = end_of_line;
293 if (line[0] == '\n')
294 line++;
297 while (line[0] != '\0') {
298 if (!(parse_word(line, (const char **)&line,
299 (const char **)&endptr) &&
300 (parse_str(line, "gl_Max", NULL) ||
301 parse_str(line, "gl_Min", NULL)))) {
302 char bad_name[80] = "";
303 parse_word_copy(line, bad_name, sizeof(bad_name), NULL);
305 fprintf(stderr,
306 "Invalid built-in constant name \"%s\".\n",
307 bad_name);
308 piglit_report_result(PIGLIT_FAIL);
311 tests[num_tests].name = line;
312 *endptr = 0;
313 line = endptr + 1;
315 if (!parse_int(line, &tests[num_tests].minimum,
316 (const char **)&endptr)) {
317 char bad_number[80] = "";
318 parse_word_copy(line, bad_number, sizeof(bad_number),
319 NULL);
321 fprintf(stderr,
322 "Invalid built-in constant value \"%s\".\n",
323 bad_number);
324 piglit_report_result(PIGLIT_FAIL);
326 line = endptr;
328 num_tests++;
330 /* Skip to the next line.
332 line = strchrnul(line, '\n');
333 if (line[0] != '\0')
334 line++;
337 /* After parsing the full list of values to test, sort the list by
338 * variable name. This ensures that the piglit results will be
339 * generated in a consistent order... no matter what happens in the
340 * control file.
342 qsort(tests, num_tests, sizeof(tests[0]), compar);
345 static bool
346 check_compile_status(const char *name, GLuint sh)
348 GLint ok;
350 glGetShaderiv(sh, GL_COMPILE_STATUS, &ok);
351 if (!ok) {
352 GLchar *info;
353 GLint size;
355 glGetShaderiv(sh, GL_INFO_LOG_LENGTH, &size);
356 info = malloc(size);
357 glGetShaderInfoLog(sh, size, NULL, info);
359 fprintf(stderr,
360 "Failed to compile shader %s: %s\n",
361 name, info);
363 free(info);
366 return !!ok;
369 static bool
370 is_tessellation_type(GLenum type)
372 return type == GL_TESS_CONTROL_SHADER ||
373 type == GL_TESS_EVALUATION_SHADER;
376 static GLuint
377 create_shader(GLenum type)
379 if (shader_type != 0 && shader_type != type && !is_tessellation_type(shader_type))
380 return 0;
381 if (es_shader) {
382 if (is_tessellation_type(type) &&
383 required_glsl_version < 320 &&
384 (required_glsl_version < 310 ||
385 !piglit_is_extension_supported("GL_OES_tessellation_shader")))
386 return 0;
388 if (type == GL_GEOMETRY_SHADER &&
389 required_glsl_version < 320 &&
390 (required_glsl_version < 310 ||
391 !piglit_is_extension_supported("GL_OES_geometry_shader")))
392 return 0;
393 } else {
394 if (is_tessellation_type(type) &&
395 (required_glsl_version < 400 &&
396 !piglit_is_extension_supported("GL_ARB_tessellation_shader")))
397 return 0;
399 /* Only support geometry shaders on desktop as introduced in
400 * OpenGL 3.2.
402 if (type == GL_GEOMETRY_SHADER &&
403 required_glsl_version < 150)
404 return 0;
406 /* Only create compute shaders when explicitly requested
408 if (type == GL_COMPUTE_SHADER && shader_type != type)
409 return 0;
410 return glCreateShader(type);
413 void
414 piglit_init(int argc, char **argv)
416 bool pass = true;
417 char uniform[80];
418 char *version_string = NULL;
419 char *passthrough_version_string = NULL;
420 unsigned i;
422 const char *shader_source[3];
424 GLuint test_vs;
425 GLuint test_tcs;
426 GLuint test_tes;
427 GLuint test_gs;
428 GLuint test_fs;
429 GLuint test_cs;
431 bool is_es;
432 int major;
433 int minor;
434 int glsl_version;
436 piglit_get_glsl_version(&is_es, &major, &minor);
437 glsl_version = major * 100 + minor;
439 if ((es_shader || required_glsl_version == 100) && !is_es) {
440 switch (required_glsl_version) {
441 case 100:
442 if (!piglit_is_extension_supported("GL_ARB_ES2_compatibility"))
443 piglit_report_result(PIGLIT_SKIP);
444 break;
445 case 300:
446 if (!piglit_is_extension_supported("GL_ARB_ES3_compatibility"))
447 piglit_report_result(PIGLIT_SKIP);
448 break;
449 case 310:
450 if (!piglit_is_extension_supported("GL_ARB_ES3_1_compatibility"))
451 piglit_report_result(PIGLIT_SKIP);
452 break;
453 default:
454 printf("Unknown GLSL ES version.\n");
455 piglit_report_result(PIGLIT_FAIL);
457 } else if ((!es_shader && required_glsl_version != 100) && is_es) {
458 /* It should actually be impossible to get here because
459 * supports_gl_es_version won't get set, and that is required
460 * in the ES builds.
462 printf("Desktop OpenGL shaders are not valid in OpenGL ES.\n");
463 piglit_report_result(PIGLIT_FAIL);
464 } else if (glsl_version < required_glsl_version)
465 piglit_report_result(PIGLIT_SKIP);
467 /* Geometry shaders must use the #extension directive in GLSL ES
468 * before version 3.20.
470 if (es_shader && required_glsl_version < 320 &&
471 required_glsl_version >= 310 &&
472 piglit_is_extension_supported("GL_OES_geometry_shader")) {
473 assert(num_required_extensions < ARRAY_SIZE(required_extensions));
474 required_extensions[num_required_extensions] =
475 strdup("GL_OES_geometry_shader");
476 num_required_extensions++;
479 /* Tessellation shaders must use the #extension directive. */
480 const char *const tess_ext_name = es_shader
481 ? "GL_OES_tessellation_shader"
482 : "GL_ARB_tessellation_shader";
483 if (((es_shader && required_glsl_version >= 310) ||
484 !es_shader) &&
485 piglit_is_extension_supported(tess_ext_name)) {
486 assert(num_required_extensions < ARRAY_SIZE(required_extensions));
487 required_extensions[num_required_extensions] =
488 strdup(tess_ext_name);
489 num_required_extensions++;
492 /* Process the list of required extensions. While doing this,
493 * generate the GLSL code that will enable those extensions in the
494 * shaders.
496 for (i = 0; i < num_required_extensions; i++) {
497 int len;
499 if (!piglit_is_extension_supported(required_extensions[i])) {
500 printf("%s not supported\n", required_extensions[i]);
501 piglit_report_result(PIGLIT_SKIP);
504 if ((extension_enables_len + MAX_EXTENSION_ENABLE_LINE_LEN)
505 >= sizeof(extension_enables)) {
506 printf("Extension enables too long.\n");
507 piglit_report_result(PIGLIT_FAIL);
510 len = snprintf(&extension_enables[extension_enables_len],
511 MAX_EXTENSION_ENABLE_LINE_LEN,
512 "#extension %s: require\n",
513 required_extensions[i]);
515 /* After the last use of the extension string, free it.
517 free(required_extensions[i]);
519 if (len <= 0) {
520 printf("Extension enable snprintf failed.\n");
521 piglit_report_result(PIGLIT_FAIL);
524 extension_enables_len += len;
527 /* Generate the version declaration that will be used by all of the
528 * shaders in the test run.
530 (void)!asprintf(&version_string,
531 "#version %s\n"
532 "%s"
533 "#ifdef GL_ES\n"
534 "precision mediump float;\n"
535 "#endif\n",
536 required_glsl_version_string,
537 extension_enables);
539 (void)!asprintf(&passthrough_version_string,
540 "#version %s\n"
541 "%s"
542 "#ifdef GL_ES\n"
543 "precision mediump float;\n"
544 "#endif\n",
545 required_glsl_version_string,
546 extension_enables);
549 /* Create the shaders that will be used for the real part of the test.
551 test_vs = create_shader(GL_VERTEX_SHADER);
552 test_tcs = create_shader(GL_TESS_CONTROL_SHADER);
553 test_tes = create_shader(GL_TESS_EVALUATION_SHADER);
554 test_gs = create_shader(GL_GEOMETRY_SHADER);
555 test_fs = create_shader(GL_FRAGMENT_SHADER);
556 test_cs = create_shader(GL_COMPUTE_SHADER);
558 for (i = 0; i < num_tests; i++) {
559 bool subtest_pass = true;
560 const char *comparitor =
561 parse_str(tests[i].name, "gl_Min", NULL) ? "<=" : ">=";
563 /* Generate the uniform declaration for the test. This will
564 * be shared by all shader stages.
566 snprintf(uniform, sizeof(uniform),
567 uniform_template,
568 tests[i].name, comparitor, tests[i].minimum);
570 /* Try to compile the vertex shader.
572 if (test_vs != 0) {
573 if (!is_tessellation_type(shader_type)) {
574 shader_source[0] = version_string;
575 shader_source[1] = uniform;
576 } else {
577 shader_source[0] = passthrough_version_string;
578 shader_source[1] = passthrough_uniform;
580 shader_source[2] = vertex_shader_body;
582 glShaderSource(test_vs, 3, shader_source, NULL);
583 glCompileShader(test_vs);
585 subtest_pass = check_compile_status(tests[i].name, test_vs)
586 && subtest_pass;
589 /* Try to compile the tessellation control shader.
591 if (test_tcs != 0) {
592 shader_source[0] = version_string;
593 shader_source[1] = uniform;
594 shader_source[2] = tessellation_control_shader_body;
596 glShaderSource(test_tcs, 3, shader_source, NULL);
597 glCompileShader(test_tcs);
599 subtest_pass = check_compile_status(tests[i].name, test_tcs)
600 && subtest_pass;
603 /* Try to compile the tessellation evaluation shader.
605 if (test_tes != 0) {
606 shader_source[0] = version_string;
607 shader_source[1] = uniform;
608 shader_source[2] = tessellation_evaluation_shader_body;
610 glShaderSource(test_tes, 3, shader_source, NULL);
611 glCompileShader(test_tes);
613 subtest_pass = check_compile_status(tests[i].name, test_tes)
614 && subtest_pass;
617 /* Try to compile the geometry shader.
619 if (test_gs != 0) {
620 if (!is_tessellation_type(shader_type)) {
621 shader_source[0] = version_string;
622 shader_source[1] = uniform;
623 } else {
624 shader_source[0] = passthrough_version_string;
625 shader_source[1] = passthrough_uniform;
627 shader_source[2] = geometry_shader_body;
629 glShaderSource(test_gs, 3, shader_source, NULL);
630 glCompileShader(test_gs);
632 subtest_pass = check_compile_status(tests[i].name, test_gs)
633 && subtest_pass;
636 /* Try to compile the fragment shader.
638 if (test_fs != 0) {
639 if (!is_tessellation_type(shader_type)) {
640 shader_source[0] = version_string;
641 shader_source[1] = uniform;
642 } else {
643 shader_source[0] = passthrough_version_string;
644 shader_source[1] = passthrough_uniform;
646 shader_source[2] = fragment_shader_body;
648 glShaderSource(test_fs, 3, shader_source, NULL);
649 glCompileShader(test_fs);
651 subtest_pass = check_compile_status(tests[i].name, test_fs)
652 && subtest_pass;
655 /* Try to compile the compute shader.
657 if (test_cs != 0) {
658 shader_source[0] = version_string;
659 shader_source[1] = uniform;
660 shader_source[2] = compute_shader_body;
662 glShaderSource(test_cs, 3, shader_source, NULL);
663 glCompileShader(test_cs);
665 subtest_pass = check_compile_status(tests[i].name, test_cs)
666 && subtest_pass;
669 /* If both compilation phases passed, try to link the shaders
670 * together.
672 if (subtest_pass) {
673 GLuint prog = glCreateProgram();
675 if (test_vs != 0)
676 glAttachShader(prog, test_vs);
677 if (test_gs != 0)
678 glAttachShader(prog, test_gs);
679 if (test_fs != 0)
680 glAttachShader(prog, test_fs);
681 if (test_cs != 0)
682 glAttachShader(prog, test_cs);
684 glLinkProgram(prog);
685 subtest_pass = !!piglit_link_check_status(prog);
687 glDeleteProgram(prog);
690 piglit_report_subtest_result(subtest_pass ? PIGLIT_PASS : PIGLIT_FAIL,
691 "%s", tests[i].name);
693 pass = subtest_pass && pass;
696 free(version_string);
697 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);