glx-multithread-texture: Avoid front-buffer rendering.
[piglit.git] / tests / shaders / shader_runner.c
blob7ba2bb00bc2d36d673d29d4ff6ede0786e2f65d8
1 /*
2 * Copyright © 2010 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 #include <stdbool.h>
25 #include <string.h>
26 #include <ctype.h>
28 #include "piglit-util.h"
29 #include "piglit-util-gl.h"
30 #include "piglit-vbo.h"
31 #include "piglit-framework-gl/piglit_gl_framework.h"
32 #include "piglit-subprocess.h"
34 #include "shader_runner_gles_workarounds.h"
35 #include "parser_utils.h"
37 #include "shader_runner_vs_passthrough_spv.h"
39 #define DEFAULT_WINDOW_WIDTH 250
40 #define DEFAULT_WINDOW_HEIGHT 250
42 static bool spirv_replaces_glsl = false;
43 static struct piglit_gl_test_config current_config;
45 static void
46 get_required_config(const char *script_name, bool spirv,
47 struct piglit_gl_test_config *config);
48 static GLenum
49 decode_drawing_mode(const char *mode_str);
51 PIGLIT_GL_TEST_CONFIG_BEGIN
53 if (!piglit_gl_test_config_override_size(&config)) {
54 config.window_width = DEFAULT_WINDOW_WIDTH;
55 config.window_height = DEFAULT_WINDOW_HEIGHT;
57 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
58 config.khr_no_error_support = PIGLIT_NO_ERRORS;
60 /* By default SPIR-V mode is false. It will not be enabled
61 * unless the script includes SPIRV YES or SPIRV ONLY lines at
62 * [require] section, so it will be handled later.
64 if (argc > 1) {
65 get_required_config(argv[1], spirv_replaces_glsl, &config);
66 } else {
67 config.supports_gl_compat_version = 10;
70 current_config = config;
72 PIGLIT_GL_TEST_CONFIG_END
74 static const char passthrough_vertex_shader_source[] =
75 "#if __VERSION__ >= 130\n"
76 "in vec4 piglit_vertex;\n"
77 "#else\n"
78 "attribute vec4 piglit_vertex;\n"
79 "#endif\n"
80 "void main() { gl_Position = piglit_vertex; }\n"
83 struct component_version {
84 enum version_tag {
85 VERSION_GL,
86 VERSION_GLSL,
87 } _tag;
89 bool core;
90 bool compat;
91 bool es;
92 unsigned num;
93 char _string[100];
96 struct block_info {
97 int array_index;
98 int binding;
99 int offset;
100 int matrix_stride;
101 int row_major; /* int as we don't have a parse_bool */
104 #define ENUM_STRING(e) { #e, e }
106 extern float piglit_tolerance[4];
108 static int test_num = 1;
109 static struct component_version gl_version;
110 static struct component_version glsl_version;
111 static struct component_version glsl_req_version;
112 static int gl_max_vertex_output_components;
113 static int gl_max_fragment_uniform_components;
114 static int gl_max_vertex_uniform_components;
115 static int gl_max_vertex_attribs;
116 static int gl_max_varying_components;
117 static int gl_max_clip_planes;
118 static int gl_num_program_binary_formats = 0;
120 static const char *test_start = NULL;
121 static unsigned test_start_line_num = 0;
123 static GLuint vertex_shaders[256];
124 static unsigned num_vertex_shaders = 0;
125 static GLuint tess_ctrl_shaders[256];
126 static unsigned num_tess_ctrl_shaders = 0;
127 static GLuint tess_eval_shaders[256];
128 static unsigned num_tess_eval_shaders = 0;
129 static GLuint geometry_shaders[256];
130 static unsigned num_geometry_shaders = 0;
131 static GLuint fragment_shaders[256];
132 static unsigned num_fragment_shaders = 0;
133 static GLuint compute_shaders[256];
134 static unsigned num_compute_shaders = 0;
135 static int num_uniform_blocks;
136 static GLuint *uniform_block_bos;
137 static int *uniform_block_indexes; /* ubo block index, indexed by ubo binding */
138 static GLenum geometry_layout_input_type = GL_TRIANGLES;
139 static GLenum geometry_layout_output_type = GL_TRIANGLE_STRIP;
140 static GLint geometry_layout_vertices_out = 0;
141 static GLuint atomics_bos[8];
142 static GLuint ssbo[32];
143 static unsigned num_shader_include_paths = 0;
144 static char **shader_include_path;
145 static char *shader_include_names[256];
146 static unsigned num_shader_includes = 0;
148 #define MAX_XFB_BUFFERS 4 /* Same value used at nir_xfb_info */
149 static GLuint xfb[MAX_XFB_BUFFERS];
151 #define MAX_QUERIES 2
152 static GLuint queries[MAX_QUERIES];
154 #define SHADER_TYPES 6
155 static GLuint *subuniform_locations[SHADER_TYPES];
156 static int num_subuniform_locations[SHADER_TYPES];
157 static char *shader_string;
158 static GLint shader_string_size;
159 static const char *vertex_data_start = NULL;
160 static const char *vertex_data_end = NULL;
161 static GLuint prog;
162 static GLuint sso_vertex_prog;
163 static GLuint sso_tess_control_prog;
164 static GLuint sso_tess_eval_prog;
165 static GLuint sso_geometry_prog;
166 static GLuint sso_fragment_prog;
167 static GLuint sso_compute_prog;
168 static GLuint pipeline = 0;
169 static size_t num_vbo_rows = 0;
170 static bool vbo_present = false;
171 static bool link_ok = false;
172 static bool prog_in_use = false;
173 static bool sso_in_use = false;
174 static bool separable_program = false;
175 static bool glsl_in_use = false;
176 static bool force_glsl = false;
177 static bool spirv_in_use = false;
178 static bool force_no_names = false;
179 static GLchar *prog_err_info = NULL;
180 static GLuint vao = 0;
181 static GLuint draw_fbo, read_fbo;
182 static GLint render_width, render_height;
183 static GLint read_width, read_height;
185 static bool use_get_program_binary = false;
187 static bool ignore_missing_uniforms = false;
189 static bool report_subtests = false;
191 struct specialization_list {
192 size_t buffer_size;
193 size_t n_entries;
194 GLuint *indices;
195 union { GLuint u; GLfloat f; } *values;
198 static struct specialization_list
199 specializations[SHADER_TYPES];
201 static struct texture_binding {
202 GLuint obj;
203 unsigned width;
204 unsigned height;
205 unsigned layers;
206 } texture_bindings[32];
208 static struct resident_handle {
209 GLuint64 handle;
210 bool is_tex;
211 } resident_handles[32];
213 static void
214 clear_texture_binding(unsigned idx)
216 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
217 "Invalid texture index %d\n", idx);
219 if (texture_bindings[idx].obj) {
220 glDeleteTextures(1, &texture_bindings[idx].obj);
221 texture_bindings[idx].obj = 0;
225 static void
226 set_texture_binding(unsigned idx, GLuint obj, unsigned w, unsigned h, unsigned l)
228 clear_texture_binding(idx);
230 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
231 "Invalid texture index %d\n", idx);
232 texture_bindings[idx].obj = obj;
233 texture_bindings[idx].width = w;
234 texture_bindings[idx].height = h;
235 texture_bindings[idx].layers = l;
238 static const struct texture_binding *
239 get_texture_binding(unsigned idx)
241 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
242 "Invalid texture index %d\n", idx);
243 REQUIRE(texture_bindings[idx].obj,
244 "No texture bound at %d\n", idx);
245 return &texture_bindings[idx];
248 static void
249 clear_resident_handle(unsigned idx)
251 REQUIRE(idx < ARRAY_SIZE(resident_handles),
252 "Invalid resident handle index %d\n", idx);
254 if (resident_handles[idx].handle) {
255 GLuint64 handle = resident_handles[idx].handle;
256 if (resident_handles[idx].is_tex) {
257 if (glIsTextureHandleResidentARB(handle))
258 glMakeTextureHandleNonResidentARB(handle);
259 } else {
260 if (glIsImageHandleResidentARB(handle))
261 glMakeImageHandleNonResidentARB(handle);
263 resident_handles[idx].handle = 0;
267 static void
268 set_resident_handle(unsigned idx, GLuint64 handle, bool is_tex)
270 clear_resident_handle(idx);
272 REQUIRE(idx < ARRAY_SIZE(resident_handles),
273 "Invalid resident handle index %d\n", idx);
274 resident_handles[idx].handle = handle;
275 resident_handles[idx].is_tex = is_tex;
278 static const struct resident_handle *
279 get_resident_handle(unsigned idx)
281 REQUIRE(idx < ARRAY_SIZE(resident_handles),
282 "Invalid resident handle index %d\n", idx);
283 REQUIRE(resident_handles[idx].handle,
284 "No resident handle at %d\n", idx);
285 return &resident_handles[idx];
288 enum states {
289 none = 0,
290 requirements,
291 vertex_shader,
292 vertex_shader_passthrough,
293 vertex_shader_spirv,
294 vertex_shader_specializations,
295 vertex_program,
296 tess_ctrl_shader,
297 tess_ctrl_shader_spirv,
298 tess_ctrl_shader_specializations,
299 tess_eval_shader,
300 tess_eval_shader_spirv,
301 tess_eval_shader_specializations,
302 geometry_shader,
303 geometry_shader_spirv,
304 geometry_shader_specializations,
305 geometry_layout,
306 fragment_shader,
307 fragment_shader_spirv,
308 fragment_shader_specializations,
309 fragment_program,
310 compute_shader,
311 compute_shader_spirv,
312 compute_shader_specializations,
313 vertex_data,
314 shader_include,
315 shader_include_paths,
316 test,
319 static const struct string_to_enum all_types[] = {
320 ENUM_STRING(GL_FLOAT),
321 ENUM_STRING(GL_FLOAT_VEC2),
322 ENUM_STRING(GL_FLOAT_VEC3),
323 ENUM_STRING(GL_FLOAT_VEC4),
324 ENUM_STRING(GL_DOUBLE),
325 ENUM_STRING(GL_DOUBLE_VEC2),
326 ENUM_STRING(GL_DOUBLE_VEC3),
327 ENUM_STRING(GL_DOUBLE_VEC4),
328 ENUM_STRING(GL_INT),
329 ENUM_STRING(GL_INT_VEC2),
330 ENUM_STRING(GL_INT_VEC3),
331 ENUM_STRING(GL_INT_VEC4),
332 ENUM_STRING(GL_UNSIGNED_INT),
333 ENUM_STRING(GL_UNSIGNED_INT_VEC2),
334 ENUM_STRING(GL_UNSIGNED_INT_VEC3),
335 ENUM_STRING(GL_UNSIGNED_INT_VEC4),
336 ENUM_STRING(GL_INT64_ARB),
337 ENUM_STRING(GL_INT64_VEC2_ARB),
338 ENUM_STRING(GL_INT64_VEC3_ARB),
339 ENUM_STRING(GL_INT64_VEC4_ARB),
340 ENUM_STRING(GL_UNSIGNED_INT64_ARB),
341 ENUM_STRING(GL_UNSIGNED_INT64_VEC2_ARB),
342 ENUM_STRING(GL_UNSIGNED_INT64_VEC3_ARB),
343 ENUM_STRING(GL_UNSIGNED_INT64_VEC4_ARB),
344 ENUM_STRING(GL_BOOL),
345 ENUM_STRING(GL_BOOL_VEC2),
346 ENUM_STRING(GL_BOOL_VEC3),
347 ENUM_STRING(GL_BOOL_VEC4),
348 ENUM_STRING(GL_FLOAT_MAT2),
349 ENUM_STRING(GL_FLOAT_MAT3),
350 ENUM_STRING(GL_FLOAT_MAT4),
351 ENUM_STRING(GL_FLOAT_MAT2x3),
352 ENUM_STRING(GL_FLOAT_MAT2x4),
353 ENUM_STRING(GL_FLOAT_MAT3x2),
354 ENUM_STRING(GL_FLOAT_MAT3x4),
355 ENUM_STRING(GL_FLOAT_MAT4x2),
356 ENUM_STRING(GL_FLOAT_MAT4x3),
357 ENUM_STRING(GL_DOUBLE_MAT2),
358 ENUM_STRING(GL_DOUBLE_MAT3),
359 ENUM_STRING(GL_DOUBLE_MAT4),
360 ENUM_STRING(GL_DOUBLE_MAT2x3),
361 ENUM_STRING(GL_DOUBLE_MAT2x4),
362 ENUM_STRING(GL_DOUBLE_MAT3x2),
363 ENUM_STRING(GL_DOUBLE_MAT3x4),
364 ENUM_STRING(GL_DOUBLE_MAT4x2),
365 ENUM_STRING(GL_DOUBLE_MAT4x3),
366 ENUM_STRING(GL_SAMPLER_1D),
367 ENUM_STRING(GL_SAMPLER_2D),
368 ENUM_STRING(GL_SAMPLER_3D),
369 ENUM_STRING(GL_SAMPLER_CUBE),
370 ENUM_STRING(GL_SAMPLER_1D_SHADOW),
371 ENUM_STRING(GL_SAMPLER_2D_SHADOW),
372 ENUM_STRING(GL_SAMPLER_1D_ARRAY),
373 ENUM_STRING(GL_SAMPLER_2D_ARRAY),
374 ENUM_STRING(GL_SAMPLER_1D_ARRAY_SHADOW),
375 ENUM_STRING(GL_SAMPLER_2D_ARRAY_SHADOW),
376 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE),
377 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE_ARRAY),
378 ENUM_STRING(GL_SAMPLER_CUBE_SHADOW),
379 ENUM_STRING(GL_SAMPLER_BUFFER),
380 ENUM_STRING(GL_SAMPLER_2D_RECT),
381 ENUM_STRING(GL_SAMPLER_2D_RECT_SHADOW),
382 ENUM_STRING(GL_INT_SAMPLER_1D),
383 ENUM_STRING(GL_INT_SAMPLER_2D),
384 ENUM_STRING(GL_INT_SAMPLER_3D),
385 ENUM_STRING(GL_INT_SAMPLER_CUBE),
386 ENUM_STRING(GL_INT_SAMPLER_1D_ARRAY),
387 ENUM_STRING(GL_INT_SAMPLER_2D_ARRAY),
388 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE),
389 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
390 ENUM_STRING(GL_INT_SAMPLER_BUFFER),
391 ENUM_STRING(GL_INT_SAMPLER_2D_RECT),
392 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D),
393 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D),
394 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_3D),
395 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_CUBE),
396 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY),
397 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY),
398 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE),
399 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
400 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_BUFFER),
401 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_RECT),
402 { NULL, 0 }
405 static bool
406 compare(float ref, float value, enum comparison cmp);
408 static bool
409 compare_uint(GLuint ref, GLuint value, enum comparison cmp);
411 static bool
412 compare_int(GLint ref, GLint value, enum comparison cmp);
414 static void
415 version_init(struct component_version *v, enum version_tag tag, bool core, bool compat, bool es, unsigned num)
417 assert(tag == VERSION_GL || tag == VERSION_GLSL);
419 v->_tag = tag;
420 v->core = core;
421 v->compat = compat;
422 v->es = es;
423 v->num = num;
424 v->_string[0] = 0;
427 static void
428 version_copy(struct component_version *dest, struct component_version *src)
430 memcpy(dest, src, sizeof(*dest));
433 static bool
434 version_compare(struct component_version *a, struct component_version *b, enum comparison cmp)
436 assert(a->_tag == b->_tag);
438 if (a->es != b->es)
439 return false;
441 return compare(a->num, b->num, cmp);
445 * Get the version string.
447 static const char*
448 version_string(struct component_version *v)
450 if (v->_string[0])
451 return v->_string;
453 switch (v->_tag) {
454 case VERSION_GL:
455 snprintf(v->_string, sizeof(v->_string) - 1, "GL%s %d.%d",
456 v->es ? " ES" : "",
457 v->num / 10, v->num % 10);
458 break;
459 case VERSION_GLSL:
460 snprintf(v->_string, sizeof(v->_string) - 1, "GLSL%s %d.%d",
461 v->es ? " ES" : "",
462 v->num / 100, v->num % 100);
463 break;
464 default:
465 assert(false);
466 break;
469 return v->_string;
473 static const char *
474 target_to_short_name(GLenum target)
476 switch (target) {
477 case GL_VERTEX_SHADER:
478 return "VS";
479 case GL_FRAGMENT_SHADER:
480 return "FS";
481 case GL_TESS_CONTROL_SHADER:
482 return "TCS";
483 case GL_TESS_EVALUATION_SHADER:
484 return "TES";
485 case GL_GEOMETRY_SHADER:
486 return "GS";
487 case GL_COMPUTE_SHADER:
488 return "CS";
489 default:
490 return "???";
495 static enum piglit_result
496 compile_glsl(GLenum target)
498 GLuint shader = glCreateShader(target);
499 GLint ok;
501 if (spirv_in_use) {
502 printf("Cannot mix SPIRV and non-SPIRV shaders\n");
503 return PIGLIT_FAIL;
506 glsl_in_use = true;
508 switch (target) {
509 case GL_VERTEX_SHADER:
510 if (piglit_get_gl_version() < 20 &&
511 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
512 piglit_is_extension_supported("GL_ARB_vertex_shader")))
513 return PIGLIT_SKIP;
514 break;
515 case GL_FRAGMENT_SHADER:
516 if (piglit_get_gl_version() < 20 &&
517 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
518 piglit_is_extension_supported("GL_ARB_fragment_shader")))
519 return PIGLIT_SKIP;
520 break;
521 case GL_TESS_CONTROL_SHADER:
522 case GL_TESS_EVALUATION_SHADER:
523 if (gl_version.num < (gl_version.es ? 32 : 40))
524 if (!piglit_is_extension_supported(gl_version.es ?
525 "GL_OES_tessellation_shader" :
526 "GL_ARB_tessellation_shader"))
527 return PIGLIT_SKIP;
528 break;
529 case GL_GEOMETRY_SHADER:
530 if (gl_version.num < 32)
531 if (!piglit_is_extension_supported(gl_version.es ?
532 "GL_OES_geometry_shader" :
533 "GL_ARB_geometry_shader4"))
534 return PIGLIT_SKIP;
535 break;
536 case GL_COMPUTE_SHADER:
537 if (gl_version.num < (gl_version.es ? 31 : 43))
538 if (!piglit_is_extension_supported("GL_ARB_compute_shader"))
539 return PIGLIT_SKIP;
540 break;
543 if (!glsl_req_version.num) {
544 printf("GLSL version requirement missing\n");
545 return PIGLIT_FAIL;
548 if (!strstr(shader_string, "#version ")) {
549 char *shader_strings[2];
550 char version_string[100];
551 GLint shader_string_sizes[2];
553 /* Add a #version directive based on the GLSL requirement. */
554 sprintf(version_string, "#version %d", glsl_req_version.num);
555 if (glsl_req_version.es && glsl_req_version.num != 100) {
556 strcat(version_string, " es");
558 strcat(version_string, "\n");
559 shader_strings[0] = version_string;
560 shader_string_sizes[0] = strlen(version_string);
561 shader_strings[1] = shader_string;
562 shader_string_sizes[1] = shader_string_size;
564 glShaderSource(shader, 2,
565 (const GLchar **) shader_strings,
566 shader_string_sizes);
568 } else {
569 glShaderSource(shader, 1,
570 (const GLchar **) &shader_string,
571 &shader_string_size);
574 if (num_shader_include_paths) {
575 glCompileShaderIncludeARB(shader, num_shader_include_paths,
576 (const char **) shader_include_path, NULL);
577 } else
578 glCompileShader(shader);
580 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
582 if (!ok) {
583 GLchar *info;
584 GLint size;
586 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
587 info = malloc(size);
589 glGetShaderInfoLog(shader, size, NULL, info);
591 fprintf(stderr, "Failed to compile %s: %s\n",
592 target_to_short_name(target),
593 info);
595 free(info);
596 return PIGLIT_FAIL;
599 switch (target) {
600 case GL_VERTEX_SHADER:
601 vertex_shaders[num_vertex_shaders] = shader;
602 num_vertex_shaders++;
603 break;
604 case GL_TESS_CONTROL_SHADER:
605 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
606 num_tess_ctrl_shaders++;
607 break;
608 case GL_TESS_EVALUATION_SHADER:
609 tess_eval_shaders[num_tess_eval_shaders] = shader;
610 num_tess_eval_shaders++;
611 break;
612 case GL_GEOMETRY_SHADER:
613 geometry_shaders[num_geometry_shaders] = shader;
614 num_geometry_shaders++;
615 break;
616 case GL_FRAGMENT_SHADER:
617 fragment_shaders[num_fragment_shaders] = shader;
618 num_fragment_shaders++;
619 break;
620 case GL_COMPUTE_SHADER:
621 compute_shaders[num_compute_shaders] = shader;
622 num_compute_shaders++;
623 break;
625 return PIGLIT_PASS;
629 static enum piglit_result
630 compile_and_bind_program(GLenum target, const char *start, int len)
632 GLuint prog;
633 char *source;
635 switch (target) {
636 case GL_VERTEX_PROGRAM_ARB:
637 if (!piglit_is_extension_supported("GL_ARB_vertex_program"))
638 return PIGLIT_SKIP;
639 break;
640 case GL_FRAGMENT_PROGRAM_ARB:
641 if (!piglit_is_extension_supported("GL_ARB_fragment_program"))
642 return PIGLIT_SKIP;
643 break;
646 source = malloc(len + 1);
647 memcpy(source, start, len);
648 source[len] = 0;
649 prog = piglit_compile_program(target, source);
651 glEnable(target);
652 glBindProgramARB(target, prog);
653 link_ok = true;
654 prog_in_use = true;
656 return PIGLIT_PASS;
659 static bool
660 program_binary_save_restore(bool script_command)
662 GLint binary_length;
663 void *binary;
664 GLenum binary_format;
665 GLint ok;
666 GLuint new_prog;
668 if (!script_command && !use_get_program_binary)
669 return true;
671 if (script_command && gl_num_program_binary_formats == 0)
672 piglit_report_result(PIGLIT_SKIP);
674 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
675 if (!ok) {
676 if (script_command) {
677 fprintf(stderr, "Can't save/restore program that is "
678 "not linked!\n");
679 piglit_report_result(PIGLIT_FAIL);
680 } else {
681 return true;
685 #ifdef PIGLIT_USE_OPENGL
686 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &binary_length);
687 #else
688 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH_OES, &binary_length);
689 #endif
690 if (!piglit_check_gl_error(GL_NO_ERROR)) {
691 fprintf(stderr, "glGetProgramiv GL_PROGRAM_BINARY_LENGTH "
692 "error\n");
693 piglit_report_result(PIGLIT_FAIL);
696 binary = malloc(binary_length);
697 if (!binary) {
698 fprintf(stderr, "Failed to allocate buffer for "
699 "GetProgramBinary\n");
700 piglit_report_result(PIGLIT_FAIL);
703 #ifdef PIGLIT_USE_OPENGL
704 glGetProgramBinary(prog, binary_length, &binary_length, &binary_format,
705 binary);
706 #else
707 glGetProgramBinaryOES(prog, binary_length, &binary_length,
708 &binary_format, binary);
709 #endif
710 if (!piglit_check_gl_error(GL_NO_ERROR)) {
711 fprintf(stderr, "glGetProgramBinary error\n");
712 free(binary);
713 piglit_report_result(PIGLIT_FAIL);
716 new_prog = glCreateProgram();
717 if (!piglit_check_gl_error(GL_NO_ERROR)) {
718 free(binary);
719 piglit_report_result(PIGLIT_FAIL);
722 #ifdef PIGLIT_USE_OPENGL
723 glProgramBinary(new_prog, binary_format, binary, binary_length);
724 #else
725 glProgramBinaryOES(new_prog, binary_format, binary, binary_length);
726 #endif
727 free(binary);
728 if (!piglit_check_gl_error(GL_NO_ERROR)) {
729 fprintf(stderr, "glProgramBinary error "
730 "(should not happend according to spec.)\n");
731 piglit_report_result(PIGLIT_FAIL);
734 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
735 if (!ok) {
736 fprintf(stderr, "link failure after glProgramBinary\n");
737 piglit_report_result(PIGLIT_FAIL);
740 if (prog_in_use) {
741 glUseProgram(new_prog);
742 if (!piglit_check_gl_error(GL_NO_ERROR))
743 piglit_report_result(PIGLIT_FAIL);
746 glDeleteProgram(prog);
747 if (!piglit_check_gl_error(GL_NO_ERROR))
748 piglit_report_result(PIGLIT_FAIL);
749 prog = new_prog;
751 return true;
754 static enum piglit_result
755 specialize_spirv(GLenum target,
756 GLuint shader)
758 if (glsl_in_use) {
759 printf("Cannot mix SPIR-V and non-SPIR-V shaders\n");
760 return PIGLIT_FAIL;
763 spirv_in_use = true;
765 const struct specialization_list *specs;
767 switch (target) {
768 case GL_VERTEX_SHADER:
769 specs = specializations + 0;
770 break;
771 case GL_TESS_CONTROL_SHADER:
772 specs = specializations + 1;
773 break;
774 case GL_TESS_EVALUATION_SHADER:
775 specs = specializations + 2;
776 break;
777 case GL_GEOMETRY_SHADER:
778 specs = specializations + 3;
779 break;
780 case GL_FRAGMENT_SHADER:
781 specs = specializations + 4;
782 break;
783 case GL_COMPUTE_SHADER:
784 specs = specializations + 5;
785 break;
786 default:
787 assert(!"Should not get here.");
790 glSpecializeShaderARB(shader,
791 "main",
792 specs->n_entries,
793 specs->indices,
794 &specs->values[0].u);
796 GLint ok;
797 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
799 if (!ok) {
800 GLchar *info;
801 GLint size;
803 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
804 info = malloc(MAX2(size, 1));
805 info[0] = 0;
807 glGetShaderInfoLog(shader, size, NULL, info);
809 printf("Failed to specialize %s: %s\n",
810 target_to_short_name(target), info);
812 free(info);
813 return PIGLIT_FAIL;
816 switch (target) {
817 case GL_VERTEX_SHADER:
818 vertex_shaders[num_vertex_shaders] = shader;
819 num_vertex_shaders++;
820 break;
821 case GL_TESS_CONTROL_SHADER:
822 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
823 num_tess_ctrl_shaders++;
824 break;
825 case GL_TESS_EVALUATION_SHADER:
826 tess_eval_shaders[num_tess_eval_shaders] = shader;
827 num_tess_eval_shaders++;
828 break;
829 case GL_GEOMETRY_SHADER:
830 geometry_shaders[num_geometry_shaders] = shader;
831 num_geometry_shaders++;
832 break;
833 case GL_FRAGMENT_SHADER:
834 fragment_shaders[num_fragment_shaders] = shader;
835 num_fragment_shaders++;
836 break;
837 case GL_COMPUTE_SHADER:
838 compute_shaders[num_compute_shaders] = shader;
839 num_compute_shaders++;
840 break;
843 return PIGLIT_PASS;
846 static enum piglit_result
847 assemble_spirv(GLenum target)
849 if (!piglit_is_extension_supported("GL_ARB_gl_spirv")) {
850 return PIGLIT_SKIP;
853 /* Strip comments from the source */
854 char *stripped_source = malloc(shader_string_size);
855 char *p = stripped_source;
856 bool at_start_of_line = true;
858 for (const char *in = shader_string;
859 in < shader_string + shader_string_size;
860 in++) {
861 if (*in == '#' && at_start_of_line) {
862 const char *end;
863 end = memchr(in,
864 '\n',
865 shader_string + shader_string_size - in);
866 if (end == NULL)
867 break;
868 in = end;
869 } else {
870 at_start_of_line = *in == '\n';
871 *(p++) = *in;
875 GLuint shader = piglit_assemble_spirv(target,
876 p - stripped_source,
877 stripped_source);
879 free(stripped_source);
881 return specialize_spirv(target, shader);
884 static enum piglit_result
885 link_sso(GLenum target)
887 GLint ok;
889 glLinkProgram(prog);
891 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
892 if (ok) {
893 link_ok = true;
894 } else {
895 GLint size;
897 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
898 prog_err_info = malloc(MAX2(size, 1));
899 prog_err_info[0] = 0;
901 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
903 fprintf(stderr, "SSO glLinkProgram(%s) failed: %s\n",
904 target_to_short_name(target),
905 prog_err_info);
907 free(prog_err_info);
908 return PIGLIT_FAIL;
911 if (!program_binary_save_restore(false))
912 return PIGLIT_FAIL;
914 switch (target) {
915 case GL_VERTEX_SHADER:
916 sso_vertex_prog = prog;
917 glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, prog);
918 break;
919 case GL_TESS_CONTROL_SHADER:
920 sso_tess_control_prog = prog;
921 glUseProgramStages(pipeline, GL_TESS_CONTROL_SHADER_BIT, prog);
922 break;
923 case GL_TESS_EVALUATION_SHADER:
924 sso_tess_eval_prog = prog;
925 glUseProgramStages(pipeline, GL_TESS_EVALUATION_SHADER_BIT, prog);
926 break;
927 case GL_GEOMETRY_SHADER:
928 sso_geometry_prog = prog;
929 glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, prog);
930 break;
931 case GL_FRAGMENT_SHADER:
932 sso_fragment_prog = prog;
933 glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, prog);
934 break;
935 case GL_COMPUTE_SHADER:
936 sso_compute_prog = prog;
937 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, prog);
938 break;
940 return PIGLIT_PASS;
944 * Compare two values given a specified comparison operator
946 static bool
947 compare(float ref, float value, enum comparison cmp)
949 switch (cmp) {
950 case equal: return value == ref;
951 case not_equal: return value != ref;
952 case less: return value < ref;
953 case greater_equal: return value >= ref;
954 case greater: return value > ref;
955 case less_equal: return value <= ref;
958 assert(!"Should not get here.");
959 return false;
962 static bool
963 compare_double(double ref, double value, enum comparison cmp)
965 switch (cmp) {
966 case equal: return fabs(value - ref) < DBL_EPSILON;
967 case not_equal: return fabs(value - ref) >= DBL_EPSILON;
968 case less: return value < ref;
969 case greater_equal: return value >= ref;
970 case greater: return value > ref;
971 case less_equal: return value <= ref;
974 assert(!"Should not get here.");
975 return false;
978 static bool
979 compare_uint(GLuint ref, GLuint value, enum comparison cmp)
981 switch (cmp) {
982 case equal: return value == ref;
983 case not_equal: return value != ref;
984 case less: return value < ref;
985 case greater_equal: return value >= ref;
986 case greater: return value > ref;
987 case less_equal: return value <= ref;
990 assert(!"Should not get here.");
991 return false;
994 static bool
995 compare_int(GLint ref, GLint value, enum comparison cmp)
997 switch (cmp) {
998 case equal: return value == ref;
999 case not_equal: return value != ref;
1000 case less: return value < ref;
1001 case greater_equal: return value >= ref;
1002 case greater: return value > ref;
1003 case less_equal: return value <= ref;
1006 assert(!"Should not get here.");
1007 return false;
1010 static bool
1011 compare_uint64(GLuint64 ref, GLuint64 value, enum comparison cmp)
1013 switch (cmp) {
1014 case equal: return value == ref;
1015 case not_equal: return value != ref;
1016 case less: return value < ref;
1017 case greater_equal: return value >= ref;
1018 case greater: return value > ref;
1019 case less_equal: return value <= ref;
1022 assert(!"Should not get here.");
1023 return false;
1026 static bool
1027 compare_int64(GLint64 ref, GLint64 value, enum comparison cmp)
1029 switch (cmp) {
1030 case equal: return value == ref;
1031 case not_equal: return value != ref;
1032 case less: return value < ref;
1033 case greater_equal: return value >= ref;
1034 case greater: return value > ref;
1035 case less_equal: return value <= ref;
1038 assert(!"Should not get here.");
1039 return false;
1043 * Get the string representation of a comparison operator
1045 static const char *
1046 comparison_string(enum comparison cmp)
1048 switch (cmp) {
1049 case equal: return "==";
1050 case not_equal: return "!=";
1051 case less: return "<";
1052 case greater_equal: return ">=";
1053 case greater: return ">";
1054 case less_equal: return "<=";
1057 assert(!"Should not get here.");
1058 return false;
1062 * " ES" before the comparison operator indicates the version
1063 * pertains to GL ES.
1065 static void
1066 parse_version_comparison(const char *line, enum comparison *cmp,
1067 struct component_version *v, enum version_tag tag)
1069 unsigned major;
1070 unsigned minor;
1071 unsigned full_num;
1072 const bool core = parse_str(line, "CORE", &line);
1073 const bool compat = parse_str(line, "COMPAT", &line);
1074 const bool es = parse_str(line, "ES", &line);
1076 REQUIRE(parse_comparison_op(line, cmp, &line),
1077 "Invalid comparison operation at: %s\n", line);
1079 REQUIRE(parse_uint(line, &major, &line) &&
1080 parse_str(line, ".", &line) &&
1081 parse_uint(line, &minor, &line),
1082 "Invalid version string: %s\n", line);
1084 parse_whitespace(line, &line);
1085 if (*line != '\n') {
1086 printf("Unexpected characters following version comparison\n");
1087 piglit_report_result(PIGLIT_FAIL);
1090 /* This hack is so that we can tell the difference between GL versions
1091 * and GLSL versions. All GL versions look like 3.2, and we want the
1092 * integer to be 32. All GLSL versions look like 1.40, and we want
1093 * the integer to be 140.
1095 if (tag == VERSION_GLSL) {
1096 full_num = (major * 100) + minor;
1097 } else {
1098 full_num = (major * 10) + minor;
1101 version_init(v, tag, core, compat, es, full_num);
1105 * Parse and check a line from the requirement section of the test
1107 static enum piglit_result
1108 process_requirement(const char *line)
1110 char buffer[4096];
1111 static const struct {
1112 const char *name;
1113 int *val;
1114 const char *desc;
1115 } getint_limits[] = {
1117 "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
1118 &gl_max_vertex_output_components,
1119 "vertex output components",
1122 "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
1123 &gl_max_fragment_uniform_components,
1124 "fragment uniform components",
1127 "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
1128 &gl_max_vertex_uniform_components,
1129 "vertex uniform components",
1132 "GL_MAX_VERTEX_ATTRIBS",
1133 &gl_max_vertex_attribs,
1134 "vertex attribs",
1137 "GL_MAX_VARYING_COMPONENTS",
1138 &gl_max_varying_components,
1139 "varying components",
1142 "GL_NUM_PROGRAM_BINARY_FORMATS",
1143 &gl_num_program_binary_formats,
1144 "num program binary formats",
1147 unsigned i;
1149 /* The INT keyword in the requirements section causes
1150 * shader_runner to read the specified integer value and
1151 * processes the given requirement.
1153 if (parse_str(line, "INT ", &line)) {
1154 enum comparison cmp;
1155 int comparison_value, gl_int_value;
1156 unsigned int_enum;
1158 REQUIRE(parse_enum_gl(line, &int_enum, &line),
1159 "Invalid comparison enum at: %s\n", line);
1160 REQUIRE(parse_comparison_op(line, &cmp, &line),
1161 "Invalid comparison operation at: %s\n", line);
1162 REQUIRE(parse_int(line, &comparison_value, &line),
1163 "Invalid comparison value at: %s\n", line);
1165 glGetIntegerv(int_enum, &gl_int_value);
1166 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1167 fprintf(stderr, "Error reading %s\n",
1168 piglit_get_gl_enum_name(int_enum));
1169 return PIGLIT_FAIL;
1172 if (!compare(comparison_value, gl_int_value, cmp)) {
1173 printf("Test requires %s %s %i. "
1174 "The driver supports %i.\n",
1175 piglit_get_gl_enum_name(int_enum),
1176 comparison_string(cmp),
1177 comparison_value,
1178 gl_int_value);
1179 return PIGLIT_SKIP;
1182 return PIGLIT_PASS;
1185 /* There are five types of requirements that a test can currently
1186 * have:
1188 * * Require that some GL extension be supported
1189 * * Require some particular versions of GL
1190 * * Require some particular versions of GLSL
1191 * * Require some particular number of uniform components
1192 * * Require shaders be built as separate shader objects
1194 * The tests for GL and GLSL versions can be equal, not equal,
1195 * less, less-or-equal, greater, or greater-or-equal. Extension tests
1196 * can also require that a particular extension not be supported by
1197 * prepending ! to the extension name.
1199 for (i = 0; i < ARRAY_SIZE(getint_limits); i++) {
1200 enum comparison cmp;
1201 int maxcomp;
1203 if (!parse_str(line, getint_limits[i].name, &line))
1204 continue;
1206 REQUIRE(parse_comparison_op(line, &cmp, &line),
1207 "Invalid comparison operation at: %s\n", line);
1209 maxcomp = atoi(line);
1210 if (!compare(maxcomp, *getint_limits[i].val, cmp)) {
1211 printf("Test requires %s %s %i. "
1212 "The driver supports %i.\n",
1213 getint_limits[i].desc,
1214 comparison_string(cmp),
1215 maxcomp,
1216 *getint_limits[i].val);
1217 return PIGLIT_SKIP;
1219 return PIGLIT_PASS;
1222 if (parse_str(line, "GL_", NULL) &&
1223 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1224 if (!piglit_is_extension_supported(buffer)) {
1225 printf("Test requires unsupported extension %s\n", buffer);
1226 return PIGLIT_SKIP;
1228 } else if (parse_str(line, "!", &line) &&
1229 parse_str(line, "GL_", NULL) &&
1230 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1231 if (piglit_is_extension_supported(buffer)) {
1232 printf("Test requires unsupported extension %s\n", buffer);
1233 return PIGLIT_SKIP;
1235 } else if (parse_str(line, "GLSL", &line)) {
1236 enum comparison cmp;
1238 parse_version_comparison(line, &cmp, &glsl_req_version,
1239 VERSION_GLSL);
1241 /* We only allow >= because we potentially use the
1242 * version number to insert a #version directive. */
1243 if (cmp != greater_equal) {
1244 printf("Unsupported GLSL version comparison\n");
1245 return PIGLIT_FAIL;
1248 if (!version_compare(&glsl_req_version, &glsl_version, cmp)) {
1249 printf("Test requires %s %s. "
1250 "Actual version %s.\n",
1251 comparison_string(cmp),
1252 version_string(&glsl_req_version),
1253 version_string(&glsl_version));
1254 return PIGLIT_SKIP;
1256 } else if (parse_str(line, "GL", &line)) {
1257 enum comparison cmp;
1258 struct component_version gl_req_version;
1260 parse_version_comparison(line, &cmp, &gl_req_version,
1261 VERSION_GL);
1263 if (!version_compare(&gl_req_version, &gl_version, cmp)) {
1264 printf("Test requires %s %s. "
1265 "Actual version is %s.\n",
1266 comparison_string(cmp),
1267 version_string(&gl_req_version),
1268 version_string(&gl_version));
1269 return PIGLIT_SKIP;
1271 } else if (parse_str(line, "rlimit", &line)) {
1272 unsigned lim;
1274 REQUIRE(parse_uint(line, &lim, &line),
1275 "Invalid rlimit argument at: %s\n", line);
1277 piglit_set_rlimit(lim);
1278 } else if (parse_str(line, "SSO", &line) &&
1279 parse_str(line, "ENABLED", NULL)) {
1280 if (separable_program) {
1281 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1282 return PIGLIT_FAIL;
1285 const char *const ext_name = gl_version.es
1286 ? "GL_EXT_separate_shader_objects"
1287 : "GL_ARB_separate_shader_objects";
1288 const unsigned min_version = gl_version.es
1289 ? 31 : 41;
1291 if (gl_version.num < min_version)
1292 piglit_require_extension(ext_name);
1294 sso_in_use = true;
1295 glGenProgramPipelines(1, &pipeline);
1296 } else if (parse_str(line, "SEPARABLE PROGRAM", &line) &&
1297 parse_str(line, "ENABLED", NULL)) {
1298 if (sso_in_use) {
1299 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1300 return PIGLIT_FAIL;
1303 const char *const ext_name = gl_version.es
1304 ? "GL_EXT_separate_shader_objects"
1305 : "GL_ARB_separate_shader_objects";
1306 const unsigned min_version = gl_version.es
1307 ? 31 : 41;
1309 if (gl_version.num < min_version)
1310 piglit_require_extension(ext_name);
1312 separable_program = true;
1313 } else if (parse_str(line, "SPIRV", &line)) {
1314 spirv_replaces_glsl = !force_glsl;
1316 if (parse_str(line, "ONLY", NULL)) {
1317 if (force_glsl) {
1318 printf("This shader is not compatible with GLSL\n");
1319 return PIGLIT_SKIP;
1321 } else if (parse_str(line, "YES", NULL)) {
1322 /* Empty. Everything already set. Just parsing
1323 * correct options
1325 } else {
1326 printf("Unknown SPIRV line in [require]\n");
1327 return PIGLIT_FAIL;
1330 if (spirv_replaces_glsl)
1331 force_no_names = true;
1333 return PIGLIT_PASS;
1338 * Process a line from the [geometry layout] section of a test
1340 static void
1341 process_geometry_layout(const char *line)
1343 char s[32];
1344 int x;
1346 parse_whitespace(line, &line);
1348 if (line[0] == '\0' || line[0] == '\n') {
1349 return;
1350 } else if (sscanf(line, "input type %31s", s) == 1) {
1351 geometry_layout_input_type = decode_drawing_mode(s);
1352 } else if (sscanf(line, "output type %31s", s) == 1) {
1353 geometry_layout_output_type = decode_drawing_mode(s);
1354 } else if (sscanf(line, "vertices out %d", &x) == 1) {
1355 geometry_layout_vertices_out = x;
1356 } else {
1357 printf("Could not parse geometry layout line: %s\n", line);
1358 piglit_report_result(PIGLIT_FAIL);
1362 static enum piglit_result
1363 leave_state(enum states state, const char *line, const char *script_name)
1365 switch (state) {
1366 case none:
1367 break;
1369 case requirements:
1370 if (spirv_replaces_glsl) {
1371 printf("Running on SPIR-V mode\n");
1373 if (force_no_names && !spirv_replaces_glsl) {
1374 printf("Running on GLSL mode, forcing not using "
1375 "uniform/uniform block names\n");
1377 break;
1379 case vertex_shader:
1380 if (spirv_replaces_glsl)
1381 break;
1382 shader_string_size = line - shader_string;
1383 return compile_glsl(GL_VERTEX_SHADER);
1385 case vertex_shader_passthrough:
1386 if (spirv_replaces_glsl) {
1387 shader_string = (char *) passthrough_vertex_shader_source_spv;
1388 shader_string_size = strlen(passthrough_vertex_shader_source_spv);
1390 return assemble_spirv(GL_VERTEX_SHADER);
1392 return compile_glsl(GL_VERTEX_SHADER);
1394 case vertex_program:
1395 return compile_and_bind_program(GL_VERTEX_PROGRAM_ARB,
1396 shader_string,
1397 line - shader_string);
1399 case vertex_shader_spirv:
1400 if (!spirv_replaces_glsl)
1401 break;
1402 shader_string_size = line - shader_string;
1403 return assemble_spirv(GL_VERTEX_SHADER);
1405 case vertex_shader_specializations:
1406 break;
1408 case tess_ctrl_shader:
1409 if (spirv_replaces_glsl)
1410 break;
1411 shader_string_size = line - shader_string;
1412 return compile_glsl(GL_TESS_CONTROL_SHADER);
1414 case tess_ctrl_shader_spirv:
1415 if (!spirv_replaces_glsl)
1416 break;
1417 shader_string_size = line - shader_string;
1418 return assemble_spirv(GL_TESS_CONTROL_SHADER);
1420 case tess_ctrl_shader_specializations:
1421 break;
1423 case tess_eval_shader:
1424 if (spirv_replaces_glsl)
1425 break;
1426 shader_string_size = line - shader_string;
1427 return compile_glsl(GL_TESS_EVALUATION_SHADER);
1429 case tess_eval_shader_spirv:
1430 if (!spirv_replaces_glsl)
1431 break;
1432 shader_string_size = line - shader_string;
1433 return assemble_spirv(GL_TESS_EVALUATION_SHADER);
1435 case tess_eval_shader_specializations:
1436 break;
1438 case geometry_shader:
1439 if (spirv_replaces_glsl)
1440 break;
1441 shader_string_size = line - shader_string;
1442 return compile_glsl(GL_GEOMETRY_SHADER);
1444 case geometry_shader_spirv:
1445 if (!spirv_replaces_glsl)
1446 break;
1447 shader_string_size = line - shader_string;
1448 return assemble_spirv(GL_GEOMETRY_SHADER);
1450 case geometry_shader_specializations:
1451 break;
1453 case geometry_layout:
1454 break;
1456 case fragment_shader:
1457 if (spirv_replaces_glsl)
1458 break;
1459 shader_string_size = line - shader_string;
1460 return compile_glsl(GL_FRAGMENT_SHADER);
1462 case fragment_program:
1463 return compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB,
1464 shader_string,
1465 line - shader_string);
1466 break;
1468 case fragment_shader_spirv:
1469 if (!spirv_replaces_glsl)
1470 break;
1471 shader_string_size = line - shader_string;
1472 return assemble_spirv(GL_FRAGMENT_SHADER);
1474 case fragment_shader_specializations:
1475 break;
1477 case compute_shader:
1478 if (spirv_replaces_glsl)
1479 break;
1480 shader_string_size = line - shader_string;
1481 return compile_glsl(GL_COMPUTE_SHADER);
1483 case compute_shader_spirv:
1484 if (!spirv_replaces_glsl)
1485 break;
1486 shader_string_size = line - shader_string;
1487 return assemble_spirv(GL_COMPUTE_SHADER);
1489 case compute_shader_specializations:
1490 break;
1492 case vertex_data:
1493 vertex_data_end = line;
1494 break;
1496 case shader_include: {
1497 const char *path_end = strchrnul(shader_string, '\n');
1499 if (shader_string == path_end) {
1500 fprintf(stderr, "No shader include path provided\n");
1501 return PIGLIT_FAIL;
1504 if (!piglit_is_extension_supported("GL_ARB_shading_language_include"))
1505 return PIGLIT_SKIP;
1507 int path_name_len = path_end - shader_string;
1508 glNamedStringARB(GL_SHADER_INCLUDE_ARB, path_name_len, shader_string,
1509 line - shader_string - path_name_len, shader_string + path_name_len);
1511 shader_include_names[num_shader_includes] = strndup(shader_string, path_name_len);
1512 num_shader_includes++;
1513 assert(num_shader_includes <= 256);
1515 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1516 fprintf(stderr, "glNamedStringARB error\n");
1517 return PIGLIT_FAIL;
1520 break;
1523 case shader_include_paths: {
1524 num_shader_include_paths = 0;
1525 const char *cursor = shader_string;
1526 do {
1527 const char *line_start = cursor;
1528 cursor = strchr(cursor, '\n');
1530 if (cursor == line_start) {
1531 cursor++;
1532 continue;
1535 cursor++;
1536 num_shader_include_paths++;
1537 } while (cursor && cursor < line);
1539 shader_include_path = calloc(num_shader_include_paths, sizeof(char *));
1541 cursor = shader_string;
1542 for (unsigned i = 0; i < num_shader_include_paths; i++) {
1543 char *line_end = strchr(cursor, '\n');
1544 unsigned path_len = line_end - cursor - 1;
1545 char *path = malloc(path_len + 1);
1546 path[path_len] = '\0';
1548 memcpy(path, cursor, path_len);
1549 shader_include_path[i] = path;
1550 cursor = line_end + 1;
1553 break;
1556 case test:
1557 break;
1559 default:
1560 assert(!"Not yet supported.");
1562 return PIGLIT_PASS;
1566 static enum piglit_result
1567 process_shader(GLenum target, unsigned num_shaders, GLuint *shaders)
1569 if (num_shaders == 0)
1570 return PIGLIT_PASS;
1572 if (sso_in_use) {
1573 prog = glCreateProgram();
1574 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1577 for (unsigned i = 0; i < num_shaders; i++) {
1578 glAttachShader(prog, shaders[i]);
1581 #ifdef PIGLIT_USE_OPENGL
1582 if (geometry_layout_input_type != GL_TRIANGLES) {
1583 glProgramParameteriARB(prog, GL_GEOMETRY_INPUT_TYPE_ARB,
1584 geometry_layout_input_type);
1586 if (geometry_layout_output_type != GL_TRIANGLE_STRIP) {
1587 glProgramParameteriARB(prog, GL_GEOMETRY_OUTPUT_TYPE_ARB,
1588 geometry_layout_output_type);
1590 if (geometry_layout_vertices_out != 0) {
1591 glProgramParameteriARB(prog, GL_GEOMETRY_VERTICES_OUT_ARB,
1592 geometry_layout_vertices_out);
1594 #endif
1596 /* If the shaders reference piglit_vertex or piglit_tex, bind
1597 * them to some fixed attribute locations so they can be used
1598 * with piglit_draw_rect_tex() in GLES.
1600 glBindAttribLocation(prog, PIGLIT_ATTRIB_POS, "piglit_vertex");
1601 glBindAttribLocation(prog, PIGLIT_ATTRIB_TEX, "piglit_texcoord");
1603 if (sso_in_use) {
1604 return link_sso(target);
1606 return PIGLIT_PASS;
1610 static enum piglit_result
1611 link_and_use_shaders(void)
1613 enum piglit_result result;
1614 unsigned i;
1615 GLenum err;
1616 GLint ok;
1618 if ((num_vertex_shaders == 0)
1619 && (num_fragment_shaders == 0)
1620 && (num_tess_ctrl_shaders == 0)
1621 && (num_tess_eval_shaders == 0)
1622 && (num_geometry_shaders == 0)
1623 && (num_compute_shaders == 0))
1624 return PIGLIT_PASS;
1626 if (!sso_in_use)
1627 prog = glCreateProgram();
1629 result = process_shader(GL_VERTEX_SHADER, num_vertex_shaders, vertex_shaders);
1630 if (result != PIGLIT_PASS)
1631 goto cleanup;
1632 result = process_shader(GL_TESS_CONTROL_SHADER, num_tess_ctrl_shaders, tess_ctrl_shaders);
1633 if (result != PIGLIT_PASS)
1634 goto cleanup;
1635 result = process_shader(GL_TESS_EVALUATION_SHADER, num_tess_eval_shaders, tess_eval_shaders);
1636 if (result != PIGLIT_PASS)
1637 goto cleanup;
1638 result = process_shader(GL_GEOMETRY_SHADER, num_geometry_shaders, geometry_shaders);
1639 if (result != PIGLIT_PASS)
1640 goto cleanup;
1641 result = process_shader(GL_FRAGMENT_SHADER, num_fragment_shaders, fragment_shaders);
1642 if (result != PIGLIT_PASS)
1643 goto cleanup;
1644 result = process_shader(GL_COMPUTE_SHADER, num_compute_shaders, compute_shaders);
1645 if (result != PIGLIT_PASS)
1646 goto cleanup;
1648 if (!sso_in_use) {
1649 if (separable_program)
1650 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1652 glLinkProgram(prog);
1655 if (!sso_in_use) {
1656 if (!program_binary_save_restore(false))
1657 return PIGLIT_FAIL;
1658 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
1659 if (ok) {
1660 link_ok = true;
1661 } else {
1662 GLint size;
1664 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1665 prog_err_info = malloc(MAX2(size, 1));
1666 prog_err_info[0] = 0;
1668 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1670 result = PIGLIT_PASS;
1671 goto cleanup;
1674 glUseProgram(prog);
1677 err = glGetError();
1678 if (!err) {
1679 prog_in_use = true;
1680 } else {
1681 GLint size;
1683 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1684 prog_err_info = malloc(MAX2(size, 1));
1685 prog_err_info[0] = 0;
1687 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1690 cleanup:
1691 for (i = 0; i < num_vertex_shaders; i++) {
1692 glDeleteShader(vertex_shaders[i]);
1694 num_vertex_shaders = 0;
1696 for (i = 0; i < num_tess_ctrl_shaders; i++) {
1697 glDeleteShader(tess_ctrl_shaders[i]);
1699 num_tess_ctrl_shaders = 0;
1701 for (i = 0; i < num_tess_eval_shaders; i++) {
1702 glDeleteShader(tess_eval_shaders[i]);
1704 num_tess_eval_shaders = 0;
1706 for (i = 0; i < num_geometry_shaders; i++) {
1707 glDeleteShader(geometry_shaders[i]);
1709 num_geometry_shaders = 0;
1711 for (i = 0; i < num_fragment_shaders; i++) {
1712 glDeleteShader(fragment_shaders[i]);
1714 num_fragment_shaders = 0;
1716 for (i = 0; i < num_compute_shaders; i++) {
1717 glDeleteShader(compute_shaders[i]);
1719 num_compute_shaders = 0;
1721 return result;
1724 static enum piglit_result
1725 process_specialization(enum states state, const char *line)
1727 const char *end = strchrnul(line, '\n');
1728 const char *next;
1729 enum { TYPE_FLOAT, TYPE_UINT } type;
1731 while (line < end && isspace(*line))
1732 line++;
1734 if (line >= end || *line == '#')
1735 return PIGLIT_PASS;
1737 if (parse_str(line, "uint", &next))
1738 type = TYPE_UINT;
1739 else if (parse_str(line, "float", &next))
1740 type = TYPE_FLOAT;
1741 else
1742 goto invalid;
1744 struct specialization_list *list;
1746 switch (state) {
1747 case vertex_shader_specializations:
1748 list = specializations + 0;
1749 break;
1750 case tess_ctrl_shader_specializations:
1751 list = specializations + 1;
1752 break;
1753 case tess_eval_shader_specializations:
1754 list = specializations + 2;
1755 break;
1756 case geometry_shader_specializations:
1757 list = specializations + 3;
1758 break;
1759 case fragment_shader_specializations:
1760 list = specializations + 4;
1761 break;
1762 case compute_shader_specializations:
1763 list = specializations + 5;
1764 break;
1765 default:
1766 assert(!"Should not get here.");
1769 if (list->n_entries >= list->buffer_size) {
1770 if (list->buffer_size == 0)
1771 list->buffer_size = 1;
1772 else
1773 list->buffer_size *= 2;
1774 list->indices = realloc(list->indices,
1775 (sizeof list->indices[0]) *
1776 list->buffer_size);
1777 list->values = realloc(list->values,
1778 (sizeof list->values[0]) *
1779 list->buffer_size);
1782 if (parse_uints(next, list->indices + list->n_entries, 1, &next) != 1)
1783 goto invalid;
1785 switch (type) {
1786 case TYPE_UINT:
1787 if (parse_uints(next,
1788 &list->values[list->n_entries].u,
1790 &next) != 1)
1791 goto invalid;
1792 break;
1793 case TYPE_FLOAT:
1794 if (parse_floats(next,
1795 &list->values[list->n_entries].f,
1797 &next) != 1)
1798 goto invalid;
1799 break;
1802 list->n_entries++;
1804 return PIGLIT_PASS;
1806 invalid:
1807 fprintf(stderr, "Invalid specialization line\n");
1808 return PIGLIT_FAIL;
1811 static enum piglit_result
1812 process_test_script(const char *script_name)
1814 unsigned text_size;
1815 unsigned line_num;
1816 char *text = piglit_load_text_file(script_name, &text_size);
1817 enum states state = none;
1818 const char *line = text;
1819 enum piglit_result result;
1821 if (line == NULL) {
1822 printf("could not read file \"%s\"\n", script_name);
1823 return PIGLIT_FAIL;
1826 line_num = 1;
1828 while (line[0] != '\0') {
1829 if (line[0] == '[') {
1830 result = leave_state(state, line, script_name);
1831 if (result != PIGLIT_PASS)
1832 return result;
1834 if (parse_str(line, "[require]", NULL)) {
1835 state = requirements;
1836 } else if (parse_str(line, "[vertex shader]", NULL)) {
1837 state = vertex_shader;
1838 shader_string = NULL;
1839 } else if (parse_str(line, "[vertex program]", NULL)) {
1840 state = vertex_program;
1841 shader_string = NULL;
1842 } else if (parse_str(line, "[vertex shader passthrough]", NULL)) {
1843 state = vertex_shader_passthrough;
1844 shader_string =
1845 (char *) passthrough_vertex_shader_source;
1846 shader_string_size = strlen(shader_string);
1847 } else if (parse_str(line, "[vertex shader spirv]", NULL)) {
1848 state = vertex_shader_spirv;
1849 shader_string = NULL;
1850 } else if (parse_str(line, "[vertex shader specializations]", NULL)) {
1851 state = vertex_shader_specializations;
1852 } else if (parse_str(line, "[tessellation control shader]", NULL)) {
1853 state = tess_ctrl_shader;
1854 shader_string = NULL;
1855 } else if (parse_str(line, "[tessellation control shader spirv]", NULL)) {
1856 state = tess_ctrl_shader_spirv;
1857 shader_string = NULL;
1858 } else if (parse_str(line, "[tessellation control shader specializations]", NULL)) {
1859 state = tess_ctrl_shader_specializations;
1860 } else if (parse_str(line, "[tessellation evaluation shader]", NULL)) {
1861 state = tess_eval_shader;
1862 shader_string = NULL;
1863 } else if (parse_str(line, "[tessellation evaluation shader spirv]", NULL)) {
1864 state = tess_eval_shader_spirv;
1865 shader_string = NULL;
1866 } else if (parse_str(line, "[tessellation evaluation shader specializations]", NULL)) {
1867 state = tess_eval_shader_specializations;
1868 } else if (parse_str(line, "[geometry shader]", NULL)) {
1869 state = geometry_shader;
1870 shader_string = NULL;
1871 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1872 state = geometry_shader_specializations;
1873 } else if (parse_str(line, "[geometry shader spirv]", NULL)) {
1874 state = geometry_shader_spirv;
1875 shader_string = NULL;
1876 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1877 state = geometry_shader_specializations;
1878 } else if (parse_str(line, "[geometry layout]", NULL)) {
1879 state = geometry_layout;
1880 shader_string = NULL;
1881 } else if (parse_str(line, "[fragment shader]", NULL)) {
1882 state = fragment_shader;
1883 shader_string = NULL;
1884 } else if (parse_str(line, "[fragment program]", NULL)) {
1885 state = fragment_program;
1886 shader_string = NULL;
1887 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1888 state = fragment_shader_specializations;
1889 } else if (parse_str(line, "[fragment shader spirv]", NULL)) {
1890 state = fragment_shader_spirv;
1891 shader_string = NULL;
1892 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1893 state = fragment_shader_specializations;
1894 } else if (parse_str(line, "[compute shader]", NULL)) {
1895 state = compute_shader;
1896 shader_string = NULL;
1897 } else if (parse_str(line, "[compute shader spirv]", NULL)) {
1898 state = compute_shader_spirv;
1899 shader_string = NULL;
1900 } else if (parse_str(line, "[compute shader specializations]", NULL)) {
1901 state = compute_shader_specializations;
1902 } else if (parse_str(line, "[vertex data]", NULL)) {
1903 state = vertex_data;
1904 vertex_data_start = NULL;
1905 } else if (parse_str(line, "[shader include]", NULL)) {
1906 state = shader_include;
1907 shader_string = NULL;
1908 } else if (parse_str(line, "[shader include paths]", NULL)) {
1909 state = shader_include_paths;
1910 shader_string = NULL;
1911 } else if (parse_str(line, "[test]", NULL)) {
1912 test_start = strchrnul(line, '\n');
1913 test_start_line_num = line_num + 1;
1914 if (test_start[0] != '\0')
1915 test_start++;
1916 return PIGLIT_PASS;
1917 } else {
1918 fprintf(stderr,
1919 "Unknown section in test script. "
1920 "Perhaps missing closing ']'?\n");
1921 return PIGLIT_FAIL;
1923 } else {
1924 switch (state) {
1925 case none:
1926 case vertex_shader_passthrough:
1927 break;
1929 case requirements:
1930 result = process_requirement(line);
1931 if (result != PIGLIT_PASS)
1932 return result;
1933 break;
1935 case geometry_layout:
1936 process_geometry_layout(line);
1937 break;
1939 case vertex_shader:
1940 case vertex_program:
1941 case tess_ctrl_shader:
1942 case tess_eval_shader:
1943 case geometry_shader:
1944 case fragment_shader:
1945 case fragment_program:
1946 case compute_shader:
1947 case vertex_shader_spirv:
1948 case tess_ctrl_shader_spirv:
1949 case tess_eval_shader_spirv:
1950 case geometry_shader_spirv:
1951 case fragment_shader_spirv:
1952 case compute_shader_spirv:
1953 case shader_include:
1954 case shader_include_paths:
1955 if (shader_string == NULL)
1956 shader_string = (char *) line;
1957 break;
1959 case vertex_shader_specializations:
1960 case tess_ctrl_shader_specializations:
1961 case tess_eval_shader_specializations:
1962 case geometry_shader_specializations:
1963 case fragment_shader_specializations:
1964 case compute_shader_specializations: {
1965 enum piglit_result result =
1966 process_specialization(state, line);
1967 if (result != PIGLIT_PASS)
1968 return result;
1969 break;
1972 case vertex_data:
1973 if (vertex_data_start == NULL)
1974 vertex_data_start = line;
1975 break;
1977 case test:
1978 break;
1982 line = strchrnul(line, '\n');
1983 if (line[0] != '\0')
1984 line++;
1986 line_num++;
1989 return leave_state(state, line, script_name);
1992 struct requirement_parse_results {
1993 bool found_gl;
1994 bool found_glsl;
1995 bool found_size;
1996 bool found_depthbuffer;
1997 struct component_version gl_version;
1998 struct component_version glsl_version;
1999 unsigned size[2];
2002 static void
2003 parse_required_config(struct requirement_parse_results *results,
2004 const char *script_name)
2006 unsigned text_size;
2007 char *text = piglit_load_text_file(script_name, &text_size);
2008 const char *line = text;
2009 bool in_requirement_section = false;
2011 results->found_gl = false;
2012 results->found_glsl = false;
2013 results->found_size = false;
2014 results->found_depthbuffer = false;
2016 if (line == NULL) {
2017 printf("could not read file \"%s\"\n", script_name);
2018 piglit_report_result(PIGLIT_FAIL);
2021 while (line[0] != '\0') {
2022 if (line[0] == '[') {
2023 if (in_requirement_section)
2024 break;
2025 else
2026 in_requirement_section = false;
2029 if (!in_requirement_section) {
2030 if (parse_str(line, "[require]", NULL)) {
2031 in_requirement_section = true;
2033 } else {
2034 if (parse_str(line, "GL_", NULL)
2035 || parse_str(line, "!GL_", NULL)) {
2036 /* empty */
2037 } else if (parse_str(line, "GLSL", &line)) {
2038 enum comparison cmp;
2039 struct component_version version;
2041 parse_version_comparison(line, &cmp,
2042 &version, VERSION_GLSL);
2043 if (cmp == greater_equal) {
2044 results->found_glsl = true;
2045 version_copy(&results->glsl_version, &version);
2047 } else if (parse_str(line, "GL", &line)) {
2048 enum comparison cmp;
2049 struct component_version version;
2051 parse_version_comparison(line, &cmp,
2052 &version, VERSION_GL);
2053 if (cmp == greater_equal
2054 || cmp == greater
2055 || cmp == equal) {
2056 results->found_gl = true;
2057 version_copy(&results->gl_version, &version);
2059 } else if (parse_str(line, "SIZE", &line)) {
2060 results->found_size = true;
2061 parse_uints(line, results->size, 2, NULL);
2062 } else if (parse_str(line, "depthbuffer", NULL)) {
2063 results->found_depthbuffer = true;
2067 line = strchrnul(line, '\n');
2068 if (line[0] != '\0')
2069 line++;
2072 free(text);
2074 if (!in_requirement_section) {
2075 printf("[require] section missing\n");
2076 piglit_report_result(PIGLIT_FAIL);
2079 if (results->found_glsl && results->glsl_version.es && !results->found_gl) {
2080 printf("%s", "The test specifies a requirement for GLSL ES, "
2081 "but specifies no GL requirement\n.");
2082 piglit_report_result(PIGLIT_FAIL);
2087 static void
2088 choose_required_gl_version(struct requirement_parse_results *parse_results,
2089 struct component_version *gl_version)
2091 if (parse_results->found_gl) {
2092 version_copy(gl_version, &parse_results->gl_version);
2093 } else {
2094 assert(!parse_results->found_glsl || !parse_results->glsl_version.es);
2095 version_init(gl_version, VERSION_GL, false, false, false, 10);
2098 if (gl_version->es)
2099 return;
2101 /* Possibly promote the GL version. */
2102 if (parse_results->found_glsl
2103 && gl_version->num < required_gl_version_from_glsl_version(
2104 parse_results->glsl_version.num)) {
2105 gl_version->num = required_gl_version_from_glsl_version(
2106 parse_results->glsl_version.num);
2111 * Just determine the GLSL version required by the shader script.
2113 * This function is a bit of a hack that is, unfortunately necessary. A test
2114 * script can require a specific GLSL version or a specific GL version. To
2115 * satisfy this requirement, the piglit framework code needs to know about the
2116 * requirement before creating the context. However, the requirements section
2117 * can contain other requirements, such as minimum number of uniforms.
2119 * The requirements section can't be fully processed until after the context
2120 * is created, but the context can't be created until after the requirements
2121 * section is processed. Do a quick scan over the requirements section to find
2122 * the GL and GLSL version requirements. Use these to guide context creation.
2124 static void
2125 get_required_config(const char *script_name, bool spirv,
2126 struct piglit_gl_test_config *config)
2128 struct requirement_parse_results parse_results;
2129 struct component_version required_gl_version;
2131 parse_required_config(&parse_results, script_name);
2132 choose_required_gl_version(&parse_results, &required_gl_version);
2134 if (spirv) {
2135 required_gl_version.es = false;
2136 required_gl_version.core = true;
2137 required_gl_version.num = MAX2(required_gl_version.num, 33);
2140 if (parse_results.found_size) {
2141 config->window_width = parse_results.size[0];
2142 config->window_height = parse_results.size[1];
2145 if (required_gl_version.es) {
2146 config->supports_gl_es_version = required_gl_version.num;
2147 } else if (required_gl_version.num >= 31) {
2148 if (!required_gl_version.compat)
2149 config->supports_gl_core_version = required_gl_version.num;
2150 if (!required_gl_version.core)
2151 config->supports_gl_compat_version = required_gl_version.num;
2152 } else {
2153 config->supports_gl_compat_version = 10;
2156 if (parse_results.found_depthbuffer) {
2157 config->window_visual |= PIGLIT_GL_VISUAL_DEPTH;
2162 * Check that the GL implementation supports unsigned uniforms
2163 * (e.g. through glUniform1ui). If not, terminate the test with a
2164 * SKIP.
2166 static void
2167 check_unsigned_support(void)
2169 if (gl_version.num < 30 && !piglit_is_extension_supported("GL_EXT_gpu_shader4"))
2170 piglit_report_result(PIGLIT_SKIP);
2174 * Check that the GL implementation supports double uniforms
2175 * (e.g. through glUniform1d). If not, terminate the test with a
2176 * SKIP.
2178 static void
2179 check_double_support(void)
2181 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_gpu_shader_fp64"))
2182 piglit_report_result(PIGLIT_SKIP);
2186 * Check that the GL implementation supports double uniforms
2187 * (e.g. through glUniform1d). If not, terminate the test with a
2188 * SKIP.
2190 static void
2191 check_int64_support(void)
2193 if (!piglit_is_extension_supported("GL_ARB_gpu_shader_int64"))
2194 piglit_report_result(PIGLIT_SKIP);
2198 * Check that the GL implementation supports shader subroutines
2199 * If not, terminate the test with a SKIP.
2201 static void
2202 check_shader_subroutine_support(void)
2204 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
2205 piglit_report_result(PIGLIT_SKIP);
2209 * Check that the GL implementation supports texture handles.
2210 * If not, terminate the test with a SKIP.
2212 static void
2213 check_texture_handle_support(void)
2215 if (!piglit_is_extension_supported("GL_ARB_bindless_texture"))
2216 piglit_report_result(PIGLIT_SKIP);
2219 static bool
2220 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2221 GLuint *uniform_index_out,
2222 GLint *block_index_out,
2223 GLint *offset_out);
2226 * Handles uploads of UBO uniforms by mapping the buffer and storing
2227 * the data. If the uniform is not in a uniform block, returns false.
2229 static bool
2230 set_ubo_uniform(char *name, const char *type,
2231 const char *line,
2232 struct block_info block_data)
2234 /* Note: on SPIR-V we can't access to uniform_index as we
2235 * could lack the name. We force that with force_no_names on
2236 * GLSL
2238 GLuint uniform_index;
2239 GLint block_index;
2240 GLint offset;
2241 char *data;
2242 float f[16];
2243 double d[16];
2244 int ints[16];
2245 unsigned uints[16];
2246 uint64_t uint64s[16];
2247 int64_t int64s[16];
2249 if (!get_indexes_and_offset_from_ubo(name, block_data, &uniform_index,
2250 &block_index, &offset)) {
2251 return false;
2254 glBindBuffer(GL_UNIFORM_BUFFER,
2255 uniform_block_bos[block_index]);
2256 data = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
2257 data += offset;
2259 if (parse_str(type, "float", NULL)) {
2260 parse_floats(line, f, 1, NULL);
2261 memcpy(data, f, sizeof(float));
2262 } else if (parse_str(type, "int64_t", NULL)) {
2263 parse_int64s(line, int64s, 1, NULL);
2264 memcpy(data, int64s, sizeof(int64_t));
2265 } else if (parse_str(type, "uint64_t", NULL)) {
2266 parse_uint64s(line, uint64s, 1, NULL);
2267 memcpy(data, uint64s, sizeof(uint64_t));
2268 } else if (parse_str(type, "int", NULL)) {
2269 parse_ints(line, ints, 1, NULL);
2270 memcpy(data, ints, sizeof(int));
2271 } else if (parse_str(type, "uint", NULL)) {
2272 parse_uints(line, uints, 1, NULL);
2273 memcpy(data, uints, sizeof(int));
2274 } else if (parse_str(type, "double", NULL)) {
2275 parse_doubles(line, d, 1, NULL);
2276 memcpy(data, d, sizeof(double));
2277 } else if (parse_str(type, "vec", NULL)) {
2278 int elements = type[3] - '0';
2279 parse_floats(line, f, elements, NULL);
2280 memcpy(data, f, elements * sizeof(float));
2281 } else if (parse_str(type, "ivec", NULL)) {
2282 int elements = type[4] - '0';
2283 parse_ints(line, ints, elements, NULL);
2284 memcpy(data, ints, elements * sizeof(int));
2285 } else if (parse_str(type, "uvec", NULL)) {
2286 int elements = type[4] - '0';
2287 parse_uints(line, uints, elements, NULL);
2288 memcpy(data, uints, elements * sizeof(unsigned));
2289 } else if (parse_str(type, "i64vec", NULL)) {
2290 int elements = type[6] - '0';
2291 parse_int64s(line, int64s, elements, NULL);
2292 memcpy(data, int64s, elements * sizeof(int64_t));
2293 } else if (parse_str(type, "u64vec", NULL)) {
2294 int elements = type[6] - '0';
2295 parse_uint64s(line, uint64s, elements, NULL);
2296 memcpy(data, uint64s, elements * sizeof(uint64_t));
2297 } else if (parse_str(type, "dvec", NULL)) {
2298 int elements = type[4] - '0';
2299 parse_doubles(line, d, elements, NULL);
2300 memcpy(data, d, elements * sizeof(double));
2301 } else if (parse_str(type, "mat", NULL)) {
2302 GLint matrix_stride, row_major;
2303 int cols = type[3] - '0';
2304 int rows = type[4] == 'x' ? type[5] - '0' : cols;
2305 int r, c;
2306 float *matrixdata = (float *)data;
2308 assert(cols >= 2 && cols <= 4);
2309 assert(rows >= 2 && rows <= 4);
2311 parse_floats(line, f, rows * cols, NULL);
2313 if (!force_no_names) {
2314 glGetActiveUniformsiv(prog, 1, &uniform_index,
2315 GL_UNIFORM_MATRIX_STRIDE,
2316 &matrix_stride);
2317 glGetActiveUniformsiv(prog, 1, &uniform_index,
2318 GL_UNIFORM_IS_ROW_MAJOR,
2319 &row_major);
2320 } else {
2321 matrix_stride = block_data.matrix_stride;
2322 row_major = block_data.row_major;
2325 matrix_stride /= sizeof(float);
2327 /* Expect the data in the .shader_test file to be listed in
2328 * column-major order no matter what the layout of the data in
2329 * the UBO will be.
2331 for (c = 0; c < cols; c++) {
2332 for (r = 0; r < rows; r++) {
2333 if (row_major) {
2334 matrixdata[matrix_stride * r + c] =
2335 f[c * rows + r];
2336 } else {
2337 matrixdata[matrix_stride * c + r] =
2338 f[c * rows + r];
2342 } else if (parse_str(type, "dmat", NULL)) {
2343 GLint matrix_stride, row_major;
2344 int cols = type[4] - '0';
2345 int rows = type[5] == 'x' ? type[6] - '0' : cols;
2346 int r, c;
2347 double *matrixdata = (double *)data;
2349 assert(cols >= 2 && cols <= 4);
2350 assert(rows >= 2 && rows <= 4);
2352 parse_doubles(line, d, rows * cols, NULL);
2354 if (!force_no_names) {
2355 glGetActiveUniformsiv(prog, 1, &uniform_index,
2356 GL_UNIFORM_MATRIX_STRIDE,
2357 &matrix_stride);
2358 glGetActiveUniformsiv(prog, 1, &uniform_index,
2359 GL_UNIFORM_IS_ROW_MAJOR,
2360 &row_major);
2361 } else {
2362 matrix_stride = block_data.matrix_stride;
2363 row_major = block_data.row_major;
2366 matrix_stride /= sizeof(double);
2368 /* Expect the data in the .shader_test file to be listed in
2369 * column-major order no matter what the layout of the data in
2370 * the UBO will be.
2372 for (c = 0; c < cols; c++) {
2373 for (r = 0; r < rows; r++) {
2374 if (row_major) {
2375 matrixdata[matrix_stride * r + c] =
2376 d[c * rows + r];
2377 } else {
2378 matrixdata[matrix_stride * c + r] =
2379 d[c * rows + r];
2383 } else if (parse_str(type, "handle", NULL)) {
2384 check_unsigned_support();
2385 check_texture_handle_support();
2386 parse_uints(line, uints, 1, NULL);
2387 GLuint64 handle = get_resident_handle(uints[0])->handle;
2388 memcpy(data, &handle, sizeof(uint64_t));
2389 } else {
2390 printf("unknown uniform type \"%s\" for \"%s\"\n", type, name);
2391 piglit_report_result(PIGLIT_FAIL);
2394 glUnmapBuffer(GL_UNIFORM_BUFFER);
2396 return true;
2400 * Get the uniform_index, block_index and offset of a given
2401 * uniform. By default it gets those values using the uniform name. If
2402 * force_no_names mode is active, it uses the current values stored at
2403 * @block_data. On the latter, uniform index is not filled up.
2405 static bool
2406 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2407 GLuint *uniform_index_out,
2408 GLint *block_index_out,
2409 GLint *offset_out)
2411 GLuint uniform_index = 0;
2412 GLint block_index;
2413 GLint offset;
2414 int name_len = strlen(name);
2415 GLint array_index = 0;
2417 if (!num_uniform_blocks)
2418 return false;
2420 if (!force_no_names) {
2421 /* if the uniform is an array, strip the index, as GL
2422 prevents non-zero indexes from matching a name */
2423 if (name[name_len - 1] == ']') {
2424 int i;
2426 for (i = name_len - 1; (i > 0) && isdigit(name[i-1]); --i)
2427 /* empty */;
2429 array_index = strtol(&name[i], NULL, 0);
2431 if (i) {
2432 i--;
2433 if (name[i] != '[') {
2434 printf("cannot parse uniform \"%s\"\n", name);
2435 piglit_report_result(PIGLIT_FAIL);
2437 name[i] = 0;
2442 glGetUniformIndices(prog, 1, (const char **)&name, &uniform_index);
2443 if (uniform_index == GL_INVALID_INDEX) {
2444 printf("cannot get index of uniform \"%s\"\n", name);
2445 piglit_report_result(PIGLIT_FAIL);
2448 glGetActiveUniformsiv(prog, 1, &uniform_index,
2449 GL_UNIFORM_BLOCK_INDEX, &block_index);
2451 if (block_index == -1)
2452 return false;
2454 GLint array_size;
2455 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_SIZE, &array_size);
2457 if (array_index > array_size) {
2458 printf("attempt to access beyond uniform \"%s\" array size (%d)\n",
2459 name, array_size);
2460 return false;
2463 /* if the uniform block is an array, then GetActiveUniformsiv with
2464 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2465 * element in the array.
2467 block_index += block_data.array_index;
2469 glGetActiveUniformsiv(prog, 1, &uniform_index,
2470 GL_UNIFORM_OFFSET, &offset);
2472 if (name[name_len - 1] == ']') {
2473 GLint stride;
2475 glGetActiveUniformsiv(prog, 1, &uniform_index,
2476 GL_UNIFORM_ARRAY_STRIDE, &stride);
2477 offset += stride * array_index;
2479 } else {
2480 if (block_data.binding < 0) {
2481 printf("if you force to use a explicit ubo binding, you "
2482 "need to provide it when filling the data with "
2483 "\"ubo binding\"\n");
2484 piglit_report_result(PIGLIT_FAIL);
2487 /* The mapping could be improved using a hash
2488 * table. For now, this is enough.
2490 block_index = uniform_block_indexes[block_data.binding];
2492 /* if the uniform block is an array, then GetActiveUniformsiv with
2493 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2494 * element in the array.
2496 block_index += block_data.array_index;
2498 if (block_data.offset < 0) {
2499 printf("if you force to use a explicit ubo binding, you "
2500 "need to provide offset when filling the data with "
2501 "\"ubo offset\"\n");
2502 piglit_report_result(PIGLIT_FAIL);
2504 offset = block_data.offset;
2507 *offset_out = offset;
2508 *block_index_out = block_index;
2509 *uniform_index_out = uniform_index;
2511 return true;
2514 static void
2515 set_uniform(const char *line, struct block_info block_data)
2517 char name[512], type[512];
2518 float f[16];
2519 double d[16];
2520 int ints[16];
2521 unsigned uints[16];
2522 int64_t int64s[16];
2523 uint64_t uint64s[16];
2524 GLint loc;
2526 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2527 parse_word_copy(line, name, sizeof(name), &line),
2528 "Invalid set uniform command at: %s\n", line);
2530 if (isdigit(name[0])) {
2531 loc = strtol(name, NULL, 0);
2532 } else {
2533 GLuint prog;
2535 if (set_ubo_uniform(name, type, line, block_data))
2536 return;
2538 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2539 loc = glGetUniformLocation(prog, name);
2540 if (loc < 0) {
2541 if (ignore_missing_uniforms)
2542 return;
2543 printf("cannot get location of uniform \"%s\"\n",
2544 name);
2545 piglit_report_result(PIGLIT_FAIL);
2549 if (parse_str(type, "float", NULL)) {
2550 parse_floats(line, f, 1, NULL);
2551 glUniform1fv(loc, 1, f);
2552 return;
2553 } else if (parse_str(type, "int64_t", NULL)) {
2554 check_int64_support();
2555 parse_int64s(line, int64s, 1, NULL);
2556 glUniform1i64vARB(loc, 1, int64s);
2557 return;
2558 } else if (parse_str(type, "uint64_t", NULL)) {
2559 check_int64_support();
2560 parse_uint64s(line, uint64s, 1, NULL);
2561 glUniform1ui64vARB(loc, 1, uint64s);
2562 return;
2563 } else if (parse_str(type, "int", NULL)) {
2564 parse_ints(line, ints, 1, NULL);
2565 glUniform1iv(loc, 1, ints);
2566 return;
2567 } else if (parse_str(type, "uint", NULL)) {
2568 check_unsigned_support();
2569 parse_uints(line, uints, 1, NULL);
2570 glUniform1uiv(loc, 1, uints);
2571 return;
2572 } else if (parse_str(type, "double", NULL)) {
2573 check_double_support();
2574 parse_doubles(line, d, 1, NULL);
2575 glUniform1dv(loc, 1, d);
2576 return;
2577 } else if (parse_str(type, "vec", NULL)) {
2578 switch (type[3]) {
2579 case '2':
2580 parse_floats(line, f, 2, NULL);
2581 glUniform2fv(loc, 1, f);
2582 return;
2583 case '3':
2584 parse_floats(line, f, 3, NULL);
2585 glUniform3fv(loc, 1, f);
2586 return;
2587 case '4':
2588 parse_floats(line, f, 4, NULL);
2589 glUniform4fv(loc, 1, f);
2590 return;
2592 } else if (parse_str(type, "ivec", NULL)) {
2593 switch (type[4]) {
2594 case '2':
2595 parse_ints(line, ints, 2, NULL);
2596 glUniform2iv(loc, 1, ints);
2597 return;
2598 case '3':
2599 parse_ints(line, ints, 3, NULL);
2600 glUniform3iv(loc, 1, ints);
2601 return;
2602 case '4':
2603 parse_ints(line, ints, 4, NULL);
2604 glUniform4iv(loc, 1, ints);
2605 return;
2607 } else if (parse_str(type, "uvec", NULL)) {
2608 check_unsigned_support();
2609 switch (type[4]) {
2610 case '2':
2611 parse_uints(line, uints, 2, NULL);
2612 glUniform2uiv(loc, 1, uints);
2613 return;
2614 case '3':
2615 parse_uints(line, uints, 3, NULL);
2616 glUniform3uiv(loc, 1, uints);
2617 return;
2618 case '4':
2619 parse_uints(line, uints, 4, NULL);
2620 glUniform4uiv(loc, 1, uints);
2621 return;
2623 } else if (parse_str(type, "dvec", NULL)) {
2624 check_double_support();
2625 switch (type[4]) {
2626 case '2':
2627 parse_doubles(line, d, 2, NULL);
2628 glUniform2dv(loc, 1, d);
2629 return;
2630 case '3':
2631 parse_doubles(line, d, 3, NULL);
2632 glUniform3dv(loc, 1, d);
2633 return;
2634 case '4':
2635 parse_doubles(line, d, 4, NULL);
2636 glUniform4dv(loc, 1, d);
2637 return;
2639 } else if (parse_str(type, "i64vec", NULL)) {
2640 check_int64_support();
2641 switch (type[6]) {
2642 case '2':
2643 parse_int64s(line, int64s, 2, NULL);
2644 glUniform2i64vARB(loc, 1, int64s);
2645 return;
2646 case '3':
2647 parse_int64s(line, int64s, 3, NULL);
2648 glUniform3i64vARB(loc, 1, int64s);
2649 return;
2650 case '4':
2651 parse_int64s(line, int64s, 4, NULL);
2652 glUniform4i64vARB(loc, 1, int64s);
2653 return;
2655 } else if (parse_str(type, "u64vec", NULL)) {
2656 check_int64_support();
2657 switch (type[6]) {
2658 case '2':
2659 parse_uint64s(line, uint64s, 2, NULL);
2660 glUniform2ui64vARB(loc, 1, uint64s);
2661 return;
2662 case '3':
2663 parse_uint64s(line, uint64s, 3, NULL);
2664 glUniform3ui64vARB(loc, 1, uint64s);
2665 return;
2666 case '4':
2667 parse_uint64s(line, uint64s, 4, NULL);
2668 glUniform4ui64vARB(loc, 1, uint64s);
2669 return;
2671 } else if (parse_str(type, "mat", NULL) && type[3] != '\0') {
2672 char cols = type[3];
2673 char rows = type[4] == 'x' ? type[5] : cols;
2674 switch (cols) {
2675 case '2':
2676 switch (rows) {
2677 case '2':
2678 parse_floats(line, f, 4, NULL);
2679 glUniformMatrix2fv(loc, 1, GL_FALSE, f);
2680 return;
2681 case '3':
2682 parse_floats(line, f, 6, NULL);
2683 glUniformMatrix2x3fv(loc, 1, GL_FALSE, f);
2684 return;
2685 case '4':
2686 parse_floats(line, f, 8, NULL);
2687 glUniformMatrix2x4fv(loc, 1, GL_FALSE, f);
2688 return;
2690 case '3':
2691 switch (rows) {
2692 case '2':
2693 parse_floats(line, f, 6, NULL);
2694 glUniformMatrix3x2fv(loc, 1, GL_FALSE, f);
2695 return;
2696 case '3':
2697 parse_floats(line, f, 9, NULL);
2698 glUniformMatrix3fv(loc, 1, GL_FALSE, f);
2699 return;
2700 case '4':
2701 parse_floats(line, f, 12, NULL);
2702 glUniformMatrix3x4fv(loc, 1, GL_FALSE, f);
2703 return;
2705 case '4':
2706 switch (rows) {
2707 case '2':
2708 parse_floats(line, f, 8, NULL);
2709 glUniformMatrix4x2fv(loc, 1, GL_FALSE, f);
2710 return;
2711 case '3':
2712 parse_floats(line, f, 12, NULL);
2713 glUniformMatrix4x3fv(loc, 1, GL_FALSE, f);
2714 return;
2715 case '4':
2716 parse_floats(line, f, 16, NULL);
2717 glUniformMatrix4fv(loc, 1, GL_FALSE, f);
2718 return;
2721 } else if (parse_str(type, "dmat", NULL) && type[4] != '\0') {
2722 char cols = type[4];
2723 char rows = type[5] == 'x' ? type[6] : cols;
2724 switch (cols) {
2725 case '2':
2726 switch (rows) {
2727 case '2':
2728 parse_doubles(line, d, 4, NULL);
2729 glUniformMatrix2dv(loc, 1, GL_FALSE, d);
2730 return;
2731 case '3':
2732 parse_doubles(line, d, 6, NULL);
2733 glUniformMatrix2x3dv(loc, 1, GL_FALSE, d);
2734 return;
2735 case '4':
2736 parse_doubles(line, d, 8, NULL);
2737 glUniformMatrix2x4dv(loc, 1, GL_FALSE, d);
2738 return;
2740 case '3':
2741 switch (rows) {
2742 case '2':
2743 parse_doubles(line, d, 6, NULL);
2744 glUniformMatrix3x2dv(loc, 1, GL_FALSE, d);
2745 return;
2746 case '3':
2747 parse_doubles(line, d, 9, NULL);
2748 glUniformMatrix3dv(loc, 1, GL_FALSE, d);
2749 return;
2750 case '4':
2751 parse_doubles(line, d, 12, NULL);
2752 glUniformMatrix3x4dv(loc, 1, GL_FALSE, d);
2753 return;
2755 case '4':
2756 switch (rows) {
2757 case '2':
2758 parse_doubles(line, d, 8, NULL);
2759 glUniformMatrix4x2dv(loc, 1, GL_FALSE, d);
2760 return;
2761 case '3':
2762 parse_doubles(line, d, 12, NULL);
2763 glUniformMatrix4x3dv(loc, 1, GL_FALSE, d);
2764 return;
2765 case '4':
2766 parse_doubles(line, d, 16, NULL);
2767 glUniformMatrix4dv(loc, 1, GL_FALSE, d);
2768 return;
2771 } else if (parse_str(type, "handle", NULL)) {
2772 check_unsigned_support();
2773 check_texture_handle_support();
2774 parse_uints(line, uints, 1, NULL);
2775 glUniformHandleui64ARB(loc, get_resident_handle(uints[0])->handle);
2776 return;
2779 printf("unknown uniform type \"%s\"\n", type);
2780 piglit_report_result(PIGLIT_FAIL);
2782 return;
2785 static void
2786 set_vertex_attrib(const char *line)
2788 char name[512], type[512];
2789 uint32_t uints[16];
2790 GLint loc;
2792 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2793 parse_word_copy(line, name, sizeof(name), &line),
2794 "Invalid set vertex attrib command at: %s\n", line);
2796 if (isdigit(name[0])) {
2797 loc = strtol(name, NULL, 0);
2798 } else {
2799 GLuint prog;
2801 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2802 loc = glGetAttribLocation(prog, name);
2803 if (loc < 0) {
2804 if (ignore_missing_uniforms)
2805 return;
2806 printf("cannot get location of vertex attrib \"%s\"\n",
2807 name);
2808 piglit_report_result(PIGLIT_FAIL);
2812 if (parse_str(type, "handle", NULL)) {
2813 check_unsigned_support();
2814 check_texture_handle_support();
2815 parse_uints(line, uints, 1, NULL);
2816 glVertexAttribL1ui64ARB(loc, get_resident_handle(uints[0])->handle);
2817 return;
2820 printf("unknown vertex attrib type \"%s\"\n", type);
2821 printf("use [vertex data] instead if possible\n");
2822 piglit_report_result(PIGLIT_FAIL);
2824 return;
2827 static GLenum lookup_shader_type(GLuint idx)
2829 switch (idx) {
2830 case 0:
2831 return GL_VERTEX_SHADER;
2832 case 1:
2833 return GL_FRAGMENT_SHADER;
2834 case 2:
2835 return GL_GEOMETRY_SHADER;
2836 case 3:
2837 return GL_TESS_CONTROL_SHADER;
2838 case 4:
2839 return GL_TESS_EVALUATION_SHADER;
2840 case 5:
2841 return GL_COMPUTE_SHADER;
2842 default:
2843 return 0;
2847 static GLenum get_shader_from_string(const char *name, int *idx)
2849 if (parse_str(name, "GL_VERTEX_SHADER", NULL)) {
2850 *idx = 0;
2851 return GL_VERTEX_SHADER;
2853 if (parse_str(name, "GL_FRAGMENT_SHADER", NULL)) {
2854 *idx = 1;
2855 return GL_FRAGMENT_SHADER;
2857 if (parse_str(name, "GL_GEOMETRY_SHADER", NULL)) {
2858 *idx = 2;
2859 return GL_GEOMETRY_SHADER;
2861 if (parse_str(name, "GL_TESS_CONTROL_SHADER", NULL)) {
2862 *idx = 3;
2863 return GL_TESS_CONTROL_SHADER;
2865 if (parse_str(name, "GL_TESS_EVALUATION_SHADER", NULL)) {
2866 *idx = 4;
2867 return GL_TESS_EVALUATION_SHADER;
2869 if (parse_str(name, "GL_COMPUTE_SHADER", NULL)) {
2870 *idx = 5;
2871 return GL_COMPUTE_SHADER;
2873 return 0;
2876 static void
2877 free_subroutine_uniforms(void)
2879 int sidx;
2880 for (sidx = 0; sidx < 4; sidx++) {
2881 free(subuniform_locations[sidx]);
2882 subuniform_locations[sidx] = NULL;
2886 static void
2887 program_subroutine_uniforms(void)
2889 int sidx;
2890 int stype;
2892 for (sidx = 0; sidx < 4; sidx++) {
2894 if (num_subuniform_locations[sidx] == 0)
2895 continue;
2897 stype = lookup_shader_type(sidx);
2898 if (!stype)
2899 continue;
2901 glUniformSubroutinesuiv(stype, num_subuniform_locations[sidx], subuniform_locations[sidx]);
2905 static void
2906 set_subroutine_uniform(const char *line)
2908 GLuint prog;
2909 char type[512];
2910 char name[512];
2911 char subname[512];
2912 GLint loc;
2913 GLuint idx;
2914 GLenum ptype = 0;
2915 int sidx = 0;
2917 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2918 parse_word_copy(line, name, sizeof(name), &line) &&
2919 parse_word_copy(line, subname, sizeof(subname), &line),
2920 "Invalid set subroutine uniform command at: %s\n", line);
2922 ptype = get_shader_from_string(type, &sidx);
2923 if (ptype == 0) {
2924 printf("illegal type in subroutine uniform\n");
2925 piglit_report_result(PIGLIT_FAIL);
2928 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2930 if (num_subuniform_locations[sidx] == 0) {
2931 glGetProgramStageiv(prog, ptype, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
2932 &num_subuniform_locations[sidx]);
2934 if (num_subuniform_locations[sidx] == 0) {
2935 printf("illegal subroutine uniform specified\n");
2936 piglit_report_result(PIGLIT_FAIL);
2939 subuniform_locations[sidx] = calloc(num_subuniform_locations[sidx], sizeof(GLuint));
2940 if (!subuniform_locations[sidx])
2941 piglit_report_result(PIGLIT_FAIL);
2944 loc = glGetSubroutineUniformLocation(prog, ptype, name);
2945 if (loc < 0) {
2946 if (ignore_missing_uniforms)
2947 return;
2948 printf("cannot get location of subroutine uniform \"%s\"\n",
2949 name);
2950 piglit_report_result(PIGLIT_FAIL);
2953 idx = glGetSubroutineIndex(prog, ptype, subname);
2954 if (idx == GL_INVALID_INDEX) {
2955 printf("cannot get index of subroutine uniform \"%s\"\n",
2956 subname);
2957 piglit_report_result(PIGLIT_FAIL);
2960 subuniform_locations[sidx][loc] = idx;
2961 return;
2965 * Query values from current program using glGetProgram.
2967 * Format of the command:
2968 * verify program_query GL_PNAME_ENUM integer
2970 * or
2972 * verify program_query GL_PNAME_ENUM <enum>
2974 * Note: GL_COMPUTE_WORK_GROUP_SIZE is not supported, as is the only
2975 * query that requires a params with more than one component, and we
2976 * want to keep things simple.
2979 static void
2980 verify_program_query(const char *line)
2982 static const struct string_to_enum all_pnames[] = {
2983 ENUM_STRING(GL_DELETE_STATUS),
2984 ENUM_STRING(GL_LINK_STATUS),
2985 ENUM_STRING(GL_VALIDATE_STATUS),
2986 ENUM_STRING(GL_INFO_LOG_LENGTH),
2987 ENUM_STRING(GL_ATTACHED_SHADERS),
2988 ENUM_STRING(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS),
2989 ENUM_STRING(GL_ACTIVE_ATTRIBUTES),
2990 ENUM_STRING(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH),
2991 ENUM_STRING(GL_ACTIVE_UNIFORMS),
2992 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCKS),
2993 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH),
2994 ENUM_STRING(GL_ACTIVE_UNIFORM_MAX_LENGTH),
2995 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
2996 ENUM_STRING(GL_PROGRAM_BINARY_LENGTH),
2997 ENUM_STRING(GL_TRANSFORM_FEEDBACK_BUFFER_MODE),
2998 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYINGS),
2999 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH),
3000 ENUM_STRING(GL_GEOMETRY_VERTICES_OUT),
3001 ENUM_STRING(GL_GEOMETRY_INPUT_TYPE),
3002 ENUM_STRING(GL_GEOMETRY_OUTPUT_TYPE),
3003 { NULL, 0 }
3006 static const struct string_to_enum all_possible_param_enums[] = {
3007 ENUM_STRING(GL_TRUE),
3008 ENUM_STRING(GL_FALSE),
3009 ENUM_STRING(GL_SEPARATE_ATTRIBS),
3010 ENUM_STRING(GL_INTERLEAVED_ATTRIBS),
3011 ENUM_STRING(GL_POINTS),
3012 ENUM_STRING(GL_LINES),
3013 ENUM_STRING(GL_LINES_ADJACENCY),
3014 ENUM_STRING(GL_TRIANGLES),
3015 ENUM_STRING(GL_TRIANGLES_ADJACENCY),
3016 ENUM_STRING(GL_LINE_STRIP),
3017 ENUM_STRING(GL_TRIANGLE_STRIP),
3018 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
3019 { NULL, 0 }
3022 unsigned pname;
3023 int expected;
3024 int value;
3026 REQUIRE(parse_enum_tab(all_pnames, line,
3027 &pname, &line),
3028 "Bad glGetProgram pname at: %s\n", line);
3030 REQUIRE(parse_enum_tab(all_possible_param_enums, line, (unsigned *)&expected, &line) ||
3031 parse_int(line, &expected, &line),
3032 "Bad expected value at: %s\n", line);
3034 if (pname == GL_COMPUTE_WORK_GROUP_SIZE) {
3035 /* TODO: eventually it would be good to add support for
3036 * this parameter. What it makes different to the rest is
3037 * that it requires a param with more than one component
3039 fprintf(stderr, "glGetProgram queries with GL_COMPUTE_WORK_GROUP_SIZE "
3040 "not supported yet\n");
3041 piglit_report_result(PIGLIT_FAIL);
3044 glGetProgramiv(prog, pname, &value);
3046 if (expected != value) {
3047 fprintf(stderr, "glGetProgram(%s): expected %d, got %d\n",
3048 piglit_get_gl_enum_name(pname), expected, value);
3049 piglit_report_result(PIGLIT_FAIL);
3054 * Query a uniform using glGetActiveUniformsiv
3056 * Format of the command:
3058 * active uniform uniform_name GL_PNAME_ENUM integer
3060 * or
3062 * active uniform uniform_name GL_PNAME_ENUM GL_TYPE_ENUM
3064 static void
3065 active_uniform(const char *line)
3067 static const struct string_to_enum all_pnames[] = {
3068 ENUM_STRING(GL_UNIFORM_TYPE),
3069 ENUM_STRING(GL_UNIFORM_SIZE),
3070 ENUM_STRING(GL_UNIFORM_NAME_LENGTH),
3071 ENUM_STRING(GL_UNIFORM_BLOCK_INDEX),
3072 ENUM_STRING(GL_UNIFORM_OFFSET),
3073 ENUM_STRING(GL_UNIFORM_ARRAY_STRIDE),
3074 ENUM_STRING(GL_UNIFORM_MATRIX_STRIDE),
3075 ENUM_STRING(GL_UNIFORM_IS_ROW_MAJOR),
3076 ENUM_STRING(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX),
3077 { NULL, 0 }
3080 const char *rest = line;
3081 char name[512];
3082 char name_buf[512];
3083 unsigned pname;
3084 int expected;
3085 int i;
3086 int num_active_uniforms;
3088 REQUIRE(parse_word_copy(rest, name, sizeof(name), &rest),
3089 "Bad uniform name at: %s\n", line);
3091 REQUIRE(parse_enum_tab(all_pnames, rest, &pname, &rest),
3092 "Bad glGetUniformsiv pname at: %s\n", line);
3094 REQUIRE(parse_enum_tab(all_types, rest, (unsigned *)&expected, &rest) ||
3095 parse_int(rest, &expected, &rest),
3096 "Bad expected value at: %s\n", line);
3098 glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
3099 for (i = 0; i < num_active_uniforms; i++) {
3100 GLint got;
3101 GLint size;
3102 GLenum type;
3103 GLsizei name_len;
3104 bool pass = true;
3106 glGetActiveUniform(prog, i, sizeof(name_buf), &name_len,
3107 &size, &type, name_buf);
3109 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3110 fprintf(stderr, "glGetActiveUniform error\n");
3111 piglit_report_result(PIGLIT_FAIL);
3114 if (strcmp(name, name_buf) != 0)
3115 continue;
3117 /* If the requested pname is one of the values that
3118 * glGetActiveUniform happens to return, check the value
3119 * returned by that function too.
3121 switch (pname) {
3122 case GL_UNIFORM_TYPE:
3123 got = (GLint) type;
3124 break;
3126 case GL_UNIFORM_SIZE:
3127 got = size;
3128 break;
3130 case GL_UNIFORM_NAME_LENGTH:
3131 got = name_len;
3132 break;
3134 default:
3135 /* This ensures the check below will pass when the
3136 * requested enum is not one of the values already
3137 * returned by glGetActiveUniform.
3139 got = expected;
3140 break;
3143 if (got != expected) {
3144 fprintf(stderr,
3145 "glGetActiveUniform(%s, %s): "
3146 "expected %d (0x%04x), got %d (0x%04x)\n",
3147 name, piglit_get_gl_enum_name(pname),
3148 expected, expected, got, got);
3149 pass = false;
3152 /* Set 'got' to some value in case glGetActiveUniformsiv
3153 * doesn't write to it. That should only be able to occur
3154 * when the function raises a GL error, but "should" is kind
3155 * of a funny word.
3157 got = ~expected;
3158 glGetActiveUniformsiv(prog, 1, (GLuint *) &i, pname, &got);
3160 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3161 fprintf(stderr, "glGetActiveUniformsiv error\n");
3162 piglit_report_result(PIGLIT_FAIL);
3165 if (got != expected) {
3166 fprintf(stderr,
3167 "glGetActiveUniformsiv(%s, %s): "
3168 "expected %d, got %d\n",
3169 name, piglit_get_gl_enum_name(pname),
3170 expected, got);
3171 pass = false;
3174 if (!pass)
3175 piglit_report_result(PIGLIT_FAIL);
3177 return;
3180 fprintf(stderr, "No active uniform named \"%s\"\n", name);
3181 piglit_report_result(PIGLIT_FAIL);
3182 return;
3187 * Confirms if @resource_index is a given resource, within @interface_type.
3189 * In order to identify it, it uses by default @resource_name. If
3190 * force_no_names mode is activated it uses the binding contained at
3191 * @block_data. Note that for the latter, only ubos or ssbos are
3192 * supported as @interface_type.
3194 * @resource_name_buf, @prop and @value_expected are only used for
3195 * some extra checks.
3197 * Return true if @resource_index is the resource within
3198 * @interface_type we search for. false otherwise.
3200 static bool
3201 confirm_program_resource(GLenum interface_type, GLuint resource_index,
3202 const char *resource_name, char *resource_name_buf,
3203 struct block_info block_data, unsigned prop,
3204 int value_expected)
3206 if (!force_no_names) {
3207 GLsizei resource_name_len;
3209 glGetProgramResourceName(prog, interface_type, resource_index,
3210 512, &resource_name_len,
3211 resource_name_buf);
3213 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3214 fprintf(stderr, "glGetProgramResourceName error\n");
3215 piglit_report_result(PIGLIT_FAIL);
3218 if (strcmp(resource_name, resource_name_buf) != 0)
3219 return false;
3221 /* glGetProgramResourceName does not consider the NULL
3222 * terminator when returning the name length, however,
3223 * glGetProgramResourceiv does. We take that into account
3224 * when doing the comparison.
3226 if (prop == GL_NAME_LENGTH &&
3227 resource_name_len != (value_expected - 1)) {
3228 fprintf(stderr,
3229 "glGetProgramResourceName(%s, %s, %s): "
3230 "expected length: %d (0x%04x), "
3231 "got length: %d (0x%04x)\n",
3232 piglit_get_gl_enum_name(interface_type),
3233 resource_name, piglit_get_gl_enum_name(prop),
3234 value_expected - 1, value_expected - 1,
3235 resource_name_len, resource_name_len);
3236 piglit_report_result(PIGLIT_FAIL);
3238 } else {
3239 unsigned binding_prop = GL_BUFFER_BINDING;
3240 int current_binding = 0;
3241 GLint length;
3243 if (interface_type != GL_SHADER_STORAGE_BLOCK &&
3244 interface_type != GL_UNIFORM_BLOCK) {
3245 fprintf(stderr,
3246 "active_program_interface queries under force_no_names "
3247 "mode are only supported for GL_SHADER_STORAGE_BLOCK "
3248 "or GL_UNIFORM_BLOCK interfaces\n");
3249 piglit_report_result(PIGLIT_FAIL);
3252 glGetProgramResourceiv(prog, interface_type,
3253 resource_index, 1, &binding_prop, 1,
3254 &length, &current_binding);
3255 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3256 fprintf(stderr, "glGetProgramResourceiv error\n");
3257 piglit_report_result(PIGLIT_FAIL);
3260 if (block_data.binding != current_binding)
3261 return false;
3264 return true;
3268 * Query an active resource using ARB_program_interface_query functions
3270 * Format of the command:
3272 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM integer
3274 * or
3276 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM GL_TYPE_ENUM
3278 static void
3279 active_program_interface(const char *line, struct block_info block_data)
3281 static const struct string_to_enum all_props[] = {
3282 ENUM_STRING(GL_TYPE),
3283 ENUM_STRING(GL_ARRAY_SIZE),
3284 ENUM_STRING(GL_NAME_LENGTH),
3285 ENUM_STRING(GL_BLOCK_INDEX),
3286 ENUM_STRING(GL_OFFSET),
3287 ENUM_STRING(GL_ARRAY_STRIDE),
3288 ENUM_STRING(GL_MATRIX_STRIDE),
3289 ENUM_STRING(GL_IS_ROW_MAJOR),
3290 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER_INDEX),
3291 ENUM_STRING(GL_BUFFER_BINDING),
3292 ENUM_STRING(GL_BUFFER_DATA_SIZE),
3293 ENUM_STRING(GL_NUM_ACTIVE_VARIABLES),
3294 ENUM_STRING(GL_REFERENCED_BY_VERTEX_SHADER),
3295 ENUM_STRING(GL_REFERENCED_BY_TESS_CONTROL_SHADER),
3296 ENUM_STRING(GL_REFERENCED_BY_TESS_EVALUATION_SHADER),
3297 ENUM_STRING(GL_REFERENCED_BY_GEOMETRY_SHADER),
3298 ENUM_STRING(GL_REFERENCED_BY_FRAGMENT_SHADER),
3299 ENUM_STRING(GL_REFERENCED_BY_COMPUTE_SHADER),
3300 ENUM_STRING(GL_TOP_LEVEL_ARRAY_SIZE),
3301 ENUM_STRING(GL_TOP_LEVEL_ARRAY_STRIDE),
3302 ENUM_STRING(GL_LOCATION),
3303 ENUM_STRING(GL_LOCATION_INDEX),
3304 ENUM_STRING(GL_LOCATION_COMPONENT),
3305 ENUM_STRING(GL_IS_PER_PATCH),
3306 ENUM_STRING(GL_NUM_COMPATIBLE_SUBROUTINES),
3307 ENUM_STRING(GL_COMPATIBLE_SUBROUTINES),
3308 { NULL, 0 }
3311 static const struct string_to_enum all_program_interface[] = {
3312 ENUM_STRING(GL_UNIFORM),
3313 ENUM_STRING(GL_UNIFORM_BLOCK),
3314 ENUM_STRING(GL_PROGRAM_INPUT),
3315 ENUM_STRING(GL_PROGRAM_OUTPUT),
3316 ENUM_STRING(GL_BUFFER_VARIABLE),
3317 ENUM_STRING(GL_SHADER_STORAGE_BLOCK),
3318 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER),
3319 ENUM_STRING(GL_VERTEX_SUBROUTINE),
3320 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE),
3321 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE),
3322 ENUM_STRING(GL_GEOMETRY_SUBROUTINE),
3323 ENUM_STRING(GL_FRAGMENT_SUBROUTINE),
3324 ENUM_STRING(GL_COMPUTE_SUBROUTINE),
3325 ENUM_STRING(GL_VERTEX_SUBROUTINE_UNIFORM),
3326 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE_UNIFORM),
3327 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE_UNIFORM),
3328 ENUM_STRING(GL_GEOMETRY_SUBROUTINE_UNIFORM),
3329 ENUM_STRING(GL_FRAGMENT_SUBROUTINE_UNIFORM),
3330 ENUM_STRING(GL_COMPUTE_SUBROUTINE_UNIFORM),
3331 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING),
3332 { NULL, 0 }
3335 char name[512];
3336 char name_buf[512];
3337 unsigned prop, interface_type;
3338 int expected;
3339 int i;
3340 int num_active_buffers;
3342 if (!piglit_is_extension_supported("GL_ARB_program_interface_query") &&
3343 piglit_get_gl_version() < 43) {
3344 fprintf(stderr,
3345 "GL_ARB_program_interface_query not supported or "
3346 "OpenGL version < 4.3\n");
3347 return;
3350 REQUIRE(parse_enum_tab(all_program_interface, line,
3351 &interface_type, &line),
3352 "Bad program interface at: %s\n", line);
3353 REQUIRE(parse_word_copy(line, name, sizeof(name), &line),
3354 "Bad program resource name at: %s\n", line);
3355 REQUIRE(parse_enum_tab(all_props, line, &prop, &line),
3356 "Bad glGetProgramResourceiv pname at: %s\n", line);
3357 REQUIRE(parse_enum_tab(all_types, line, (unsigned *)&expected, &line) ||
3358 parse_int(line, &expected, &line),
3359 "Bad expected value at: %s\n", line);
3361 glGetProgramInterfaceiv(prog, interface_type,
3362 GL_ACTIVE_RESOURCES, &num_active_buffers);
3363 for (i = 0; i < num_active_buffers; i++) {
3364 GLint got;
3365 GLint length;
3366 bool pass = true;
3368 if (!confirm_program_resource(interface_type, i, name, name_buf,
3369 block_data, prop, expected))
3370 continue;
3372 /* Set 'got' to some value in case glGetActiveUniformsiv
3373 * doesn't write to it. That should only be able to occur
3374 * when the function raises a GL error, but "should" is kind
3375 * of a funny word.
3377 got = ~expected;
3378 glGetProgramResourceiv(prog, interface_type,
3379 i, 1, &prop, 1,
3380 &length, &got);
3382 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3383 fprintf(stderr, "glGetProgramResourceiv error\n");
3384 piglit_report_result(PIGLIT_FAIL);
3387 if (got != expected) {
3388 fprintf(stderr,
3389 "glGetProgramResourceiv(%s, %s): "
3390 "expected %d, got %d\n",
3391 name, piglit_get_gl_enum_name(prop),
3392 expected, got);
3393 pass = false;
3396 if (!pass)
3397 piglit_report_result(PIGLIT_FAIL);
3399 return;
3402 if (!force_no_names)
3403 fprintf(stderr, "No active resource named \"%s\"\n", name);
3404 else
3405 fprintf(stderr, "No active resource with binding %i\n", block_data.binding);
3407 piglit_report_result(PIGLIT_FAIL);
3408 return;
3412 static unsigned
3413 query_index(GLenum query)
3415 switch (query) {
3416 case GL_PRIMITIVES_GENERATED:
3417 return 0;
3418 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
3419 return 1;
3420 default:
3421 return 0;
3425 * Checks if the GL_QUERY_RESULT of a given query object has the
3426 * expected value.
3428 * Note that right now it only supports the following two queries:
3429 * * GL_PRIMITIVES_GENERATED
3430 * * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
3432 * As right now we are only creating those query objects with xfb
3433 * rendering.
3435 * Format of the command:
3437 * verify query_object GL_PRIMITIVES_GENERATED integer
3439 * or
3441 * verify query_object GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN integer
3443 static enum piglit_result
3444 verify_query_object_result(const char *line)
3446 static const struct string_to_enum all_targets[] = {
3447 ENUM_STRING(GL_PRIMITIVES_GENERATED),
3448 ENUM_STRING(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
3449 { NULL, 0 }
3452 unsigned target;
3453 unsigned expected;
3454 unsigned value = 0;
3455 unsigned index = 0;
3457 REQUIRE(parse_enum_tab(all_targets, line,
3458 &target, &line),
3459 "Bad query object target at: %s\n", line);
3461 REQUIRE(parse_uint(line, &expected, &line),
3462 "Bad expected value at: %s\n", line);
3464 /* Previous require already checks if the target is one of the
3465 * supported ones.
3467 index = query_index(target);
3469 if (queries[index]) {
3470 glGetQueryObjectuiv(queries[index], GL_QUERY_RESULT, &value);
3471 } else {
3472 fprintf(stderr, "query object for target %s is not initialized. "
3473 "Did you forget to call \"xfb draw arrays\"?\n",
3474 piglit_get_gl_enum_name(target));
3475 return PIGLIT_FAIL;
3478 if (expected != value) {
3479 fprintf(stderr, "glGetQueryObjectuiv(GL_QUERY_RESULT) for a %s "
3480 "query object: expected %d, got %d\n",
3481 piglit_get_gl_enum_name(target), expected, value);
3482 return PIGLIT_FAIL;
3484 return PIGLIT_PASS;
3487 static void
3488 set_parameter(const char *line)
3490 float f[4];
3491 int index, count;
3492 char type[1024];
3494 count = sscanf(line, "%s %d (%f , %f , %f , %f)",
3495 type, &index, &f[0], &f[1], &f[2], &f[3]);
3496 if (count != 6) {
3497 fprintf(stderr, "Couldn't parse parameter command:\n%s\n", line);
3498 piglit_report_result(PIGLIT_FAIL);
3501 if (parse_str(type, "env_vp", NULL)) {
3502 glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3503 } else if (parse_str(type, "local_vp", NULL)) {
3504 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3505 } else if (parse_str(type, "env_fp", NULL)) {
3506 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3507 } else if (parse_str(type, "local_fp", NULL)) {
3508 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3509 } else {
3510 fprintf(stderr, "Unknown parameter type `%s'\n", type);
3511 piglit_report_result(PIGLIT_FAIL);
3515 static void
3516 set_patch_parameter(const char *line)
3518 #ifdef PIGLIT_USE_OPENGL
3519 float f[4];
3520 int i, count;
3521 const char *const line0 = line;
3523 if (gl_version.num < 40)
3524 piglit_require_extension("GL_ARB_tessellation_shader");
3526 if (parse_str(line, "vertices ", &line)) {
3527 count = sscanf(line, "%d", &i);
3528 if (count != 1) {
3529 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3530 piglit_report_result(PIGLIT_FAIL);
3532 glPatchParameteri(GL_PATCH_VERTICES, i);
3533 } else if (parse_str(line, "default level outer ", &line)) {
3534 count = sscanf(line, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
3535 if (count != 4) {
3536 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3537 piglit_report_result(PIGLIT_FAIL);
3539 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, f);
3540 } else if (parse_str(line, "default level inner ", &line)) {
3541 count = sscanf(line, "%f %f", &f[0], &f[1]);
3542 if (count != 2) {
3543 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3544 piglit_report_result(PIGLIT_FAIL);
3546 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, f);
3547 } else {
3548 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line);
3549 piglit_report_result(PIGLIT_FAIL);
3551 #else
3552 printf("patch parameters are only available in desktop GL\n");
3553 piglit_report_result(PIGLIT_SKIP);
3554 #endif
3557 static void
3558 set_provoking_vertex(const char *line)
3560 if (parse_str(line, "first", NULL)) {
3561 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT);
3562 } else if (parse_str(line, "last", NULL)) {
3563 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
3564 } else {
3565 fprintf(stderr, "Unknown provoking vertex parameter `%s'\n", line);
3566 piglit_report_result(PIGLIT_FAIL);
3570 static const struct string_to_enum enable_table[] = {
3571 { "GL_CLIP_PLANE0", GL_CLIP_PLANE0 },
3572 { "GL_CLIP_PLANE1", GL_CLIP_PLANE1 },
3573 { "GL_CLIP_PLANE2", GL_CLIP_PLANE2 },
3574 { "GL_CLIP_PLANE3", GL_CLIP_PLANE3 },
3575 { "GL_CLIP_PLANE4", GL_CLIP_PLANE4 },
3576 { "GL_CLIP_PLANE5", GL_CLIP_PLANE5 },
3577 { "GL_CLIP_PLANE6", GL_CLIP_PLANE0+6 },
3578 { "GL_CLIP_PLANE7", GL_CLIP_PLANE0+7 },
3579 { "GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE },
3580 { "GL_PROGRAM_POINT_SIZE", GL_PROGRAM_POINT_SIZE },
3581 { "GL_DEPTH_TEST", GL_DEPTH_TEST },
3582 { "GL_DEPTH_CLAMP", GL_DEPTH_CLAMP },
3583 { NULL, 0 }
3586 static void
3587 do_enable_disable(const char *line, bool enable_flag)
3589 GLenum value;
3590 REQUIRE(parse_enum_tab(enable_table, line, &value, NULL),
3591 "Bad enable/disable enum at: %s\n", line);
3593 if (enable_flag)
3594 glEnable(value);
3595 else
3596 glDisable(value);
3599 static const struct string_to_enum hint_target_table[] = {
3600 ENUM_STRING(GL_LINE_SMOOTH_HINT),
3601 ENUM_STRING(GL_POLYGON_SMOOTH_HINT),
3602 ENUM_STRING(GL_TEXTURE_COMPRESSION_HINT),
3603 ENUM_STRING(GL_FRAGMENT_SHADER_DERIVATIVE_HINT),
3604 { NULL, 0 }
3607 static const struct string_to_enum hint_param_table[] = {
3608 ENUM_STRING(GL_FASTEST),
3609 ENUM_STRING(GL_NICEST),
3610 ENUM_STRING(GL_DONT_CARE),
3611 { NULL, 0 }
3614 static void do_hint(const char *line)
3616 unsigned target, param;
3617 REQUIRE(parse_enum_tab(hint_target_table, line, &target, &line),
3618 "Bad hint target at: %s\n", line);
3619 REQUIRE(parse_enum_tab(hint_param_table, line, &param, &line),
3620 "Bad hint param at: %s\n", line);
3622 glHint(target, param);
3625 static void
3626 draw_instanced_rect(int primcount, float x, float y, float w, float h)
3628 float verts[4][4];
3630 piglit_require_extension("GL_ARB_draw_instanced");
3632 verts[0][0] = x;
3633 verts[0][1] = y;
3634 verts[0][2] = 0.0;
3635 verts[0][3] = 1.0;
3636 verts[1][0] = x + w;
3637 verts[1][1] = y;
3638 verts[1][2] = 0.0;
3639 verts[1][3] = 1.0;
3640 verts[2][0] = x;
3641 verts[2][1] = y + h;
3642 verts[2][2] = 0.0;
3643 verts[2][3] = 1.0;
3644 verts[3][0] = x + w;
3645 verts[3][1] = y + h;
3646 verts[3][2] = 0.0;
3647 verts[3][3] = 1.0;
3649 glVertexPointer(4, GL_FLOAT, 0, verts);
3650 glEnableClientState(GL_VERTEX_ARRAY);
3652 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, primcount);
3654 glDisableClientState(GL_VERTEX_ARRAY);
3658 static GLenum
3659 decode_drawing_mode(const char *mode_str)
3661 int i;
3663 for (i = GL_POINTS; i <= GL_PATCHES; ++i) {
3664 const char *name = piglit_get_prim_name(i);
3665 if (0 == strcmp(mode_str, name))
3666 return i;
3669 printf("unknown drawing mode \"%s\"\n", mode_str);
3670 piglit_report_result(PIGLIT_FAIL);
3672 /* Should not be reached, but return 0 to avoid compiler warning */
3673 return 0;
3676 static void
3677 handle_texparameter(const char *line)
3679 static const struct string_to_enum compare_funcs[] = {
3680 { "greater", GL_GREATER },
3681 { "gequal", GL_GEQUAL },
3682 { "less", GL_LESS },
3683 { "lequal", GL_LEQUAL },
3684 { "equal", GL_EQUAL },
3685 { "notequal", GL_NOTEQUAL },
3686 { "never", GL_NEVER },
3687 { "always", GL_ALWAYS },
3688 { NULL, 0 },
3690 static const struct string_to_enum depth_modes[] = {
3691 { "intensity", GL_INTENSITY },
3692 { "luminance", GL_LUMINANCE },
3693 { "alpha", GL_ALPHA },
3694 { "red", GL_RED }, /* Requires GL 3.0 or GL_ARB_texture_rg */
3695 { NULL, 0 },
3697 static const struct string_to_enum min_filter_modes[] = {
3698 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
3699 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
3700 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
3701 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR },
3702 { "nearest", GL_NEAREST },
3703 { "linear", GL_LINEAR },
3704 { NULL, 0 }
3706 static const struct string_to_enum mag_filter_modes[] = {
3707 { "nearest", GL_NEAREST },
3708 { "linear", GL_LINEAR },
3709 { NULL, 0 }
3711 static const struct string_to_enum wrap_modes[] = {
3712 { "repeat", GL_REPEAT },
3713 { "clamp_to_edge", GL_CLAMP_TO_EDGE },
3714 { "clamp_to_border", GL_CLAMP_TO_BORDER },
3715 { NULL, 0 }
3717 static const struct string_to_enum swizzle_modes[] = {
3718 { "red", GL_RED },
3719 { "green", GL_GREEN },
3720 { "blue", GL_BLUE },
3721 { "alpha", GL_ALPHA },
3722 { NULL, 0 }
3724 unsigned target = 0;
3725 GLenum parameter = GL_NONE;
3726 const char *parameter_name = NULL;
3727 const struct string_to_enum *strings = NULL;
3728 unsigned value;
3730 REQUIRE(parse_tex_target(line, &target, &line),
3731 "Bad texture target at: %s\n", line);
3733 if (parse_str(line, "compare_func ", &line)) {
3734 parameter = GL_TEXTURE_COMPARE_FUNC;
3735 parameter_name = "compare_func";
3736 strings = compare_funcs;
3737 } else if (parse_str(line, "depth_mode ", &line)) {
3738 parameter = GL_DEPTH_TEXTURE_MODE;
3739 parameter_name = "depth_mode";
3740 strings = depth_modes;
3741 } else if (parse_str(line, "min ", &line)) {
3742 parameter = GL_TEXTURE_MIN_FILTER;
3743 parameter_name = "min";
3744 strings = min_filter_modes;
3745 } else if (parse_str(line, "mag ", &line)) {
3746 parameter = GL_TEXTURE_MAG_FILTER;
3747 parameter_name = "mag";
3748 strings = mag_filter_modes;
3749 } else if (parse_str(line, "wrap_s ", &line)) {
3750 parameter = GL_TEXTURE_WRAP_S;
3751 parameter_name = "wrap_s";
3752 strings = wrap_modes;
3753 } else if (parse_str(line, "wrap_t ", &line)) {
3754 parameter = GL_TEXTURE_WRAP_T;
3755 parameter_name = "wrap_t";
3756 strings = wrap_modes;
3757 } else if (parse_str(line, "wrap_r ", &line)) {
3758 parameter = GL_TEXTURE_WRAP_R;
3759 parameter_name = "wrap_r";
3760 strings = wrap_modes;
3761 } else if (parse_str(line, "lod_bias ", &line)) {
3762 #ifdef PIGLIT_USE_OPENGL
3763 glTexParameterf(target, GL_TEXTURE_LOD_BIAS,
3764 strtod(line, NULL));
3765 return;
3766 #else
3767 printf("lod_bias feature is only available in desktop GL\n");
3768 piglit_report_result(PIGLIT_SKIP);
3769 #endif
3770 } else if (parse_str(line, "max_level ", &line)) {
3771 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL,
3772 strtol(line, NULL, 10));
3773 return;
3774 } else if (parse_str(line, "base_level ", &line)) {
3775 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL,
3776 strtol(line, NULL, 10));
3777 return;
3778 } else if (parse_str(line, "border_color ", &line)) {
3779 float bc[4];
3780 int count;
3781 count = sscanf(line, "%f %f %f %f", &bc[0], &bc[1], &bc[2], &bc[3]);
3782 if (count != 4) {
3783 fprintf(stderr, "Could not parse border_color texture parameter.\n");
3784 piglit_report_result(PIGLIT_FAIL);
3786 glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bc);
3787 return;
3788 } else if (parse_str(line, "swizzle_r ", &line)) {
3789 parameter = GL_TEXTURE_SWIZZLE_R;
3790 parameter_name = "swizzle_r";
3791 strings = swizzle_modes;
3792 } else {
3793 fprintf(stderr, "unknown texture parameter in `%s'\n", line);
3794 piglit_report_result(PIGLIT_FAIL);
3797 REQUIRE(parse_enum_tab(strings, line, &value, &line),
3798 "Bad %s at: %s\n", parameter_name, line);
3800 glTexParameteri(target, parameter, value);
3803 static const struct string_to_enum viewport_swizzle_table[] = {
3804 { "POSITIVE_X", GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV },
3805 { "NEGATIVE_X", GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV },
3806 { "POSITIVE_Y", GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV },
3807 { "NEGATIVE_Y", GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV },
3808 { "POSITIVE_Z", GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV },
3809 { "NEGATIVE_Z", GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV },
3810 { "POSITIVE_W", GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV },
3811 { "NEGATIVE_W", GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV },
3812 { NULL, 0 }
3815 static void
3816 handle_viewport_swizzle(const char *line)
3818 unsigned viewport;
3819 GLenum x, y, z, w;
3821 viewport = strtol(line, (char **)&line, 0);
3822 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &x, &line),
3823 "Bad ViewportSwizzle swizzle at: %s\n", line);
3824 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &y, &line),
3825 "Bad ViewportSwizzle swizzle at: %s\n", line);
3826 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &z, &line),
3827 "Bad ViewportSwizzle swizzle at: %s\n", line);
3828 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &w, &line),
3829 "Bad ViewportSwizzle swizzle at: %s\n", line);
3831 glViewportSwizzleNV(viewport, x, y, z, w);
3834 static void
3835 setup_ubos(void)
3837 int i;
3839 if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
3840 piglit_get_gl_version() < 31) {
3841 return;
3844 if (prog == 0) {
3845 /* probably running an ARB_vertex/fragment_program test */
3846 return;
3849 glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &num_uniform_blocks);
3850 if (num_uniform_blocks == 0)
3851 return;
3853 uniform_block_bos = calloc(num_uniform_blocks, sizeof(GLuint));
3854 glGenBuffers(num_uniform_blocks, uniform_block_bos);
3856 int max_ubos;
3857 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_ubos);
3858 uniform_block_indexes = calloc(max_ubos, sizeof(int));
3860 for (i = 0; i < num_uniform_blocks; i++) {
3861 GLint size;
3862 GLint binding;
3864 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_DATA_SIZE,
3865 &size);
3867 glBindBuffer(GL_UNIFORM_BUFFER, uniform_block_bos[i]);
3868 glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
3870 if (!force_no_names) {
3871 glUniformBlockBinding(prog, i, i);
3872 uniform_block_indexes[i] = i;
3873 binding = i;
3874 } else {
3875 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_BINDING,
3876 &binding);
3877 uniform_block_indexes[binding] = i;
3880 glBindBufferBase(GL_UNIFORM_BUFFER, binding, uniform_block_bos[i]);
3884 static void
3885 teardown_fbos(void)
3887 if (draw_fbo != 0 &&
3888 draw_fbo != piglit_winsys_fbo)
3889 glDeleteFramebuffers(1, &draw_fbo);
3891 if (read_fbo != 0 &&
3892 read_fbo != piglit_winsys_fbo &&
3893 read_fbo != draw_fbo)
3894 glDeleteFramebuffers(1, &read_fbo);
3896 draw_fbo = 0;
3897 read_fbo = 0;
3900 static void
3901 teardown_ubos(void)
3903 if (num_uniform_blocks == 0) {
3904 return;
3907 glDeleteBuffers(num_uniform_blocks, uniform_block_bos);
3908 free(uniform_block_bos);
3909 uniform_block_bos = NULL;
3910 free(uniform_block_indexes);
3911 uniform_block_indexes = NULL;
3912 num_uniform_blocks = 0;
3915 static void
3916 teardown_atomics(void)
3918 for (unsigned i = 0; i < ARRAY_SIZE(atomics_bos); ++i) {
3919 if (atomics_bos[i])
3920 glDeleteBuffers(1, &atomics_bos[i]);
3924 static void
3925 teardown_shader_include_paths(void)
3927 for (unsigned i = 0; i < num_shader_include_paths; i++)
3928 free(shader_include_path[i]);
3930 for (unsigned i = 0; i < num_shader_includes; i++) {
3931 glDeleteNamedStringARB(-1, shader_include_names[i]);
3932 free(shader_include_names[i]);
3935 num_shader_includes = 0;
3936 num_shader_include_paths = 0;
3937 free(shader_include_path);
3938 shader_include_path = NULL;
3941 static void
3942 teardown_xfb(void)
3944 glDeleteBuffers(MAX_XFB_BUFFERS, xfb);
3946 glDeleteQueries(1, &queries[query_index(GL_PRIMITIVES_GENERATED)]);
3947 glDeleteQueries(1, &queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)]);
3948 queries[query_index(GL_PRIMITIVES_GENERATED)] = 0;
3949 queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)] = 0;
3952 static enum piglit_result
3953 program_must_be_in_use(void)
3955 if (!link_ok) {
3956 fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
3957 return PIGLIT_FAIL;
3958 } else if (!prog_in_use) {
3959 fprintf(stderr, "Failed to use program: %s\n", prog_err_info);
3960 return PIGLIT_FAIL;
3962 return PIGLIT_PASS;
3965 static void
3966 bind_vao_if_supported()
3968 if (vao == 0 && piglit_is_core_profile) {
3969 glGenVertexArrays(1, &vao);
3970 glBindVertexArray(vao);
3974 static enum piglit_result
3975 draw_arrays_common(int first, size_t count)
3977 enum piglit_result result = program_must_be_in_use();
3978 if (first < 0) {
3979 printf("draw arrays 'first' must be >= 0\n");
3980 piglit_report_result(PIGLIT_FAIL);
3981 } else if (vbo_present &&
3982 (size_t) first >= num_vbo_rows) {
3983 printf("draw arrays 'first' must be < %lu\n",
3984 (unsigned long) num_vbo_rows);
3985 piglit_report_result(PIGLIT_FAIL);
3987 if (count <= 0) {
3988 printf("draw arrays 'count' must be > 0\n");
3989 piglit_report_result(PIGLIT_FAIL);
3990 } else if (vbo_present &&
3991 count > num_vbo_rows - (size_t) first) {
3992 printf("draw arrays cannot draw beyond %lu\n",
3993 (unsigned long) num_vbo_rows);
3994 piglit_report_result(PIGLIT_FAIL);
3996 bind_vao_if_supported();
3997 return result;
4000 static const struct string_to_enum light_table[] = {
4001 ENUM_STRING(GL_AMBIENT),
4002 ENUM_STRING(GL_DIFFUSE),
4003 ENUM_STRING(GL_SPECULAR),
4004 ENUM_STRING(GL_POSITION),
4005 ENUM_STRING(GL_SPOT_DIRECTION),
4006 ENUM_STRING(GL_SPOT_EXPONENT),
4007 ENUM_STRING(GL_SPOT_CUTOFF),
4008 ENUM_STRING(GL_CONSTANT_ATTENUATION),
4009 ENUM_STRING(GL_LINEAR_ATTENUATION),
4010 ENUM_STRING(GL_QUADRATIC_ATTENUATION),
4011 { NULL, 0 },
4014 static void
4015 set_light(const char *line)
4017 int index;
4018 GLenum attrib;
4020 REQUIRE(parse_int(line, &index, &line),
4021 "Bad light index at: %s\n", line);
4023 REQUIRE(parse_enum_tab(light_table, line, &attrib, &line),
4024 "Bad light enum at: %s\n", line);
4026 if (parse_str(line, "float", &line)) {
4027 float f[16];
4028 int n;
4030 REQUIRE((n = parse_floats(line, f, 16, NULL)) > 0,
4031 "No float found for light %s\n", line);
4033 if (n == 1)
4034 glLightf(GL_LIGHT0 + index, attrib, f[0]);
4035 else
4036 glLightfv(GL_LIGHT0 + index, attrib, f);
4037 } else if (parse_str(line, "int", &line)) {
4038 int i[16];
4039 int n;
4041 REQUIRE((n = parse_ints(line, i, 16, NULL)) > 0,
4042 "No int found for light %s\n", line);
4044 if (n == 1)
4045 glLighti(GL_LIGHT0 + index, attrib, i[0]);
4046 else
4047 glLightiv(GL_LIGHT0 + index, attrib, i);
4048 } else {
4049 printf("Invalid light value type \"%s\"\n", line);
4050 piglit_report_result(PIGLIT_FAIL);
4054 static bool
4055 probe_atomic_counter(unsigned buffer_num, GLint counter_num, const char *op,
4056 uint32_t value, bool uses_layout_qualifiers)
4058 uint32_t *p;
4059 uint32_t observed;
4060 enum comparison cmp;
4061 bool result;
4063 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4064 "Invalid comparison operation at: %s\n", op);
4066 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomics_bos[buffer_num]);
4067 p = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER,
4068 uses_layout_qualifiers ? counter_num : counter_num * sizeof(uint32_t),
4069 sizeof(uint32_t), GL_MAP_READ_BIT);
4071 if (!p) {
4072 printf("Couldn't map atomic counter to verify expected value.\n");
4073 return false;
4076 observed = *p;
4077 result = compare_uint(value, observed, cmp);
4079 if (!result) {
4080 if (uses_layout_qualifiers)
4081 printf("Atomic counter (binding = %d, offset = %d) test failed: "
4082 "Reference %s Observed\n",
4083 buffer_num, counter_num, comparison_string(cmp));
4084 else
4085 printf("Atomic counter %d test failed: Reference %s Observed\n",
4086 counter_num, comparison_string(cmp));
4087 printf(" Reference: %u\n", value);
4088 printf(" Observed: %u\n", observed);
4089 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4090 return false;
4093 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4094 return true;
4097 static bool
4098 probe_ssbo_uint(GLint ssbo_index, GLint ssbo_offset, const char *op, uint32_t value)
4100 uint32_t *p;
4101 uint32_t observed;
4102 enum comparison cmp;
4103 bool result;
4105 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4106 "Invalid comparison operation at: %s\n", op);
4108 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4109 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4110 sizeof(uint32_t), GL_MAP_READ_BIT);
4112 if (!p) {
4113 printf("Couldn't map ssbo to verify expected value.\n");
4114 return false;
4117 observed = *p;
4118 result = compare_uint(value, observed, cmp);
4120 if (!result) {
4121 printf("SSBO %d test failed: Reference %s Observed\n",
4122 ssbo_offset, comparison_string(cmp));
4123 printf(" Reference: %u\n", value);
4124 printf(" Observed: %u\n", observed);
4125 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4126 return false;
4129 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4130 return true;
4133 static bool
4134 probe_ssbo_uint64(GLint ssbo_index, GLint ssbo_offset, const char *op, uint64_t value)
4136 uint64_t *p;
4137 uint64_t observed;
4138 enum comparison cmp;
4139 bool result;
4141 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4142 "Invalid comparison operation at: %s\n", op);
4144 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4145 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4146 sizeof(uint64_t), GL_MAP_READ_BIT);
4148 if (!p) {
4149 printf("Couldn't map ssbo to verify expected value.\n");
4150 return false;
4153 observed = *p;
4154 result = compare_uint64(value, observed, cmp);
4156 if (!result) {
4157 printf("SSBO %d test failed: Reference %s Observed\n",
4158 ssbo_offset, comparison_string(cmp));
4159 printf(" Reference: %lu\n", value);
4160 printf(" Observed: %lu\n", observed);
4161 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4162 return false;
4165 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4166 return true;
4169 static bool
4170 probe_ssbo_int(GLint ssbo_index, GLint ssbo_offset, const char *op, int32_t value)
4172 int32_t *p;
4173 int32_t observed;
4174 enum comparison cmp;
4175 bool result;
4177 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4178 "Invalid comparison operation at: %s\n", op);
4180 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4181 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4182 sizeof(uint32_t), GL_MAP_READ_BIT);
4184 if (!p) {
4185 printf("Couldn't map ssbo to verify expected value.\n");
4186 return false;
4189 observed = *p;
4190 result = compare_int(value, observed, cmp);
4192 if (!result) {
4193 printf("SSBO %d test failed: Reference %s Observed\n",
4194 ssbo_offset, comparison_string(cmp));
4195 printf(" Reference: %d\n", value);
4196 printf(" Observed: %d\n", observed);
4197 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4198 return false;
4201 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4202 return true;
4205 static bool
4206 probe_ssbo_int64(GLint ssbo_index, GLint ssbo_offset, const char *op, int64_t value)
4208 int64_t *p;
4209 int64_t observed;
4210 enum comparison cmp;
4211 bool result;
4213 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4214 "Invalid comparison operation at: %s\n", op);
4216 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4217 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4218 sizeof(uint64_t), GL_MAP_READ_BIT);
4220 if (!p) {
4221 printf("Couldn't map ssbo to verify expected value.\n");
4222 return false;
4225 observed = *p;
4226 result = compare_int64(value, observed, cmp);
4228 if (!result) {
4229 printf("SSBO %d test failed: Reference %s Observed\n",
4230 ssbo_offset, comparison_string(cmp));
4231 printf(" Reference: %ld\n", value);
4232 printf(" Observed: %ld\n", observed);
4233 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4234 return false;
4237 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4238 return true;
4241 static bool
4242 probe_ssbo_double(GLint ssbo_index, GLint ssbo_offset, const char *op, double value)
4244 double *p;
4245 double observed;
4246 enum comparison cmp;
4247 bool result;
4249 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4250 "Invalid comparison operation at: %s\n", op);
4252 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4253 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4254 sizeof(double), GL_MAP_READ_BIT);
4256 if (!p) {
4257 printf("Couldn't map ssbo to verify expected value.\n");
4258 return false;
4261 observed = *p;
4262 result = compare_double(value, observed, cmp);
4264 if (!result) {
4265 printf("SSBO %d test failed: Reference %s Observed\n",
4266 ssbo_offset, comparison_string(cmp));
4267 printf(" Reference: %g\n", value);
4268 printf(" Observed: %g\n", observed);
4269 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4270 return false;
4273 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4274 return true;
4277 static bool
4278 probe_ssbo_float(GLint ssbo_index, GLint ssbo_offset, const char *op, float value)
4280 float *p;
4281 float observed;
4282 enum comparison cmp;
4283 bool result;
4285 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4286 "Invalid comparison operation at: %s\n", op);
4288 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4289 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4290 sizeof(float), GL_MAP_READ_BIT);
4292 if (!p) {
4293 printf("Couldn't map ssbo to verify expected value.\n");
4294 return false;
4297 observed = *p;
4298 result = compare_double(value, observed, cmp);
4300 if (!result) {
4301 printf("SSBO %d test failed: Reference %s Observed\n",
4302 ssbo_offset, comparison_string(cmp));
4303 printf(" Reference: %g\n", value);
4304 printf(" Observed: %g\n", observed);
4305 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4306 return false;
4309 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4310 return true;
4313 GLenum piglit_xfb_primitive_mode(GLenum draw_arrays_mode)
4315 switch (draw_arrays_mode) {
4316 case GL_POINTS:
4317 return GL_POINTS;
4318 case GL_LINES:
4319 case GL_LINE_LOOP:
4320 case GL_LINE_STRIP:
4321 case GL_LINES_ADJACENCY:
4322 case GL_LINE_STRIP_ADJACENCY:
4323 return GL_LINES;
4324 case GL_TRIANGLES:
4325 case GL_TRIANGLE_STRIP:
4326 case GL_TRIANGLE_FAN:
4327 case GL_TRIANGLES_ADJACENCY:
4328 case GL_TRIANGLE_STRIP_ADJACENCY:
4329 return GL_TRIANGLES;
4332 printf("glDrawArrays mode %s not supported for a transform feedback operation\n",
4333 piglit_get_gl_enum_name(draw_arrays_mode));
4334 piglit_report_result(PIGLIT_FAIL);
4337 static void
4338 begin_query(GLenum query_type)
4340 unsigned idx = query_index(query_type);
4341 if (queries[idx] == 0)
4342 glGenQueries(1, &queries[idx]);
4343 glBeginQuery(query_type, queries[idx]);
4346 static void
4347 piglit_xfb_draw_arrays(GLenum mode, int first, size_t count)
4349 GLenum primitive_mode = piglit_xfb_primitive_mode(mode);
4351 begin_query(GL_PRIMITIVES_GENERATED);
4352 begin_query(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4354 glEnable(GL_RASTERIZER_DISCARD);
4356 /* We don't need to call glBindBufferBase here, it is done on
4357 * the "xfb buffer object" command
4360 glBeginTransformFeedback(primitive_mode);
4361 glDrawArrays(mode, first, count);
4362 glEndTransformFeedback();
4364 glDisable(GL_RASTERIZER_DISCARD);
4366 glFlush();
4368 glEndQuery(GL_PRIMITIVES_GENERATED);
4369 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4372 static bool
4373 probe_xfb_float(GLuint buf, unsigned n, float expected)
4375 float *p;
4376 bool result;
4377 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4378 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(float),
4379 sizeof(float), GL_MAP_READ_BIT);
4380 if (!p) {
4381 printf("Couldn't map xfb buffer %u\n", buf);
4382 return false;
4384 result = fabsf(expected - *p) < piglit_tolerance[0];
4385 if (!result) {
4386 printf("xfb buffer %i[%i]: %f, Expected: %f\n",
4387 buf, n, *p, expected);
4390 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4391 return result;
4394 static bool
4395 probe_xfb_double(GLuint buf, unsigned n, double expected)
4397 double *p;
4398 bool result;
4400 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4401 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(double),
4402 sizeof(double), GL_MAP_READ_BIT);
4403 if (!p) {
4404 printf("Couldn't map xfb buffer %u\n", buf);
4405 return false;
4407 result = fabs(expected - *p) < piglit_tolerance[0];
4408 if (!result) {
4409 printf("xfb buffer %i[%i]: %lf, Expected: %lf\n",
4410 buf, n, *p, expected);
4413 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4414 return result;
4417 enum piglit_result
4418 piglit_display(void)
4420 const char *line, *next_line, *rest;
4421 unsigned line_num;
4422 enum piglit_result full_result = PIGLIT_PASS;
4423 GLbitfield clear_bits = 0;
4424 bool link_error_expected = false;
4425 unsigned list = 0;
4426 struct block_info block_data = {0, -1, -1, -1, -1};
4428 if (test_start == NULL)
4429 return PIGLIT_PASS;
4431 next_line = test_start;
4432 line_num = test_start_line_num;
4433 while (next_line[0] != '\0') {
4434 float c[32];
4435 double d[4];
4436 int x, y, z, w, h, l, tex, level;
4437 unsigned ux, uy, uz;
4438 int64_t ly, lz;
4439 uint64_t luy, luz;
4440 char s[300]; // 300 for safety
4441 enum piglit_result result = PIGLIT_PASS;
4443 parse_whitespace(next_line, &line);
4445 next_line = strchrnul(next_line, '\n');
4447 /* Duplicate the line to make it null terminated */
4448 line = strndup(line, next_line - line);
4450 /* If strchrnul found a newline, then skip it */
4451 if (next_line[0] != '\0')
4452 next_line++;
4454 if (line[0] == '\0') {
4455 } else if (sscanf(line, "active shader program %s", s) == 1) {
4456 switch (get_shader_from_string(s, &x)) {
4457 case GL_VERTEX_SHADER:
4458 glActiveShaderProgram(pipeline, sso_vertex_prog);
4459 break;
4460 case GL_TESS_CONTROL_SHADER:
4461 glActiveShaderProgram(pipeline, sso_tess_control_prog);
4462 break;
4463 case GL_TESS_EVALUATION_SHADER:
4464 glActiveShaderProgram(pipeline, sso_tess_eval_prog);
4465 break;
4466 case GL_GEOMETRY_SHADER:
4467 glActiveShaderProgram(pipeline, sso_geometry_prog);
4468 break;
4469 case GL_FRAGMENT_SHADER:
4470 glActiveShaderProgram(pipeline, sso_fragment_prog);
4471 break;
4472 case GL_COMPUTE_SHADER:
4473 glActiveShaderProgram(pipeline, sso_compute_prog);
4474 break;
4476 } else if (sscanf(line, "atomic counter buffer %u %u", &x, &y) == 2) {
4477 GLuint *atomics_buf = calloc(y, sizeof(GLuint));
4478 glGenBuffers(1, &atomics_bos[x]);
4479 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4480 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4481 sizeof(GLuint) * y, atomics_buf,
4482 GL_STATIC_DRAW);
4483 free(atomics_buf);
4484 } else if (sscanf(line, "atomic counters %d", &x) == 1) {
4485 GLuint *atomics_buf = calloc(x, sizeof(GLuint));
4486 glGenBuffers(1, &atomics_bos[0]);
4487 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomics_bos[0]);
4488 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4489 sizeof(GLuint) * x,
4490 atomics_buf, GL_STATIC_DRAW);
4491 free(atomics_buf);
4492 } else if (sscanf(line, "atomic counter %u %u %u", &x, &y, &z) == 3) {
4493 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4494 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER,
4495 sizeof(GLuint) * y, sizeof(GLuint),
4496 &z);
4497 } else if (parse_str(line, "clear color ", &rest)) {
4498 parse_floats(rest, c, 4, NULL);
4499 glClearColor(c[0], c[1], c[2], c[3]);
4500 clear_bits |= GL_COLOR_BUFFER_BIT;
4501 } else if (parse_str(line, "clear depth ", &rest)) {
4502 parse_floats(rest, c, 1, NULL);
4503 glClearDepth(c[0]);
4504 clear_bits |= GL_DEPTH_BUFFER_BIT;
4505 } else if (parse_str(line, "clear", NULL)) {
4506 glClear(clear_bits);
4507 } else if (sscanf(line,
4508 "clip plane %d %lf %lf %lf %lf",
4509 &x, &d[0], &d[1], &d[2], &d[3]) == 5) {
4510 if (x < 0 || x >= gl_max_clip_planes) {
4511 printf("clip plane id %d out of range\n", x);
4512 piglit_report_result(PIGLIT_FAIL);
4514 glClipPlane(GL_CLIP_PLANE0 + x, d);
4515 #ifdef PIGLIT_USE_OPENGL
4516 } else if (parse_str(line, "color ", &rest)) {
4517 parse_floats(rest, c, 4, NULL);
4518 assert(!piglit_is_core_profile);
4519 glColor4fv(c);
4520 #endif
4521 } else if (sscanf(line,
4522 "compute %d %d %d",
4523 &x, &y, &z) == 3) {
4524 result = program_must_be_in_use();
4525 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4526 glDispatchCompute(x, y, z);
4527 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4528 } else if (sscanf(line,
4529 "compute group size %d %d %d %d %d %d",
4530 &x, &y, &z, &w, &h, &l) == 6) {
4531 result = program_must_be_in_use();
4532 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4533 glDispatchComputeGroupSizeARB(x, y, z, w, h, l);
4534 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4535 } else if (parse_str(line, "draw rect tex ", &rest)) {
4536 result = program_must_be_in_use();
4537 program_subroutine_uniforms();
4538 parse_floats(rest, c, 8, NULL);
4539 piglit_draw_rect_tex(c[0], c[1], c[2], c[3],
4540 c[4], c[5], c[6], c[7]);
4541 } else if (parse_str(line, "draw rect ortho patch ", &rest)) {
4542 result = program_must_be_in_use();
4543 program_subroutine_uniforms();
4544 parse_floats(rest, c, 4, NULL);
4546 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4547 -1.0 + 2.0 * (c[1] / piglit_height),
4548 2.0 * (c[2] / piglit_width),
4549 2.0 * (c[3] / piglit_height), true, 1);
4550 } else if (parse_str(line, "draw rect ortho ", &rest)) {
4551 result = program_must_be_in_use();
4552 program_subroutine_uniforms();
4553 parse_floats(rest, c, 4, NULL);
4555 piglit_draw_rect(-1.0 + 2.0 * (c[0] / piglit_width),
4556 -1.0 + 2.0 * (c[1] / piglit_height),
4557 2.0 * (c[2] / piglit_width),
4558 2.0 * (c[3] / piglit_height));
4559 } else if (parse_str(line, "draw rect patch ", &rest)) {
4560 result = program_must_be_in_use();
4561 parse_floats(rest, c, 4, NULL);
4562 piglit_draw_rect_custom(c[0], c[1], c[2], c[3], true, 1);
4563 } else if (parse_str(line, "draw rect ", &rest)) {
4564 result = program_must_be_in_use();
4565 program_subroutine_uniforms();
4566 parse_floats(rest, c, 4, NULL);
4567 piglit_draw_rect(c[0], c[1], c[2], c[3]);
4568 } else if (parse_str(line, "draw instanced rect ortho patch ", &rest)) {
4569 int instance_count;
4571 result = program_must_be_in_use();
4572 sscanf(rest, "%d %f %f %f %f",
4573 &instance_count,
4574 c + 0, c + 1, c + 2, c + 3);
4575 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4576 -1.0 + 2.0 * (c[1] / piglit_height),
4577 2.0 * (c[2] / piglit_width),
4578 2.0 * (c[3] / piglit_height), true,
4579 instance_count);
4580 } else if (parse_str(line, "draw instanced rect ortho ", &rest)) {
4581 int instance_count;
4583 result = program_must_be_in_use();
4584 sscanf(rest, "%d %f %f %f %f",
4585 &instance_count,
4586 c + 0, c + 1, c + 2, c + 3);
4587 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4588 -1.0 + 2.0 * (c[1] / piglit_height),
4589 2.0 * (c[2] / piglit_width),
4590 2.0 * (c[3] / piglit_height), false,
4591 instance_count);
4592 } else if (parse_str(line, "draw instanced rect ", &rest)) {
4593 int primcount;
4595 result = program_must_be_in_use();
4596 sscanf(rest, "%d %f %f %f %f",
4597 &primcount,
4598 c + 0, c + 1, c + 2, c + 3);
4599 draw_instanced_rect(primcount, c[0], c[1], c[2], c[3]);
4600 } else if (sscanf(line, "draw arrays instanced %31s %d %d %d", s, &x, &y, &z) == 4) {
4601 GLenum mode = decode_drawing_mode(s);
4602 int first = x;
4603 size_t count = (size_t) y;
4604 size_t primcount = (size_t) z;
4605 draw_arrays_common(first, count);
4606 glDrawArraysInstanced(mode, first, count, primcount);
4607 } else if (sscanf(line, "draw arrays %31s %d %d", s, &x, &y) == 3) {
4608 GLenum mode = decode_drawing_mode(s);
4609 int first = x;
4610 size_t count = (size_t) y;
4611 result = draw_arrays_common(first, count);
4612 glDrawArrays(mode, first, count);
4613 } else if (parse_str(line, "disable ", &rest)) {
4614 do_enable_disable(rest, false);
4615 } else if (parse_str(line, "enable ", &rest)) {
4616 do_enable_disable(rest, true);
4617 } else if (sscanf(line, "depthfunc %31s", s) == 1) {
4618 glDepthFunc(piglit_get_gl_enum_from_name(s));
4619 } else if (parse_str(line, "fb ", &rest)) {
4620 const GLenum target =
4621 parse_str(rest, "draw ", &rest) ? GL_DRAW_FRAMEBUFFER :
4622 parse_str(rest, "read ", &rest) ? GL_READ_FRAMEBUFFER :
4623 GL_FRAMEBUFFER;
4624 GLuint fbo = 0;
4626 if (parse_str(rest, "tex 2d ", &rest)) {
4627 GLenum attachments[32];
4628 unsigned num_attachments = 0;
4630 glGenFramebuffers(1, &fbo);
4631 glBindFramebuffer(target, fbo);
4633 while (parse_int(rest, &tex, &rest)) {
4634 attachments[num_attachments] =
4635 GL_COLOR_ATTACHMENT0 + num_attachments;
4636 glFramebufferTexture2D(
4637 target, attachments[num_attachments],
4638 GL_TEXTURE_2D,
4639 get_texture_binding(tex)->obj, 0);
4641 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4642 fprintf(stderr,
4643 "glFramebufferTexture2D error\n");
4644 piglit_report_result(PIGLIT_FAIL);
4647 num_attachments++;
4650 if (target != GL_READ_FRAMEBUFFER)
4651 glDrawBuffers(num_attachments, attachments);
4653 w = get_texture_binding(tex)->width;
4654 h = get_texture_binding(tex)->height;
4656 } else if (parse_str(rest, "tex slice ", &rest)) {
4657 GLenum tex_target;
4659 REQUIRE(parse_tex_target(rest, &tex_target, &rest) &&
4660 parse_int(rest, &tex, &rest) &&
4661 parse_int(rest, &l, &rest) &&
4662 parse_int(rest, &z, &rest),
4663 "Framebuffer binding command not "
4664 "understood at: %s\n", rest);
4666 const GLuint tex_obj = get_texture_binding(tex)->obj;
4668 glGenFramebuffers(1, &fbo);
4669 glBindFramebuffer(target, fbo);
4671 if (tex_target == GL_TEXTURE_1D) {
4672 REQUIRE(z == 0,
4673 "Invalid layer index provided "
4674 "in command: %s\n", line);
4675 glFramebufferTexture1D(
4676 target, GL_COLOR_ATTACHMENT0,
4677 tex_target, tex_obj, l);
4679 } else if (tex_target == GL_TEXTURE_2D ||
4680 tex_target == GL_TEXTURE_RECTANGLE ||
4681 tex_target == GL_TEXTURE_2D_MULTISAMPLE) {
4682 REQUIRE(z == 0,
4683 "Invalid layer index provided "
4684 "in command: %s\n", line);
4685 glFramebufferTexture2D(
4686 target, GL_COLOR_ATTACHMENT0,
4687 tex_target, tex_obj, l);
4689 } else if (tex_target == GL_TEXTURE_CUBE_MAP) {
4690 static const GLenum cubemap_targets[] = {
4691 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
4692 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4693 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
4694 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4695 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
4696 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4698 REQUIRE(z < ARRAY_SIZE(cubemap_targets),
4699 "Invalid layer index provided "
4700 "in command: %s\n", line);
4701 tex_target = cubemap_targets[z];
4703 glFramebufferTexture2D(
4704 target, GL_COLOR_ATTACHMENT0,
4705 tex_target, tex_obj, l);
4707 } else {
4708 glFramebufferTextureLayer(
4709 target, GL_COLOR_ATTACHMENT0,
4710 tex_obj, l, z);
4713 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4714 fprintf(stderr, "Error binding texture "
4715 "attachment for command: %s\n",
4716 line);
4717 piglit_report_result(PIGLIT_FAIL);
4720 w = MAX2(1, get_texture_binding(tex)->width >> l);
4721 h = MAX2(1, get_texture_binding(tex)->height >> l);
4723 } else if (sscanf(rest, "tex layered %d", &tex) == 1) {
4724 glGenFramebuffers(1, &fbo);
4725 glBindFramebuffer(target, fbo);
4727 glFramebufferTexture(
4728 target, GL_COLOR_ATTACHMENT0,
4729 get_texture_binding(tex)->obj, 0);
4730 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4731 fprintf(stderr,
4732 "glFramebufferTexture error\n");
4733 piglit_report_result(PIGLIT_FAIL);
4736 w = get_texture_binding(tex)->width;
4737 h = get_texture_binding(tex)->height;
4739 } else if (parse_str(rest, "ms ", &rest)) {
4740 GLuint rb;
4741 GLenum format;
4742 int samples;
4744 REQUIRE(parse_enum_gl(rest, &format, &rest) &&
4745 parse_int(rest, &w, &rest) &&
4746 parse_int(rest, &h, &rest) &&
4747 parse_int(rest, &samples, &rest),
4748 "Framebuffer binding command not "
4749 "understood at: %s\n", rest);
4751 glGenFramebuffers(1, &fbo);
4752 glBindFramebuffer(target, fbo);
4754 glGenRenderbuffers(1, &rb);
4755 glBindRenderbuffer(GL_RENDERBUFFER, rb);
4757 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
4758 format, w, h);
4760 glFramebufferRenderbuffer(target,
4761 GL_COLOR_ATTACHMENT0,
4762 GL_RENDERBUFFER, rb);
4764 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4765 fprintf(stderr, "glFramebufferRenderbuffer error\n");
4766 piglit_report_result(PIGLIT_FAIL);
4769 } else if (parse_str(rest, "winsys", &rest)) {
4770 fbo = piglit_winsys_fbo;
4771 glBindFramebuffer(target, fbo);
4772 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4773 fprintf(stderr, "glBindFramebuffer error\n");
4774 piglit_report_result(PIGLIT_FAIL);
4777 w = piglit_width;
4778 h = piglit_height;
4780 } else {
4781 fprintf(stderr, "Unknown fb bind subcommand "
4782 "\"%s\"\n", rest);
4783 piglit_report_result(PIGLIT_FAIL);
4786 const GLenum status = glCheckFramebufferStatus(target);
4787 if (status != GL_FRAMEBUFFER_COMPLETE) {
4788 fprintf(stderr, "incomplete fbo (status 0x%x)\n",
4789 status);
4790 piglit_report_result(PIGLIT_FAIL);
4793 if (target != GL_READ_FRAMEBUFFER) {
4794 render_width = w;
4795 render_height = h;
4797 /* Delete the previous draw FB in case
4798 * it's no longer reachable.
4800 if (draw_fbo != 0 &&
4801 draw_fbo != piglit_winsys_fbo &&
4802 draw_fbo != (target == GL_DRAW_FRAMEBUFFER ?
4803 read_fbo : 0))
4804 glDeleteFramebuffers(1, &draw_fbo);
4806 draw_fbo = fbo;
4809 if (target != GL_DRAW_FRAMEBUFFER) {
4810 read_width = w;
4811 read_height = h;
4813 /* Delete the previous read FB in case
4814 * it's no longer reachable.
4816 if (read_fbo != 0 &&
4817 read_fbo != piglit_winsys_fbo &&
4818 read_fbo != (target == GL_READ_FRAMEBUFFER ?
4819 draw_fbo : 0))
4820 glDeleteFramebuffers(1, &read_fbo);
4822 read_fbo = fbo;
4825 } else if (parse_str(line, "blit ", &rest)) {
4826 static const struct string_to_enum buffers[] = {
4827 { "color", GL_COLOR_BUFFER_BIT },
4828 { "depth", GL_DEPTH_BUFFER_BIT },
4829 { "stencil", GL_STENCIL_BUFFER_BIT },
4830 { NULL }
4832 static const struct string_to_enum filters[] = {
4833 { "linear", GL_LINEAR },
4834 { "nearest", GL_NEAREST },
4835 { NULL }
4837 unsigned buffer, filter;
4839 REQUIRE(parse_enum_tab(buffers, rest, &buffer, &rest) &&
4840 parse_enum_tab(filters, rest, &filter, &rest),
4841 "FB blit command not understood at: %s\n",
4842 rest);
4844 glBlitFramebuffer(0, 0, read_width, read_height,
4845 0, 0, render_width, render_height,
4846 buffer, filter);
4848 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4849 fprintf(stderr, "glBlitFramebuffer error\n");
4850 piglit_report_result(PIGLIT_FAIL);
4853 } else if (parse_str(line, "frustum", &rest)) {
4854 parse_floats(rest, c, 6, NULL);
4855 piglit_frustum_projection(false, c[0], c[1], c[2],
4856 c[3], c[4], c[5]);
4857 } else if (parse_str(line, "hint", &rest)) {
4858 do_hint(rest);
4859 } else if (sscanf(line,
4860 "image texture %d %31s",
4861 &tex, s) == 2) {
4862 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
4863 glBindImageTexture(tex, get_texture_binding(tex)->obj, 0,
4864 GL_FALSE, 0, GL_READ_WRITE, img_fmt);
4865 } else if (sscanf(line, "memory barrier %s", s) == 1) {
4866 glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s));
4867 } else if (parse_str(line, "blend barrier", NULL)) {
4868 glBlendBarrier();
4869 } else if (parse_str(line, "fbfetch barrier", NULL)) {
4870 glFramebufferFetchBarrierEXT();
4871 } else if (sscanf(line, "ortho %f %f %f %f",
4872 c + 0, c + 1, c + 2, c + 3) == 4) {
4873 piglit_gen_ortho_projection(c[0], c[1], c[2], c[3],
4874 -1, 1, GL_FALSE);
4875 } else if (parse_str(line, "ortho", NULL)) {
4876 piglit_ortho_projection(render_width, render_height,
4877 GL_FALSE);
4878 } else if (sscanf(line, "viewport indexed %u %f %f %f %f",
4879 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
4880 glViewportIndexedfv(x, c);
4881 } else if (parse_str(line, "probe rgba ", &rest)) {
4882 parse_floats(rest, c, 6, NULL);
4883 if (!piglit_probe_pixel_rgba((int) c[0], (int) c[1],
4884 & c[2])) {
4885 result = PIGLIT_FAIL;
4887 } else if (parse_str(line, "probe depth ", &rest)) {
4888 parse_floats(rest, c, 3, NULL);
4889 if (!piglit_probe_pixel_depth((int) c[0], (int) c[1],
4890 c[2])) {
4891 result = PIGLIT_FAIL;
4893 } else if (sscanf(line,
4894 "probe atomic counter buffer %u %u %s %u",
4895 &ux, &uy, s, &uz) == 4) {
4896 if (!probe_atomic_counter(ux, uy, s, uz, true)) {
4897 result = PIGLIT_FAIL;
4899 } else if (sscanf(line,
4900 "probe atomic counter %u %s %u",
4901 &ux, s, &uy) == 3) {
4902 if (!probe_atomic_counter(0, ux, s, uy, false)) {
4903 result = PIGLIT_FAIL;
4905 } else if (sscanf(line, "probe ssbo uint %d %d %s 0x%x",
4906 &x, &y, s, &z) == 4) {
4907 if (!probe_ssbo_uint(x, y, s, z))
4908 result = PIGLIT_FAIL;
4909 } else if (sscanf(line, "probe ssbo uint %d %d %s %d",
4910 &x, &y, s, &z) == 4) {
4911 if (!probe_ssbo_uint(x, y, s, z))
4912 result = PIGLIT_FAIL;
4913 } else if (sscanf(line, "probe ssbo uint64 %d %d %s %lu",
4914 &x, &y, s, &luz) == 4) {
4915 if (!probe_ssbo_uint64(x, y, s, luz))
4916 result = PIGLIT_FAIL;
4917 } else if (sscanf(line, "probe ssbo int %d %d %s %d",
4918 &x, &y, s, &z) == 4) {
4919 if (!probe_ssbo_int(x, y, s, z))
4920 result = PIGLIT_FAIL;
4921 } else if (sscanf(line, "probe ssbo int64 %d %d %s %ld",
4922 &x, &y, s, &lz) == 4) {
4923 if (!probe_ssbo_int64(x, y, s, lz))
4924 result = PIGLIT_FAIL;
4925 } else if (sscanf(line, "probe ssbo double %d %d %s %lf",
4926 &x, &y, s, &d[0]) == 4) {
4927 if (!probe_ssbo_double(x, y, s, d[0]))
4928 result = PIGLIT_FAIL;
4929 } else if (sscanf(line, "probe ssbo float %d %d %s %f",
4930 &x, &y, s, &c[0]) == 4) {
4931 if (!probe_ssbo_float(x, y, s, c[0]))
4932 result = PIGLIT_FAIL;
4933 } else if (sscanf(line,
4934 "relative probe rgba ( %f , %f ) "
4935 "( %f , %f , %f , %f )",
4936 c + 0, c + 1,
4937 c + 2, c + 3, c + 4, c + 5) == 6) {
4938 x = c[0] * read_width;
4939 y = c[1] * read_height;
4940 if (x >= read_width)
4941 x = read_width - 1;
4942 if (y >= read_height)
4943 y = read_height - 1;
4945 if (!piglit_probe_pixel_rgba(x, y, &c[2])) {
4946 result = PIGLIT_FAIL;
4948 } else if (parse_str(line, "probe rgb ", &rest)) {
4949 parse_floats(rest, c, 5, NULL);
4950 if (!piglit_probe_pixel_rgb((int) c[0], (int) c[1],
4951 & c[2])) {
4952 result = PIGLIT_FAIL;
4954 } else if (sscanf(line,
4955 "relative probe rgb ( %f , %f ) "
4956 "( %f , %f , %f )",
4957 c + 0, c + 1,
4958 c + 2, c + 3, c + 4) == 5) {
4959 x = c[0] * read_width;
4960 y = c[1] * read_height;
4961 if (x >= read_width)
4962 x = read_width - 1;
4963 if (y >= read_height)
4964 y = read_height - 1;
4966 if (!piglit_probe_pixel_rgb(x, y, &c[2])) {
4967 result = PIGLIT_FAIL;
4969 } else if (sscanf(line, "probe rect rgba "
4970 "( %d , %d , %d , %d ) "
4971 "( %f , %f , %f , %f )",
4972 &x, &y, &w, &h,
4973 c + 0, c + 1, c + 2, c + 3) == 8) {
4974 if (!piglit_probe_rect_rgba(x, y, w, h, c)) {
4975 result = PIGLIT_FAIL;
4977 } else if (sscanf(line, "relative probe rect rgb "
4978 "( %f , %f , %f , %f ) "
4979 "( %f , %f , %f )",
4980 c + 0, c + 1, c + 2, c + 3,
4981 c + 4, c + 5, c + 6) == 7) {
4982 x = c[0] * read_width;
4983 y = c[1] * read_height;
4984 w = c[2] * read_width;
4985 h = c[3] * read_height;
4987 if (!piglit_probe_rect_rgb(x, y, w, h, &c[4])) {
4988 result = PIGLIT_FAIL;
4990 } else if (sscanf(line, "relative probe rect rgba "
4991 "( %f , %f , %f , %f ) "
4992 "( %f , %f , %f , %f )",
4993 c + 0, c + 1, c + 2, c + 3,
4994 c + 4, c + 5, c + 6, c + 7) == 8) {
4995 x = c[0] * read_width;
4996 y = c[1] * read_height;
4997 w = c[2] * read_width;
4998 h = c[3] * read_height;
5000 if (!piglit_probe_rect_rgba(x, y, w, h, &c[4])) {
5001 result = PIGLIT_FAIL;
5003 } else if (sscanf(line, "relative probe rect rgba int "
5004 "( %f , %f , %f , %f ) "
5005 "( %d , %d , %d , %d )",
5006 c + 0, c + 1, c + 2, c + 3,
5007 &x, &y, &z, &w) == 8) {
5008 const int expected[] = { x, y, z, w };
5009 if (!piglit_probe_rect_rgba_int(c[0] * read_width,
5010 c[1] * read_height,
5011 c[2] * read_width,
5012 c[3] * read_height,
5013 expected))
5014 result = PIGLIT_FAIL;
5016 } else if (parse_str(line, "polygon mode ", &rest)) {
5017 GLenum face, mode;
5019 REQUIRE(parse_enum_gl(rest, &face, &rest) &&
5020 parse_enum_gl(rest, &mode, &rest),
5021 "Polygon mode command not understood at %s\n",
5022 rest);
5024 glPolygonMode(face, mode);
5026 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5027 fprintf(stderr, "glPolygonMode error\n");
5028 piglit_report_result(PIGLIT_FAIL);
5030 } else if (parse_str(line, "probe all rgba ", &rest)) {
5031 parse_floats(rest, c, 4, NULL);
5032 if (result != PIGLIT_FAIL &&
5033 !piglit_probe_rect_rgba(0, 0, read_width,
5034 read_height, c))
5035 result = PIGLIT_FAIL;
5036 } else if (parse_str(line, "probe warn all rgba ", &rest)) {
5037 parse_floats(rest, c, 4, NULL);
5038 if (result == PIGLIT_PASS &&
5039 !piglit_probe_rect_rgba(0, 0, read_width,
5040 read_height, c))
5041 result = PIGLIT_WARN;
5042 } else if (parse_str(line, "probe all rgb", &rest)) {
5043 parse_floats(rest, c, 3, NULL);
5044 if (result != PIGLIT_FAIL &&
5045 !piglit_probe_rect_rgb(0, 0, read_width,
5046 read_height, c))
5047 result = PIGLIT_FAIL;
5048 } else if (parse_str(line, "tolerance", &rest)) {
5049 parse_floats(rest, piglit_tolerance, 4, NULL);
5050 } else if (parse_str(line, "shade model smooth", NULL)) {
5051 glShadeModel(GL_SMOOTH);
5052 } else if (parse_str(line, "shade model flat", NULL)) {
5053 glShadeModel(GL_FLAT);
5054 } else if (sscanf(line, "ssbo %d %d", &x, &y) == 2) {
5055 GLuint *ssbo_init = calloc(y, 1);
5056 glGenBuffers(1, &ssbo[x]);
5057 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, x, ssbo[x]);
5058 glBufferData(GL_SHADER_STORAGE_BUFFER, y,
5059 ssbo_init, GL_DYNAMIC_DRAW);
5060 free(ssbo_init);
5062 else if (sscanf(line, "xfb buffer object %u %u", &ux, &uy) == 2) {
5063 GLuint *xfb_init = calloc(uy, 1);
5064 if (ux < 0 || ux >= MAX_XFB_BUFFERS) {
5065 printf("xfb buffer id %d out of range\n", ux);
5066 piglit_report_result(PIGLIT_FAIL);
5068 glGenBuffers(1, &xfb[ux]);
5069 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, ux, xfb[ux]);
5070 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, uy,
5071 xfb_init, GL_STREAM_READ);
5072 free(xfb_init);
5073 } else if (sscanf(line, "xfb draw arrays %31s %d %d", s, &x, &y) == 3) {
5074 GLenum mode = decode_drawing_mode(s);
5075 int first = x;
5076 size_t count = (size_t) y;
5077 result = draw_arrays_common(first, count);
5078 piglit_xfb_draw_arrays(mode, first, count);
5079 } else if (sscanf(line, "probe xfb buffer float %u %u %f",
5080 &ux, &uy, &c[0]) == 3) {
5081 if (!probe_xfb_float(xfb[ux], uy, c[0]))
5082 result = PIGLIT_FAIL;
5083 } else if (sscanf(line, "probe xfb buffer double %u %u %lf",
5084 &ux, &uy, &d[0]) == 3) {
5085 if (!probe_xfb_double(xfb[ux], uy, d[0]))
5086 result = PIGLIT_FAIL;
5087 } else if (sscanf(line, "ssbo %d subdata float %d %f", &x, &y, &c[0]) == 3) {
5088 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5089 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &c[0]);
5090 } else if (sscanf(line, "ssbo %d subdata double %d %s", &x, &y, s) == 3) {
5091 parse_doubles(s, &d[0], 1, NULL);
5092 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5093 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, sizeof(double), &d[0]);
5094 } else if (sscanf(line, "ssbo %d subdata int64 %ld %s", &x, &ly, s) == 3) {
5095 parse_int64s(s, &lz, 1, NULL);
5096 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5097 glBufferSubData(GL_SHADER_STORAGE_BUFFER, ly, sizeof(int64_t), &lz);
5098 } else if (sscanf(line, "ssbo %d subdata uint64 %lu %s", &x, &luy, s) == 3) {
5099 parse_uint64s(s, &luz, 1, NULL);
5100 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5101 glBufferSubData(GL_SHADER_STORAGE_BUFFER, luy, sizeof(uint64_t), &luz);
5102 } else if (sscanf(line, "ssbo %d subdata int %d %s", &x, &y, s) == 3) {
5103 parse_ints(s, &z, 1, NULL);
5104 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5105 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &z);
5106 } else if (sscanf(line, "texture rgbw %d ( %d", &tex, &w) == 2) {
5107 GLenum int_fmt = GL_RGBA;
5108 int num_scanned =
5109 sscanf(line,
5110 "texture rgbw %d ( %d , %d ) %31s",
5111 &tex, &w, &h, s);
5112 if (num_scanned < 3) {
5113 fprintf(stderr,
5114 "invalid texture rgbw command!\n");
5115 piglit_report_result(PIGLIT_FAIL);
5118 if (num_scanned >= 4) {
5119 int_fmt = piglit_get_gl_enum_from_name(s);
5122 glActiveTexture(GL_TEXTURE0 + tex);
5123 int handle = piglit_rgbw_texture(
5124 int_fmt, w, h, GL_FALSE, GL_FALSE,
5125 (piglit_is_gles() ? GL_UNSIGNED_BYTE :
5126 GL_UNSIGNED_NORMALIZED));
5127 set_texture_binding(tex, handle, w, h, 1);
5129 if (!piglit_is_core_profile &&
5130 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5131 glEnable(GL_TEXTURE_2D);
5133 } else if (sscanf(line, "resident texture %d", &tex) == 1) {
5134 GLuint64 handle;
5136 glBindTexture(GL_TEXTURE_2D, 0);
5138 handle = glGetTextureHandleARB(get_texture_binding(tex)->obj);
5139 glMakeTextureHandleResidentARB(handle);
5141 set_resident_handle(tex, handle, true);
5143 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5144 fprintf(stderr,
5145 "glMakeTextureHandleResidentARB error\n");
5146 piglit_report_result(PIGLIT_FAIL);
5148 } else if (sscanf(line, "resident texture 1D %d", &tex) == 1) {
5149 GLuint64 handle;
5151 glBindTexture(GL_TEXTURE_1D, 0);
5153 handle = glGetTextureHandleARB(get_texture_binding(tex)->obj);
5154 glMakeTextureHandleResidentARB(handle);
5156 set_resident_handle(tex, handle, true);
5158 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5159 fprintf(stderr,
5160 "glMakeTextureHandleResidentARB error\n");
5161 piglit_report_result(PIGLIT_FAIL);
5163 } else if (sscanf(line, "resident image texture %d %31s",
5164 &tex, s) == 2) {
5165 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
5166 GLuint64 handle;
5168 glBindTexture(GL_TEXTURE_2D, 0);
5170 handle = glGetImageHandleARB(get_texture_binding(tex)->obj,
5171 0, GL_FALSE, 0, img_fmt);
5172 glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
5174 set_resident_handle(tex, handle, false);
5176 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5177 fprintf(stderr,
5178 "glMakeImageHandleResidentARB error\n");
5179 piglit_report_result(PIGLIT_FAIL);
5181 } else if (parse_str(line, "texture integer ", &rest)) {
5182 GLenum int_fmt;
5183 int b, a;
5184 int num_scanned =
5185 sscanf(rest, "%d ( %d , %d ) ( %d, %d ) %31s",
5186 &tex, &w, &h, &b, &a, s);
5187 if (num_scanned < 6) {
5188 fprintf(stderr,
5189 "invalid texture integer command!\n");
5190 piglit_report_result(PIGLIT_FAIL);
5193 int_fmt = piglit_get_gl_enum_from_name(s);
5195 glActiveTexture(GL_TEXTURE0 + tex);
5196 const GLuint handle =
5197 piglit_integer_texture(int_fmt, w, h, b, a);
5198 set_texture_binding(tex, handle, w, h, 1);
5200 } else if (sscanf(line, "texture miptree %d", &tex) == 1) {
5201 glActiveTexture(GL_TEXTURE0 + tex);
5202 const GLuint handle = piglit_miptree_texture();
5203 set_texture_binding(tex, handle, 8, 8, 1);
5205 if (!piglit_is_core_profile &&
5206 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5207 glEnable(GL_TEXTURE_2D);
5208 } else if (sscanf(line,
5209 "texture checkerboard %d %d ( %d , %d ) "
5210 "( %f , %f , %f , %f ) "
5211 "( %f , %f , %f , %f )",
5212 &tex, &level, &w, &h,
5213 c + 0, c + 1, c + 2, c + 3,
5214 c + 4, c + 5, c + 6, c + 7) == 12) {
5215 glActiveTexture(GL_TEXTURE0 + tex);
5216 const GLuint handle = piglit_checkerboard_texture(
5217 0, level, w, h, w / 2, h / 2, c + 0, c + 4);
5218 set_texture_binding(tex, handle, w, h, 1);
5220 if (!piglit_is_core_profile &&
5221 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5222 glEnable(GL_TEXTURE_2D);
5223 } else if (sscanf(line,
5224 "texture quads %d %d ( %d , %d ) ( %d , %d ) "
5225 "( %f , %f , %f , %f ) "
5226 "( %f , %f , %f , %f ) "
5227 "( %f , %f , %f , %f ) "
5228 "( %f , %f , %f , %f )",
5229 &tex, &level, &w, &h, &x, &y,
5230 c + 0, c + 1, c + 2, c + 3,
5231 c + 4, c + 5, c + 6, c + 7,
5232 c + 8, c + 9, c + 10, c + 11,
5233 c + 12, c + 13, c + 14, c + 15) == 22) {
5234 glActiveTexture(GL_TEXTURE0 + tex);
5235 const GLuint handle = piglit_quads_texture(
5236 0, level, w, h, x, y, c + 0, c + 4, c + 8, c + 12);
5237 set_texture_binding(tex, handle, w, h, 1);
5239 if (!piglit_is_core_profile &&
5240 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5241 glEnable(GL_TEXTURE_2D);
5242 } else if (sscanf(line,
5243 "texture junk 2DArray %d ( %d , %d , %d )",
5244 &tex, &w, &h, &l) == 4) {
5245 GLuint texobj;
5246 glActiveTexture(GL_TEXTURE0 + tex);
5247 glGenTextures(1, &texobj);
5248 glBindTexture(GL_TEXTURE_2D_ARRAY, texobj);
5249 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA,
5250 w, h, l, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
5251 set_texture_binding(tex, texobj, w, h, l);
5253 } else if (parse_str(line, "texture storage ", &rest)) {
5254 GLenum target, format;
5255 GLuint tex_obj;
5256 int d = h = w = 1;
5258 REQUIRE(parse_int(rest, &tex, &rest) &&
5259 parse_tex_target(rest, &target, &rest) &&
5260 parse_enum_gl(rest, &format, &rest) &&
5261 parse_str(rest, "(", &rest) &&
5262 parse_int(rest, &l, &rest) &&
5263 parse_int(rest, &w, &rest),
5264 "Texture storage command not understood "
5265 "at: %s\n", rest);
5267 glActiveTexture(GL_TEXTURE0 + tex);
5268 glGenTextures(1, &tex_obj);
5269 glBindTexture(target, tex_obj);
5271 if (!parse_int(rest, &h, &rest))
5272 glTexStorage1D(target, l, format, w);
5273 else if (!parse_int(rest, &d, &rest))
5274 glTexStorage2D(target, l, format, w, h);
5275 else
5276 glTexStorage3D(target, l, format, w, h, d);
5278 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5279 fprintf(stderr, "glTexStorage error\n");
5280 piglit_report_result(PIGLIT_FAIL);
5283 if (target == GL_TEXTURE_1D_ARRAY)
5284 set_texture_binding(tex, tex_obj, w, 1, h);
5285 else
5286 set_texture_binding(tex, tex_obj, w, h, d);
5288 #ifdef PIGLIT_USE_OPENGL
5289 } else if (sscanf(line,
5290 "texture rgbw 1D %d",
5291 &tex) == 1) {
5292 glActiveTexture(GL_TEXTURE0 + tex);
5293 const GLuint handle = piglit_rgbw_texture_1d();
5294 set_texture_binding(tex, handle, 4, 1, 1);
5295 #endif
5297 } else if (sscanf(line,
5298 "texture rgbw 3D %d",
5299 &tex) == 1) {
5300 glActiveTexture(GL_TEXTURE0 + tex);
5301 const GLuint handle = piglit_rgbw_texture_3d();
5302 set_texture_binding(tex, handle, 2, 2, 2);
5304 } else if (sscanf(line,
5305 "texture rgbw 2DArray %d ( %d , %d , %d )",
5306 &tex, &w, &h, &l) == 4) {
5307 glActiveTexture(GL_TEXTURE0 + tex);
5308 const GLuint handle = piglit_array_texture(
5309 GL_TEXTURE_2D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5310 set_texture_binding(tex, handle, w, h, l);
5312 } else if (sscanf(line,
5313 "texture rgbw 1DArray %d ( %d , %d )",
5314 &tex, &w, &l) == 3) {
5315 glActiveTexture(GL_TEXTURE0 + tex);
5316 h = 1;
5317 const GLuint handle = piglit_array_texture(
5318 GL_TEXTURE_1D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5319 set_texture_binding(tex, handle, w, 1, l);
5321 } else if (sscanf(line,
5322 "texture shadow2D %d ( %d , %d )",
5323 &tex, &w, &h) == 3) {
5324 glActiveTexture(GL_TEXTURE0 + tex);
5325 const GLuint handle = piglit_depth_texture(
5326 GL_TEXTURE_2D, GL_DEPTH_COMPONENT,
5327 w, h, 1, GL_FALSE);
5328 glTexParameteri(GL_TEXTURE_2D,
5329 GL_TEXTURE_COMPARE_MODE,
5330 GL_COMPARE_R_TO_TEXTURE);
5331 glTexParameteri(GL_TEXTURE_2D,
5332 GL_TEXTURE_COMPARE_FUNC,
5333 GL_GREATER);
5334 set_texture_binding(tex, handle, w, h, 1);
5336 if (!piglit_is_core_profile &&
5337 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5338 glEnable(GL_TEXTURE_2D);
5339 } else if (sscanf(line,
5340 "texture shadowRect %d ( %d , %d )",
5341 &tex, &w, &h) == 3) {
5342 glActiveTexture(GL_TEXTURE0 + tex);
5343 const GLuint handle = piglit_depth_texture(
5344 GL_TEXTURE_RECTANGLE, GL_DEPTH_COMPONENT,
5345 w, h, 1, GL_FALSE);
5346 glTexParameteri(GL_TEXTURE_RECTANGLE,
5347 GL_TEXTURE_COMPARE_MODE,
5348 GL_COMPARE_R_TO_TEXTURE);
5349 glTexParameteri(GL_TEXTURE_RECTANGLE,
5350 GL_TEXTURE_COMPARE_FUNC,
5351 GL_GREATER);
5352 set_texture_binding(tex, handle, w, h, 1);
5353 } else if (sscanf(line,
5354 "texture shadow1D %d ( %d )",
5355 &tex, &w) == 2) {
5356 glActiveTexture(GL_TEXTURE0 + tex);
5357 const GLuint handle = piglit_depth_texture(
5358 GL_TEXTURE_1D, GL_DEPTH_COMPONENT,
5359 w, 1, 1, GL_FALSE);
5360 glTexParameteri(GL_TEXTURE_1D,
5361 GL_TEXTURE_COMPARE_MODE,
5362 GL_COMPARE_R_TO_TEXTURE);
5363 glTexParameteri(GL_TEXTURE_1D,
5364 GL_TEXTURE_COMPARE_FUNC,
5365 GL_GREATER);
5366 set_texture_binding(tex, handle, w, 1, 1);
5367 } else if (sscanf(line,
5368 "texture shadow1DArray %d ( %d , %d )",
5369 &tex, &w, &l) == 3) {
5370 glActiveTexture(GL_TEXTURE0 + tex);
5371 const GLuint handle = piglit_depth_texture(
5372 GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT,
5373 w, l, 1, GL_FALSE);
5374 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5375 GL_TEXTURE_COMPARE_MODE,
5376 GL_COMPARE_R_TO_TEXTURE);
5377 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5378 GL_TEXTURE_COMPARE_FUNC,
5379 GL_GREATER);
5380 set_texture_binding(tex, handle, w, 1, l);
5381 } else if (sscanf(line,
5382 "texture shadow2DArray %d ( %d , %d , %d )",
5383 &tex, &w, &h, &l) == 4) {
5384 glActiveTexture(GL_TEXTURE0 + tex);
5385 const GLuint handle = piglit_depth_texture(
5386 GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT,
5387 w, h, l, GL_FALSE);
5388 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5389 GL_TEXTURE_COMPARE_MODE,
5390 GL_COMPARE_R_TO_TEXTURE);
5391 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5392 GL_TEXTURE_COMPARE_FUNC,
5393 GL_GREATER);
5394 set_texture_binding(tex, handle, w, h, l);
5395 } else if (sscanf(line, "texcoord %d ( %f , %f , %f , %f )",
5396 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
5397 glMultiTexCoord4fv(GL_TEXTURE0 + x, c);
5398 } else if (parse_str(line, "texparameter ", &rest)) {
5399 handle_texparameter(rest);
5400 } else if (parse_str(line, "uniform ", &rest)) {
5401 result = program_must_be_in_use();
5402 set_uniform(rest, block_data);
5403 } else if (parse_str(line, "subuniform ", &rest)) {
5404 result = program_must_be_in_use();
5405 check_shader_subroutine_support();
5406 set_subroutine_uniform(rest);
5407 } else if (parse_str(line, "parameter ", &rest)) {
5408 set_parameter(rest);
5409 } else if (parse_str(line, "patch parameter ", &rest)) {
5410 set_patch_parameter(rest);
5411 } else if (parse_str(line, "program binary save restore", &rest)) {
5412 program_binary_save_restore(true);
5413 } else if (parse_str(line, "provoking vertex ", &rest)) {
5414 set_provoking_vertex(rest);
5415 } else if (parse_str(line, "link error", &rest)) {
5416 link_error_expected = true;
5417 if (link_ok) {
5418 printf("shader link error expected, but it was successful!\n");
5419 piglit_report_result(PIGLIT_FAIL);
5420 } else {
5421 fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
5423 } else if (parse_str(line, "link success", &rest)) {
5424 result = program_must_be_in_use();
5425 } else if (parse_str(line, "ubo array index ", &rest)) {
5426 /* we allow "ubo array index" in order to not
5427 * change existing tests using ubo array index
5429 parse_ints(rest, &block_data.array_index, 1, NULL);
5430 } else if (parse_str(line, "block array index ", &rest)) {
5431 parse_ints(rest, &block_data.array_index, 1, NULL);
5432 } else if (parse_str(line, "block binding ", &rest)) {
5433 parse_ints(rest, &block_data.binding, 1, NULL);
5434 } else if (parse_str(line, "block offset ", &rest)) {
5435 parse_ints(rest, &block_data.offset, 1, NULL);
5436 } else if (parse_str(line, "block matrix stride", &rest)) {
5437 parse_ints(rest, &block_data.matrix_stride, 1, NULL);
5438 } else if (parse_str(line, "block row major", &rest)) {
5439 parse_ints(rest, &block_data.row_major, 1, NULL);
5440 } else if (parse_str(line, "active uniform ", &rest)) {
5441 active_uniform(rest);
5442 } else if (parse_str(line, "verify program_query", &rest)) {
5443 verify_program_query(rest);
5444 } else if (parse_str(line, "verify program_interface_query ", &rest)) {
5445 active_program_interface(rest, block_data);
5446 } else if (parse_str(line, "verify query_object", &rest)) {
5447 result = verify_query_object_result(rest);
5448 } else if (parse_str(line, "vertex attrib ", &rest)) {
5449 set_vertex_attrib(rest);
5450 } else if (parse_str(line, "newlist ", &rest)) {
5451 GLenum mode;
5453 REQUIRE(parse_enum_gl(rest, &mode, &rest),
5454 "NewList mode command not understood at %s\n",
5455 rest);
5457 list = glGenLists(1);
5458 glNewList(list, mode);
5459 } else if (parse_str(line, "endlist", NULL)) {
5460 glEndList();
5461 } else if (parse_str(line, "calllist", NULL)) {
5462 glCallList(list);
5463 } else if (parse_str(line, "deletelist", NULL)) {
5464 glDeleteLists(list, 1);
5465 } else if (parse_str(line, "viewport swizzle ", &rest)) {
5466 handle_viewport_swizzle(rest);
5467 } else if (parse_str(line, "light ", &rest)) {
5468 set_light(rest);
5469 } else if ((line[0] != '\n') && (line[0] != '\0')
5470 && (line[0] != '#')) {
5471 printf("unknown command \"%s\"\n", line);
5472 piglit_report_result(PIGLIT_FAIL);
5475 free((void*) line);
5477 if (result != PIGLIT_PASS) {
5478 printf("Test failure on line %u\n", line_num);
5479 full_result = result;
5482 line_num++;
5485 if (!link_ok && !link_error_expected) {
5486 full_result = program_must_be_in_use();
5489 piglit_present_results();
5491 if (piglit_automatic) {
5492 unsigned i;
5494 /* Free our resources, useful for valgrinding. */
5495 free_subroutine_uniforms();
5497 for (i = 0; i < ARRAY_SIZE(resident_handles); i++)
5498 clear_resident_handle(i);
5500 for (i = 0; i < ARRAY_SIZE(texture_bindings); i++)
5501 clear_texture_binding(i);
5503 if (prog != 0) {
5504 glDeleteProgram(prog);
5505 glUseProgram(0);
5506 } else {
5507 if (!sso_in_use)
5508 glDeleteProgramsARB(1, &prog);
5511 if (pipeline != 0)
5512 glDeleteProgramPipelines(1, &pipeline);
5515 return full_result;
5518 static enum piglit_result
5519 init_test(const char *file)
5521 enum piglit_result result;
5523 result = process_test_script(file);
5524 if (result != PIGLIT_PASS)
5525 return result;
5527 result = link_and_use_shaders();
5528 if (result != PIGLIT_PASS)
5529 return result;
5531 if (sso_in_use)
5532 glBindProgramPipeline(pipeline);
5534 if (link_ok && vertex_data_start != NULL) {
5535 result = program_must_be_in_use();
5536 if (result != PIGLIT_PASS)
5537 return result;
5539 bind_vao_if_supported();
5541 num_vbo_rows = setup_vbo_from_text(prog, vertex_data_start,
5542 vertex_data_end);
5543 vbo_present = true;
5545 setup_ubos();
5546 return PIGLIT_PASS;
5549 static void
5550 recreate_gl_context(char *exec_arg, int param_argc, char **param_argv)
5552 int argc = param_argc + 4;
5553 char **argv = malloc(sizeof(char*) * argc);
5555 if (!argv) {
5556 fprintf(stderr, "%s: malloc failed.\n", __func__);
5557 piglit_report_result(PIGLIT_FAIL);
5560 argv[0] = exec_arg;
5561 memcpy(&argv[1], param_argv, param_argc * sizeof(char*));
5562 argv[argc-3] = "-auto";
5563 argv[argc-2] = "-fbo";
5564 argv[argc-1] = "-report-subtests";
5566 if (gl_fw->destroy)
5567 gl_fw->destroy(gl_fw);
5568 gl_fw = NULL;
5570 exit(main(argc, argv));
5573 static bool
5574 validate_current_gl_context(const char *filename)
5576 struct piglit_gl_test_config config = { 0 };
5578 if (!piglit_gl_test_config_override_size(&config)) {
5579 config.window_width = DEFAULT_WINDOW_WIDTH;
5580 config.window_height = DEFAULT_WINDOW_HEIGHT;
5583 get_required_config(filename, spirv_replaces_glsl, &config);
5585 if (!current_config.supports_gl_compat_version !=
5586 !config.supports_gl_compat_version)
5587 return false;
5589 if (!current_config.supports_gl_core_version !=
5590 !config.supports_gl_core_version)
5591 return false;
5593 if (!current_config.supports_gl_es_version !=
5594 !config.supports_gl_es_version)
5595 return false;
5597 if (current_config.window_width != config.window_width ||
5598 current_config.window_height != config.window_height)
5599 return false;
5601 if (!(current_config.window_visual & PIGLIT_GL_VISUAL_DEPTH) &&
5602 config.window_visual & PIGLIT_GL_VISUAL_DEPTH)
5603 return false;
5605 return true;
5608 void
5609 piglit_init(int argc, char **argv)
5611 int major;
5612 int minor;
5613 bool core = piglit_is_core_profile;
5614 bool es;
5615 enum piglit_result result;
5616 float default_piglit_tolerance[4];
5618 use_get_program_binary =
5619 piglit_strip_arg(&argc, argv, "-get-program-binary") ||
5620 piglit_env_var_as_boolean("SHADER_RUNNER_GET_PROGRAM_BINARY",
5621 false);
5623 report_subtests = piglit_strip_arg(&argc, argv, "-report-subtests");
5624 force_glsl = piglit_strip_arg(&argc, argv, "-glsl");
5625 ignore_missing_uniforms = piglit_strip_arg(&argc, argv, "-ignore-missing-uniforms");
5627 force_no_names = piglit_strip_arg(&argc, argv, "-force-no-names");
5629 if (force_glsl && spirv_replaces_glsl) {
5630 printf("Options -glsl and -spirv can't be used at the same time\n");
5631 piglit_report_result(PIGLIT_FAIL);
5634 if (spirv_replaces_glsl)
5635 force_no_names = true;
5637 if (argc < 2) {
5638 printf("usage: shader_runner <test.shader_test> [-glsl] [-force-no-names]\n");
5639 exit(1);
5642 memcpy(default_piglit_tolerance, piglit_tolerance,
5643 sizeof(piglit_tolerance));
5645 piglit_require_GLSL();
5647 version_init(&gl_version, VERSION_GL,
5648 core, !core,
5649 piglit_is_gles(),
5650 piglit_get_gl_version());
5651 piglit_get_glsl_version(&es, &major, &minor);
5652 version_init(&glsl_version, VERSION_GLSL, core, !core, es,
5653 (major * 100) + minor);
5655 #ifdef PIGLIT_USE_OPENGL
5656 if (piglit_get_gl_version() >= 32)
5657 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
5658 &gl_max_vertex_output_components);
5659 if (piglit_get_gl_version() >= 20 ||
5660 piglit_is_extension_supported("GL_ARB_fragment_shader"))
5661 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
5662 &gl_max_fragment_uniform_components);
5663 if (piglit_get_gl_version() >= 20 ||
5664 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5665 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
5666 &gl_max_vertex_uniform_components);
5667 if (piglit_get_gl_version() >= 20 ||
5668 piglit_is_extension_supported("GL_ARB_vertex_shader") ||
5669 piglit_is_extension_supported("GL_ARB_geometry_shader4") ||
5670 piglit_is_extension_supported("GL_EXT_geometry_shader4"))
5671 glGetIntegerv(GL_MAX_VARYING_COMPONENTS,
5672 &gl_max_varying_components);
5673 #else
5674 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
5675 &gl_max_fragment_uniform_components);
5676 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
5677 &gl_max_vertex_uniform_components);
5678 glGetIntegerv(GL_MAX_VARYING_VECTORS,
5679 &gl_max_varying_components);
5680 gl_max_fragment_uniform_components *= 4;
5681 gl_max_vertex_uniform_components *= 4;
5682 gl_max_varying_components *= 4;
5683 #endif
5684 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max_clip_planes);
5686 if (gl_version.num >= 20 ||
5687 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5688 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,
5689 &gl_max_vertex_attribs);
5690 else
5691 gl_max_vertex_attribs = 16;
5693 read_width = render_width = piglit_width;
5694 read_height = render_height = piglit_height;
5696 #ifdef PIGLIT_USE_OPENGL
5697 if (piglit_is_extension_supported("GL_ARB_get_program_binary"))
5698 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
5699 &gl_num_program_binary_formats);
5700 #else
5701 if (piglit_is_extension_supported("GL_OES_get_program_binary"))
5702 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES,
5703 &gl_num_program_binary_formats);
5704 #endif
5706 if (use_get_program_binary) {
5707 if (gl_num_program_binary_formats == 0) {
5708 printf("Trying to use get_program_binary, but "
5709 "GL_NUM_PROGRAM_BINARY == 0\n");
5710 piglit_report_result(PIGLIT_SKIP);
5714 /* Run multiple tests per session. */
5715 if (argc > 2) {
5716 char testname[4096], *ext;
5717 int i, j;
5718 enum piglit_result all = PIGLIT_PASS;
5720 for (i = 1; i < argc; i++) {
5721 const char *hit, *filename = argv[i];
5723 memcpy(piglit_tolerance, default_piglit_tolerance,
5724 sizeof(piglit_tolerance));
5726 for (unsigned i = 0; i < ARRAY_SIZE(specializations); i++) {
5727 free(specializations[i].indices);
5728 free(specializations[i].values);
5730 memset(specializations, 0, sizeof(specializations));
5732 /* Re-initialize the GL context if a different GL config is required. */
5733 if (!validate_current_gl_context(filename))
5734 recreate_gl_context(argv[0], argc - i, argv + i);
5736 /* Clear global variables to defaults. */
5737 test_start = NULL;
5738 assert(num_vertex_shaders == 0);
5739 assert(num_tess_ctrl_shaders == 0);
5740 assert(num_tess_eval_shaders == 0);
5741 assert(num_geometry_shaders == 0);
5742 assert(num_fragment_shaders == 0);
5743 assert(num_compute_shaders == 0);
5744 assert(num_uniform_blocks == 0);
5745 assert(uniform_block_bos == NULL);
5746 assert(uniform_block_indexes == NULL);
5747 geometry_layout_input_type = GL_TRIANGLES;
5748 geometry_layout_output_type = GL_TRIANGLE_STRIP;
5749 geometry_layout_vertices_out = 0;
5750 memset(atomics_bos, 0, sizeof(atomics_bos));
5751 memset(ssbo, 0, sizeof(ssbo));
5752 for (j = 0; j < ARRAY_SIZE(subuniform_locations); j++)
5753 assert(subuniform_locations[j] == NULL);
5754 memset(num_subuniform_locations, 0, sizeof(num_subuniform_locations));
5755 shader_string = NULL;
5756 shader_string_size = 0;
5757 vertex_data_start = NULL;
5758 vertex_data_end = NULL;
5759 prog = 0;
5760 sso_vertex_prog = 0;
5761 sso_tess_control_prog = 0;
5762 sso_tess_eval_prog = 0;
5763 sso_geometry_prog = 0;
5764 sso_fragment_prog = 0;
5765 sso_compute_prog = 0;
5766 num_vbo_rows = 0;
5767 vbo_present = false;
5768 link_ok = false;
5769 prog_in_use = false;
5770 sso_in_use = false;
5771 separable_program = false;
5772 prog_err_info = NULL;
5773 vao = 0;
5775 /* Clear GL states to defaults. */
5776 glClearColor(0, 0, 0, 0);
5777 # if PIGLIT_USE_OPENGL
5778 glClearDepth(1);
5779 # else
5780 glClearDepthf(1.0);
5781 # endif
5782 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
5783 glActiveTexture(GL_TEXTURE0);
5784 glUseProgram(0);
5785 glDisable(GL_DEPTH_TEST);
5786 glBindBuffer(GL_ARRAY_BUFFER, 0);
5787 if (!es)
5788 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
5790 for (int k = 0; k < gl_max_clip_planes; k++) {
5791 static const GLdouble zero[4];
5793 if (!piglit_is_core_profile && !es)
5794 glClipPlane(GL_CLIP_PLANE0 + k, zero);
5795 glDisable(GL_CLIP_PLANE0 + k);
5798 if (!(es) && (gl_version.num >= 20 ||
5799 piglit_is_extension_supported("GL_ARB_vertex_program")))
5800 glDisable(GL_PROGRAM_POINT_SIZE);
5802 for (int i = 0; i < 16; i++)
5803 glDisableVertexAttribArray(i);
5805 if (!piglit_is_core_profile && !es) {
5806 glMatrixMode(GL_PROJECTION);
5807 glLoadIdentity();
5808 glMatrixMode(GL_MODELVIEW);
5809 glLoadIdentity();
5810 glShadeModel(GL_SMOOTH);
5811 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
5814 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
5815 glDisable(GL_VERTEX_PROGRAM_ARB);
5816 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0);
5818 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
5819 glDisable(GL_FRAGMENT_PROGRAM_ARB);
5820 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
5822 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
5823 if (!pipeline)
5824 glGenProgramPipelines(1, &pipeline);
5825 glBindProgramPipeline(0);
5828 if (piglit_is_extension_supported("GL_EXT_provoking_vertex"))
5829 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
5831 # if PIGLIT_USE_OPENGL
5832 if (gl_version.num >= 40 ||
5833 piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
5834 static float ones[] = {1, 1, 1, 1};
5835 glPatchParameteri(GL_PATCH_VERTICES, 3);
5836 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, ones);
5837 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, ones);
5839 # else
5840 /* Ideally one would use the following code:
5842 * if (gl_version.num >= 32) {
5843 * glPatchParameteri(GL_PATCH_VERTICES, 3);
5846 * however, that doesn't work with mesa because those
5847 * symbols apparently need to be exported, but that
5848 * breaks non-gles builds.
5850 * It seems rather unlikely that an implementation
5851 * would have GLES 3.2 support but not
5852 * OES_tessellation_shader.
5854 if (piglit_is_extension_supported("GL_OES_tessellation_shader")) {
5855 glPatchParameteriOES(GL_PATCH_VERTICES_OES, 3);
5857 # endif
5859 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5861 /* Strip the file path. */
5862 hit = strrchr(filename, PIGLIT_PATH_SEP);
5863 if (hit)
5864 strcpy(testname, hit+1);
5865 else
5866 strcpy(testname, filename);
5868 /* Strip the file extension. */
5869 ext = strstr(testname, ".shader_test");
5870 if (ext && !ext[12])
5871 *ext = 0;
5873 /* Print the name before we start the test, that way if
5874 * the test fails we can still resume and know which
5875 * test failed */
5876 printf("PIGLIT TEST: %i - %s\n", test_num, testname);
5877 fprintf(stderr, "PIGLIT TEST: %i - %s\n", test_num, testname);
5878 test_num++;
5880 /* Run the test. */
5881 result = init_test(filename);
5883 if (result == PIGLIT_PASS) {
5884 result = piglit_display();
5886 /* Use subtest when running with more than one test,
5887 * but use regular test result when running with just
5888 * one. This allows the standard process-at-a-time
5889 * mode to keep working.
5891 if (report_subtests) {
5892 piglit_report_subtest_result(
5893 result, "%s", testname);
5894 } else {
5895 piglit_merge_result(&all, result);
5898 /* destroy GL objects? */
5899 teardown_ubos();
5900 teardown_atomics();
5901 teardown_fbos();
5902 teardown_shader_include_paths();
5903 teardown_xfb();
5905 if (!report_subtests)
5906 piglit_report_result(all);
5907 exit(0);
5910 result = init_test(argv[1]);
5911 if (result != PIGLIT_PASS)
5912 piglit_report_result(result);