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
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.
26 #include "piglit-util-gl.h"
27 #include "parser_utils.h"
29 static void parse_file(const char *filename
);
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;
46 * List of extensions required by the current test set.
48 char *required_extensions
[32];
49 unsigned num_required_extensions
= 0;
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"
94 /* The __VERSION__ stuff is to work-around gl_FragColor not existing in GLSL
97 static const char *const fragment_shader_body
=
98 "#if __VERSION__ >= 300\n"
100 "#define gl_FragColor color\n"
102 "void main() { gl_FragColor = vec4(f[0]); }\n"
106 PIGLIT_GL_TEST_CONFIG_BEGIN
110 switch (required_glsl_version
) {
112 config
.supports_gl_compat_version
= 10;
113 config
.supports_gl_es_version
= 20;
116 config
.supports_gl_compat_version
= 10;
117 config
.supports_gl_es_version
= 30;
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
129 if (!compat_shader
) {
130 config
.supports_gl_core_version
= 32;
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;
140 config
.supports_gl_core_version
= gl_version
;
145 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
147 PIGLIT_GL_TEST_CONFIG_END
158 * Comparison function for qsort of test_vector list
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
);
170 parse_shader_type(const char *line
, ptrdiff_t len
)
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
;
196 * Parse the file of values to test, fill in test vector list.
199 parse_file(const char *filename
)
202 char *text
= piglit_load_text_file(filename
, &text_size
);
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
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');
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.
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
] =
288 num_required_extensions
++;
290 /* Advance to the next input 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
);
306 "Invalid built-in constant name \"%s\".\n",
308 piglit_report_result(PIGLIT_FAIL
);
311 tests
[num_tests
].name
= line
;
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
),
322 "Invalid built-in constant value \"%s\".\n",
324 piglit_report_result(PIGLIT_FAIL
);
330 /* Skip to the next line.
332 line
= strchrnul(line
, '\n');
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
342 qsort(tests
, num_tests
, sizeof(tests
[0]), compar
);
346 check_compile_status(const char *name
, GLuint sh
)
350 glGetShaderiv(sh
, GL_COMPILE_STATUS
, &ok
);
355 glGetShaderiv(sh
, GL_INFO_LOG_LENGTH
, &size
);
357 glGetShaderInfoLog(sh
, size
, NULL
, info
);
360 "Failed to compile shader %s: %s\n",
370 is_tessellation_type(GLenum type
)
372 return type
== GL_TESS_CONTROL_SHADER
||
373 type
== GL_TESS_EVALUATION_SHADER
;
377 create_shader(GLenum type
)
379 if (shader_type
!= 0 && shader_type
!= type
&& !is_tessellation_type(shader_type
))
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")))
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")))
394 if (is_tessellation_type(type
) &&
395 (required_glsl_version
< 400 &&
396 !piglit_is_extension_supported("GL_ARB_tessellation_shader")))
399 /* Only support geometry shaders on desktop as introduced in
402 if (type
== GL_GEOMETRY_SHADER
&&
403 required_glsl_version
< 150)
406 /* Only create compute shaders when explicitly requested
408 if (type
== GL_COMPUTE_SHADER
&& shader_type
!= type
)
410 return glCreateShader(type
);
414 piglit_init(int argc
, char **argv
)
418 char *version_string
= NULL
;
419 char *passthrough_version_string
= NULL
;
422 const char *shader_source
[3];
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
) {
442 if (!piglit_is_extension_supported("GL_ARB_ES2_compatibility"))
443 piglit_report_result(PIGLIT_SKIP
);
446 if (!piglit_is_extension_supported("GL_ARB_ES3_compatibility"))
447 piglit_report_result(PIGLIT_SKIP
);
450 if (!piglit_is_extension_supported("GL_ARB_ES3_1_compatibility"))
451 piglit_report_result(PIGLIT_SKIP
);
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
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) ||
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
496 for (i
= 0; i
< num_required_extensions
; i
++) {
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
]);
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
,
534 "precision mediump float;\n"
536 required_glsl_version_string
,
539 (void)!asprintf(&passthrough_version_string
,
543 "precision mediump float;\n"
545 required_glsl_version_string
,
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
),
568 tests
[i
].name
, comparitor
, tests
[i
].minimum
);
570 /* Try to compile the vertex shader.
573 if (!is_tessellation_type(shader_type
)) {
574 shader_source
[0] = version_string
;
575 shader_source
[1] = uniform
;
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
)
589 /* Try to compile the tessellation control shader.
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
)
603 /* Try to compile the tessellation evaluation shader.
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
)
617 /* Try to compile the geometry shader.
620 if (!is_tessellation_type(shader_type
)) {
621 shader_source
[0] = version_string
;
622 shader_source
[1] = uniform
;
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
)
636 /* Try to compile the fragment shader.
639 if (!is_tessellation_type(shader_type
)) {
640 shader_source
[0] = version_string
;
641 shader_source
[1] = uniform
;
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
)
655 /* Try to compile the compute shader.
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
)
669 /* If both compilation phases passed, try to link the shaders
673 GLuint prog
= glCreateProgram();
676 glAttachShader(prog
, test_vs
);
678 glAttachShader(prog
, test_gs
);
680 glAttachShader(prog
, test_fs
);
682 glAttachShader(prog
, test_cs
);
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
);