cl: Don't use device_infos if num_device_infos == 0
[piglit.git] / tests / shaders / shader_runner.c
blobf5772779742c7ba5d96a03c1db7879f817f01477
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 <ctype.h>
25 #include <inttypes.h>
26 #include <stdbool.h>
27 #include <string.h>
29 #include "piglit-util.h"
30 #include "piglit-util-gl.h"
31 #include "piglit-vbo.h"
32 #include "piglit-framework-gl/piglit_gl_framework.h"
33 #include "piglit-subprocess.h"
35 #include "shader_runner_gles_workarounds.h"
36 #include "parser_utils.h"
38 #include "shader_runner_vs_passthrough_spv.h"
40 #define DEFAULT_WINDOW_WIDTH 250
41 #define DEFAULT_WINDOW_HEIGHT 250
43 static bool spirv_replaces_glsl = false;
44 static struct piglit_gl_test_config current_config;
46 static void
47 get_required_config(const char *script_name, bool spirv,
48 struct piglit_gl_test_config *config);
49 static GLenum
50 decode_drawing_mode(const char *mode_str);
52 PIGLIT_GL_TEST_CONFIG_BEGIN
54 if (!piglit_gl_test_config_override_size(&config)) {
55 config.window_width = DEFAULT_WINDOW_WIDTH;
56 config.window_height = DEFAULT_WINDOW_HEIGHT;
58 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
59 config.khr_no_error_support = PIGLIT_NO_ERRORS;
61 /* By default SPIR-V mode is false. It will not be enabled
62 * unless the script includes SPIRV YES or SPIRV ONLY lines at
63 * [require] section, so it will be handled later.
65 if (argc > 1) {
66 get_required_config(argv[1], spirv_replaces_glsl, &config);
67 } else {
68 config.supports_gl_compat_version = 10;
71 current_config = config;
73 PIGLIT_GL_TEST_CONFIG_END
75 static const char passthrough_vertex_shader_source[] =
76 "#if __VERSION__ >= 130\n"
77 "in vec4 piglit_vertex;\n"
78 "#else\n"
79 "attribute vec4 piglit_vertex;\n"
80 "#endif\n"
81 "void main() { gl_Position = piglit_vertex; }\n"
84 struct component_version {
85 enum version_tag {
86 VERSION_GL,
87 VERSION_GLSL,
88 } _tag;
90 bool core;
91 bool compat;
92 bool es;
93 unsigned num;
94 char _string[100];
97 struct block_info {
98 int array_index;
99 int binding;
100 int offset;
101 int matrix_stride;
102 int row_major; /* int as we don't have a parse_bool */
105 #define ENUM_STRING(e) { #e, e }
107 extern float piglit_tolerance[4];
109 static int test_num = 1;
110 static struct component_version gl_version;
111 static struct component_version glsl_version;
112 static struct component_version glsl_req_version;
113 static int gl_max_vertex_output_components;
114 static int gl_max_fragment_uniform_components;
115 static int gl_max_vertex_uniform_components;
116 static int gl_max_vertex_attribs;
117 static int gl_max_varying_components;
118 static int gl_max_clip_planes;
119 static int gl_num_program_binary_formats = 0;
121 static const char *test_start = NULL;
122 static unsigned test_start_line_num = 0;
124 static GLuint vertex_shaders[256];
125 static unsigned num_vertex_shaders = 0;
126 static GLuint tess_ctrl_shaders[256];
127 static unsigned num_tess_ctrl_shaders = 0;
128 static GLuint tess_eval_shaders[256];
129 static unsigned num_tess_eval_shaders = 0;
130 static GLuint geometry_shaders[256];
131 static unsigned num_geometry_shaders = 0;
132 static GLuint fragment_shaders[256];
133 static unsigned num_fragment_shaders = 0;
134 static GLuint compute_shaders[256];
135 static unsigned num_compute_shaders = 0;
136 static int num_uniform_blocks;
137 static GLuint *uniform_block_bos;
138 static int *uniform_block_indexes; /* ubo block index, indexed by ubo binding */
139 static GLenum geometry_layout_input_type = GL_TRIANGLES;
140 static GLenum geometry_layout_output_type = GL_TRIANGLE_STRIP;
141 static GLint geometry_layout_vertices_out = 0;
142 static GLuint atomics_bos[8];
143 static GLuint ssbo[32];
144 static unsigned num_shader_include_paths = 0;
145 static char **shader_include_path;
146 static char *shader_include_names[256];
147 static unsigned num_shader_includes = 0;
149 #define MAX_XFB_BUFFERS 4 /* Same value used at nir_xfb_info */
150 static GLuint xfb[MAX_XFB_BUFFERS];
152 #define MAX_QUERIES 2
153 static GLuint queries[MAX_QUERIES];
155 #define SHADER_TYPES 6
156 static GLuint *subuniform_locations[SHADER_TYPES];
157 static int num_subuniform_locations[SHADER_TYPES];
158 static char *shader_string;
159 static GLint shader_string_size;
160 static const char *vertex_data_start = NULL;
161 static const char *vertex_data_end = NULL;
162 static GLuint prog;
163 static GLuint sso_vertex_prog;
164 static GLuint sso_tess_control_prog;
165 static GLuint sso_tess_eval_prog;
166 static GLuint sso_geometry_prog;
167 static GLuint sso_fragment_prog;
168 static GLuint sso_compute_prog;
169 static GLuint pipeline = 0;
170 static size_t num_vbo_rows = 0;
171 static bool vbo_present = false;
172 static bool link_ok = false;
173 static bool prog_in_use = false;
174 static bool sso_in_use = false;
175 static bool separable_program = false;
176 static bool glsl_in_use = false;
177 static bool force_glsl = false;
178 static bool spirv_in_use = false;
179 static bool force_no_names = false;
180 static GLchar *prog_err_info = NULL;
181 static GLuint vao = 0;
182 static GLuint draw_fbo, read_fbo;
183 static GLint render_width, render_height;
184 static GLint read_width, read_height;
186 static bool use_get_program_binary = false;
188 static bool ignore_missing_uniforms = false;
190 static bool report_subtests = false;
192 struct specialization_list {
193 size_t buffer_size;
194 size_t n_entries;
195 GLuint *indices;
196 union { GLuint u; GLfloat f; } *values;
199 static struct specialization_list
200 specializations[SHADER_TYPES];
202 static struct texture_binding {
203 GLuint obj;
204 unsigned width;
205 unsigned height;
206 unsigned layers;
207 } texture_bindings[32];
209 static struct resident_handle {
210 GLuint64 handle;
211 bool is_tex;
212 } resident_handles[32];
214 static void
215 clear_texture_binding(unsigned idx)
217 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
218 "Invalid texture index %d\n", idx);
220 if (texture_bindings[idx].obj) {
221 glDeleteTextures(1, &texture_bindings[idx].obj);
222 texture_bindings[idx].obj = 0;
226 static void
227 set_texture_binding(unsigned idx, GLuint obj, unsigned w, unsigned h, unsigned l)
229 clear_texture_binding(idx);
231 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
232 "Invalid texture index %d\n", idx);
233 texture_bindings[idx].obj = obj;
234 texture_bindings[idx].width = w;
235 texture_bindings[idx].height = h;
236 texture_bindings[idx].layers = l;
239 static const struct texture_binding *
240 get_texture_binding(unsigned idx)
242 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
243 "Invalid texture index %d\n", idx);
244 REQUIRE(texture_bindings[idx].obj,
245 "No texture bound at %d\n", idx);
246 return &texture_bindings[idx];
249 static void
250 clear_resident_handle(unsigned idx)
252 REQUIRE(idx < ARRAY_SIZE(resident_handles),
253 "Invalid resident handle index %d\n", idx);
255 if (resident_handles[idx].handle) {
256 GLuint64 handle = resident_handles[idx].handle;
257 if (resident_handles[idx].is_tex) {
258 if (glIsTextureHandleResidentARB(handle))
259 glMakeTextureHandleNonResidentARB(handle);
260 } else {
261 if (glIsImageHandleResidentARB(handle))
262 glMakeImageHandleNonResidentARB(handle);
264 resident_handles[idx].handle = 0;
268 static void
269 set_resident_handle(unsigned idx, GLuint64 handle, bool is_tex)
271 clear_resident_handle(idx);
273 REQUIRE(idx < ARRAY_SIZE(resident_handles),
274 "Invalid resident handle index %d\n", idx);
275 resident_handles[idx].handle = handle;
276 resident_handles[idx].is_tex = is_tex;
279 static const struct resident_handle *
280 get_resident_handle(unsigned idx)
282 REQUIRE(idx < ARRAY_SIZE(resident_handles),
283 "Invalid resident handle index %d\n", idx);
284 REQUIRE(resident_handles[idx].handle,
285 "No resident handle at %d\n", idx);
286 return &resident_handles[idx];
289 enum states {
290 none = 0,
291 requirements,
292 vertex_shader,
293 vertex_shader_passthrough,
294 vertex_shader_spirv,
295 vertex_shader_specializations,
296 vertex_program,
297 tess_ctrl_shader,
298 tess_ctrl_shader_spirv,
299 tess_ctrl_shader_specializations,
300 tess_eval_shader,
301 tess_eval_shader_spirv,
302 tess_eval_shader_specializations,
303 geometry_shader,
304 geometry_shader_spirv,
305 geometry_shader_specializations,
306 geometry_layout,
307 fragment_shader,
308 fragment_shader_spirv,
309 fragment_shader_specializations,
310 fragment_program,
311 compute_shader,
312 compute_shader_spirv,
313 compute_shader_specializations,
314 vertex_data,
315 shader_include,
316 shader_include_paths,
317 test,
320 static const struct string_to_enum all_types[] = {
321 ENUM_STRING(GL_FLOAT),
322 ENUM_STRING(GL_FLOAT_VEC2),
323 ENUM_STRING(GL_FLOAT_VEC3),
324 ENUM_STRING(GL_FLOAT_VEC4),
325 ENUM_STRING(GL_DOUBLE),
326 ENUM_STRING(GL_DOUBLE_VEC2),
327 ENUM_STRING(GL_DOUBLE_VEC3),
328 ENUM_STRING(GL_DOUBLE_VEC4),
329 ENUM_STRING(GL_INT),
330 ENUM_STRING(GL_INT_VEC2),
331 ENUM_STRING(GL_INT_VEC3),
332 ENUM_STRING(GL_INT_VEC4),
333 ENUM_STRING(GL_UNSIGNED_INT),
334 ENUM_STRING(GL_UNSIGNED_INT_VEC2),
335 ENUM_STRING(GL_UNSIGNED_INT_VEC3),
336 ENUM_STRING(GL_UNSIGNED_INT_VEC4),
337 ENUM_STRING(GL_INT64_ARB),
338 ENUM_STRING(GL_INT64_VEC2_ARB),
339 ENUM_STRING(GL_INT64_VEC3_ARB),
340 ENUM_STRING(GL_INT64_VEC4_ARB),
341 ENUM_STRING(GL_UNSIGNED_INT64_ARB),
342 ENUM_STRING(GL_UNSIGNED_INT64_VEC2_ARB),
343 ENUM_STRING(GL_UNSIGNED_INT64_VEC3_ARB),
344 ENUM_STRING(GL_UNSIGNED_INT64_VEC4_ARB),
345 ENUM_STRING(GL_BOOL),
346 ENUM_STRING(GL_BOOL_VEC2),
347 ENUM_STRING(GL_BOOL_VEC3),
348 ENUM_STRING(GL_BOOL_VEC4),
349 ENUM_STRING(GL_FLOAT_MAT2),
350 ENUM_STRING(GL_FLOAT_MAT3),
351 ENUM_STRING(GL_FLOAT_MAT4),
352 ENUM_STRING(GL_FLOAT_MAT2x3),
353 ENUM_STRING(GL_FLOAT_MAT2x4),
354 ENUM_STRING(GL_FLOAT_MAT3x2),
355 ENUM_STRING(GL_FLOAT_MAT3x4),
356 ENUM_STRING(GL_FLOAT_MAT4x2),
357 ENUM_STRING(GL_FLOAT_MAT4x3),
358 ENUM_STRING(GL_DOUBLE_MAT2),
359 ENUM_STRING(GL_DOUBLE_MAT3),
360 ENUM_STRING(GL_DOUBLE_MAT4),
361 ENUM_STRING(GL_DOUBLE_MAT2x3),
362 ENUM_STRING(GL_DOUBLE_MAT2x4),
363 ENUM_STRING(GL_DOUBLE_MAT3x2),
364 ENUM_STRING(GL_DOUBLE_MAT3x4),
365 ENUM_STRING(GL_DOUBLE_MAT4x2),
366 ENUM_STRING(GL_DOUBLE_MAT4x3),
367 ENUM_STRING(GL_SAMPLER_1D),
368 ENUM_STRING(GL_SAMPLER_2D),
369 ENUM_STRING(GL_SAMPLER_3D),
370 ENUM_STRING(GL_SAMPLER_CUBE),
371 ENUM_STRING(GL_SAMPLER_1D_SHADOW),
372 ENUM_STRING(GL_SAMPLER_2D_SHADOW),
373 ENUM_STRING(GL_SAMPLER_1D_ARRAY),
374 ENUM_STRING(GL_SAMPLER_2D_ARRAY),
375 ENUM_STRING(GL_SAMPLER_1D_ARRAY_SHADOW),
376 ENUM_STRING(GL_SAMPLER_2D_ARRAY_SHADOW),
377 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE),
378 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE_ARRAY),
379 ENUM_STRING(GL_SAMPLER_CUBE_SHADOW),
380 ENUM_STRING(GL_SAMPLER_BUFFER),
381 ENUM_STRING(GL_SAMPLER_2D_RECT),
382 ENUM_STRING(GL_SAMPLER_2D_RECT_SHADOW),
383 ENUM_STRING(GL_INT_SAMPLER_1D),
384 ENUM_STRING(GL_INT_SAMPLER_2D),
385 ENUM_STRING(GL_INT_SAMPLER_3D),
386 ENUM_STRING(GL_INT_SAMPLER_CUBE),
387 ENUM_STRING(GL_INT_SAMPLER_1D_ARRAY),
388 ENUM_STRING(GL_INT_SAMPLER_2D_ARRAY),
389 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE),
390 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
391 ENUM_STRING(GL_INT_SAMPLER_BUFFER),
392 ENUM_STRING(GL_INT_SAMPLER_2D_RECT),
393 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D),
394 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D),
395 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_3D),
396 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_CUBE),
397 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY),
398 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY),
399 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE),
400 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
401 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_BUFFER),
402 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_RECT),
403 { NULL, 0 }
406 static bool
407 compare(float ref, float value, enum comparison cmp);
409 static bool
410 compare_uint(GLuint ref, GLuint value, enum comparison cmp);
412 static bool
413 compare_int(GLint ref, GLint value, enum comparison cmp);
415 static void
416 version_init(struct component_version *v, enum version_tag tag, bool core, bool compat, bool es, unsigned num)
418 assert(tag == VERSION_GL || tag == VERSION_GLSL);
420 v->_tag = tag;
421 v->core = core;
422 v->compat = compat;
423 v->es = es;
424 v->num = num;
425 v->_string[0] = 0;
428 static void
429 version_copy(struct component_version *dest, struct component_version *src)
431 memcpy(dest, src, sizeof(*dest));
434 static bool
435 version_compare(struct component_version *a, struct component_version *b, enum comparison cmp)
437 assert(a->_tag == b->_tag);
439 if (a->es != b->es)
440 return false;
442 return compare(a->num, b->num, cmp);
446 * Get the version string.
448 static const char*
449 version_string(struct component_version *v)
451 if (v->_string[0])
452 return v->_string;
454 switch (v->_tag) {
455 case VERSION_GL:
456 snprintf(v->_string, sizeof(v->_string) - 1, "GL%s %d.%d",
457 v->es ? " ES" : "",
458 v->num / 10, v->num % 10);
459 break;
460 case VERSION_GLSL:
461 snprintf(v->_string, sizeof(v->_string) - 1, "GLSL%s %d.%d",
462 v->es ? " ES" : "",
463 v->num / 100, v->num % 100);
464 break;
465 default:
466 assert(false);
467 break;
470 return v->_string;
474 static const char *
475 target_to_short_name(GLenum target)
477 switch (target) {
478 case GL_VERTEX_SHADER:
479 return "VS";
480 case GL_FRAGMENT_SHADER:
481 return "FS";
482 case GL_TESS_CONTROL_SHADER:
483 return "TCS";
484 case GL_TESS_EVALUATION_SHADER:
485 return "TES";
486 case GL_GEOMETRY_SHADER:
487 return "GS";
488 case GL_COMPUTE_SHADER:
489 return "CS";
490 default:
491 return "???";
496 static enum piglit_result
497 compile_glsl(GLenum target)
499 GLuint shader = glCreateShader(target);
500 GLint ok;
502 if (spirv_in_use) {
503 printf("Cannot mix SPIRV and non-SPIRV shaders\n");
504 return PIGLIT_FAIL;
507 glsl_in_use = true;
509 switch (target) {
510 case GL_VERTEX_SHADER:
511 if (piglit_get_gl_version() < 20 &&
512 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
513 piglit_is_extension_supported("GL_ARB_vertex_shader")))
514 return PIGLIT_SKIP;
515 break;
516 case GL_FRAGMENT_SHADER:
517 if (piglit_get_gl_version() < 20 &&
518 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
519 piglit_is_extension_supported("GL_ARB_fragment_shader")))
520 return PIGLIT_SKIP;
521 break;
522 case GL_TESS_CONTROL_SHADER:
523 case GL_TESS_EVALUATION_SHADER:
524 if (gl_version.num < (gl_version.es ? 32 : 40))
525 if (!piglit_is_extension_supported(gl_version.es ?
526 "GL_OES_tessellation_shader" :
527 "GL_ARB_tessellation_shader"))
528 return PIGLIT_SKIP;
529 break;
530 case GL_GEOMETRY_SHADER:
531 if (gl_version.num < 32)
532 if (!piglit_is_extension_supported(gl_version.es ?
533 "GL_OES_geometry_shader" :
534 "GL_ARB_geometry_shader4"))
535 return PIGLIT_SKIP;
536 break;
537 case GL_COMPUTE_SHADER:
538 if (gl_version.num < (gl_version.es ? 31 : 43))
539 if (!piglit_is_extension_supported("GL_ARB_compute_shader"))
540 return PIGLIT_SKIP;
541 break;
544 if (!glsl_req_version.num) {
545 printf("GLSL version requirement missing\n");
546 return PIGLIT_FAIL;
549 if (!strstr(shader_string, "#version ")) {
550 char *shader_strings[2];
551 char version_string[100];
552 GLint shader_string_sizes[2];
554 /* Add a #version directive based on the GLSL requirement. */
555 sprintf(version_string, "#version %d", glsl_req_version.num);
556 if (glsl_req_version.es && glsl_req_version.num != 100) {
557 strcat(version_string, " es");
559 strcat(version_string, "\n");
560 shader_strings[0] = version_string;
561 shader_string_sizes[0] = strlen(version_string);
562 shader_strings[1] = shader_string;
563 shader_string_sizes[1] = shader_string_size;
565 glShaderSource(shader, 2,
566 (const GLchar **) shader_strings,
567 shader_string_sizes);
569 } else {
570 glShaderSource(shader, 1,
571 (const GLchar **) &shader_string,
572 &shader_string_size);
575 if (num_shader_include_paths) {
576 glCompileShaderIncludeARB(shader, num_shader_include_paths,
577 (const char **) shader_include_path, NULL);
578 } else
579 glCompileShader(shader);
581 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
583 if (!ok) {
584 GLchar *info;
585 GLint size;
587 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
588 info = malloc(size);
590 glGetShaderInfoLog(shader, size, NULL, info);
592 fprintf(stderr, "Failed to compile %s: %s\n",
593 target_to_short_name(target),
594 info);
596 free(info);
597 return PIGLIT_FAIL;
600 switch (target) {
601 case GL_VERTEX_SHADER:
602 vertex_shaders[num_vertex_shaders] = shader;
603 num_vertex_shaders++;
604 break;
605 case GL_TESS_CONTROL_SHADER:
606 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
607 num_tess_ctrl_shaders++;
608 break;
609 case GL_TESS_EVALUATION_SHADER:
610 tess_eval_shaders[num_tess_eval_shaders] = shader;
611 num_tess_eval_shaders++;
612 break;
613 case GL_GEOMETRY_SHADER:
614 geometry_shaders[num_geometry_shaders] = shader;
615 num_geometry_shaders++;
616 break;
617 case GL_FRAGMENT_SHADER:
618 fragment_shaders[num_fragment_shaders] = shader;
619 num_fragment_shaders++;
620 break;
621 case GL_COMPUTE_SHADER:
622 compute_shaders[num_compute_shaders] = shader;
623 num_compute_shaders++;
624 break;
626 return PIGLIT_PASS;
630 static enum piglit_result
631 compile_and_bind_program(GLenum target, const char *start, int len)
633 GLuint prog;
634 char *source;
636 switch (target) {
637 case GL_VERTEX_PROGRAM_ARB:
638 if (!piglit_is_extension_supported("GL_ARB_vertex_program"))
639 return PIGLIT_SKIP;
640 break;
641 case GL_FRAGMENT_PROGRAM_ARB:
642 if (!piglit_is_extension_supported("GL_ARB_fragment_program"))
643 return PIGLIT_SKIP;
644 break;
647 source = malloc(len + 1);
648 memcpy(source, start, len);
649 source[len] = 0;
650 prog = piglit_compile_program(target, source);
652 glEnable(target);
653 glBindProgramARB(target, prog);
654 link_ok = true;
655 prog_in_use = true;
657 return PIGLIT_PASS;
660 static bool
661 program_binary_save_restore(bool script_command)
663 GLint binary_length;
664 void *binary;
665 GLenum binary_format;
666 GLint ok;
667 GLuint new_prog;
669 if (!script_command && !use_get_program_binary)
670 return true;
672 if (script_command && gl_num_program_binary_formats == 0)
673 piglit_report_result(PIGLIT_SKIP);
675 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
676 if (!ok) {
677 if (script_command) {
678 fprintf(stderr, "Can't save/restore program that is "
679 "not linked!\n");
680 piglit_report_result(PIGLIT_FAIL);
681 } else {
682 return true;
686 #ifdef PIGLIT_USE_OPENGL
687 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &binary_length);
688 #else
689 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH_OES, &binary_length);
690 #endif
691 if (!piglit_check_gl_error(GL_NO_ERROR)) {
692 fprintf(stderr, "glGetProgramiv GL_PROGRAM_BINARY_LENGTH "
693 "error\n");
694 piglit_report_result(PIGLIT_FAIL);
697 binary = malloc(binary_length);
698 if (!binary) {
699 fprintf(stderr, "Failed to allocate buffer for "
700 "GetProgramBinary\n");
701 piglit_report_result(PIGLIT_FAIL);
704 #ifdef PIGLIT_USE_OPENGL
705 glGetProgramBinary(prog, binary_length, &binary_length, &binary_format,
706 binary);
707 #else
708 glGetProgramBinaryOES(prog, binary_length, &binary_length,
709 &binary_format, binary);
710 #endif
711 if (!piglit_check_gl_error(GL_NO_ERROR)) {
712 fprintf(stderr, "glGetProgramBinary error\n");
713 free(binary);
714 piglit_report_result(PIGLIT_FAIL);
717 new_prog = glCreateProgram();
718 if (!piglit_check_gl_error(GL_NO_ERROR)) {
719 free(binary);
720 piglit_report_result(PIGLIT_FAIL);
723 #ifdef PIGLIT_USE_OPENGL
724 glProgramBinary(new_prog, binary_format, binary, binary_length);
725 #else
726 glProgramBinaryOES(new_prog, binary_format, binary, binary_length);
727 #endif
728 free(binary);
729 if (!piglit_check_gl_error(GL_NO_ERROR)) {
730 fprintf(stderr, "glProgramBinary error "
731 "(should not happen according to spec.)\n");
732 piglit_report_result(PIGLIT_FAIL);
735 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
736 if (!ok) {
737 fprintf(stderr, "link failure after glProgramBinary\n");
738 piglit_report_result(PIGLIT_FAIL);
741 if (prog_in_use) {
742 glUseProgram(new_prog);
743 if (!piglit_check_gl_error(GL_NO_ERROR))
744 piglit_report_result(PIGLIT_FAIL);
747 glDeleteProgram(prog);
748 if (!piglit_check_gl_error(GL_NO_ERROR))
749 piglit_report_result(PIGLIT_FAIL);
750 prog = new_prog;
752 return true;
755 static enum piglit_result
756 specialize_spirv(GLenum target,
757 GLuint shader)
759 if (glsl_in_use) {
760 printf("Cannot mix SPIR-V and non-SPIR-V shaders\n");
761 return PIGLIT_FAIL;
764 spirv_in_use = true;
766 const struct specialization_list *specs;
768 switch (target) {
769 case GL_VERTEX_SHADER:
770 specs = specializations + 0;
771 break;
772 case GL_TESS_CONTROL_SHADER:
773 specs = specializations + 1;
774 break;
775 case GL_TESS_EVALUATION_SHADER:
776 specs = specializations + 2;
777 break;
778 case GL_GEOMETRY_SHADER:
779 specs = specializations + 3;
780 break;
781 case GL_FRAGMENT_SHADER:
782 specs = specializations + 4;
783 break;
784 case GL_COMPUTE_SHADER:
785 specs = specializations + 5;
786 break;
787 default:
788 assert(!"Should not get here.");
791 glSpecializeShaderARB(shader,
792 "main",
793 specs->n_entries,
794 specs->indices,
795 &specs->values[0].u);
797 GLint ok;
798 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
800 if (!ok) {
801 GLchar *info;
802 GLint size;
804 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
805 info = malloc(MAX2(size, 1));
806 info[0] = 0;
808 glGetShaderInfoLog(shader, size, NULL, info);
810 printf("Failed to specialize %s: %s\n",
811 target_to_short_name(target), info);
813 free(info);
814 return PIGLIT_FAIL;
817 switch (target) {
818 case GL_VERTEX_SHADER:
819 vertex_shaders[num_vertex_shaders] = shader;
820 num_vertex_shaders++;
821 break;
822 case GL_TESS_CONTROL_SHADER:
823 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
824 num_tess_ctrl_shaders++;
825 break;
826 case GL_TESS_EVALUATION_SHADER:
827 tess_eval_shaders[num_tess_eval_shaders] = shader;
828 num_tess_eval_shaders++;
829 break;
830 case GL_GEOMETRY_SHADER:
831 geometry_shaders[num_geometry_shaders] = shader;
832 num_geometry_shaders++;
833 break;
834 case GL_FRAGMENT_SHADER:
835 fragment_shaders[num_fragment_shaders] = shader;
836 num_fragment_shaders++;
837 break;
838 case GL_COMPUTE_SHADER:
839 compute_shaders[num_compute_shaders] = shader;
840 num_compute_shaders++;
841 break;
844 return PIGLIT_PASS;
847 static enum piglit_result
848 assemble_spirv(GLenum target)
850 if (!piglit_is_extension_supported("GL_ARB_gl_spirv")) {
851 return PIGLIT_SKIP;
854 /* Strip comments from the source */
855 char *stripped_source = malloc(shader_string_size);
856 char *p = stripped_source;
857 bool at_start_of_line = true;
859 for (const char *in = shader_string;
860 in < shader_string + shader_string_size;
861 in++) {
862 if (*in == '#' && at_start_of_line) {
863 const char *end;
864 end = memchr(in,
865 '\n',
866 shader_string + shader_string_size - in);
867 if (end == NULL)
868 break;
869 in = end;
870 } else {
871 at_start_of_line = *in == '\n';
872 *(p++) = *in;
876 GLuint shader = piglit_assemble_spirv(target,
877 p - stripped_source,
878 stripped_source);
880 free(stripped_source);
882 return specialize_spirv(target, shader);
885 static enum piglit_result
886 link_sso(GLenum target)
888 GLint ok;
890 glLinkProgram(prog);
892 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
893 if (ok) {
894 link_ok = true;
895 } else {
896 GLint size;
898 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
899 prog_err_info = malloc(MAX2(size, 1));
900 prog_err_info[0] = 0;
902 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
904 fprintf(stderr, "SSO glLinkProgram(%s) failed: %s\n",
905 target_to_short_name(target),
906 prog_err_info);
908 free(prog_err_info);
909 return PIGLIT_FAIL;
912 if (!program_binary_save_restore(false))
913 return PIGLIT_FAIL;
915 switch (target) {
916 case GL_VERTEX_SHADER:
917 sso_vertex_prog = prog;
918 glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, prog);
919 break;
920 case GL_TESS_CONTROL_SHADER:
921 sso_tess_control_prog = prog;
922 glUseProgramStages(pipeline, GL_TESS_CONTROL_SHADER_BIT, prog);
923 break;
924 case GL_TESS_EVALUATION_SHADER:
925 sso_tess_eval_prog = prog;
926 glUseProgramStages(pipeline, GL_TESS_EVALUATION_SHADER_BIT, prog);
927 break;
928 case GL_GEOMETRY_SHADER:
929 sso_geometry_prog = prog;
930 glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, prog);
931 break;
932 case GL_FRAGMENT_SHADER:
933 sso_fragment_prog = prog;
934 glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, prog);
935 break;
936 case GL_COMPUTE_SHADER:
937 sso_compute_prog = prog;
938 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, prog);
939 break;
941 return PIGLIT_PASS;
945 * Compare two values given a specified comparison operator
947 static bool
948 compare(float ref, float value, enum comparison cmp)
950 switch (cmp) {
951 case equal: return value == ref;
952 case not_equal: return value != ref;
953 case less: return value < ref;
954 case greater_equal: return value >= ref;
955 case greater: return value > ref;
956 case less_equal: return value <= ref;
959 assert(!"Should not get here.");
960 return false;
963 static bool
964 compare_double(double ref, double value, enum comparison cmp)
966 switch (cmp) {
967 case equal: return fabs(value - ref) < DBL_EPSILON;
968 case not_equal: return fabs(value - ref) >= DBL_EPSILON;
969 case less: return value < ref;
970 case greater_equal: return value >= ref;
971 case greater: return value > ref;
972 case less_equal: return value <= ref;
975 assert(!"Should not get here.");
976 return false;
979 static bool
980 compare_uint(GLuint ref, GLuint value, enum comparison cmp)
982 switch (cmp) {
983 case equal: return value == ref;
984 case not_equal: return value != ref;
985 case less: return value < ref;
986 case greater_equal: return value >= ref;
987 case greater: return value > ref;
988 case less_equal: return value <= ref;
991 assert(!"Should not get here.");
992 return false;
995 static bool
996 compare_int(GLint ref, GLint value, enum comparison cmp)
998 switch (cmp) {
999 case equal: return value == ref;
1000 case not_equal: return value != ref;
1001 case less: return value < ref;
1002 case greater_equal: return value >= ref;
1003 case greater: return value > ref;
1004 case less_equal: return value <= ref;
1007 assert(!"Should not get here.");
1008 return false;
1011 static bool
1012 compare_uint64(GLuint64 ref, GLuint64 value, enum comparison cmp)
1014 switch (cmp) {
1015 case equal: return value == ref;
1016 case not_equal: return value != ref;
1017 case less: return value < ref;
1018 case greater_equal: return value >= ref;
1019 case greater: return value > ref;
1020 case less_equal: return value <= ref;
1023 assert(!"Should not get here.");
1024 return false;
1027 static bool
1028 compare_int64(GLint64 ref, GLint64 value, enum comparison cmp)
1030 switch (cmp) {
1031 case equal: return value == ref;
1032 case not_equal: return value != ref;
1033 case less: return value < ref;
1034 case greater_equal: return value >= ref;
1035 case greater: return value > ref;
1036 case less_equal: return value <= ref;
1039 assert(!"Should not get here.");
1040 return false;
1044 * Get the string representation of a comparison operator
1046 static const char *
1047 comparison_string(enum comparison cmp)
1049 switch (cmp) {
1050 case equal: return "==";
1051 case not_equal: return "!=";
1052 case less: return "<";
1053 case greater_equal: return ">=";
1054 case greater: return ">";
1055 case less_equal: return "<=";
1058 assert(!"Should not get here.");
1059 return false;
1063 * " ES" before the comparison operator indicates the version
1064 * pertains to GL ES.
1066 static void
1067 parse_version_comparison(const char *line, enum comparison *cmp,
1068 struct component_version *v, enum version_tag tag)
1070 unsigned major;
1071 unsigned minor;
1072 unsigned full_num;
1073 const bool core = parse_str(line, "CORE", &line);
1074 const bool compat = parse_str(line, "COMPAT", &line);
1075 const bool es = parse_str(line, "ES", &line);
1077 REQUIRE(parse_comparison_op(line, cmp, &line),
1078 "Invalid comparison operation at: %s\n", line);
1080 REQUIRE(parse_uint(line, &major, &line) &&
1081 parse_str(line, ".", &line) &&
1082 parse_uint(line, &minor, &line),
1083 "Invalid version string: %s\n", line);
1085 parse_whitespace(line, &line);
1086 if (*line != '\n') {
1087 printf("Unexpected characters following version comparison\n");
1088 piglit_report_result(PIGLIT_FAIL);
1091 /* This hack is so that we can tell the difference between GL versions
1092 * and GLSL versions. All GL versions look like 3.2, and we want the
1093 * integer to be 32. All GLSL versions look like 1.40, and we want
1094 * the integer to be 140.
1096 if (tag == VERSION_GLSL) {
1097 full_num = (major * 100) + minor;
1098 } else {
1099 full_num = (major * 10) + minor;
1102 version_init(v, tag, core, compat, es, full_num);
1106 * Parse and check a line from the requirement section of the test
1108 static enum piglit_result
1109 process_requirement(const char *line)
1111 char buffer[4096];
1112 static const struct {
1113 const char *name;
1114 int *val;
1115 const char *desc;
1116 } getint_limits[] = {
1118 "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
1119 &gl_max_vertex_output_components,
1120 "vertex output components",
1123 "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
1124 &gl_max_fragment_uniform_components,
1125 "fragment uniform components",
1128 "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
1129 &gl_max_vertex_uniform_components,
1130 "vertex uniform components",
1133 "GL_MAX_VERTEX_ATTRIBS",
1134 &gl_max_vertex_attribs,
1135 "vertex attribs",
1138 "GL_MAX_VARYING_COMPONENTS",
1139 &gl_max_varying_components,
1140 "varying components",
1143 "GL_NUM_PROGRAM_BINARY_FORMATS",
1144 &gl_num_program_binary_formats,
1145 "num program binary formats",
1148 unsigned i;
1150 /* The INT keyword in the requirements section causes
1151 * shader_runner to read the specified integer value and
1152 * processes the given requirement.
1154 if (parse_str(line, "INT ", &line)) {
1155 enum comparison cmp;
1156 int comparison_value, gl_int_value;
1157 unsigned int_enum;
1159 REQUIRE(parse_enum_gl(line, &int_enum, &line),
1160 "Invalid comparison enum at: %s\n", line);
1161 REQUIRE(parse_comparison_op(line, &cmp, &line),
1162 "Invalid comparison operation at: %s\n", line);
1163 REQUIRE(parse_int(line, &comparison_value, &line),
1164 "Invalid comparison value at: %s\n", line);
1166 glGetIntegerv(int_enum, &gl_int_value);
1167 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1168 fprintf(stderr, "Error reading %s\n",
1169 piglit_get_gl_enum_name(int_enum));
1170 return PIGLIT_FAIL;
1173 if (!compare(comparison_value, gl_int_value, cmp)) {
1174 printf("Test requires %s %s %i. "
1175 "The driver supports %i.\n",
1176 piglit_get_gl_enum_name(int_enum),
1177 comparison_string(cmp),
1178 comparison_value,
1179 gl_int_value);
1180 return PIGLIT_SKIP;
1183 return PIGLIT_PASS;
1186 /* There are five types of requirements that a test can currently
1187 * have:
1189 * * Require that some GL extension be supported
1190 * * Require some particular versions of GL
1191 * * Require some particular versions of GLSL
1192 * * Require some particular number of uniform components
1193 * * Require shaders be built as separate shader objects
1195 * The tests for GL and GLSL versions can be equal, not equal,
1196 * less, less-or-equal, greater, or greater-or-equal. Extension tests
1197 * can also require that a particular extension not be supported by
1198 * prepending ! to the extension name.
1200 for (i = 0; i < ARRAY_SIZE(getint_limits); i++) {
1201 enum comparison cmp;
1202 int maxcomp;
1204 if (!parse_str(line, getint_limits[i].name, &line))
1205 continue;
1207 REQUIRE(parse_comparison_op(line, &cmp, &line),
1208 "Invalid comparison operation at: %s\n", line);
1210 maxcomp = atoi(line);
1211 if (!compare(maxcomp, *getint_limits[i].val, cmp)) {
1212 printf("Test requires %s %s %i. "
1213 "The driver supports %i.\n",
1214 getint_limits[i].desc,
1215 comparison_string(cmp),
1216 maxcomp,
1217 *getint_limits[i].val);
1218 return PIGLIT_SKIP;
1220 return PIGLIT_PASS;
1223 if (parse_str(line, "GL_", NULL) &&
1224 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1225 if (!piglit_is_extension_supported(buffer)) {
1226 printf("Test requires unsupported extension %s\n", buffer);
1227 return PIGLIT_SKIP;
1229 } else if (parse_str(line, "!", &line) &&
1230 parse_str(line, "GL_", NULL) &&
1231 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1232 if (piglit_is_extension_supported(buffer)) {
1233 printf("Test requires unsupported extension %s\n", buffer);
1234 return PIGLIT_SKIP;
1236 } else if (parse_str(line, "GLSL", &line)) {
1237 enum comparison cmp;
1239 parse_version_comparison(line, &cmp, &glsl_req_version,
1240 VERSION_GLSL);
1242 /* We only allow >= because we potentially use the
1243 * version number to insert a #version directive. */
1244 if (cmp != greater_equal) {
1245 printf("Unsupported GLSL version comparison\n");
1246 return PIGLIT_FAIL;
1249 if (!version_compare(&glsl_req_version, &glsl_version, cmp)) {
1250 printf("Test requires %s %s. "
1251 "Actual version %s.\n",
1252 comparison_string(cmp),
1253 version_string(&glsl_req_version),
1254 version_string(&glsl_version));
1255 return PIGLIT_SKIP;
1257 } else if (parse_str(line, "GL", &line)) {
1258 enum comparison cmp;
1259 struct component_version gl_req_version;
1261 parse_version_comparison(line, &cmp, &gl_req_version,
1262 VERSION_GL);
1264 if (!version_compare(&gl_req_version, &gl_version, cmp)) {
1265 printf("Test requires %s %s. "
1266 "Actual version is %s.\n",
1267 comparison_string(cmp),
1268 version_string(&gl_req_version),
1269 version_string(&gl_version));
1270 return PIGLIT_SKIP;
1272 } else if (parse_str(line, "rlimit", &line)) {
1273 unsigned lim;
1275 REQUIRE(parse_uint(line, &lim, &line),
1276 "Invalid rlimit argument at: %s\n", line);
1278 piglit_set_rlimit(lim);
1279 } else if (parse_str(line, "SSO", &line) &&
1280 parse_str(line, "ENABLED", NULL)) {
1281 if (separable_program) {
1282 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1283 return PIGLIT_FAIL;
1286 const char *const ext_name = gl_version.es
1287 ? "GL_EXT_separate_shader_objects"
1288 : "GL_ARB_separate_shader_objects";
1289 const unsigned min_version = gl_version.es
1290 ? 31 : 41;
1292 if (gl_version.num < min_version)
1293 piglit_require_extension(ext_name);
1295 sso_in_use = true;
1296 glGenProgramPipelines(1, &pipeline);
1297 } else if (parse_str(line, "SEPARABLE PROGRAM", &line) &&
1298 parse_str(line, "ENABLED", NULL)) {
1299 if (sso_in_use) {
1300 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1301 return PIGLIT_FAIL;
1304 const char *const ext_name = gl_version.es
1305 ? "GL_EXT_separate_shader_objects"
1306 : "GL_ARB_separate_shader_objects";
1307 const unsigned min_version = gl_version.es
1308 ? 31 : 41;
1310 if (gl_version.num < min_version)
1311 piglit_require_extension(ext_name);
1313 separable_program = true;
1314 } else if (parse_str(line, "SPIRV", &line)) {
1315 spirv_replaces_glsl = !force_glsl;
1317 if (parse_str(line, "ONLY", NULL)) {
1318 if (force_glsl) {
1319 printf("This shader is not compatible with GLSL\n");
1320 return PIGLIT_SKIP;
1322 } else if (parse_str(line, "YES", NULL)) {
1323 /* Empty. Everything already set. Just parsing
1324 * correct options
1326 } else {
1327 printf("Unknown SPIRV line in [require]\n");
1328 return PIGLIT_FAIL;
1331 if (spirv_replaces_glsl)
1332 force_no_names = true;
1333 } else if (parse_str(line, "ignore_missing_uniforms", &line)) {
1334 ignore_missing_uniforms = true;
1336 return PIGLIT_PASS;
1341 * Process a line from the [geometry layout] section of a test
1343 static void
1344 process_geometry_layout(const char *line)
1346 char s[32];
1347 int x;
1349 parse_whitespace(line, &line);
1351 if (line[0] == '\0' || line[0] == '\n') {
1352 return;
1353 } else if (sscanf(line, "input type %31s", s) == 1) {
1354 geometry_layout_input_type = decode_drawing_mode(s);
1355 } else if (sscanf(line, "output type %31s", s) == 1) {
1356 geometry_layout_output_type = decode_drawing_mode(s);
1357 } else if (sscanf(line, "vertices out %d", &x) == 1) {
1358 geometry_layout_vertices_out = x;
1359 } else {
1360 printf("Could not parse geometry layout line: %s\n", line);
1361 piglit_report_result(PIGLIT_FAIL);
1365 static enum piglit_result
1366 leave_state(enum states state, const char *line, const char *script_name)
1368 switch (state) {
1369 case none:
1370 break;
1372 case requirements:
1373 if (spirv_replaces_glsl) {
1374 printf("Running on SPIR-V mode\n");
1376 if (force_no_names && !spirv_replaces_glsl) {
1377 printf("Running on GLSL mode, forcing not using "
1378 "uniform/uniform block names\n");
1380 break;
1382 case vertex_shader:
1383 if (spirv_replaces_glsl)
1384 break;
1385 shader_string_size = line - shader_string;
1386 return compile_glsl(GL_VERTEX_SHADER);
1388 case vertex_shader_passthrough:
1389 if (spirv_replaces_glsl) {
1390 shader_string = (char *) passthrough_vertex_shader_source_spv;
1391 shader_string_size = strlen(passthrough_vertex_shader_source_spv);
1393 return assemble_spirv(GL_VERTEX_SHADER);
1395 return compile_glsl(GL_VERTEX_SHADER);
1397 case vertex_program:
1398 return compile_and_bind_program(GL_VERTEX_PROGRAM_ARB,
1399 shader_string,
1400 line - shader_string);
1402 case vertex_shader_spirv:
1403 if (!spirv_replaces_glsl)
1404 break;
1405 shader_string_size = line - shader_string;
1406 return assemble_spirv(GL_VERTEX_SHADER);
1408 case vertex_shader_specializations:
1409 break;
1411 case tess_ctrl_shader:
1412 if (spirv_replaces_glsl)
1413 break;
1414 shader_string_size = line - shader_string;
1415 return compile_glsl(GL_TESS_CONTROL_SHADER);
1417 case tess_ctrl_shader_spirv:
1418 if (!spirv_replaces_glsl)
1419 break;
1420 shader_string_size = line - shader_string;
1421 return assemble_spirv(GL_TESS_CONTROL_SHADER);
1423 case tess_ctrl_shader_specializations:
1424 break;
1426 case tess_eval_shader:
1427 if (spirv_replaces_glsl)
1428 break;
1429 shader_string_size = line - shader_string;
1430 return compile_glsl(GL_TESS_EVALUATION_SHADER);
1432 case tess_eval_shader_spirv:
1433 if (!spirv_replaces_glsl)
1434 break;
1435 shader_string_size = line - shader_string;
1436 return assemble_spirv(GL_TESS_EVALUATION_SHADER);
1438 case tess_eval_shader_specializations:
1439 break;
1441 case geometry_shader:
1442 if (spirv_replaces_glsl)
1443 break;
1444 shader_string_size = line - shader_string;
1445 return compile_glsl(GL_GEOMETRY_SHADER);
1447 case geometry_shader_spirv:
1448 if (!spirv_replaces_glsl)
1449 break;
1450 shader_string_size = line - shader_string;
1451 return assemble_spirv(GL_GEOMETRY_SHADER);
1453 case geometry_shader_specializations:
1454 break;
1456 case geometry_layout:
1457 break;
1459 case fragment_shader:
1460 if (spirv_replaces_glsl)
1461 break;
1462 shader_string_size = line - shader_string;
1463 return compile_glsl(GL_FRAGMENT_SHADER);
1465 case fragment_program:
1466 return compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB,
1467 shader_string,
1468 line - shader_string);
1469 break;
1471 case fragment_shader_spirv:
1472 if (!spirv_replaces_glsl)
1473 break;
1474 shader_string_size = line - shader_string;
1475 return assemble_spirv(GL_FRAGMENT_SHADER);
1477 case fragment_shader_specializations:
1478 break;
1480 case compute_shader:
1481 if (spirv_replaces_glsl)
1482 break;
1483 shader_string_size = line - shader_string;
1484 return compile_glsl(GL_COMPUTE_SHADER);
1486 case compute_shader_spirv:
1487 if (!spirv_replaces_glsl)
1488 break;
1489 shader_string_size = line - shader_string;
1490 return assemble_spirv(GL_COMPUTE_SHADER);
1492 case compute_shader_specializations:
1493 break;
1495 case vertex_data:
1496 vertex_data_end = line;
1497 break;
1499 case shader_include: {
1500 const char *path_end = strchrnul(shader_string, '\n');
1502 if (shader_string == path_end) {
1503 fprintf(stderr, "No shader include path provided\n");
1504 return PIGLIT_FAIL;
1507 if (!piglit_is_extension_supported("GL_ARB_shading_language_include"))
1508 return PIGLIT_SKIP;
1510 int path_name_len = path_end - shader_string;
1511 glNamedStringARB(GL_SHADER_INCLUDE_ARB, path_name_len, shader_string,
1512 line - shader_string - path_name_len, shader_string + path_name_len);
1514 shader_include_names[num_shader_includes] = strndup(shader_string, path_name_len);
1515 num_shader_includes++;
1516 assert(num_shader_includes <= 256);
1518 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1519 fprintf(stderr, "glNamedStringARB error\n");
1520 return PIGLIT_FAIL;
1523 break;
1526 case shader_include_paths: {
1527 num_shader_include_paths = 0;
1528 const char *cursor = shader_string;
1529 do {
1530 const char *line_start = cursor;
1531 cursor = strchr(cursor, '\n');
1533 if (cursor == line_start) {
1534 cursor++;
1535 continue;
1538 cursor++;
1539 num_shader_include_paths++;
1540 } while (cursor && cursor < line);
1542 shader_include_path = calloc(num_shader_include_paths, sizeof(char *));
1544 cursor = shader_string;
1545 for (unsigned i = 0; i < num_shader_include_paths; i++) {
1546 char *line_end = strchr(cursor, '\n');
1547 unsigned path_len = line_end - cursor - 1;
1548 char *path = malloc(path_len + 1);
1549 path[path_len] = '\0';
1551 memcpy(path, cursor, path_len);
1552 shader_include_path[i] = path;
1553 cursor = line_end + 1;
1556 break;
1559 case test:
1560 break;
1562 default:
1563 assert(!"Not yet supported.");
1565 return PIGLIT_PASS;
1569 static enum piglit_result
1570 process_shader(GLenum target, unsigned num_shaders, GLuint *shaders)
1572 if (num_shaders == 0)
1573 return PIGLIT_PASS;
1575 if (sso_in_use) {
1576 prog = glCreateProgram();
1577 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1580 for (unsigned i = 0; i < num_shaders; i++) {
1581 glAttachShader(prog, shaders[i]);
1584 #ifdef PIGLIT_USE_OPENGL
1585 if (geometry_layout_input_type != GL_TRIANGLES) {
1586 glProgramParameteriARB(prog, GL_GEOMETRY_INPUT_TYPE_ARB,
1587 geometry_layout_input_type);
1589 if (geometry_layout_output_type != GL_TRIANGLE_STRIP) {
1590 glProgramParameteriARB(prog, GL_GEOMETRY_OUTPUT_TYPE_ARB,
1591 geometry_layout_output_type);
1593 if (geometry_layout_vertices_out != 0) {
1594 glProgramParameteriARB(prog, GL_GEOMETRY_VERTICES_OUT_ARB,
1595 geometry_layout_vertices_out);
1597 #endif
1599 /* If the shaders reference piglit_vertex or piglit_tex, bind
1600 * them to some fixed attribute locations so they can be used
1601 * with piglit_draw_rect_tex() in GLES.
1603 glBindAttribLocation(prog, PIGLIT_ATTRIB_POS, "piglit_vertex");
1604 glBindAttribLocation(prog, PIGLIT_ATTRIB_TEX, "piglit_texcoord");
1606 if (sso_in_use) {
1607 return link_sso(target);
1609 return PIGLIT_PASS;
1613 static enum piglit_result
1614 link_and_use_shaders(void)
1616 enum piglit_result result;
1617 unsigned i;
1618 GLenum err;
1619 GLint ok;
1621 if ((num_vertex_shaders == 0)
1622 && (num_fragment_shaders == 0)
1623 && (num_tess_ctrl_shaders == 0)
1624 && (num_tess_eval_shaders == 0)
1625 && (num_geometry_shaders == 0)
1626 && (num_compute_shaders == 0))
1627 return PIGLIT_PASS;
1629 if (!sso_in_use)
1630 prog = glCreateProgram();
1632 result = process_shader(GL_VERTEX_SHADER, num_vertex_shaders, vertex_shaders);
1633 if (result != PIGLIT_PASS)
1634 goto cleanup;
1635 result = process_shader(GL_TESS_CONTROL_SHADER, num_tess_ctrl_shaders, tess_ctrl_shaders);
1636 if (result != PIGLIT_PASS)
1637 goto cleanup;
1638 result = process_shader(GL_TESS_EVALUATION_SHADER, num_tess_eval_shaders, tess_eval_shaders);
1639 if (result != PIGLIT_PASS)
1640 goto cleanup;
1641 result = process_shader(GL_GEOMETRY_SHADER, num_geometry_shaders, geometry_shaders);
1642 if (result != PIGLIT_PASS)
1643 goto cleanup;
1644 result = process_shader(GL_FRAGMENT_SHADER, num_fragment_shaders, fragment_shaders);
1645 if (result != PIGLIT_PASS)
1646 goto cleanup;
1647 result = process_shader(GL_COMPUTE_SHADER, num_compute_shaders, compute_shaders);
1648 if (result != PIGLIT_PASS)
1649 goto cleanup;
1651 if (!sso_in_use) {
1652 if (separable_program)
1653 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1655 glLinkProgram(prog);
1658 if (!sso_in_use) {
1659 if (!program_binary_save_restore(false))
1660 return PIGLIT_FAIL;
1661 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
1662 if (ok) {
1663 link_ok = true;
1664 } else {
1665 GLint size;
1667 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1668 prog_err_info = malloc(MAX2(size, 1));
1669 prog_err_info[0] = 0;
1671 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1673 result = PIGLIT_PASS;
1674 goto cleanup;
1677 glUseProgram(prog);
1680 err = glGetError();
1681 if (!err) {
1682 prog_in_use = true;
1683 } else {
1684 GLint size;
1686 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1687 prog_err_info = malloc(MAX2(size, 1));
1688 prog_err_info[0] = 0;
1690 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1693 cleanup:
1694 for (i = 0; i < num_vertex_shaders; i++) {
1695 glDeleteShader(vertex_shaders[i]);
1697 num_vertex_shaders = 0;
1699 for (i = 0; i < num_tess_ctrl_shaders; i++) {
1700 glDeleteShader(tess_ctrl_shaders[i]);
1702 num_tess_ctrl_shaders = 0;
1704 for (i = 0; i < num_tess_eval_shaders; i++) {
1705 glDeleteShader(tess_eval_shaders[i]);
1707 num_tess_eval_shaders = 0;
1709 for (i = 0; i < num_geometry_shaders; i++) {
1710 glDeleteShader(geometry_shaders[i]);
1712 num_geometry_shaders = 0;
1714 for (i = 0; i < num_fragment_shaders; i++) {
1715 glDeleteShader(fragment_shaders[i]);
1717 num_fragment_shaders = 0;
1719 for (i = 0; i < num_compute_shaders; i++) {
1720 glDeleteShader(compute_shaders[i]);
1722 num_compute_shaders = 0;
1724 return result;
1727 static enum piglit_result
1728 process_specialization(enum states state, const char *line)
1730 const char *end = strchrnul(line, '\n');
1731 const char *next;
1732 enum { TYPE_FLOAT, TYPE_UINT } type;
1734 while (line < end && isspace(*line))
1735 line++;
1737 if (line >= end || *line == '#')
1738 return PIGLIT_PASS;
1740 if (parse_str(line, "uint", &next))
1741 type = TYPE_UINT;
1742 else if (parse_str(line, "float", &next))
1743 type = TYPE_FLOAT;
1744 else
1745 goto invalid;
1747 struct specialization_list *list;
1749 switch (state) {
1750 case vertex_shader_specializations:
1751 list = specializations + 0;
1752 break;
1753 case tess_ctrl_shader_specializations:
1754 list = specializations + 1;
1755 break;
1756 case tess_eval_shader_specializations:
1757 list = specializations + 2;
1758 break;
1759 case geometry_shader_specializations:
1760 list = specializations + 3;
1761 break;
1762 case fragment_shader_specializations:
1763 list = specializations + 4;
1764 break;
1765 case compute_shader_specializations:
1766 list = specializations + 5;
1767 break;
1768 default:
1769 assert(!"Should not get here.");
1772 if (list->n_entries >= list->buffer_size) {
1773 if (list->buffer_size == 0)
1774 list->buffer_size = 1;
1775 else
1776 list->buffer_size *= 2;
1777 list->indices = realloc(list->indices,
1778 (sizeof list->indices[0]) *
1779 list->buffer_size);
1780 list->values = realloc(list->values,
1781 (sizeof list->values[0]) *
1782 list->buffer_size);
1785 if (parse_uints(next, list->indices + list->n_entries, 1, &next) != 1)
1786 goto invalid;
1788 switch (type) {
1789 case TYPE_UINT:
1790 if (parse_uints(next,
1791 &list->values[list->n_entries].u,
1793 &next) != 1)
1794 goto invalid;
1795 break;
1796 case TYPE_FLOAT:
1797 if (parse_floats(next,
1798 &list->values[list->n_entries].f,
1800 &next) != 1)
1801 goto invalid;
1802 break;
1805 list->n_entries++;
1807 return PIGLIT_PASS;
1809 invalid:
1810 fprintf(stderr, "Invalid specialization line\n");
1811 return PIGLIT_FAIL;
1814 static enum piglit_result
1815 process_test_script(const char *script_name)
1817 unsigned text_size;
1818 unsigned line_num;
1819 char *text = piglit_load_text_file(script_name, &text_size);
1820 enum states state = none;
1821 const char *line = text;
1822 enum piglit_result result;
1824 if (line == NULL) {
1825 printf("could not read file \"%s\"\n", script_name);
1826 return PIGLIT_FAIL;
1829 line_num = 1;
1831 while (line[0] != '\0') {
1832 if (line[0] == '[') {
1833 result = leave_state(state, line, script_name);
1834 if (result != PIGLIT_PASS)
1835 return result;
1837 if (parse_str(line, "[require]", NULL)) {
1838 state = requirements;
1839 } else if (parse_str(line, "[vertex shader]", NULL)) {
1840 state = vertex_shader;
1841 shader_string = NULL;
1842 } else if (parse_str(line, "[vertex program]", NULL)) {
1843 state = vertex_program;
1844 shader_string = NULL;
1845 } else if (parse_str(line, "[vertex shader passthrough]", NULL)) {
1846 state = vertex_shader_passthrough;
1847 shader_string =
1848 (char *) passthrough_vertex_shader_source;
1849 shader_string_size = strlen(shader_string);
1850 } else if (parse_str(line, "[vertex shader spirv]", NULL)) {
1851 state = vertex_shader_spirv;
1852 shader_string = NULL;
1853 } else if (parse_str(line, "[vertex shader specializations]", NULL)) {
1854 state = vertex_shader_specializations;
1855 } else if (parse_str(line, "[tessellation control shader]", NULL)) {
1856 state = tess_ctrl_shader;
1857 shader_string = NULL;
1858 } else if (parse_str(line, "[tessellation control shader spirv]", NULL)) {
1859 state = tess_ctrl_shader_spirv;
1860 shader_string = NULL;
1861 } else if (parse_str(line, "[tessellation control shader specializations]", NULL)) {
1862 state = tess_ctrl_shader_specializations;
1863 } else if (parse_str(line, "[tessellation evaluation shader]", NULL)) {
1864 state = tess_eval_shader;
1865 shader_string = NULL;
1866 } else if (parse_str(line, "[tessellation evaluation shader spirv]", NULL)) {
1867 state = tess_eval_shader_spirv;
1868 shader_string = NULL;
1869 } else if (parse_str(line, "[tessellation evaluation shader specializations]", NULL)) {
1870 state = tess_eval_shader_specializations;
1871 } else if (parse_str(line, "[geometry shader]", NULL)) {
1872 state = geometry_shader;
1873 shader_string = NULL;
1874 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1875 state = geometry_shader_specializations;
1876 } else if (parse_str(line, "[geometry shader spirv]", NULL)) {
1877 state = geometry_shader_spirv;
1878 shader_string = NULL;
1879 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1880 state = geometry_shader_specializations;
1881 } else if (parse_str(line, "[geometry layout]", NULL)) {
1882 state = geometry_layout;
1883 shader_string = NULL;
1884 } else if (parse_str(line, "[fragment shader]", NULL)) {
1885 state = fragment_shader;
1886 shader_string = NULL;
1887 } else if (parse_str(line, "[fragment program]", NULL)) {
1888 state = fragment_program;
1889 shader_string = NULL;
1890 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1891 state = fragment_shader_specializations;
1892 } else if (parse_str(line, "[fragment shader spirv]", NULL)) {
1893 state = fragment_shader_spirv;
1894 shader_string = NULL;
1895 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1896 state = fragment_shader_specializations;
1897 } else if (parse_str(line, "[compute shader]", NULL)) {
1898 state = compute_shader;
1899 shader_string = NULL;
1900 } else if (parse_str(line, "[compute shader spirv]", NULL)) {
1901 state = compute_shader_spirv;
1902 shader_string = NULL;
1903 } else if (parse_str(line, "[compute shader specializations]", NULL)) {
1904 state = compute_shader_specializations;
1905 } else if (parse_str(line, "[vertex data]", NULL)) {
1906 state = vertex_data;
1907 vertex_data_start = NULL;
1908 } else if (parse_str(line, "[shader include]", NULL)) {
1909 state = shader_include;
1910 shader_string = NULL;
1911 } else if (parse_str(line, "[shader include paths]", NULL)) {
1912 state = shader_include_paths;
1913 shader_string = NULL;
1914 } else if (parse_str(line, "[test]", NULL)) {
1915 test_start = strchrnul(line, '\n');
1916 test_start_line_num = line_num + 1;
1917 if (test_start[0] != '\0')
1918 test_start++;
1919 return PIGLIT_PASS;
1920 } else {
1921 fprintf(stderr,
1922 "Unknown section in test script. "
1923 "Perhaps missing closing ']'?\n");
1924 return PIGLIT_FAIL;
1926 } else {
1927 switch (state) {
1928 case none:
1929 case vertex_shader_passthrough:
1930 break;
1932 case requirements:
1933 result = process_requirement(line);
1934 if (result != PIGLIT_PASS)
1935 return result;
1936 break;
1938 case geometry_layout:
1939 process_geometry_layout(line);
1940 break;
1942 case vertex_shader:
1943 case vertex_program:
1944 case tess_ctrl_shader:
1945 case tess_eval_shader:
1946 case geometry_shader:
1947 case fragment_shader:
1948 case fragment_program:
1949 case compute_shader:
1950 case vertex_shader_spirv:
1951 case tess_ctrl_shader_spirv:
1952 case tess_eval_shader_spirv:
1953 case geometry_shader_spirv:
1954 case fragment_shader_spirv:
1955 case compute_shader_spirv:
1956 case shader_include:
1957 case shader_include_paths:
1958 if (shader_string == NULL)
1959 shader_string = (char *) line;
1960 break;
1962 case vertex_shader_specializations:
1963 case tess_ctrl_shader_specializations:
1964 case tess_eval_shader_specializations:
1965 case geometry_shader_specializations:
1966 case fragment_shader_specializations:
1967 case compute_shader_specializations: {
1968 enum piglit_result result =
1969 process_specialization(state, line);
1970 if (result != PIGLIT_PASS)
1971 return result;
1972 break;
1975 case vertex_data:
1976 if (vertex_data_start == NULL)
1977 vertex_data_start = line;
1978 break;
1980 case test:
1981 break;
1985 line = strchrnul(line, '\n');
1986 if (line[0] != '\0')
1987 line++;
1989 line_num++;
1992 return leave_state(state, line, script_name);
1995 struct requirement_parse_results {
1996 bool found_gl;
1997 bool found_glsl;
1998 bool found_size;
1999 bool found_depthbuffer;
2000 struct component_version gl_version;
2001 struct component_version glsl_version;
2002 unsigned size[2];
2005 static void
2006 parse_required_config(struct requirement_parse_results *results,
2007 const char *script_name)
2009 unsigned text_size;
2010 char *text = piglit_load_text_file(script_name, &text_size);
2011 const char *line = text;
2012 bool in_requirement_section = false;
2014 results->found_gl = false;
2015 results->found_glsl = false;
2016 results->found_size = false;
2017 results->found_depthbuffer = false;
2019 if (line == NULL) {
2020 printf("could not read file \"%s\"\n", script_name);
2021 piglit_report_result(PIGLIT_FAIL);
2024 while (line[0] != '\0') {
2025 if (line[0] == '[') {
2026 if (in_requirement_section)
2027 break;
2028 else
2029 in_requirement_section = false;
2032 if (!in_requirement_section) {
2033 if (parse_str(line, "[require]", NULL)) {
2034 in_requirement_section = true;
2036 } else {
2037 if (parse_str(line, "GL_", NULL)
2038 || parse_str(line, "!GL_", NULL)) {
2039 /* empty */
2040 } else if (parse_str(line, "GLSL", &line)) {
2041 enum comparison cmp;
2042 struct component_version version;
2044 parse_version_comparison(line, &cmp,
2045 &version, VERSION_GLSL);
2046 if (cmp == greater_equal) {
2047 results->found_glsl = true;
2048 version_copy(&results->glsl_version, &version);
2050 } else if (parse_str(line, "GL", &line)) {
2051 enum comparison cmp;
2052 struct component_version version;
2054 parse_version_comparison(line, &cmp,
2055 &version, VERSION_GL);
2056 if (cmp == greater_equal
2057 || cmp == greater
2058 || cmp == equal) {
2059 results->found_gl = true;
2060 version_copy(&results->gl_version, &version);
2062 } else if (parse_str(line, "SIZE", &line)) {
2063 results->found_size = true;
2064 parse_uints(line, results->size, 2, NULL);
2065 } else if (parse_str(line, "depthbuffer", NULL)) {
2066 results->found_depthbuffer = true;
2070 line = strchrnul(line, '\n');
2071 if (line[0] != '\0')
2072 line++;
2075 free(text);
2077 if (!in_requirement_section) {
2078 printf("[require] section missing\n");
2079 piglit_report_result(PIGLIT_FAIL);
2082 if (results->found_glsl && results->glsl_version.es && !results->found_gl) {
2083 printf("%s", "The test specifies a requirement for GLSL ES, "
2084 "but specifies no GL requirement\n.");
2085 piglit_report_result(PIGLIT_FAIL);
2090 static void
2091 choose_required_gl_version(struct requirement_parse_results *parse_results,
2092 struct component_version *gl_version)
2094 if (parse_results->found_gl) {
2095 version_copy(gl_version, &parse_results->gl_version);
2096 } else {
2097 assert(!parse_results->found_glsl || !parse_results->glsl_version.es);
2098 version_init(gl_version, VERSION_GL, false, false, false, 10);
2101 if (gl_version->es)
2102 return;
2104 /* Possibly promote the GL version. */
2105 if (parse_results->found_glsl
2106 && gl_version->num < required_gl_version_from_glsl_version(
2107 parse_results->glsl_version.num)) {
2108 gl_version->num = required_gl_version_from_glsl_version(
2109 parse_results->glsl_version.num);
2114 * Just determine the GLSL version required by the shader script.
2116 * This function is a bit of a hack that is, unfortunately necessary. A test
2117 * script can require a specific GLSL version or a specific GL version. To
2118 * satisfy this requirement, the piglit framework code needs to know about the
2119 * requirement before creating the context. However, the requirements section
2120 * can contain other requirements, such as minimum number of uniforms.
2122 * The requirements section can't be fully processed until after the context
2123 * is created, but the context can't be created until after the requirements
2124 * section is processed. Do a quick scan over the requirements section to find
2125 * the GL and GLSL version requirements. Use these to guide context creation.
2127 static void
2128 get_required_config(const char *script_name, bool spirv,
2129 struct piglit_gl_test_config *config)
2131 struct requirement_parse_results parse_results;
2132 struct component_version required_gl_version;
2134 parse_required_config(&parse_results, script_name);
2135 choose_required_gl_version(&parse_results, &required_gl_version);
2137 if (spirv) {
2138 required_gl_version.es = false;
2139 required_gl_version.core = true;
2140 required_gl_version.num = MAX2(required_gl_version.num, 33);
2143 if (parse_results.found_size) {
2144 config->window_width = parse_results.size[0];
2145 config->window_height = parse_results.size[1];
2148 if (required_gl_version.es) {
2149 config->supports_gl_es_version = required_gl_version.num;
2150 } else if (required_gl_version.num >= 31) {
2151 if (!required_gl_version.compat)
2152 config->supports_gl_core_version = required_gl_version.num;
2153 if (!required_gl_version.core)
2154 config->supports_gl_compat_version = required_gl_version.num;
2155 } else {
2156 config->supports_gl_compat_version = 10;
2159 if (parse_results.found_depthbuffer) {
2160 config->window_visual |= PIGLIT_GL_VISUAL_DEPTH;
2165 * Check that the GL implementation supports unsigned uniforms
2166 * (e.g. through glUniform1ui). If not, terminate the test with a
2167 * SKIP.
2169 static void
2170 check_unsigned_support(void)
2172 if (gl_version.num < 30 && !piglit_is_extension_supported("GL_EXT_gpu_shader4"))
2173 piglit_report_result(PIGLIT_SKIP);
2177 * Check that the GL implementation supports double uniforms
2178 * (e.g. through glUniform1d). If not, terminate the test with a
2179 * SKIP.
2181 static void
2182 check_double_support(void)
2184 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_gpu_shader_fp64"))
2185 piglit_report_result(PIGLIT_SKIP);
2189 * Check that the GL implementation supports double uniforms
2190 * (e.g. through glUniform1d). If not, terminate the test with a
2191 * SKIP.
2193 static void
2194 check_int64_support(void)
2196 if (!piglit_is_extension_supported("GL_ARB_gpu_shader_int64"))
2197 piglit_report_result(PIGLIT_SKIP);
2201 * Check that the GL implementation supports shader subroutines
2202 * If not, terminate the test with a SKIP.
2204 static void
2205 check_shader_subroutine_support(void)
2207 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
2208 piglit_report_result(PIGLIT_SKIP);
2212 * Check that the GL implementation supports texture handles.
2213 * If not, terminate the test with a SKIP.
2215 static void
2216 check_texture_handle_support(void)
2218 if (!piglit_is_extension_supported("GL_ARB_bindless_texture"))
2219 piglit_report_result(PIGLIT_SKIP);
2222 static bool
2223 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2224 GLuint *uniform_index_out,
2225 GLint *block_index_out,
2226 GLint *offset_out);
2229 * Handles uploads of UBO uniforms by mapping the buffer and storing
2230 * the data. If the uniform is not in a uniform block, returns false.
2232 static bool
2233 set_ubo_uniform(char *name, const char *type,
2234 const char *line,
2235 struct block_info block_data)
2237 /* Note: on SPIR-V we can't access to uniform_index as we
2238 * could lack the name. We force that with force_no_names on
2239 * GLSL
2241 GLuint uniform_index;
2242 GLint block_index;
2243 GLint offset;
2244 char *data;
2245 float f[16];
2246 double d[16];
2247 int ints[16];
2248 unsigned uints[16];
2249 uint64_t uint64s[16];
2250 int64_t int64s[16];
2252 if (!get_indexes_and_offset_from_ubo(name, block_data, &uniform_index,
2253 &block_index, &offset)) {
2254 return false;
2257 glBindBuffer(GL_UNIFORM_BUFFER,
2258 uniform_block_bos[block_index]);
2259 data = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
2260 data += offset;
2262 if (parse_str(type, "float", NULL)) {
2263 parse_floats(line, f, 1, NULL);
2264 memcpy(data, f, sizeof(float));
2265 } else if (parse_str(type, "int64_t", NULL)) {
2266 parse_int64s(line, int64s, 1, NULL);
2267 memcpy(data, int64s, sizeof(int64_t));
2268 } else if (parse_str(type, "uint64_t", NULL)) {
2269 parse_uint64s(line, uint64s, 1, NULL);
2270 memcpy(data, uint64s, sizeof(uint64_t));
2271 } else if (parse_str(type, "int", NULL)) {
2272 parse_ints(line, ints, 1, NULL);
2273 memcpy(data, ints, sizeof(int));
2274 } else if (parse_str(type, "uint", NULL)) {
2275 parse_uints(line, uints, 1, NULL);
2276 memcpy(data, uints, sizeof(int));
2277 } else if (parse_str(type, "double", NULL)) {
2278 parse_doubles(line, d, 1, NULL);
2279 memcpy(data, d, sizeof(double));
2280 } else if (parse_str(type, "vec", NULL)) {
2281 int elements = type[3] - '0';
2282 parse_floats(line, f, elements, NULL);
2283 memcpy(data, f, elements * sizeof(float));
2284 } else if (parse_str(type, "ivec", NULL)) {
2285 int elements = type[4] - '0';
2286 parse_ints(line, ints, elements, NULL);
2287 memcpy(data, ints, elements * sizeof(int));
2288 } else if (parse_str(type, "uvec", NULL)) {
2289 int elements = type[4] - '0';
2290 parse_uints(line, uints, elements, NULL);
2291 memcpy(data, uints, elements * sizeof(unsigned));
2292 } else if (parse_str(type, "i64vec", NULL)) {
2293 int elements = type[6] - '0';
2294 parse_int64s(line, int64s, elements, NULL);
2295 memcpy(data, int64s, elements * sizeof(int64_t));
2296 } else if (parse_str(type, "u64vec", NULL)) {
2297 int elements = type[6] - '0';
2298 parse_uint64s(line, uint64s, elements, NULL);
2299 memcpy(data, uint64s, elements * sizeof(uint64_t));
2300 } else if (parse_str(type, "dvec", NULL)) {
2301 int elements = type[4] - '0';
2302 parse_doubles(line, d, elements, NULL);
2303 memcpy(data, d, elements * sizeof(double));
2304 } else if (parse_str(type, "mat", NULL)) {
2305 GLint matrix_stride, row_major;
2306 int cols = type[3] - '0';
2307 int rows = type[4] == 'x' ? type[5] - '0' : cols;
2308 int r, c;
2309 float *matrixdata = (float *)data;
2311 assert(cols >= 2 && cols <= 4);
2312 assert(rows >= 2 && rows <= 4);
2314 parse_floats(line, f, rows * cols, NULL);
2316 if (!force_no_names) {
2317 glGetActiveUniformsiv(prog, 1, &uniform_index,
2318 GL_UNIFORM_MATRIX_STRIDE,
2319 &matrix_stride);
2320 glGetActiveUniformsiv(prog, 1, &uniform_index,
2321 GL_UNIFORM_IS_ROW_MAJOR,
2322 &row_major);
2323 } else {
2324 matrix_stride = block_data.matrix_stride;
2325 row_major = block_data.row_major;
2328 matrix_stride /= sizeof(float);
2330 /* Expect the data in the .shader_test file to be listed in
2331 * column-major order no matter what the layout of the data in
2332 * the UBO will be.
2334 for (c = 0; c < cols; c++) {
2335 for (r = 0; r < rows; r++) {
2336 if (row_major) {
2337 matrixdata[matrix_stride * r + c] =
2338 f[c * rows + r];
2339 } else {
2340 matrixdata[matrix_stride * c + r] =
2341 f[c * rows + r];
2345 } else if (parse_str(type, "dmat", NULL)) {
2346 GLint matrix_stride, row_major;
2347 int cols = type[4] - '0';
2348 int rows = type[5] == 'x' ? type[6] - '0' : cols;
2349 int r, c;
2350 double *matrixdata = (double *)data;
2352 assert(cols >= 2 && cols <= 4);
2353 assert(rows >= 2 && rows <= 4);
2355 parse_doubles(line, d, rows * cols, NULL);
2357 if (!force_no_names) {
2358 glGetActiveUniformsiv(prog, 1, &uniform_index,
2359 GL_UNIFORM_MATRIX_STRIDE,
2360 &matrix_stride);
2361 glGetActiveUniformsiv(prog, 1, &uniform_index,
2362 GL_UNIFORM_IS_ROW_MAJOR,
2363 &row_major);
2364 } else {
2365 matrix_stride = block_data.matrix_stride;
2366 row_major = block_data.row_major;
2369 matrix_stride /= sizeof(double);
2371 /* Expect the data in the .shader_test file to be listed in
2372 * column-major order no matter what the layout of the data in
2373 * the UBO will be.
2375 for (c = 0; c < cols; c++) {
2376 for (r = 0; r < rows; r++) {
2377 if (row_major) {
2378 matrixdata[matrix_stride * r + c] =
2379 d[c * rows + r];
2380 } else {
2381 matrixdata[matrix_stride * c + r] =
2382 d[c * rows + r];
2386 } else if (parse_str(type, "handle", NULL)) {
2387 check_unsigned_support();
2388 check_texture_handle_support();
2389 parse_uints(line, uints, 1, NULL);
2390 GLuint64 handle = get_resident_handle(uints[0])->handle;
2391 memcpy(data, &handle, sizeof(uint64_t));
2392 } else {
2393 printf("unknown uniform type \"%s\" for \"%s\"\n", type, name);
2394 piglit_report_result(PIGLIT_FAIL);
2397 glUnmapBuffer(GL_UNIFORM_BUFFER);
2399 return true;
2403 * Get the uniform_index, block_index and offset of a given
2404 * uniform. By default it gets those values using the uniform name. If
2405 * force_no_names mode is active, it uses the current values stored at
2406 * @block_data. On the latter, uniform index is not filled up.
2408 static bool
2409 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2410 GLuint *uniform_index_out,
2411 GLint *block_index_out,
2412 GLint *offset_out)
2414 GLuint uniform_index = 0;
2415 GLint block_index;
2416 GLint offset;
2417 int name_len = strlen(name);
2418 GLint array_index = 0;
2420 if (!num_uniform_blocks)
2421 return false;
2423 if (!force_no_names) {
2424 /* if the uniform is an array, strip the index, as GL
2425 prevents non-zero indexes from matching a name */
2426 if (name[name_len - 1] == ']') {
2427 int i;
2429 for (i = name_len - 1; (i > 0) && isdigit(name[i-1]); --i)
2430 /* empty */;
2432 array_index = strtol(&name[i], NULL, 0);
2434 if (i) {
2435 i--;
2436 if (name[i] != '[') {
2437 printf("cannot parse uniform \"%s\"\n", name);
2438 piglit_report_result(PIGLIT_FAIL);
2440 name[i] = 0;
2445 glGetUniformIndices(prog, 1, (const char **)&name, &uniform_index);
2446 if (uniform_index == GL_INVALID_INDEX) {
2447 printf("cannot get index of uniform \"%s\"\n", name);
2448 piglit_report_result(PIGLIT_FAIL);
2451 glGetActiveUniformsiv(prog, 1, &uniform_index,
2452 GL_UNIFORM_BLOCK_INDEX, &block_index);
2454 if (block_index == -1)
2455 return false;
2457 GLint array_size;
2458 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_SIZE, &array_size);
2460 if (array_index > array_size) {
2461 printf("attempt to access beyond uniform \"%s\" array size (%d)\n",
2462 name, array_size);
2463 return false;
2466 /* if the uniform block is an array, then GetActiveUniformsiv with
2467 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2468 * element in the array.
2470 block_index += block_data.array_index;
2472 glGetActiveUniformsiv(prog, 1, &uniform_index,
2473 GL_UNIFORM_OFFSET, &offset);
2475 if (name[name_len - 1] == ']') {
2476 GLint stride;
2478 glGetActiveUniformsiv(prog, 1, &uniform_index,
2479 GL_UNIFORM_ARRAY_STRIDE, &stride);
2480 offset += stride * array_index;
2482 } else {
2483 if (block_data.binding < 0) {
2484 printf("if you force to use a explicit ubo binding, you "
2485 "need to provide it when filling the data with "
2486 "\"ubo binding\"\n");
2487 piglit_report_result(PIGLIT_FAIL);
2490 /* The mapping could be improved using a hash
2491 * table. For now, this is enough.
2493 block_index = uniform_block_indexes[block_data.binding];
2495 /* if the uniform block is an array, then GetActiveUniformsiv with
2496 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2497 * element in the array.
2499 block_index += block_data.array_index;
2501 if (block_data.offset < 0) {
2502 printf("if you force to use a explicit ubo binding, you "
2503 "need to provide offset when filling the data with "
2504 "\"ubo offset\"\n");
2505 piglit_report_result(PIGLIT_FAIL);
2507 offset = block_data.offset;
2510 *offset_out = offset;
2511 *block_index_out = block_index;
2512 *uniform_index_out = uniform_index;
2514 return true;
2517 static void
2518 set_uniform(const char *line, struct block_info block_data)
2520 char name[512], type[512];
2521 float f[16];
2522 double d[16];
2523 int ints[16];
2524 unsigned uints[16];
2525 int64_t int64s[16];
2526 uint64_t uint64s[16];
2527 GLint loc;
2529 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2530 parse_word_copy(line, name, sizeof(name), &line),
2531 "Invalid set uniform command at: %s\n", line);
2533 if (isdigit(name[0])) {
2534 loc = strtol(name, NULL, 0);
2535 } else {
2536 GLuint prog;
2538 if (set_ubo_uniform(name, type, line, block_data))
2539 return;
2541 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2542 loc = glGetUniformLocation(prog, name);
2543 if (loc < 0) {
2544 if (ignore_missing_uniforms)
2545 return;
2546 printf("cannot get location of uniform \"%s\"\n",
2547 name);
2548 piglit_report_result(PIGLIT_FAIL);
2552 if (parse_str(type, "float", NULL)) {
2553 parse_floats(line, f, 1, NULL);
2554 glUniform1fv(loc, 1, f);
2555 return;
2556 } else if (parse_str(type, "int64_t", NULL)) {
2557 check_int64_support();
2558 parse_int64s(line, int64s, 1, NULL);
2559 glUniform1i64vARB(loc, 1, int64s);
2560 return;
2561 } else if (parse_str(type, "uint64_t", NULL)) {
2562 check_int64_support();
2563 parse_uint64s(line, uint64s, 1, NULL);
2564 glUniform1ui64vARB(loc, 1, uint64s);
2565 return;
2566 } else if (parse_str(type, "int", NULL)) {
2567 parse_ints(line, ints, 1, NULL);
2568 glUniform1iv(loc, 1, ints);
2569 return;
2570 } else if (parse_str(type, "uint", NULL)) {
2571 check_unsigned_support();
2572 parse_uints(line, uints, 1, NULL);
2573 glUniform1uiv(loc, 1, uints);
2574 return;
2575 } else if (parse_str(type, "double", NULL)) {
2576 check_double_support();
2577 parse_doubles(line, d, 1, NULL);
2578 glUniform1dv(loc, 1, d);
2579 return;
2580 } else if (parse_str(type, "vec", NULL)) {
2581 switch (type[3]) {
2582 case '2':
2583 parse_floats(line, f, 2, NULL);
2584 glUniform2fv(loc, 1, f);
2585 return;
2586 case '3':
2587 parse_floats(line, f, 3, NULL);
2588 glUniform3fv(loc, 1, f);
2589 return;
2590 case '4':
2591 parse_floats(line, f, 4, NULL);
2592 glUniform4fv(loc, 1, f);
2593 return;
2595 } else if (parse_str(type, "ivec", NULL)) {
2596 switch (type[4]) {
2597 case '2':
2598 parse_ints(line, ints, 2, NULL);
2599 glUniform2iv(loc, 1, ints);
2600 return;
2601 case '3':
2602 parse_ints(line, ints, 3, NULL);
2603 glUniform3iv(loc, 1, ints);
2604 return;
2605 case '4':
2606 parse_ints(line, ints, 4, NULL);
2607 glUniform4iv(loc, 1, ints);
2608 return;
2610 } else if (parse_str(type, "uvec", NULL)) {
2611 check_unsigned_support();
2612 switch (type[4]) {
2613 case '2':
2614 parse_uints(line, uints, 2, NULL);
2615 glUniform2uiv(loc, 1, uints);
2616 return;
2617 case '3':
2618 parse_uints(line, uints, 3, NULL);
2619 glUniform3uiv(loc, 1, uints);
2620 return;
2621 case '4':
2622 parse_uints(line, uints, 4, NULL);
2623 glUniform4uiv(loc, 1, uints);
2624 return;
2626 } else if (parse_str(type, "dvec", NULL)) {
2627 check_double_support();
2628 switch (type[4]) {
2629 case '2':
2630 parse_doubles(line, d, 2, NULL);
2631 glUniform2dv(loc, 1, d);
2632 return;
2633 case '3':
2634 parse_doubles(line, d, 3, NULL);
2635 glUniform3dv(loc, 1, d);
2636 return;
2637 case '4':
2638 parse_doubles(line, d, 4, NULL);
2639 glUniform4dv(loc, 1, d);
2640 return;
2642 } else if (parse_str(type, "i64vec", NULL)) {
2643 check_int64_support();
2644 switch (type[6]) {
2645 case '2':
2646 parse_int64s(line, int64s, 2, NULL);
2647 glUniform2i64vARB(loc, 1, int64s);
2648 return;
2649 case '3':
2650 parse_int64s(line, int64s, 3, NULL);
2651 glUniform3i64vARB(loc, 1, int64s);
2652 return;
2653 case '4':
2654 parse_int64s(line, int64s, 4, NULL);
2655 glUniform4i64vARB(loc, 1, int64s);
2656 return;
2658 } else if (parse_str(type, "u64vec", NULL)) {
2659 check_int64_support();
2660 switch (type[6]) {
2661 case '2':
2662 parse_uint64s(line, uint64s, 2, NULL);
2663 glUniform2ui64vARB(loc, 1, uint64s);
2664 return;
2665 case '3':
2666 parse_uint64s(line, uint64s, 3, NULL);
2667 glUniform3ui64vARB(loc, 1, uint64s);
2668 return;
2669 case '4':
2670 parse_uint64s(line, uint64s, 4, NULL);
2671 glUniform4ui64vARB(loc, 1, uint64s);
2672 return;
2674 } else if (parse_str(type, "mat", NULL) && type[3] != '\0') {
2675 char cols = type[3];
2676 char rows = type[4] == 'x' ? type[5] : cols;
2677 switch (cols) {
2678 case '2':
2679 switch (rows) {
2680 case '2':
2681 parse_floats(line, f, 4, NULL);
2682 glUniformMatrix2fv(loc, 1, GL_FALSE, f);
2683 return;
2684 case '3':
2685 parse_floats(line, f, 6, NULL);
2686 glUniformMatrix2x3fv(loc, 1, GL_FALSE, f);
2687 return;
2688 case '4':
2689 parse_floats(line, f, 8, NULL);
2690 glUniformMatrix2x4fv(loc, 1, GL_FALSE, f);
2691 return;
2693 case '3':
2694 switch (rows) {
2695 case '2':
2696 parse_floats(line, f, 6, NULL);
2697 glUniformMatrix3x2fv(loc, 1, GL_FALSE, f);
2698 return;
2699 case '3':
2700 parse_floats(line, f, 9, NULL);
2701 glUniformMatrix3fv(loc, 1, GL_FALSE, f);
2702 return;
2703 case '4':
2704 parse_floats(line, f, 12, NULL);
2705 glUniformMatrix3x4fv(loc, 1, GL_FALSE, f);
2706 return;
2708 case '4':
2709 switch (rows) {
2710 case '2':
2711 parse_floats(line, f, 8, NULL);
2712 glUniformMatrix4x2fv(loc, 1, GL_FALSE, f);
2713 return;
2714 case '3':
2715 parse_floats(line, f, 12, NULL);
2716 glUniformMatrix4x3fv(loc, 1, GL_FALSE, f);
2717 return;
2718 case '4':
2719 parse_floats(line, f, 16, NULL);
2720 glUniformMatrix4fv(loc, 1, GL_FALSE, f);
2721 return;
2724 } else if (parse_str(type, "dmat", NULL) && type[4] != '\0') {
2725 char cols = type[4];
2726 char rows = type[5] == 'x' ? type[6] : cols;
2727 switch (cols) {
2728 case '2':
2729 switch (rows) {
2730 case '2':
2731 parse_doubles(line, d, 4, NULL);
2732 glUniformMatrix2dv(loc, 1, GL_FALSE, d);
2733 return;
2734 case '3':
2735 parse_doubles(line, d, 6, NULL);
2736 glUniformMatrix2x3dv(loc, 1, GL_FALSE, d);
2737 return;
2738 case '4':
2739 parse_doubles(line, d, 8, NULL);
2740 glUniformMatrix2x4dv(loc, 1, GL_FALSE, d);
2741 return;
2743 case '3':
2744 switch (rows) {
2745 case '2':
2746 parse_doubles(line, d, 6, NULL);
2747 glUniformMatrix3x2dv(loc, 1, GL_FALSE, d);
2748 return;
2749 case '3':
2750 parse_doubles(line, d, 9, NULL);
2751 glUniformMatrix3dv(loc, 1, GL_FALSE, d);
2752 return;
2753 case '4':
2754 parse_doubles(line, d, 12, NULL);
2755 glUniformMatrix3x4dv(loc, 1, GL_FALSE, d);
2756 return;
2758 case '4':
2759 switch (rows) {
2760 case '2':
2761 parse_doubles(line, d, 8, NULL);
2762 glUniformMatrix4x2dv(loc, 1, GL_FALSE, d);
2763 return;
2764 case '3':
2765 parse_doubles(line, d, 12, NULL);
2766 glUniformMatrix4x3dv(loc, 1, GL_FALSE, d);
2767 return;
2768 case '4':
2769 parse_doubles(line, d, 16, NULL);
2770 glUniformMatrix4dv(loc, 1, GL_FALSE, d);
2771 return;
2774 } else if (parse_str(type, "handle", NULL)) {
2775 check_unsigned_support();
2776 check_texture_handle_support();
2777 parse_uints(line, uints, 1, NULL);
2778 glUniformHandleui64ARB(loc, get_resident_handle(uints[0])->handle);
2779 return;
2782 printf("unknown uniform type \"%s\"\n", type);
2783 piglit_report_result(PIGLIT_FAIL);
2785 return;
2788 static void
2789 set_vertex_attrib(const char *line)
2791 char name[512], type[512];
2792 uint32_t uints[16];
2793 GLint loc;
2795 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2796 parse_word_copy(line, name, sizeof(name), &line),
2797 "Invalid set vertex attrib command at: %s\n", line);
2799 if (isdigit(name[0])) {
2800 loc = strtol(name, NULL, 0);
2801 } else {
2802 GLuint prog;
2804 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2805 loc = glGetAttribLocation(prog, name);
2806 if (loc < 0) {
2807 if (ignore_missing_uniforms)
2808 return;
2809 printf("cannot get location of vertex attrib \"%s\"\n",
2810 name);
2811 piglit_report_result(PIGLIT_FAIL);
2815 if (parse_str(type, "handle", NULL)) {
2816 check_unsigned_support();
2817 check_texture_handle_support();
2818 parse_uints(line, uints, 1, NULL);
2819 glVertexAttribL1ui64ARB(loc, get_resident_handle(uints[0])->handle);
2820 return;
2823 printf("unknown vertex attrib type \"%s\"\n", type);
2824 printf("use [vertex data] instead if possible\n");
2825 piglit_report_result(PIGLIT_FAIL);
2827 return;
2830 static GLenum lookup_shader_type(GLuint idx)
2832 switch (idx) {
2833 case 0:
2834 return GL_VERTEX_SHADER;
2835 case 1:
2836 return GL_FRAGMENT_SHADER;
2837 case 2:
2838 return GL_GEOMETRY_SHADER;
2839 case 3:
2840 return GL_TESS_CONTROL_SHADER;
2841 case 4:
2842 return GL_TESS_EVALUATION_SHADER;
2843 case 5:
2844 return GL_COMPUTE_SHADER;
2845 default:
2846 return 0;
2850 static GLenum get_shader_from_string(const char *name, int *idx)
2852 if (parse_str(name, "GL_VERTEX_SHADER", NULL)) {
2853 *idx = 0;
2854 return GL_VERTEX_SHADER;
2856 if (parse_str(name, "GL_FRAGMENT_SHADER", NULL)) {
2857 *idx = 1;
2858 return GL_FRAGMENT_SHADER;
2860 if (parse_str(name, "GL_GEOMETRY_SHADER", NULL)) {
2861 *idx = 2;
2862 return GL_GEOMETRY_SHADER;
2864 if (parse_str(name, "GL_TESS_CONTROL_SHADER", NULL)) {
2865 *idx = 3;
2866 return GL_TESS_CONTROL_SHADER;
2868 if (parse_str(name, "GL_TESS_EVALUATION_SHADER", NULL)) {
2869 *idx = 4;
2870 return GL_TESS_EVALUATION_SHADER;
2872 if (parse_str(name, "GL_COMPUTE_SHADER", NULL)) {
2873 *idx = 5;
2874 return GL_COMPUTE_SHADER;
2876 return 0;
2879 static void
2880 free_subroutine_uniforms(void)
2882 int sidx;
2883 for (sidx = 0; sidx < 4; sidx++) {
2884 free(subuniform_locations[sidx]);
2885 subuniform_locations[sidx] = NULL;
2889 static void
2890 program_subroutine_uniforms(void)
2892 int sidx;
2893 int stype;
2895 for (sidx = 0; sidx < 4; sidx++) {
2897 if (num_subuniform_locations[sidx] == 0)
2898 continue;
2900 stype = lookup_shader_type(sidx);
2901 if (!stype)
2902 continue;
2904 glUniformSubroutinesuiv(stype, num_subuniform_locations[sidx], subuniform_locations[sidx]);
2908 static void
2909 set_subroutine_uniform(const char *line)
2911 GLuint prog;
2912 char type[512];
2913 char name[512];
2914 char subname[512];
2915 GLint loc;
2916 GLuint idx;
2917 GLenum ptype = 0;
2918 int sidx = 0;
2920 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2921 parse_word_copy(line, name, sizeof(name), &line) &&
2922 parse_word_copy(line, subname, sizeof(subname), &line),
2923 "Invalid set subroutine uniform command at: %s\n", line);
2925 ptype = get_shader_from_string(type, &sidx);
2926 if (ptype == 0) {
2927 printf("illegal type in subroutine uniform\n");
2928 piglit_report_result(PIGLIT_FAIL);
2931 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2933 if (num_subuniform_locations[sidx] == 0) {
2934 glGetProgramStageiv(prog, ptype, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
2935 &num_subuniform_locations[sidx]);
2937 if (num_subuniform_locations[sidx] == 0) {
2938 printf("illegal subroutine uniform specified\n");
2939 piglit_report_result(PIGLIT_FAIL);
2942 subuniform_locations[sidx] = calloc(num_subuniform_locations[sidx], sizeof(GLuint));
2943 if (!subuniform_locations[sidx])
2944 piglit_report_result(PIGLIT_FAIL);
2947 loc = glGetSubroutineUniformLocation(prog, ptype, name);
2948 if (loc < 0) {
2949 if (ignore_missing_uniforms)
2950 return;
2951 printf("cannot get location of subroutine uniform \"%s\"\n",
2952 name);
2953 piglit_report_result(PIGLIT_FAIL);
2956 idx = glGetSubroutineIndex(prog, ptype, subname);
2957 if (idx == GL_INVALID_INDEX) {
2958 printf("cannot get index of subroutine uniform \"%s\"\n",
2959 subname);
2960 piglit_report_result(PIGLIT_FAIL);
2963 subuniform_locations[sidx][loc] = idx;
2964 return;
2968 * Query values from current program using glGetProgram.
2970 * Format of the command:
2971 * verify program_query GL_PNAME_ENUM integer
2973 * or
2975 * verify program_query GL_PNAME_ENUM <enum>
2977 * Note: GL_COMPUTE_WORK_GROUP_SIZE is not supported, as is the only
2978 * query that requires a params with more than one component, and we
2979 * want to keep things simple.
2982 static void
2983 verify_program_query(const char *line)
2985 static const struct string_to_enum all_pnames[] = {
2986 ENUM_STRING(GL_DELETE_STATUS),
2987 ENUM_STRING(GL_LINK_STATUS),
2988 ENUM_STRING(GL_VALIDATE_STATUS),
2989 ENUM_STRING(GL_INFO_LOG_LENGTH),
2990 ENUM_STRING(GL_ATTACHED_SHADERS),
2991 ENUM_STRING(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS),
2992 ENUM_STRING(GL_ACTIVE_ATTRIBUTES),
2993 ENUM_STRING(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH),
2994 ENUM_STRING(GL_ACTIVE_UNIFORMS),
2995 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCKS),
2996 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH),
2997 ENUM_STRING(GL_ACTIVE_UNIFORM_MAX_LENGTH),
2998 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
2999 ENUM_STRING(GL_PROGRAM_BINARY_LENGTH),
3000 ENUM_STRING(GL_TRANSFORM_FEEDBACK_BUFFER_MODE),
3001 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYINGS),
3002 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH),
3003 ENUM_STRING(GL_GEOMETRY_VERTICES_OUT),
3004 ENUM_STRING(GL_GEOMETRY_INPUT_TYPE),
3005 ENUM_STRING(GL_GEOMETRY_OUTPUT_TYPE),
3006 { NULL, 0 }
3009 static const struct string_to_enum all_possible_param_enums[] = {
3010 ENUM_STRING(GL_TRUE),
3011 ENUM_STRING(GL_FALSE),
3012 ENUM_STRING(GL_SEPARATE_ATTRIBS),
3013 ENUM_STRING(GL_INTERLEAVED_ATTRIBS),
3014 ENUM_STRING(GL_POINTS),
3015 ENUM_STRING(GL_LINES),
3016 ENUM_STRING(GL_LINES_ADJACENCY),
3017 ENUM_STRING(GL_TRIANGLES),
3018 ENUM_STRING(GL_TRIANGLES_ADJACENCY),
3019 ENUM_STRING(GL_LINE_STRIP),
3020 ENUM_STRING(GL_TRIANGLE_STRIP),
3021 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
3022 { NULL, 0 }
3025 unsigned pname;
3026 int expected;
3027 int value;
3029 REQUIRE(parse_enum_tab(all_pnames, line,
3030 &pname, &line),
3031 "Bad glGetProgram pname at: %s\n", line);
3033 REQUIRE(parse_enum_tab(all_possible_param_enums, line, (unsigned *)&expected, &line) ||
3034 parse_int(line, &expected, &line),
3035 "Bad expected value at: %s\n", line);
3037 if (pname == GL_COMPUTE_WORK_GROUP_SIZE) {
3038 /* TODO: eventually it would be good to add support for
3039 * this parameter. What it makes different to the rest is
3040 * that it requires a param with more than one component
3042 fprintf(stderr, "glGetProgram queries with GL_COMPUTE_WORK_GROUP_SIZE "
3043 "not supported yet\n");
3044 piglit_report_result(PIGLIT_FAIL);
3047 glGetProgramiv(prog, pname, &value);
3049 if (expected != value) {
3050 fprintf(stderr, "glGetProgram(%s): expected %d, got %d\n",
3051 piglit_get_gl_enum_name(pname), expected, value);
3052 piglit_report_result(PIGLIT_FAIL);
3057 * Query a uniform using glGetActiveUniformsiv
3059 * Format of the command:
3061 * active uniform uniform_name GL_PNAME_ENUM integer
3063 * or
3065 * active uniform uniform_name GL_PNAME_ENUM GL_TYPE_ENUM
3067 static void
3068 active_uniform(const char *line)
3070 static const struct string_to_enum all_pnames[] = {
3071 ENUM_STRING(GL_UNIFORM_TYPE),
3072 ENUM_STRING(GL_UNIFORM_SIZE),
3073 ENUM_STRING(GL_UNIFORM_NAME_LENGTH),
3074 ENUM_STRING(GL_UNIFORM_BLOCK_INDEX),
3075 ENUM_STRING(GL_UNIFORM_OFFSET),
3076 ENUM_STRING(GL_UNIFORM_ARRAY_STRIDE),
3077 ENUM_STRING(GL_UNIFORM_MATRIX_STRIDE),
3078 ENUM_STRING(GL_UNIFORM_IS_ROW_MAJOR),
3079 ENUM_STRING(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX),
3080 { NULL, 0 }
3083 const char *rest = line;
3084 char name[512];
3085 char name_buf[512];
3086 unsigned pname;
3087 int expected;
3088 int i;
3089 int num_active_uniforms;
3091 REQUIRE(parse_word_copy(rest, name, sizeof(name), &rest),
3092 "Bad uniform name at: %s\n", line);
3094 REQUIRE(parse_enum_tab(all_pnames, rest, &pname, &rest),
3095 "Bad glGetUniformsiv pname at: %s\n", line);
3097 REQUIRE(parse_enum_tab(all_types, rest, (unsigned *)&expected, &rest) ||
3098 parse_int(rest, &expected, &rest),
3099 "Bad expected value at: %s\n", line);
3101 glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
3102 for (i = 0; i < num_active_uniforms; i++) {
3103 GLint got;
3104 GLint size;
3105 GLenum type;
3106 GLsizei name_len;
3107 bool pass = true;
3109 glGetActiveUniform(prog, i, sizeof(name_buf), &name_len,
3110 &size, &type, name_buf);
3112 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3113 fprintf(stderr, "glGetActiveUniform error\n");
3114 piglit_report_result(PIGLIT_FAIL);
3117 if (strcmp(name, name_buf) != 0)
3118 continue;
3120 /* If the requested pname is one of the values that
3121 * glGetActiveUniform happens to return, check the value
3122 * returned by that function too.
3124 switch (pname) {
3125 case GL_UNIFORM_TYPE:
3126 got = (GLint) type;
3127 break;
3129 case GL_UNIFORM_SIZE:
3130 got = size;
3131 break;
3133 case GL_UNIFORM_NAME_LENGTH:
3134 got = name_len;
3135 break;
3137 default:
3138 /* This ensures the check below will pass when the
3139 * requested enum is not one of the values already
3140 * returned by glGetActiveUniform.
3142 got = expected;
3143 break;
3146 if (got != expected) {
3147 fprintf(stderr,
3148 "glGetActiveUniform(%s, %s): "
3149 "expected %d (0x%04x), got %d (0x%04x)\n",
3150 name, piglit_get_gl_enum_name(pname),
3151 expected, expected, got, got);
3152 pass = false;
3155 /* Set 'got' to some value in case glGetActiveUniformsiv
3156 * doesn't write to it. That should only be able to occur
3157 * when the function raises a GL error, but "should" is kind
3158 * of a funny word.
3160 got = ~expected;
3161 glGetActiveUniformsiv(prog, 1, (GLuint *) &i, pname, &got);
3163 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3164 fprintf(stderr, "glGetActiveUniformsiv error\n");
3165 piglit_report_result(PIGLIT_FAIL);
3168 if (got != expected) {
3169 fprintf(stderr,
3170 "glGetActiveUniformsiv(%s, %s): "
3171 "expected %d, got %d\n",
3172 name, piglit_get_gl_enum_name(pname),
3173 expected, got);
3174 pass = false;
3177 if (!pass)
3178 piglit_report_result(PIGLIT_FAIL);
3180 return;
3183 fprintf(stderr, "No active uniform named \"%s\"\n", name);
3184 piglit_report_result(PIGLIT_FAIL);
3185 return;
3190 * Confirms if @resource_index is a given resource, within @interface_type.
3192 * In order to identify it, it uses by default @resource_name. If
3193 * force_no_names mode is activated it uses the binding contained at
3194 * @block_data. Note that for the latter, only ubos or ssbos are
3195 * supported as @interface_type.
3197 * @resource_name_buf, @prop and @value_expected are only used for
3198 * some extra checks.
3200 * Return true if @resource_index is the resource within
3201 * @interface_type we search for. false otherwise.
3203 static bool
3204 confirm_program_resource(GLenum interface_type, GLuint resource_index,
3205 const char *resource_name, char *resource_name_buf,
3206 struct block_info block_data, unsigned prop,
3207 int value_expected)
3209 if (!force_no_names) {
3210 GLsizei resource_name_len;
3212 glGetProgramResourceName(prog, interface_type, resource_index,
3213 512, &resource_name_len,
3214 resource_name_buf);
3216 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3217 fprintf(stderr, "glGetProgramResourceName error\n");
3218 piglit_report_result(PIGLIT_FAIL);
3221 if (strcmp(resource_name, resource_name_buf) != 0)
3222 return false;
3224 /* glGetProgramResourceName does not consider the NULL
3225 * terminator when returning the name length, however,
3226 * glGetProgramResourceiv does. We take that into account
3227 * when doing the comparison.
3229 if (prop == GL_NAME_LENGTH &&
3230 resource_name_len != (value_expected - 1)) {
3231 fprintf(stderr,
3232 "glGetProgramResourceName(%s, %s, %s): "
3233 "expected length: %d (0x%04x), "
3234 "got length: %d (0x%04x)\n",
3235 piglit_get_gl_enum_name(interface_type),
3236 resource_name, piglit_get_gl_enum_name(prop),
3237 value_expected - 1, value_expected - 1,
3238 resource_name_len, resource_name_len);
3239 piglit_report_result(PIGLIT_FAIL);
3241 } else {
3242 unsigned binding_prop = GL_BUFFER_BINDING;
3243 int current_binding = 0;
3244 GLint length;
3246 if (interface_type != GL_SHADER_STORAGE_BLOCK &&
3247 interface_type != GL_UNIFORM_BLOCK) {
3248 fprintf(stderr,
3249 "active_program_interface queries under force_no_names "
3250 "mode are only supported for GL_SHADER_STORAGE_BLOCK "
3251 "or GL_UNIFORM_BLOCK interfaces\n");
3252 piglit_report_result(PIGLIT_FAIL);
3255 glGetProgramResourceiv(prog, interface_type,
3256 resource_index, 1, &binding_prop, 1,
3257 &length, &current_binding);
3258 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3259 fprintf(stderr, "glGetProgramResourceiv error\n");
3260 piglit_report_result(PIGLIT_FAIL);
3263 if (block_data.binding != current_binding)
3264 return false;
3267 return true;
3271 * Query an active resource using ARB_program_interface_query functions
3273 * Format of the command:
3275 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM integer
3277 * or
3279 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM GL_TYPE_ENUM
3281 static void
3282 active_program_interface(const char *line, struct block_info block_data)
3284 static const struct string_to_enum all_props[] = {
3285 ENUM_STRING(GL_TYPE),
3286 ENUM_STRING(GL_ARRAY_SIZE),
3287 ENUM_STRING(GL_NAME_LENGTH),
3288 ENUM_STRING(GL_BLOCK_INDEX),
3289 ENUM_STRING(GL_OFFSET),
3290 ENUM_STRING(GL_ARRAY_STRIDE),
3291 ENUM_STRING(GL_MATRIX_STRIDE),
3292 ENUM_STRING(GL_IS_ROW_MAJOR),
3293 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER_INDEX),
3294 ENUM_STRING(GL_BUFFER_BINDING),
3295 ENUM_STRING(GL_BUFFER_DATA_SIZE),
3296 ENUM_STRING(GL_NUM_ACTIVE_VARIABLES),
3297 ENUM_STRING(GL_REFERENCED_BY_VERTEX_SHADER),
3298 ENUM_STRING(GL_REFERENCED_BY_TESS_CONTROL_SHADER),
3299 ENUM_STRING(GL_REFERENCED_BY_TESS_EVALUATION_SHADER),
3300 ENUM_STRING(GL_REFERENCED_BY_GEOMETRY_SHADER),
3301 ENUM_STRING(GL_REFERENCED_BY_FRAGMENT_SHADER),
3302 ENUM_STRING(GL_REFERENCED_BY_COMPUTE_SHADER),
3303 ENUM_STRING(GL_TOP_LEVEL_ARRAY_SIZE),
3304 ENUM_STRING(GL_TOP_LEVEL_ARRAY_STRIDE),
3305 ENUM_STRING(GL_LOCATION),
3306 ENUM_STRING(GL_LOCATION_INDEX),
3307 ENUM_STRING(GL_LOCATION_COMPONENT),
3308 ENUM_STRING(GL_IS_PER_PATCH),
3309 ENUM_STRING(GL_NUM_COMPATIBLE_SUBROUTINES),
3310 ENUM_STRING(GL_COMPATIBLE_SUBROUTINES),
3311 { NULL, 0 }
3314 static const struct string_to_enum all_program_interface[] = {
3315 ENUM_STRING(GL_UNIFORM),
3316 ENUM_STRING(GL_UNIFORM_BLOCK),
3317 ENUM_STRING(GL_PROGRAM_INPUT),
3318 ENUM_STRING(GL_PROGRAM_OUTPUT),
3319 ENUM_STRING(GL_BUFFER_VARIABLE),
3320 ENUM_STRING(GL_SHADER_STORAGE_BLOCK),
3321 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER),
3322 ENUM_STRING(GL_VERTEX_SUBROUTINE),
3323 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE),
3324 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE),
3325 ENUM_STRING(GL_GEOMETRY_SUBROUTINE),
3326 ENUM_STRING(GL_FRAGMENT_SUBROUTINE),
3327 ENUM_STRING(GL_COMPUTE_SUBROUTINE),
3328 ENUM_STRING(GL_VERTEX_SUBROUTINE_UNIFORM),
3329 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE_UNIFORM),
3330 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE_UNIFORM),
3331 ENUM_STRING(GL_GEOMETRY_SUBROUTINE_UNIFORM),
3332 ENUM_STRING(GL_FRAGMENT_SUBROUTINE_UNIFORM),
3333 ENUM_STRING(GL_COMPUTE_SUBROUTINE_UNIFORM),
3334 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING),
3335 { NULL, 0 }
3338 char name[512];
3339 char name_buf[512];
3340 unsigned prop, interface_type;
3341 int expected;
3342 int i;
3343 int num_active_buffers;
3345 if (!piglit_is_extension_supported("GL_ARB_program_interface_query") &&
3346 piglit_get_gl_version() < 43) {
3347 fprintf(stderr,
3348 "GL_ARB_program_interface_query not supported or "
3349 "OpenGL version < 4.3\n");
3350 return;
3353 REQUIRE(parse_enum_tab(all_program_interface, line,
3354 &interface_type, &line),
3355 "Bad program interface at: %s\n", line);
3356 REQUIRE(parse_word_copy(line, name, sizeof(name), &line),
3357 "Bad program resource name at: %s\n", line);
3358 REQUIRE(parse_enum_tab(all_props, line, &prop, &line),
3359 "Bad glGetProgramResourceiv pname at: %s\n", line);
3360 REQUIRE(parse_enum_tab(all_types, line, (unsigned *)&expected, &line) ||
3361 parse_int(line, &expected, &line),
3362 "Bad expected value at: %s\n", line);
3364 glGetProgramInterfaceiv(prog, interface_type,
3365 GL_ACTIVE_RESOURCES, &num_active_buffers);
3366 for (i = 0; i < num_active_buffers; i++) {
3367 GLint got;
3368 GLint length;
3369 bool pass = true;
3371 if (!confirm_program_resource(interface_type, i, name, name_buf,
3372 block_data, prop, expected))
3373 continue;
3375 /* Set 'got' to some value in case glGetActiveUniformsiv
3376 * doesn't write to it. That should only be able to occur
3377 * when the function raises a GL error, but "should" is kind
3378 * of a funny word.
3380 got = ~expected;
3381 glGetProgramResourceiv(prog, interface_type,
3382 i, 1, &prop, 1,
3383 &length, &got);
3385 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3386 fprintf(stderr, "glGetProgramResourceiv error\n");
3387 piglit_report_result(PIGLIT_FAIL);
3390 if (got != expected) {
3391 fprintf(stderr,
3392 "glGetProgramResourceiv(%s, %s): "
3393 "expected %d, got %d\n",
3394 name, piglit_get_gl_enum_name(prop),
3395 expected, got);
3396 pass = false;
3399 if (!pass)
3400 piglit_report_result(PIGLIT_FAIL);
3402 return;
3405 if (!force_no_names)
3406 fprintf(stderr, "No active resource named \"%s\"\n", name);
3407 else
3408 fprintf(stderr, "No active resource with binding %i\n", block_data.binding);
3410 piglit_report_result(PIGLIT_FAIL);
3411 return;
3415 static unsigned
3416 query_index(GLenum query)
3418 switch (query) {
3419 case GL_PRIMITIVES_GENERATED:
3420 return 0;
3421 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
3422 return 1;
3423 default:
3424 return 0;
3428 * Checks if the GL_QUERY_RESULT of a given query object has the
3429 * expected value.
3431 * Note that right now it only supports the following two queries:
3432 * * GL_PRIMITIVES_GENERATED
3433 * * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
3435 * As right now we are only creating those query objects with xfb
3436 * rendering.
3438 * Format of the command:
3440 * verify query_object GL_PRIMITIVES_GENERATED integer
3442 * or
3444 * verify query_object GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN integer
3446 static enum piglit_result
3447 verify_query_object_result(const char *line)
3449 static const struct string_to_enum all_targets[] = {
3450 ENUM_STRING(GL_PRIMITIVES_GENERATED),
3451 ENUM_STRING(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
3452 { NULL, 0 }
3455 unsigned target;
3456 unsigned expected;
3457 unsigned value = 0;
3458 unsigned index = 0;
3460 REQUIRE(parse_enum_tab(all_targets, line,
3461 &target, &line),
3462 "Bad query object target at: %s\n", line);
3464 REQUIRE(parse_uint(line, &expected, &line),
3465 "Bad expected value at: %s\n", line);
3467 /* Previous require already checks if the target is one of the
3468 * supported ones.
3470 index = query_index(target);
3472 if (queries[index]) {
3473 glGetQueryObjectuiv(queries[index], GL_QUERY_RESULT, &value);
3474 } else {
3475 fprintf(stderr, "query object for target %s is not initialized. "
3476 "Did you forget to call \"xfb draw arrays\"?\n",
3477 piglit_get_gl_enum_name(target));
3478 return PIGLIT_FAIL;
3481 if (expected != value) {
3482 fprintf(stderr, "glGetQueryObjectuiv(GL_QUERY_RESULT) for a %s "
3483 "query object: expected %d, got %d\n",
3484 piglit_get_gl_enum_name(target), expected, value);
3485 return PIGLIT_FAIL;
3487 return PIGLIT_PASS;
3490 static void
3491 set_parameter(const char *line)
3493 float f[4];
3494 int index, count;
3495 char type[1024];
3497 count = sscanf(line, "%s %d (%f , %f , %f , %f)",
3498 type, &index, &f[0], &f[1], &f[2], &f[3]);
3499 if (count != 6) {
3500 fprintf(stderr, "Couldn't parse parameter command:\n%s\n", line);
3501 piglit_report_result(PIGLIT_FAIL);
3504 if (parse_str(type, "env_vp", NULL)) {
3505 glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3506 } else if (parse_str(type, "local_vp", NULL)) {
3507 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3508 } else if (parse_str(type, "env_fp", NULL)) {
3509 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3510 } else if (parse_str(type, "local_fp", NULL)) {
3511 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3512 } else {
3513 fprintf(stderr, "Unknown parameter type `%s'\n", type);
3514 piglit_report_result(PIGLIT_FAIL);
3518 static void
3519 set_patch_parameter(const char *line)
3521 #ifdef PIGLIT_USE_OPENGL
3522 float f[4];
3523 int i, count;
3524 const char *const line0 = line;
3526 if (gl_version.num < 40)
3527 piglit_require_extension("GL_ARB_tessellation_shader");
3529 if (parse_str(line, "vertices ", &line)) {
3530 count = sscanf(line, "%d", &i);
3531 if (count != 1) {
3532 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3533 piglit_report_result(PIGLIT_FAIL);
3535 glPatchParameteri(GL_PATCH_VERTICES, i);
3536 } else if (parse_str(line, "default level outer ", &line)) {
3537 count = sscanf(line, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
3538 if (count != 4) {
3539 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3540 piglit_report_result(PIGLIT_FAIL);
3542 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, f);
3543 } else if (parse_str(line, "default level inner ", &line)) {
3544 count = sscanf(line, "%f %f", &f[0], &f[1]);
3545 if (count != 2) {
3546 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3547 piglit_report_result(PIGLIT_FAIL);
3549 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, f);
3550 } else {
3551 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line);
3552 piglit_report_result(PIGLIT_FAIL);
3554 #else
3555 printf("patch parameters are only available in desktop GL\n");
3556 piglit_report_result(PIGLIT_SKIP);
3557 #endif
3560 static void
3561 set_provoking_vertex(const char *line)
3563 if (parse_str(line, "first", NULL)) {
3564 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT);
3565 } else if (parse_str(line, "last", NULL)) {
3566 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
3567 } else {
3568 fprintf(stderr, "Unknown provoking vertex parameter `%s'\n", line);
3569 piglit_report_result(PIGLIT_FAIL);
3573 static const struct string_to_enum enable_table[] = {
3574 { "GL_CLIP_PLANE0", GL_CLIP_PLANE0 },
3575 { "GL_CLIP_PLANE1", GL_CLIP_PLANE1 },
3576 { "GL_CLIP_PLANE2", GL_CLIP_PLANE2 },
3577 { "GL_CLIP_PLANE3", GL_CLIP_PLANE3 },
3578 { "GL_CLIP_PLANE4", GL_CLIP_PLANE4 },
3579 { "GL_CLIP_PLANE5", GL_CLIP_PLANE5 },
3580 { "GL_CLIP_PLANE6", GL_CLIP_PLANE0+6 },
3581 { "GL_CLIP_PLANE7", GL_CLIP_PLANE0+7 },
3582 { "GL_CLIP_DISTANCE0", GL_CLIP_DISTANCE0 },
3583 { "GL_CLIP_DISTANCE1", GL_CLIP_DISTANCE1 },
3584 { "GL_CLIP_DISTANCE2", GL_CLIP_DISTANCE2 },
3585 { "GL_CLIP_DISTANCE3", GL_CLIP_DISTANCE3 },
3586 { "GL_CLIP_DISTANCE4", GL_CLIP_DISTANCE4 },
3587 { "GL_CLIP_DISTANCE5", GL_CLIP_DISTANCE5 },
3588 { "GL_CLIP_DISTANCE6", GL_CLIP_DISTANCE6 },
3589 { "GL_CLIP_DISTANCE7", GL_CLIP_DISTANCE7 },
3590 { "GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE },
3591 { "GL_PROGRAM_POINT_SIZE", GL_PROGRAM_POINT_SIZE },
3592 { "GL_DEPTH_TEST", GL_DEPTH_TEST },
3593 { "GL_DEPTH_CLAMP", GL_DEPTH_CLAMP },
3594 { NULL, 0 }
3597 static void
3598 do_enable_disable(const char *line, bool enable_flag)
3600 GLenum value;
3601 REQUIRE(parse_enum_tab(enable_table, line, &value, NULL),
3602 "Bad enable/disable enum at: %s\n", line);
3604 if (enable_flag)
3605 glEnable(value);
3606 else
3607 glDisable(value);
3610 static const struct string_to_enum hint_target_table[] = {
3611 ENUM_STRING(GL_LINE_SMOOTH_HINT),
3612 ENUM_STRING(GL_POLYGON_SMOOTH_HINT),
3613 ENUM_STRING(GL_TEXTURE_COMPRESSION_HINT),
3614 ENUM_STRING(GL_FRAGMENT_SHADER_DERIVATIVE_HINT),
3615 { NULL, 0 }
3618 static const struct string_to_enum hint_param_table[] = {
3619 ENUM_STRING(GL_FASTEST),
3620 ENUM_STRING(GL_NICEST),
3621 ENUM_STRING(GL_DONT_CARE),
3622 { NULL, 0 }
3625 static void do_hint(const char *line)
3627 unsigned target, param;
3628 REQUIRE(parse_enum_tab(hint_target_table, line, &target, &line),
3629 "Bad hint target at: %s\n", line);
3630 REQUIRE(parse_enum_tab(hint_param_table, line, &param, &line),
3631 "Bad hint param at: %s\n", line);
3633 glHint(target, param);
3636 static void
3637 draw_instanced_rect(int primcount, float x, float y, float w, float h)
3639 float verts[4][4];
3641 piglit_require_extension("GL_ARB_draw_instanced");
3643 verts[0][0] = x;
3644 verts[0][1] = y;
3645 verts[0][2] = 0.0;
3646 verts[0][3] = 1.0;
3647 verts[1][0] = x + w;
3648 verts[1][1] = y;
3649 verts[1][2] = 0.0;
3650 verts[1][3] = 1.0;
3651 verts[2][0] = x;
3652 verts[2][1] = y + h;
3653 verts[2][2] = 0.0;
3654 verts[2][3] = 1.0;
3655 verts[3][0] = x + w;
3656 verts[3][1] = y + h;
3657 verts[3][2] = 0.0;
3658 verts[3][3] = 1.0;
3660 glVertexPointer(4, GL_FLOAT, 0, verts);
3661 glEnableClientState(GL_VERTEX_ARRAY);
3663 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, primcount);
3665 glDisableClientState(GL_VERTEX_ARRAY);
3669 static GLenum
3670 decode_drawing_mode(const char *mode_str)
3672 int i;
3674 for (i = GL_POINTS; i <= GL_PATCHES; ++i) {
3675 const char *name = piglit_get_prim_name(i);
3676 if (0 == strcmp(mode_str, name))
3677 return i;
3680 printf("unknown drawing mode \"%s\"\n", mode_str);
3681 piglit_report_result(PIGLIT_FAIL);
3683 /* Should not be reached, but return 0 to avoid compiler warning */
3684 return 0;
3687 static void
3688 handle_texparameter(const char *line)
3690 static const struct string_to_enum compare_funcs[] = {
3691 { "greater", GL_GREATER },
3692 { "gequal", GL_GEQUAL },
3693 { "less", GL_LESS },
3694 { "lequal", GL_LEQUAL },
3695 { "equal", GL_EQUAL },
3696 { "notequal", GL_NOTEQUAL },
3697 { "never", GL_NEVER },
3698 { "always", GL_ALWAYS },
3699 { NULL, 0 },
3701 static const struct string_to_enum depth_modes[] = {
3702 { "intensity", GL_INTENSITY },
3703 { "luminance", GL_LUMINANCE },
3704 { "alpha", GL_ALPHA },
3705 { "red", GL_RED }, /* Requires GL 3.0 or GL_ARB_texture_rg */
3706 { NULL, 0 },
3708 static const struct string_to_enum min_filter_modes[] = {
3709 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
3710 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
3711 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
3712 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR },
3713 { "nearest", GL_NEAREST },
3714 { "linear", GL_LINEAR },
3715 { NULL, 0 }
3717 static const struct string_to_enum mag_filter_modes[] = {
3718 { "nearest", GL_NEAREST },
3719 { "linear", GL_LINEAR },
3720 { NULL, 0 }
3722 static const struct string_to_enum wrap_modes[] = {
3723 { "repeat", GL_REPEAT },
3724 { "clamp_to_edge", GL_CLAMP_TO_EDGE },
3725 { "clamp_to_border", GL_CLAMP_TO_BORDER },
3726 { NULL, 0 }
3728 static const struct string_to_enum swizzle_modes[] = {
3729 { "red", GL_RED },
3730 { "green", GL_GREEN },
3731 { "blue", GL_BLUE },
3732 { "alpha", GL_ALPHA },
3733 { NULL, 0 }
3735 unsigned target = 0;
3736 GLenum parameter = GL_NONE;
3737 const char *parameter_name = NULL;
3738 const struct string_to_enum *strings = NULL;
3739 unsigned value;
3741 REQUIRE(parse_tex_target(line, &target, &line),
3742 "Bad texture target at: %s\n", line);
3744 if (parse_str(line, "compare_func ", &line)) {
3745 parameter = GL_TEXTURE_COMPARE_FUNC;
3746 parameter_name = "compare_func";
3747 strings = compare_funcs;
3748 } else if (parse_str(line, "depth_mode ", &line)) {
3749 parameter = GL_DEPTH_TEXTURE_MODE;
3750 parameter_name = "depth_mode";
3751 strings = depth_modes;
3752 } else if (parse_str(line, "min ", &line)) {
3753 parameter = GL_TEXTURE_MIN_FILTER;
3754 parameter_name = "min";
3755 strings = min_filter_modes;
3756 } else if (parse_str(line, "mag ", &line)) {
3757 parameter = GL_TEXTURE_MAG_FILTER;
3758 parameter_name = "mag";
3759 strings = mag_filter_modes;
3760 } else if (parse_str(line, "wrap_s ", &line)) {
3761 parameter = GL_TEXTURE_WRAP_S;
3762 parameter_name = "wrap_s";
3763 strings = wrap_modes;
3764 } else if (parse_str(line, "wrap_t ", &line)) {
3765 parameter = GL_TEXTURE_WRAP_T;
3766 parameter_name = "wrap_t";
3767 strings = wrap_modes;
3768 } else if (parse_str(line, "wrap_r ", &line)) {
3769 parameter = GL_TEXTURE_WRAP_R;
3770 parameter_name = "wrap_r";
3771 strings = wrap_modes;
3772 } else if (parse_str(line, "lod_bias ", &line)) {
3773 #ifdef PIGLIT_USE_OPENGL
3774 glTexParameterf(target, GL_TEXTURE_LOD_BIAS,
3775 strtod(line, NULL));
3776 return;
3777 #else
3778 printf("lod_bias feature is only available in desktop GL\n");
3779 piglit_report_result(PIGLIT_SKIP);
3780 #endif
3781 } else if (parse_str(line, "max_level ", &line)) {
3782 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL,
3783 strtol(line, NULL, 10));
3784 return;
3785 } else if (parse_str(line, "base_level ", &line)) {
3786 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL,
3787 strtol(line, NULL, 10));
3788 return;
3789 } else if (parse_str(line, "border_color ", &line)) {
3790 float bc[4];
3791 int count;
3792 count = sscanf(line, "%f %f %f %f", &bc[0], &bc[1], &bc[2], &bc[3]);
3793 if (count != 4) {
3794 fprintf(stderr, "Could not parse border_color texture parameter.\n");
3795 piglit_report_result(PIGLIT_FAIL);
3797 glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bc);
3798 return;
3799 } else if (parse_str(line, "swizzle_r ", &line)) {
3800 parameter = GL_TEXTURE_SWIZZLE_R;
3801 parameter_name = "swizzle_r";
3802 strings = swizzle_modes;
3803 } else {
3804 fprintf(stderr, "unknown texture parameter in `%s'\n", line);
3805 piglit_report_result(PIGLIT_FAIL);
3808 REQUIRE(parse_enum_tab(strings, line, &value, &line),
3809 "Bad %s at: %s\n", parameter_name, line);
3811 glTexParameteri(target, parameter, value);
3814 static const struct string_to_enum viewport_swizzle_table[] = {
3815 { "POSITIVE_X", GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV },
3816 { "NEGATIVE_X", GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV },
3817 { "POSITIVE_Y", GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV },
3818 { "NEGATIVE_Y", GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV },
3819 { "POSITIVE_Z", GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV },
3820 { "NEGATIVE_Z", GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV },
3821 { "POSITIVE_W", GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV },
3822 { "NEGATIVE_W", GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV },
3823 { NULL, 0 }
3826 static void
3827 handle_viewport_swizzle(const char *line)
3829 unsigned viewport;
3830 GLenum x, y, z, w;
3832 viewport = strtol(line, (char **)&line, 0);
3833 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &x, &line),
3834 "Bad ViewportSwizzle swizzle at: %s\n", line);
3835 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &y, &line),
3836 "Bad ViewportSwizzle swizzle at: %s\n", line);
3837 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &z, &line),
3838 "Bad ViewportSwizzle swizzle at: %s\n", line);
3839 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &w, &line),
3840 "Bad ViewportSwizzle swizzle at: %s\n", line);
3842 glViewportSwizzleNV(viewport, x, y, z, w);
3845 static void
3846 setup_ubos(void)
3848 int i;
3850 if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
3851 piglit_get_gl_version() < 31) {
3852 return;
3855 if (prog == 0) {
3856 /* probably running an ARB_vertex/fragment_program test */
3857 return;
3860 glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &num_uniform_blocks);
3861 if (num_uniform_blocks == 0)
3862 return;
3864 uniform_block_bos = calloc(num_uniform_blocks, sizeof(GLuint));
3865 glGenBuffers(num_uniform_blocks, uniform_block_bos);
3867 int max_ubos;
3868 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_ubos);
3869 uniform_block_indexes = calloc(max_ubos, sizeof(int));
3871 for (i = 0; i < num_uniform_blocks; i++) {
3872 GLint size;
3873 GLint binding;
3875 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_DATA_SIZE,
3876 &size);
3878 glBindBuffer(GL_UNIFORM_BUFFER, uniform_block_bos[i]);
3879 glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
3881 if (!force_no_names) {
3882 glUniformBlockBinding(prog, i, i);
3883 uniform_block_indexes[i] = i;
3884 binding = i;
3885 } else {
3886 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_BINDING,
3887 &binding);
3888 uniform_block_indexes[binding] = i;
3891 glBindBufferBase(GL_UNIFORM_BUFFER, binding, uniform_block_bos[i]);
3895 static void
3896 teardown_fbos(void)
3898 if (draw_fbo != 0 &&
3899 draw_fbo != piglit_winsys_fbo)
3900 glDeleteFramebuffers(1, &draw_fbo);
3902 if (read_fbo != 0 &&
3903 read_fbo != piglit_winsys_fbo &&
3904 read_fbo != draw_fbo)
3905 glDeleteFramebuffers(1, &read_fbo);
3907 draw_fbo = 0;
3908 read_fbo = 0;
3911 static void
3912 teardown_ubos(void)
3914 if (num_uniform_blocks == 0) {
3915 return;
3918 glDeleteBuffers(num_uniform_blocks, uniform_block_bos);
3919 free(uniform_block_bos);
3920 uniform_block_bos = NULL;
3921 free(uniform_block_indexes);
3922 uniform_block_indexes = NULL;
3923 num_uniform_blocks = 0;
3926 static void
3927 teardown_atomics(void)
3929 for (unsigned i = 0; i < ARRAY_SIZE(atomics_bos); ++i) {
3930 if (atomics_bos[i])
3931 glDeleteBuffers(1, &atomics_bos[i]);
3935 static void
3936 teardown_shader_include_paths(void)
3938 for (unsigned i = 0; i < num_shader_include_paths; i++)
3939 free(shader_include_path[i]);
3941 for (unsigned i = 0; i < num_shader_includes; i++) {
3942 glDeleteNamedStringARB(-1, shader_include_names[i]);
3943 free(shader_include_names[i]);
3946 num_shader_includes = 0;
3947 num_shader_include_paths = 0;
3948 free(shader_include_path);
3949 shader_include_path = NULL;
3952 static void
3953 teardown_xfb(void)
3955 glDeleteBuffers(MAX_XFB_BUFFERS, xfb);
3957 glDeleteQueries(1, &queries[query_index(GL_PRIMITIVES_GENERATED)]);
3958 glDeleteQueries(1, &queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)]);
3959 queries[query_index(GL_PRIMITIVES_GENERATED)] = 0;
3960 queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)] = 0;
3963 static enum piglit_result
3964 program_must_be_in_use(void)
3966 if (!link_ok) {
3967 fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
3968 return PIGLIT_FAIL;
3969 } else if (!prog_in_use) {
3970 fprintf(stderr, "Failed to use program: %s\n", prog_err_info);
3971 return PIGLIT_FAIL;
3973 return PIGLIT_PASS;
3976 static void
3977 bind_vao_if_supported()
3979 if (vao == 0 && piglit_is_core_profile) {
3980 glGenVertexArrays(1, &vao);
3981 glBindVertexArray(vao);
3985 static enum piglit_result
3986 draw_arrays_common(int first, size_t count)
3988 enum piglit_result result = program_must_be_in_use();
3989 if (first < 0) {
3990 printf("draw arrays 'first' must be >= 0\n");
3991 piglit_report_result(PIGLIT_FAIL);
3992 } else if (vbo_present &&
3993 (size_t) first >= num_vbo_rows) {
3994 printf("draw arrays 'first' must be < %lu\n",
3995 (unsigned long) num_vbo_rows);
3996 piglit_report_result(PIGLIT_FAIL);
3998 if (count <= 0) {
3999 printf("draw arrays 'count' must be > 0\n");
4000 piglit_report_result(PIGLIT_FAIL);
4001 } else if (vbo_present &&
4002 count > num_vbo_rows - (size_t) first) {
4003 printf("draw arrays cannot draw beyond %lu\n",
4004 (unsigned long) num_vbo_rows);
4005 piglit_report_result(PIGLIT_FAIL);
4007 bind_vao_if_supported();
4008 return result;
4011 static const struct string_to_enum light_table[] = {
4012 ENUM_STRING(GL_AMBIENT),
4013 ENUM_STRING(GL_DIFFUSE),
4014 ENUM_STRING(GL_SPECULAR),
4015 ENUM_STRING(GL_POSITION),
4016 ENUM_STRING(GL_SPOT_DIRECTION),
4017 ENUM_STRING(GL_SPOT_EXPONENT),
4018 ENUM_STRING(GL_SPOT_CUTOFF),
4019 ENUM_STRING(GL_CONSTANT_ATTENUATION),
4020 ENUM_STRING(GL_LINEAR_ATTENUATION),
4021 ENUM_STRING(GL_QUADRATIC_ATTENUATION),
4022 { NULL, 0 },
4025 static void
4026 set_light(const char *line)
4028 int index;
4029 GLenum attrib;
4031 REQUIRE(parse_int(line, &index, &line),
4032 "Bad light index at: %s\n", line);
4034 REQUIRE(parse_enum_tab(light_table, line, &attrib, &line),
4035 "Bad light enum at: %s\n", line);
4037 if (parse_str(line, "float", &line)) {
4038 float f[16];
4039 int n;
4041 REQUIRE((n = parse_floats(line, f, 16, NULL)) > 0,
4042 "No float found for light %s\n", line);
4044 if (n == 1)
4045 glLightf(GL_LIGHT0 + index, attrib, f[0]);
4046 else
4047 glLightfv(GL_LIGHT0 + index, attrib, f);
4048 } else if (parse_str(line, "int", &line)) {
4049 int i[16];
4050 int n;
4052 REQUIRE((n = parse_ints(line, i, 16, NULL)) > 0,
4053 "No int found for light %s\n", line);
4055 if (n == 1)
4056 glLighti(GL_LIGHT0 + index, attrib, i[0]);
4057 else
4058 glLightiv(GL_LIGHT0 + index, attrib, i);
4059 } else {
4060 printf("Invalid light value type \"%s\"\n", line);
4061 piglit_report_result(PIGLIT_FAIL);
4065 static bool
4066 probe_atomic_counter(unsigned buffer_num, GLint counter_num, const char *op,
4067 uint32_t value, bool uses_layout_qualifiers)
4069 uint32_t *p;
4070 uint32_t observed;
4071 enum comparison cmp;
4072 bool result;
4074 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4075 "Invalid comparison operation at: %s\n", op);
4077 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomics_bos[buffer_num]);
4078 p = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER,
4079 uses_layout_qualifiers ? counter_num : counter_num * sizeof(uint32_t),
4080 sizeof(uint32_t), GL_MAP_READ_BIT);
4082 if (!p) {
4083 printf("Couldn't map atomic counter to verify expected value.\n");
4084 return false;
4087 observed = *p;
4088 result = compare_uint(value, observed, cmp);
4090 if (!result) {
4091 if (uses_layout_qualifiers)
4092 printf("Atomic counter (binding = %d, offset = %d) test failed: "
4093 "Reference %s Observed\n",
4094 buffer_num, counter_num, comparison_string(cmp));
4095 else
4096 printf("Atomic counter %d test failed: Reference %s Observed\n",
4097 counter_num, comparison_string(cmp));
4098 printf(" Reference: %u\n", value);
4099 printf(" Observed: %u\n", observed);
4100 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4101 return false;
4104 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4105 return true;
4108 static bool
4109 probe_ssbo_uint(GLint ssbo_index, GLint ssbo_offset, const char *op, uint32_t value)
4111 uint32_t *p;
4112 uint32_t observed;
4113 enum comparison cmp;
4114 bool result;
4116 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4117 "Invalid comparison operation at: %s\n", op);
4119 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4120 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4121 sizeof(uint32_t), GL_MAP_READ_BIT);
4123 if (!p) {
4124 printf("Couldn't map ssbo to verify expected value.\n");
4125 return false;
4128 observed = *p;
4129 result = compare_uint(value, observed, cmp);
4131 if (!result) {
4132 printf("SSBO %d test failed: Reference %s Observed\n",
4133 ssbo_offset, comparison_string(cmp));
4134 printf(" Reference: %u\n", value);
4135 printf(" Observed: %u\n", observed);
4136 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4137 return false;
4140 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4141 return true;
4144 static bool
4145 probe_ssbo_uint64(GLint ssbo_index, GLint ssbo_offset, const char *op, uint64_t value)
4147 uint64_t *p;
4148 uint64_t observed;
4149 enum comparison cmp;
4150 bool result;
4152 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4153 "Invalid comparison operation at: %s\n", op);
4155 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4156 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4157 sizeof(uint64_t), GL_MAP_READ_BIT);
4159 if (!p) {
4160 printf("Couldn't map ssbo to verify expected value.\n");
4161 return false;
4164 observed = *p;
4165 result = compare_uint64(value, observed, cmp);
4167 if (!result) {
4168 printf("SSBO %d test failed: Reference %s Observed\n",
4169 ssbo_offset, comparison_string(cmp));
4170 printf(" Reference: %"PRIu64"\n", value);
4171 printf(" Observed: %"PRIu64"\n", observed);
4172 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4173 return false;
4176 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4177 return true;
4180 static bool
4181 probe_ssbo_int(GLint ssbo_index, GLint ssbo_offset, const char *op, int32_t value)
4183 int32_t *p;
4184 int32_t observed;
4185 enum comparison cmp;
4186 bool result;
4188 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4189 "Invalid comparison operation at: %s\n", op);
4191 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4192 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4193 sizeof(uint32_t), GL_MAP_READ_BIT);
4195 if (!p) {
4196 printf("Couldn't map ssbo to verify expected value.\n");
4197 return false;
4200 observed = *p;
4201 result = compare_int(value, observed, cmp);
4203 if (!result) {
4204 printf("SSBO %d test failed: Reference %s Observed\n",
4205 ssbo_offset, comparison_string(cmp));
4206 printf(" Reference: %d\n", value);
4207 printf(" Observed: %d\n", observed);
4208 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4209 return false;
4212 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4213 return true;
4216 static bool
4217 probe_ssbo_int64(GLint ssbo_index, GLint ssbo_offset, const char *op, int64_t value)
4219 int64_t *p;
4220 int64_t observed;
4221 enum comparison cmp;
4222 bool result;
4224 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4225 "Invalid comparison operation at: %s\n", op);
4227 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4228 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4229 sizeof(uint64_t), GL_MAP_READ_BIT);
4231 if (!p) {
4232 printf("Couldn't map ssbo to verify expected value.\n");
4233 return false;
4236 observed = *p;
4237 result = compare_int64(value, observed, cmp);
4239 if (!result) {
4240 printf("SSBO %d test failed: Reference %s Observed\n",
4241 ssbo_offset, comparison_string(cmp));
4242 printf(" Reference: %"PRId64"\n", value);
4243 printf(" Observed: %"PRId64"\n", observed);
4244 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4245 return false;
4248 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4249 return true;
4252 static bool
4253 probe_ssbo_double(GLint ssbo_index, GLint ssbo_offset, const char *op, double value)
4255 double *p;
4256 double observed;
4257 enum comparison cmp;
4258 bool result;
4260 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4261 "Invalid comparison operation at: %s\n", op);
4263 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4264 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4265 sizeof(double), GL_MAP_READ_BIT);
4267 if (!p) {
4268 printf("Couldn't map ssbo to verify expected value.\n");
4269 return false;
4272 observed = *p;
4273 result = compare_double(value, observed, cmp);
4275 if (!result) {
4276 printf("SSBO %d test failed: Reference %s Observed\n",
4277 ssbo_offset, comparison_string(cmp));
4278 printf(" Reference: %g\n", value);
4279 printf(" Observed: %g\n", observed);
4280 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4281 return false;
4284 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4285 return true;
4288 static bool
4289 probe_ssbo_float(GLint ssbo_index, GLint ssbo_offset, const char *op, float value)
4291 float *p;
4292 float observed;
4293 enum comparison cmp;
4294 bool result;
4296 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4297 "Invalid comparison operation at: %s\n", op);
4299 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4300 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4301 sizeof(float), GL_MAP_READ_BIT);
4303 if (!p) {
4304 printf("Couldn't map ssbo to verify expected value.\n");
4305 return false;
4308 observed = *p;
4309 result = compare_double(value, observed, cmp);
4311 if (!result) {
4312 printf("SSBO %d test failed: Reference %s Observed\n",
4313 ssbo_offset, comparison_string(cmp));
4314 printf(" Reference: %g\n", value);
4315 printf(" Observed: %g\n", observed);
4316 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4317 return false;
4320 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4321 return true;
4324 GLenum piglit_xfb_primitive_mode(GLenum draw_arrays_mode)
4326 switch (draw_arrays_mode) {
4327 case GL_POINTS:
4328 return GL_POINTS;
4329 case GL_LINES:
4330 case GL_LINE_LOOP:
4331 case GL_LINE_STRIP:
4332 case GL_LINES_ADJACENCY:
4333 case GL_LINE_STRIP_ADJACENCY:
4334 return GL_LINES;
4335 case GL_TRIANGLES:
4336 case GL_TRIANGLE_STRIP:
4337 case GL_TRIANGLE_FAN:
4338 case GL_TRIANGLES_ADJACENCY:
4339 case GL_TRIANGLE_STRIP_ADJACENCY:
4340 return GL_TRIANGLES;
4343 printf("glDrawArrays mode %s not supported for a transform feedback operation\n",
4344 piglit_get_gl_enum_name(draw_arrays_mode));
4345 piglit_report_result(PIGLIT_FAIL);
4348 static void
4349 begin_query(GLenum query_type)
4351 unsigned idx = query_index(query_type);
4352 if (queries[idx] == 0)
4353 glGenQueries(1, &queries[idx]);
4354 glBeginQuery(query_type, queries[idx]);
4357 static void
4358 piglit_xfb_draw_arrays(GLenum mode, int first, size_t count)
4360 GLenum primitive_mode = piglit_xfb_primitive_mode(mode);
4362 begin_query(GL_PRIMITIVES_GENERATED);
4363 begin_query(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4365 glEnable(GL_RASTERIZER_DISCARD);
4367 /* We don't need to call glBindBufferBase here, it is done on
4368 * the "xfb buffer object" command
4371 glBeginTransformFeedback(primitive_mode);
4372 glDrawArrays(mode, first, count);
4373 glEndTransformFeedback();
4375 glDisable(GL_RASTERIZER_DISCARD);
4377 glFlush();
4379 glEndQuery(GL_PRIMITIVES_GENERATED);
4380 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4383 static bool
4384 probe_xfb_float(GLuint buf, unsigned n, float expected)
4386 float *p;
4387 bool result;
4388 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4389 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(float),
4390 sizeof(float), GL_MAP_READ_BIT);
4391 if (!p) {
4392 printf("Couldn't map xfb buffer %u\n", buf);
4393 return false;
4395 result = fabsf(expected - *p) < piglit_tolerance[0];
4396 if (!result) {
4397 printf("xfb buffer %i[%i]: %f, Expected: %f\n",
4398 buf, n, *p, expected);
4401 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4402 return result;
4405 static bool
4406 probe_xfb_double(GLuint buf, unsigned n, double expected)
4408 double *p;
4409 bool result;
4411 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4412 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(double),
4413 sizeof(double), GL_MAP_READ_BIT);
4414 if (!p) {
4415 printf("Couldn't map xfb buffer %u\n", buf);
4416 return false;
4418 result = fabs(expected - *p) < piglit_tolerance[0];
4419 if (!result) {
4420 printf("xfb buffer %i[%i]: %lf, Expected: %lf\n",
4421 buf, n, *p, expected);
4424 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4425 return result;
4428 enum piglit_result
4429 piglit_display(void)
4431 const char *line, *next_line, *rest;
4432 unsigned line_num;
4433 enum piglit_result full_result = PIGLIT_PASS;
4434 GLbitfield clear_bits = 0;
4435 bool link_error_expected = false;
4436 unsigned list = 0;
4437 struct block_info block_data = {0, -1, -1, -1, -1};
4439 if (test_start == NULL)
4440 return PIGLIT_PASS;
4442 next_line = test_start;
4443 line_num = test_start_line_num;
4444 while (next_line[0] != '\0') {
4445 float c[32];
4446 double d[4];
4447 int x, y, z, w, h, l, tex, level;
4448 unsigned ux, uy, uz;
4449 int64_t ly, lz;
4450 uint64_t luy, luz;
4451 char s[300]; // 300 for safety
4452 enum piglit_result result = PIGLIT_PASS;
4454 parse_whitespace(next_line, &line);
4456 next_line = strchrnul(next_line, '\n');
4458 /* Duplicate the line to make it null terminated */
4459 line = strndup(line, next_line - line);
4461 /* If strchrnul found a newline, then skip it */
4462 if (next_line[0] != '\0')
4463 next_line++;
4465 if (line[0] == '\0') {
4466 } else if (sscanf(line, "active shader program %s", s) == 1) {
4467 switch (get_shader_from_string(s, &x)) {
4468 case GL_VERTEX_SHADER:
4469 glActiveShaderProgram(pipeline, sso_vertex_prog);
4470 break;
4471 case GL_TESS_CONTROL_SHADER:
4472 glActiveShaderProgram(pipeline, sso_tess_control_prog);
4473 break;
4474 case GL_TESS_EVALUATION_SHADER:
4475 glActiveShaderProgram(pipeline, sso_tess_eval_prog);
4476 break;
4477 case GL_GEOMETRY_SHADER:
4478 glActiveShaderProgram(pipeline, sso_geometry_prog);
4479 break;
4480 case GL_FRAGMENT_SHADER:
4481 glActiveShaderProgram(pipeline, sso_fragment_prog);
4482 break;
4483 case GL_COMPUTE_SHADER:
4484 glActiveShaderProgram(pipeline, sso_compute_prog);
4485 break;
4487 } else if (sscanf(line, "atomic counter buffer %u %u", &x, &y) == 2) {
4488 GLuint *atomics_buf = calloc(y, sizeof(GLuint));
4489 glGenBuffers(1, &atomics_bos[x]);
4490 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4491 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4492 sizeof(GLuint) * y, atomics_buf,
4493 GL_STATIC_DRAW);
4494 free(atomics_buf);
4495 } else if (sscanf(line, "atomic counters %d", &x) == 1) {
4496 GLuint *atomics_buf = calloc(x, sizeof(GLuint));
4497 glGenBuffers(1, &atomics_bos[0]);
4498 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomics_bos[0]);
4499 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4500 sizeof(GLuint) * x,
4501 atomics_buf, GL_STATIC_DRAW);
4502 free(atomics_buf);
4503 } else if (sscanf(line, "atomic counter %u %u %u", &x, &y, &z) == 3) {
4504 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4505 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER,
4506 sizeof(GLuint) * y, sizeof(GLuint),
4507 &z);
4508 } else if (parse_str(line, "clear color ", &rest)) {
4509 parse_floats(rest, c, 4, NULL);
4510 glClearColor(c[0], c[1], c[2], c[3]);
4511 clear_bits |= GL_COLOR_BUFFER_BIT;
4512 } else if (parse_str(line, "clear depth ", &rest)) {
4513 parse_floats(rest, c, 1, NULL);
4514 glClearDepth(c[0]);
4515 clear_bits |= GL_DEPTH_BUFFER_BIT;
4516 } else if (parse_str(line, "clear", NULL)) {
4517 glClear(clear_bits);
4518 } else if (sscanf(line,
4519 "clip plane %d %lf %lf %lf %lf",
4520 &x, &d[0], &d[1], &d[2], &d[3]) == 5) {
4521 if (x < 0 || x >= gl_max_clip_planes) {
4522 printf("clip plane id %d out of range\n", x);
4523 piglit_report_result(PIGLIT_FAIL);
4525 glClipPlane(GL_CLIP_PLANE0 + x, d);
4526 #ifdef PIGLIT_USE_OPENGL
4527 } else if (parse_str(line, "color ", &rest)) {
4528 parse_floats(rest, c, 4, NULL);
4529 assert(!piglit_is_core_profile);
4530 glColor4fv(c);
4531 #endif
4532 } else if (sscanf(line,
4533 "compute %d %d %d",
4534 &x, &y, &z) == 3) {
4535 result = program_must_be_in_use();
4536 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4537 glDispatchCompute(x, y, z);
4538 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4539 } else if (sscanf(line,
4540 "compute group size %d %d %d %d %d %d",
4541 &x, &y, &z, &w, &h, &l) == 6) {
4542 result = program_must_be_in_use();
4543 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4544 glDispatchComputeGroupSizeARB(x, y, z, w, h, l);
4545 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4546 } else if (parse_str(line, "draw rect tex ", &rest)) {
4547 result = program_must_be_in_use();
4548 program_subroutine_uniforms();
4549 parse_floats(rest, c, 8, NULL);
4550 piglit_draw_rect_tex(c[0], c[1], c[2], c[3],
4551 c[4], c[5], c[6], c[7]);
4552 } else if (parse_str(line, "draw rect ortho patch ", &rest)) {
4553 result = program_must_be_in_use();
4554 program_subroutine_uniforms();
4555 parse_floats(rest, c, 4, NULL);
4557 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4558 -1.0 + 2.0 * (c[1] / piglit_height),
4559 2.0 * (c[2] / piglit_width),
4560 2.0 * (c[3] / piglit_height), true, 1);
4561 } else if (parse_str(line, "draw rect ortho ", &rest)) {
4562 result = program_must_be_in_use();
4563 program_subroutine_uniforms();
4564 parse_floats(rest, c, 4, NULL);
4566 piglit_draw_rect(-1.0 + 2.0 * (c[0] / piglit_width),
4567 -1.0 + 2.0 * (c[1] / piglit_height),
4568 2.0 * (c[2] / piglit_width),
4569 2.0 * (c[3] / piglit_height));
4570 } else if (parse_str(line, "draw rect patch ", &rest)) {
4571 result = program_must_be_in_use();
4572 parse_floats(rest, c, 4, NULL);
4573 piglit_draw_rect_custom(c[0], c[1], c[2], c[3], true, 1);
4574 } else if (parse_str(line, "draw rect ", &rest)) {
4575 result = program_must_be_in_use();
4576 program_subroutine_uniforms();
4577 parse_floats(rest, c, 4, NULL);
4578 piglit_draw_rect(c[0], c[1], c[2], c[3]);
4579 } else if (parse_str(line, "draw instanced rect ortho patch ", &rest)) {
4580 int instance_count;
4582 result = program_must_be_in_use();
4583 sscanf(rest, "%d %f %f %f %f",
4584 &instance_count,
4585 c + 0, c + 1, c + 2, c + 3);
4586 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4587 -1.0 + 2.0 * (c[1] / piglit_height),
4588 2.0 * (c[2] / piglit_width),
4589 2.0 * (c[3] / piglit_height), true,
4590 instance_count);
4591 } else if (parse_str(line, "draw instanced rect ortho ", &rest)) {
4592 int instance_count;
4594 result = program_must_be_in_use();
4595 sscanf(rest, "%d %f %f %f %f",
4596 &instance_count,
4597 c + 0, c + 1, c + 2, c + 3);
4598 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4599 -1.0 + 2.0 * (c[1] / piglit_height),
4600 2.0 * (c[2] / piglit_width),
4601 2.0 * (c[3] / piglit_height), false,
4602 instance_count);
4603 } else if (parse_str(line, "draw instanced rect ", &rest)) {
4604 int primcount;
4606 result = program_must_be_in_use();
4607 sscanf(rest, "%d %f %f %f %f",
4608 &primcount,
4609 c + 0, c + 1, c + 2, c + 3);
4610 draw_instanced_rect(primcount, c[0], c[1], c[2], c[3]);
4611 } else if (sscanf(line, "draw arrays instanced %31s %d %d %d", s, &x, &y, &z) == 4) {
4612 GLenum mode = decode_drawing_mode(s);
4613 int first = x;
4614 size_t count = (size_t) y;
4615 size_t primcount = (size_t) z;
4616 draw_arrays_common(first, count);
4617 glDrawArraysInstanced(mode, first, count, primcount);
4618 } else if (sscanf(line, "draw arrays %31s %d %d", s, &x, &y) == 3) {
4619 GLenum mode = decode_drawing_mode(s);
4620 int first = x;
4621 size_t count = (size_t) y;
4622 result = draw_arrays_common(first, count);
4623 glDrawArrays(mode, first, count);
4624 } else if (parse_str(line, "disable ", &rest)) {
4625 do_enable_disable(rest, false);
4626 } else if (parse_str(line, "enable ", &rest)) {
4627 do_enable_disable(rest, true);
4628 } else if (sscanf(line, "depthfunc %31s", s) == 1) {
4629 glDepthFunc(piglit_get_gl_enum_from_name(s));
4630 } else if (parse_str(line, "fb ", &rest)) {
4631 const GLenum target =
4632 parse_str(rest, "draw ", &rest) ? GL_DRAW_FRAMEBUFFER :
4633 parse_str(rest, "read ", &rest) ? GL_READ_FRAMEBUFFER :
4634 GL_FRAMEBUFFER;
4635 GLuint fbo = 0;
4637 if (parse_str(rest, "tex 2d ", &rest)) {
4638 GLenum attachments[32];
4639 unsigned num_attachments = 0;
4641 glGenFramebuffers(1, &fbo);
4642 glBindFramebuffer(target, fbo);
4644 while (parse_int(rest, &tex, &rest)) {
4645 attachments[num_attachments] =
4646 GL_COLOR_ATTACHMENT0 + num_attachments;
4647 glFramebufferTexture2D(
4648 target, attachments[num_attachments],
4649 GL_TEXTURE_2D,
4650 tex == -1 ? 0 : get_texture_binding(tex)->obj, 0);
4652 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4653 fprintf(stderr,
4654 "glFramebufferTexture2D error\n");
4655 piglit_report_result(PIGLIT_FAIL);
4658 num_attachments++;
4659 if (tex != -1) {
4660 w = get_texture_binding(tex)->width;
4661 h = get_texture_binding(tex)->height;
4665 if (target != GL_READ_FRAMEBUFFER)
4666 glDrawBuffers(num_attachments, attachments);
4669 } else if (parse_str(rest, "tex slice ", &rest)) {
4670 GLenum tex_target;
4672 REQUIRE(parse_tex_target(rest, &tex_target, &rest) &&
4673 parse_int(rest, &tex, &rest) &&
4674 parse_int(rest, &l, &rest) &&
4675 parse_int(rest, &z, &rest),
4676 "Framebuffer binding command not "
4677 "understood at: %s\n", rest);
4679 const GLuint tex_obj = get_texture_binding(tex)->obj;
4681 glGenFramebuffers(1, &fbo);
4682 glBindFramebuffer(target, fbo);
4684 if (tex_target == GL_TEXTURE_1D) {
4685 REQUIRE(z == 0,
4686 "Invalid layer index provided "
4687 "in command: %s\n", line);
4688 glFramebufferTexture1D(
4689 target, GL_COLOR_ATTACHMENT0,
4690 tex_target, tex_obj, l);
4692 } else if (tex_target == GL_TEXTURE_2D ||
4693 tex_target == GL_TEXTURE_RECTANGLE ||
4694 tex_target == GL_TEXTURE_2D_MULTISAMPLE) {
4695 REQUIRE(z == 0,
4696 "Invalid layer index provided "
4697 "in command: %s\n", line);
4698 glFramebufferTexture2D(
4699 target, GL_COLOR_ATTACHMENT0,
4700 tex_target, tex_obj, l);
4702 } else if (tex_target == GL_TEXTURE_CUBE_MAP) {
4703 static const GLenum cubemap_targets[] = {
4704 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
4705 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4706 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
4707 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4708 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
4709 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4711 REQUIRE(z < ARRAY_SIZE(cubemap_targets),
4712 "Invalid layer index provided "
4713 "in command: %s\n", line);
4714 tex_target = cubemap_targets[z];
4716 glFramebufferTexture2D(
4717 target, GL_COLOR_ATTACHMENT0,
4718 tex_target, tex_obj, l);
4720 } else {
4721 glFramebufferTextureLayer(
4722 target, GL_COLOR_ATTACHMENT0,
4723 tex_obj, l, z);
4726 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4727 fprintf(stderr, "Error binding texture "
4728 "attachment for command: %s\n",
4729 line);
4730 piglit_report_result(PIGLIT_FAIL);
4733 w = MAX2(1, get_texture_binding(tex)->width >> l);
4734 h = MAX2(1, get_texture_binding(tex)->height >> l);
4736 } else if (sscanf(rest, "tex layered %d", &tex) == 1) {
4737 glGenFramebuffers(1, &fbo);
4738 glBindFramebuffer(target, fbo);
4740 glFramebufferTexture(
4741 target, GL_COLOR_ATTACHMENT0,
4742 get_texture_binding(tex)->obj, 0);
4743 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4744 fprintf(stderr,
4745 "glFramebufferTexture error\n");
4746 piglit_report_result(PIGLIT_FAIL);
4749 w = get_texture_binding(tex)->width;
4750 h = get_texture_binding(tex)->height;
4752 } else if (parse_str(rest, "ms ", &rest)) {
4753 GLuint rb;
4754 GLenum format;
4755 int samples;
4757 REQUIRE(parse_enum_gl(rest, &format, &rest) &&
4758 parse_int(rest, &w, &rest) &&
4759 parse_int(rest, &h, &rest) &&
4760 parse_int(rest, &samples, &rest),
4761 "Framebuffer binding command not "
4762 "understood at: %s\n", rest);
4764 glGenFramebuffers(1, &fbo);
4765 glBindFramebuffer(target, fbo);
4767 glGenRenderbuffers(1, &rb);
4768 glBindRenderbuffer(GL_RENDERBUFFER, rb);
4770 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
4771 format, w, h);
4773 glFramebufferRenderbuffer(target,
4774 GL_COLOR_ATTACHMENT0,
4775 GL_RENDERBUFFER, rb);
4777 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4778 fprintf(stderr, "glFramebufferRenderbuffer error\n");
4779 piglit_report_result(PIGLIT_FAIL);
4782 } else if (parse_str(rest, "winsys", &rest)) {
4783 fbo = piglit_winsys_fbo;
4784 glBindFramebuffer(target, fbo);
4785 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4786 fprintf(stderr, "glBindFramebuffer error\n");
4787 piglit_report_result(PIGLIT_FAIL);
4790 w = piglit_width;
4791 h = piglit_height;
4793 } else {
4794 fprintf(stderr, "Unknown fb bind subcommand "
4795 "\"%s\"\n", rest);
4796 piglit_report_result(PIGLIT_FAIL);
4799 const GLenum status = glCheckFramebufferStatus(target);
4800 if (status != GL_FRAMEBUFFER_COMPLETE) {
4801 fprintf(stderr, "incomplete fbo (status 0x%x)\n",
4802 status);
4803 piglit_report_result(PIGLIT_FAIL);
4806 if (target != GL_READ_FRAMEBUFFER) {
4807 render_width = w;
4808 render_height = h;
4810 /* Delete the previous draw FB in case
4811 * it's no longer reachable.
4813 if (draw_fbo != 0 &&
4814 draw_fbo != piglit_winsys_fbo &&
4815 draw_fbo != (target == GL_DRAW_FRAMEBUFFER ?
4816 read_fbo : 0))
4817 glDeleteFramebuffers(1, &draw_fbo);
4819 draw_fbo = fbo;
4822 if (target != GL_DRAW_FRAMEBUFFER) {
4823 read_width = w;
4824 read_height = h;
4826 /* Delete the previous read FB in case
4827 * it's no longer reachable.
4829 if (read_fbo != 0 &&
4830 read_fbo != piglit_winsys_fbo &&
4831 read_fbo != (target == GL_READ_FRAMEBUFFER ?
4832 draw_fbo : 0))
4833 glDeleteFramebuffers(1, &read_fbo);
4835 read_fbo = fbo;
4838 } else if (parse_str(line, "blit ", &rest)) {
4839 static const struct string_to_enum buffers[] = {
4840 { "color", GL_COLOR_BUFFER_BIT },
4841 { "depth", GL_DEPTH_BUFFER_BIT },
4842 { "stencil", GL_STENCIL_BUFFER_BIT },
4843 { NULL }
4845 static const struct string_to_enum filters[] = {
4846 { "linear", GL_LINEAR },
4847 { "nearest", GL_NEAREST },
4848 { NULL }
4850 unsigned buffer, filter;
4852 REQUIRE(parse_enum_tab(buffers, rest, &buffer, &rest) &&
4853 parse_enum_tab(filters, rest, &filter, &rest),
4854 "FB blit command not understood at: %s\n",
4855 rest);
4857 glBlitFramebuffer(0, 0, read_width, read_height,
4858 0, 0, render_width, render_height,
4859 buffer, filter);
4861 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4862 fprintf(stderr, "glBlitFramebuffer error\n");
4863 piglit_report_result(PIGLIT_FAIL);
4866 } else if (parse_str(line, "frustum", &rest)) {
4867 parse_floats(rest, c, 6, NULL);
4868 piglit_frustum_projection(false, c[0], c[1], c[2],
4869 c[3], c[4], c[5]);
4870 } else if (parse_str(line, "hint", &rest)) {
4871 do_hint(rest);
4872 } else if (sscanf(line,
4873 "image texture %d %31s",
4874 &tex, s) == 2) {
4875 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
4876 glBindImageTexture(tex, get_texture_binding(tex)->obj, 0,
4877 GL_FALSE, 0, GL_READ_WRITE, img_fmt);
4878 } else if (sscanf(line, "memory barrier %s", s) == 1) {
4879 glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s));
4880 } else if (parse_str(line, "blend barrier", NULL)) {
4881 glBlendBarrier();
4882 } else if (parse_str(line, "fbfetch barrier", NULL)) {
4883 glFramebufferFetchBarrierEXT();
4884 } else if (sscanf(line, "ortho %f %f %f %f",
4885 c + 0, c + 1, c + 2, c + 3) == 4) {
4886 piglit_gen_ortho_projection(c[0], c[1], c[2], c[3],
4887 -1, 1, GL_FALSE);
4888 } else if (parse_str(line, "ortho", NULL)) {
4889 piglit_ortho_projection(render_width, render_height,
4890 GL_FALSE);
4891 } else if (sscanf(line, "viewport indexed %u %f %f %f %f",
4892 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
4893 glViewportIndexedfv(x, c);
4894 } else if (parse_str(line, "probe rgba ", &rest)) {
4895 parse_floats(rest, c, 6, NULL);
4896 if (!piglit_probe_pixel_rgba((int) c[0], (int) c[1],
4897 & c[2])) {
4898 result = PIGLIT_FAIL;
4900 } else if (parse_str(line, "probe depth ", &rest)) {
4901 parse_floats(rest, c, 3, NULL);
4902 if (!piglit_probe_pixel_depth((int) c[0], (int) c[1],
4903 c[2])) {
4904 result = PIGLIT_FAIL;
4906 } else if (sscanf(line,
4907 "probe atomic counter buffer %u %u %s %u",
4908 &ux, &uy, s, &uz) == 4) {
4909 if (!probe_atomic_counter(ux, uy, s, uz, true)) {
4910 result = PIGLIT_FAIL;
4912 } else if (sscanf(line,
4913 "probe atomic counter %u %s %u",
4914 &ux, s, &uy) == 3) {
4915 if (!probe_atomic_counter(0, ux, s, uy, false)) {
4916 result = PIGLIT_FAIL;
4918 } else if (sscanf(line, "probe ssbo uint %d %d %s 0x%x",
4919 &x, &y, s, &z) == 4) {
4920 if (!probe_ssbo_uint(x, y, s, z))
4921 result = PIGLIT_FAIL;
4922 } else if (sscanf(line, "probe ssbo uint %d %d %s %d",
4923 &x, &y, s, &z) == 4) {
4924 if (!probe_ssbo_uint(x, y, s, z))
4925 result = PIGLIT_FAIL;
4926 } else if (sscanf(line, "probe ssbo uint64 %d %d %s %"PRIu64,
4927 &x, &y, s, &luz) == 4) {
4928 if (!probe_ssbo_uint64(x, y, s, luz))
4929 result = PIGLIT_FAIL;
4930 } else if (sscanf(line, "probe ssbo int %d %d %s %d",
4931 &x, &y, s, &z) == 4) {
4932 if (!probe_ssbo_int(x, y, s, z))
4933 result = PIGLIT_FAIL;
4934 } else if (sscanf(line, "probe ssbo int64 %d %d %s %"PRId64,
4935 &x, &y, s, &lz) == 4) {
4936 if (!probe_ssbo_int64(x, y, s, lz))
4937 result = PIGLIT_FAIL;
4938 } else if (sscanf(line, "probe ssbo double %d %d %s %lf",
4939 &x, &y, s, &d[0]) == 4) {
4940 if (!probe_ssbo_double(x, y, s, d[0]))
4941 result = PIGLIT_FAIL;
4942 } else if (sscanf(line, "probe ssbo float %d %d %s %f",
4943 &x, &y, s, &c[0]) == 4) {
4944 if (!probe_ssbo_float(x, y, s, c[0]))
4945 result = PIGLIT_FAIL;
4946 } else if (sscanf(line,
4947 "relative probe rgba ( %f , %f ) "
4948 "( %f , %f , %f , %f )",
4949 c + 0, c + 1,
4950 c + 2, c + 3, c + 4, c + 5) == 6) {
4951 x = c[0] * read_width;
4952 y = c[1] * read_height;
4953 if (x >= read_width)
4954 x = read_width - 1;
4955 if (y >= read_height)
4956 y = read_height - 1;
4958 if (!piglit_probe_pixel_rgba(x, y, &c[2])) {
4959 result = PIGLIT_FAIL;
4961 } else if (parse_str(line, "probe rgb ", &rest)) {
4962 parse_floats(rest, c, 5, NULL);
4963 if (!piglit_probe_pixel_rgb((int) c[0], (int) c[1],
4964 & c[2])) {
4965 result = PIGLIT_FAIL;
4967 } else if (sscanf(line,
4968 "relative probe rgb ( %f , %f ) "
4969 "( %f , %f , %f )",
4970 c + 0, c + 1,
4971 c + 2, c + 3, c + 4) == 5) {
4972 x = c[0] * read_width;
4973 y = c[1] * read_height;
4974 if (x >= read_width)
4975 x = read_width - 1;
4976 if (y >= read_height)
4977 y = read_height - 1;
4979 if (!piglit_probe_pixel_rgb(x, y, &c[2])) {
4980 result = PIGLIT_FAIL;
4982 } else if (sscanf(line, "probe rect rgba "
4983 "( %d , %d , %d , %d ) "
4984 "( %f , %f , %f , %f )",
4985 &x, &y, &w, &h,
4986 c + 0, c + 1, c + 2, c + 3) == 8) {
4987 if (!piglit_probe_rect_rgba(x, y, w, h, c)) {
4988 result = PIGLIT_FAIL;
4990 } else if (sscanf(line, "relative probe rect rgb "
4991 "( %f , %f , %f , %f ) "
4992 "( %f , %f , %f )",
4993 c + 0, c + 1, c + 2, c + 3,
4994 c + 4, c + 5, c + 6) == 7) {
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_rgb(x, y, w, h, &c[4])) {
5001 result = PIGLIT_FAIL;
5003 } else if (sscanf(line, "relative probe rect rgba "
5004 "( %f , %f , %f , %f ) "
5005 "( %f , %f , %f , %f )",
5006 c + 0, c + 1, c + 2, c + 3,
5007 c + 4, c + 5, c + 6, c + 7) == 8) {
5008 x = c[0] * read_width;
5009 y = c[1] * read_height;
5010 w = c[2] * read_width;
5011 h = c[3] * read_height;
5013 if (!piglit_probe_rect_rgba(x, y, w, h, &c[4])) {
5014 result = PIGLIT_FAIL;
5016 } else if (sscanf(line, "relative probe rect rgba int "
5017 "( %f , %f , %f , %f ) "
5018 "( %d , %d , %d , %d )",
5019 c + 0, c + 1, c + 2, c + 3,
5020 &x, &y, &z, &w) == 8) {
5021 const int expected[] = { x, y, z, w };
5022 if (!piglit_probe_rect_rgba_int(c[0] * read_width,
5023 c[1] * read_height,
5024 c[2] * read_width,
5025 c[3] * read_height,
5026 expected))
5027 result = PIGLIT_FAIL;
5029 } else if (parse_str(line, "polygon mode ", &rest)) {
5030 GLenum face, mode;
5032 REQUIRE(parse_enum_gl(rest, &face, &rest) &&
5033 parse_enum_gl(rest, &mode, &rest),
5034 "Polygon mode command not understood at %s\n",
5035 rest);
5037 glPolygonMode(face, mode);
5039 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5040 fprintf(stderr, "glPolygonMode error\n");
5041 piglit_report_result(PIGLIT_FAIL);
5043 } else if (parse_str(line, "probe all rgba ", &rest)) {
5044 parse_floats(rest, c, 4, NULL);
5045 if (result != PIGLIT_FAIL &&
5046 !piglit_probe_rect_rgba(0, 0, read_width,
5047 read_height, c))
5048 result = PIGLIT_FAIL;
5049 } else if (parse_str(line, "probe warn all rgba ", &rest)) {
5050 parse_floats(rest, c, 4, NULL);
5051 if (result == PIGLIT_PASS &&
5052 !piglit_probe_rect_rgba(0, 0, read_width,
5053 read_height, c))
5054 result = PIGLIT_WARN;
5055 } else if (parse_str(line, "probe all rgb", &rest)) {
5056 parse_floats(rest, c, 3, NULL);
5057 if (result != PIGLIT_FAIL &&
5058 !piglit_probe_rect_rgb(0, 0, read_width,
5059 read_height, c))
5060 result = PIGLIT_FAIL;
5061 } else if (parse_str(line, "tolerance", &rest)) {
5062 parse_floats(rest, piglit_tolerance, 4, NULL);
5063 } else if (parse_str(line, "shade model smooth", NULL)) {
5064 glShadeModel(GL_SMOOTH);
5065 } else if (parse_str(line, "shade model flat", NULL)) {
5066 glShadeModel(GL_FLAT);
5067 } else if (sscanf(line, "ssbo %d %d", &x, &y) == 2) {
5068 GLuint *ssbo_init = calloc(y, 1);
5069 glGenBuffers(1, &ssbo[x]);
5070 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, x, ssbo[x]);
5071 glBufferData(GL_SHADER_STORAGE_BUFFER, y,
5072 ssbo_init, GL_DYNAMIC_DRAW);
5073 free(ssbo_init);
5075 else if (sscanf(line, "xfb buffer object %u %u", &ux, &uy) == 2) {
5076 GLuint *xfb_init = calloc(uy, 1);
5077 if (ux >= MAX_XFB_BUFFERS) {
5078 printf("xfb buffer id %d out of range\n", ux);
5079 piglit_report_result(PIGLIT_FAIL);
5081 glGenBuffers(1, &xfb[ux]);
5082 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, ux, xfb[ux]);
5083 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, uy,
5084 xfb_init, GL_STREAM_READ);
5085 free(xfb_init);
5086 } else if (sscanf(line, "xfb draw arrays %31s %d %d", s, &x, &y) == 3) {
5087 GLenum mode = decode_drawing_mode(s);
5088 int first = x;
5089 size_t count = (size_t) y;
5090 result = draw_arrays_common(first, count);
5091 piglit_xfb_draw_arrays(mode, first, count);
5092 } else if (sscanf(line, "probe xfb buffer float %u %u %f",
5093 &ux, &uy, &c[0]) == 3) {
5094 if (!probe_xfb_float(xfb[ux], uy, c[0]))
5095 result = PIGLIT_FAIL;
5096 } else if (sscanf(line, "probe xfb buffer double %u %u %lf",
5097 &ux, &uy, &d[0]) == 3) {
5098 if (!probe_xfb_double(xfb[ux], uy, d[0]))
5099 result = PIGLIT_FAIL;
5100 } else if (sscanf(line, "ssbo %d subdata float %d %f", &x, &y, &c[0]) == 3) {
5101 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5102 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &c[0]);
5103 } else if (sscanf(line, "ssbo %d subdata double %d %s", &x, &y, s) == 3) {
5104 parse_doubles(s, &d[0], 1, NULL);
5105 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5106 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, sizeof(double), &d[0]);
5107 } else if (sscanf(line, "ssbo %d subdata int64 %"PRId64" %s", &x, &ly, s) == 3) {
5108 parse_int64s(s, &lz, 1, NULL);
5109 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5110 glBufferSubData(GL_SHADER_STORAGE_BUFFER, ly, sizeof(int64_t), &lz);
5111 } else if (sscanf(line, "ssbo %d subdata uint64 %"PRIu64" %s", &x, &luy, s) == 3) {
5112 parse_uint64s(s, &luz, 1, NULL);
5113 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5114 glBufferSubData(GL_SHADER_STORAGE_BUFFER, luy, sizeof(uint64_t), &luz);
5115 } else if (sscanf(line, "ssbo %d subdata int %d %s", &x, &y, s) == 3) {
5116 parse_ints(s, &z, 1, NULL);
5117 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
5118 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &z);
5119 } else if (sscanf(line, "texture rgbw %d ( %d", &tex, &w) == 2) {
5120 GLenum int_fmt = GL_RGBA;
5121 int num_scanned =
5122 sscanf(line,
5123 "texture rgbw %d ( %d , %d ) %31s",
5124 &tex, &w, &h, s);
5125 if (num_scanned < 3) {
5126 fprintf(stderr,
5127 "invalid texture rgbw command!\n");
5128 piglit_report_result(PIGLIT_FAIL);
5131 if (num_scanned >= 4) {
5132 int_fmt = piglit_get_gl_enum_from_name(s);
5135 glActiveTexture(GL_TEXTURE0 + tex);
5136 int handle = piglit_rgbw_texture(
5137 int_fmt, w, h, GL_FALSE, GL_FALSE,
5138 (piglit_is_gles() ? GL_UNSIGNED_BYTE :
5139 GL_UNSIGNED_NORMALIZED));
5140 set_texture_binding(tex, handle, w, h, 1);
5142 if (!piglit_is_core_profile &&
5143 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5144 glEnable(GL_TEXTURE_2D);
5146 } else if (sscanf(line, "resident texture %d", &tex) == 1) {
5147 GLuint64 handle;
5149 glBindTexture(GL_TEXTURE_2D, 0);
5151 handle = glGetTextureHandleARB(get_texture_binding(tex)->obj);
5152 glMakeTextureHandleResidentARB(handle);
5154 set_resident_handle(tex, handle, true);
5156 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5157 fprintf(stderr,
5158 "glMakeTextureHandleResidentARB error\n");
5159 piglit_report_result(PIGLIT_FAIL);
5161 } else if (sscanf(line, "resident texture 1D %d", &tex) == 1) {
5162 GLuint64 handle;
5164 glBindTexture(GL_TEXTURE_1D, 0);
5166 handle = glGetTextureHandleARB(get_texture_binding(tex)->obj);
5167 glMakeTextureHandleResidentARB(handle);
5169 set_resident_handle(tex, handle, true);
5171 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5172 fprintf(stderr,
5173 "glMakeTextureHandleResidentARB error\n");
5174 piglit_report_result(PIGLIT_FAIL);
5176 } else if (sscanf(line, "resident image texture %d %31s",
5177 &tex, s) == 2) {
5178 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
5179 GLuint64 handle;
5181 glBindTexture(GL_TEXTURE_2D, 0);
5183 handle = glGetImageHandleARB(get_texture_binding(tex)->obj,
5184 0, GL_FALSE, 0, img_fmt);
5185 glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
5187 set_resident_handle(tex, handle, false);
5189 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5190 fprintf(stderr,
5191 "glMakeImageHandleResidentARB error\n");
5192 piglit_report_result(PIGLIT_FAIL);
5194 } else if (parse_str(line, "texture integer ", &rest)) {
5195 GLenum int_fmt;
5196 int b, a;
5197 int num_scanned =
5198 sscanf(rest, "%d ( %d , %d ) ( %d, %d ) %31s",
5199 &tex, &w, &h, &b, &a, s);
5200 if (num_scanned < 6) {
5201 fprintf(stderr,
5202 "invalid texture integer command!\n");
5203 piglit_report_result(PIGLIT_FAIL);
5206 int_fmt = piglit_get_gl_enum_from_name(s);
5208 glActiveTexture(GL_TEXTURE0 + tex);
5209 const GLuint handle =
5210 piglit_integer_texture(int_fmt, w, h, b, a);
5211 set_texture_binding(tex, handle, w, h, 1);
5213 } else if (sscanf(line, "texture miptree %d", &tex) == 1) {
5214 glActiveTexture(GL_TEXTURE0 + tex);
5215 const GLuint handle = piglit_miptree_texture();
5216 set_texture_binding(tex, handle, 8, 8, 1);
5218 if (!piglit_is_core_profile &&
5219 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5220 glEnable(GL_TEXTURE_2D);
5221 } else if (sscanf(line,
5222 "texture checkerboard %d %d ( %d , %d ) "
5223 "( %f , %f , %f , %f ) "
5224 "( %f , %f , %f , %f )",
5225 &tex, &level, &w, &h,
5226 c + 0, c + 1, c + 2, c + 3,
5227 c + 4, c + 5, c + 6, c + 7) == 12) {
5228 glActiveTexture(GL_TEXTURE0 + tex);
5229 const GLuint handle = piglit_checkerboard_texture(
5230 0, level, w, h, w / 2, h / 2, c + 0, c + 4);
5231 set_texture_binding(tex, handle, w, h, 1);
5233 if (!piglit_is_core_profile &&
5234 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5235 glEnable(GL_TEXTURE_2D);
5236 } else if (sscanf(line,
5237 "texture quads %d %d ( %d , %d ) ( %d , %d ) "
5238 "( %f , %f , %f , %f ) "
5239 "( %f , %f , %f , %f ) "
5240 "( %f , %f , %f , %f ) "
5241 "( %f , %f , %f , %f )",
5242 &tex, &level, &w, &h, &x, &y,
5243 c + 0, c + 1, c + 2, c + 3,
5244 c + 4, c + 5, c + 6, c + 7,
5245 c + 8, c + 9, c + 10, c + 11,
5246 c + 12, c + 13, c + 14, c + 15) == 22) {
5247 glActiveTexture(GL_TEXTURE0 + tex);
5248 const GLuint handle = piglit_quads_texture(
5249 0, level, w, h, x, y, c + 0, c + 4, c + 8, c + 12);
5250 set_texture_binding(tex, handle, w, h, 1);
5252 if (!piglit_is_core_profile &&
5253 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5254 glEnable(GL_TEXTURE_2D);
5255 } else if (sscanf(line,
5256 "texture junk 2DArray %d ( %d , %d , %d )",
5257 &tex, &w, &h, &l) == 4) {
5258 GLuint texobj;
5259 glActiveTexture(GL_TEXTURE0 + tex);
5260 glGenTextures(1, &texobj);
5261 glBindTexture(GL_TEXTURE_2D_ARRAY, texobj);
5262 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA,
5263 w, h, l, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
5264 set_texture_binding(tex, texobj, w, h, l);
5266 } else if (parse_str(line, "texture storage ", &rest)) {
5267 GLenum target, format;
5268 GLuint tex_obj;
5269 int d = h = w = 1;
5271 REQUIRE(parse_int(rest, &tex, &rest) &&
5272 parse_tex_target(rest, &target, &rest) &&
5273 parse_enum_gl(rest, &format, &rest) &&
5274 parse_str(rest, "(", &rest) &&
5275 parse_int(rest, &l, &rest) &&
5276 parse_int(rest, &w, &rest),
5277 "Texture storage command not understood "
5278 "at: %s\n", rest);
5280 glActiveTexture(GL_TEXTURE0 + tex);
5281 glGenTextures(1, &tex_obj);
5282 glBindTexture(target, tex_obj);
5284 if (!parse_int(rest, &h, &rest))
5285 glTexStorage1D(target, l, format, w);
5286 else if (!parse_int(rest, &d, &rest))
5287 glTexStorage2D(target, l, format, w, h);
5288 else
5289 glTexStorage3D(target, l, format, w, h, d);
5291 if (!piglit_check_gl_error(GL_NO_ERROR)) {
5292 fprintf(stderr, "glTexStorage error\n");
5293 piglit_report_result(PIGLIT_FAIL);
5296 if (target == GL_TEXTURE_1D_ARRAY)
5297 set_texture_binding(tex, tex_obj, w, 1, h);
5298 else
5299 set_texture_binding(tex, tex_obj, w, h, d);
5301 #ifdef PIGLIT_USE_OPENGL
5302 } else if (sscanf(line,
5303 "texture rgbw 1D %d",
5304 &tex) == 1) {
5305 glActiveTexture(GL_TEXTURE0 + tex);
5306 const GLuint handle = piglit_rgbw_texture_1d();
5307 set_texture_binding(tex, handle, 4, 1, 1);
5308 #endif
5310 } else if (sscanf(line,
5311 "texture rgbw 3D %d",
5312 &tex) == 1) {
5313 glActiveTexture(GL_TEXTURE0 + tex);
5314 const GLuint handle = piglit_rgbw_texture_3d();
5315 set_texture_binding(tex, handle, 2, 2, 2);
5317 } else if (sscanf(line,
5318 "texture rgbw 2DArray %d ( %d , %d , %d )",
5319 &tex, &w, &h, &l) == 4) {
5320 glActiveTexture(GL_TEXTURE0 + tex);
5321 const GLuint handle = piglit_array_texture(
5322 GL_TEXTURE_2D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5323 set_texture_binding(tex, handle, w, h, l);
5325 } else if (sscanf(line,
5326 "texture rgbw 1DArray %d ( %d , %d )",
5327 &tex, &w, &l) == 3) {
5328 glActiveTexture(GL_TEXTURE0 + tex);
5329 h = 1;
5330 const GLuint handle = piglit_array_texture(
5331 GL_TEXTURE_1D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5332 set_texture_binding(tex, handle, w, 1, l);
5334 } else if (sscanf(line,
5335 "texture shadow2D %d ( %d , %d )",
5336 &tex, &w, &h) == 3) {
5337 glActiveTexture(GL_TEXTURE0 + tex);
5338 const GLuint handle = piglit_depth_texture(
5339 GL_TEXTURE_2D, GL_DEPTH_COMPONENT,
5340 w, h, 1, GL_FALSE);
5341 glTexParameteri(GL_TEXTURE_2D,
5342 GL_TEXTURE_COMPARE_MODE,
5343 GL_COMPARE_R_TO_TEXTURE);
5344 glTexParameteri(GL_TEXTURE_2D,
5345 GL_TEXTURE_COMPARE_FUNC,
5346 GL_GREATER);
5347 set_texture_binding(tex, handle, w, h, 1);
5349 if (!piglit_is_core_profile &&
5350 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5351 glEnable(GL_TEXTURE_2D);
5352 } else if (sscanf(line,
5353 "texture shadowRect %d ( %d , %d )",
5354 &tex, &w, &h) == 3) {
5355 glActiveTexture(GL_TEXTURE0 + tex);
5356 const GLuint handle = piglit_depth_texture(
5357 GL_TEXTURE_RECTANGLE, GL_DEPTH_COMPONENT,
5358 w, h, 1, GL_FALSE);
5359 glTexParameteri(GL_TEXTURE_RECTANGLE,
5360 GL_TEXTURE_COMPARE_MODE,
5361 GL_COMPARE_R_TO_TEXTURE);
5362 glTexParameteri(GL_TEXTURE_RECTANGLE,
5363 GL_TEXTURE_COMPARE_FUNC,
5364 GL_GREATER);
5365 set_texture_binding(tex, handle, w, h, 1);
5366 } else if (sscanf(line,
5367 "texture shadow1D %d ( %d )",
5368 &tex, &w) == 2) {
5369 glActiveTexture(GL_TEXTURE0 + tex);
5370 const GLuint handle = piglit_depth_texture(
5371 GL_TEXTURE_1D, GL_DEPTH_COMPONENT,
5372 w, 1, 1, GL_FALSE);
5373 glTexParameteri(GL_TEXTURE_1D,
5374 GL_TEXTURE_COMPARE_MODE,
5375 GL_COMPARE_R_TO_TEXTURE);
5376 glTexParameteri(GL_TEXTURE_1D,
5377 GL_TEXTURE_COMPARE_FUNC,
5378 GL_GREATER);
5379 set_texture_binding(tex, handle, w, 1, 1);
5380 } else if (sscanf(line,
5381 "texture shadow1DArray %d ( %d , %d )",
5382 &tex, &w, &l) == 3) {
5383 glActiveTexture(GL_TEXTURE0 + tex);
5384 const GLuint handle = piglit_depth_texture(
5385 GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT,
5386 w, l, 1, GL_FALSE);
5387 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5388 GL_TEXTURE_COMPARE_MODE,
5389 GL_COMPARE_R_TO_TEXTURE);
5390 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5391 GL_TEXTURE_COMPARE_FUNC,
5392 GL_GREATER);
5393 set_texture_binding(tex, handle, w, 1, l);
5394 } else if (sscanf(line,
5395 "texture shadow2DArray %d ( %d , %d , %d )",
5396 &tex, &w, &h, &l) == 4) {
5397 glActiveTexture(GL_TEXTURE0 + tex);
5398 const GLuint handle = piglit_depth_texture(
5399 GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT,
5400 w, h, l, GL_FALSE);
5401 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5402 GL_TEXTURE_COMPARE_MODE,
5403 GL_COMPARE_R_TO_TEXTURE);
5404 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5405 GL_TEXTURE_COMPARE_FUNC,
5406 GL_GREATER);
5407 set_texture_binding(tex, handle, w, h, l);
5408 } else if (sscanf(line, "texcoord %d ( %f , %f , %f , %f )",
5409 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
5410 glMultiTexCoord4fv(GL_TEXTURE0 + x, c);
5411 } else if (parse_str(line, "texparameter ", &rest)) {
5412 handle_texparameter(rest);
5413 } else if (parse_str(line, "uniform ", &rest)) {
5414 result = program_must_be_in_use();
5415 set_uniform(rest, block_data);
5416 } else if (parse_str(line, "subuniform ", &rest)) {
5417 result = program_must_be_in_use();
5418 check_shader_subroutine_support();
5419 set_subroutine_uniform(rest);
5420 } else if (parse_str(line, "parameter ", &rest)) {
5421 set_parameter(rest);
5422 } else if (parse_str(line, "patch parameter ", &rest)) {
5423 set_patch_parameter(rest);
5424 } else if (parse_str(line, "program binary save restore", &rest)) {
5425 program_binary_save_restore(true);
5426 } else if (parse_str(line, "provoking vertex ", &rest)) {
5427 set_provoking_vertex(rest);
5428 } else if (parse_str(line, "link error", &rest)) {
5429 link_error_expected = true;
5430 if (link_ok) {
5431 fprintf(stderr, "shader link error expected, but it was successful!\n");
5432 piglit_report_result(PIGLIT_FAIL);
5433 } else {
5434 printf("Failed to link (as expected):\n%s\n", prog_err_info);
5436 } else if (parse_str(line, "link success", &rest)) {
5437 result = program_must_be_in_use();
5438 } else if (parse_str(line, "ubo array index ", &rest)) {
5439 /* we allow "ubo array index" in order to not
5440 * change existing tests using ubo array index
5442 parse_ints(rest, &block_data.array_index, 1, NULL);
5443 } else if (parse_str(line, "block array index ", &rest)) {
5444 parse_ints(rest, &block_data.array_index, 1, NULL);
5445 } else if (parse_str(line, "block binding ", &rest)) {
5446 parse_ints(rest, &block_data.binding, 1, NULL);
5447 } else if (parse_str(line, "block offset ", &rest)) {
5448 parse_ints(rest, &block_data.offset, 1, NULL);
5449 } else if (parse_str(line, "block matrix stride", &rest)) {
5450 parse_ints(rest, &block_data.matrix_stride, 1, NULL);
5451 } else if (parse_str(line, "block row major", &rest)) {
5452 parse_ints(rest, &block_data.row_major, 1, NULL);
5453 } else if (parse_str(line, "active uniform ", &rest)) {
5454 active_uniform(rest);
5455 } else if (parse_str(line, "verify program_query", &rest)) {
5456 verify_program_query(rest);
5457 } else if (parse_str(line, "verify program_interface_query ", &rest)) {
5458 active_program_interface(rest, block_data);
5459 } else if (parse_str(line, "verify query_object", &rest)) {
5460 result = verify_query_object_result(rest);
5461 } else if (parse_str(line, "vertex attrib ", &rest)) {
5462 set_vertex_attrib(rest);
5463 } else if (parse_str(line, "newlist ", &rest)) {
5464 GLenum mode;
5466 REQUIRE(parse_enum_gl(rest, &mode, &rest),
5467 "NewList mode command not understood at %s\n",
5468 rest);
5470 list = glGenLists(1);
5471 glNewList(list, mode);
5472 } else if (parse_str(line, "endlist", NULL)) {
5473 glEndList();
5474 } else if (parse_str(line, "calllist", NULL)) {
5475 glCallList(list);
5476 } else if (parse_str(line, "deletelist", NULL)) {
5477 glDeleteLists(list, 1);
5478 } else if (parse_str(line, "viewport swizzle ", &rest)) {
5479 handle_viewport_swizzle(rest);
5480 } else if (parse_str(line, "light ", &rest)) {
5481 set_light(rest);
5482 } else if ((line[0] != '\n') && (line[0] != '\0')
5483 && (line[0] != '#')) {
5484 printf("unknown command \"%s\"\n", line);
5485 piglit_report_result(PIGLIT_FAIL);
5488 free((void*) line);
5490 if (result != PIGLIT_PASS) {
5491 printf("Test failure on line %u\n", line_num);
5492 full_result = result;
5495 line_num++;
5498 if (!link_ok && !link_error_expected) {
5499 full_result = program_must_be_in_use();
5502 piglit_present_results();
5504 if (piglit_automatic) {
5505 unsigned i;
5507 /* Free our resources, useful for valgrinding. */
5508 free_subroutine_uniforms();
5510 for (i = 0; i < ARRAY_SIZE(resident_handles); i++)
5511 clear_resident_handle(i);
5513 for (i = 0; i < ARRAY_SIZE(texture_bindings); i++)
5514 clear_texture_binding(i);
5516 if (prog != 0) {
5517 glDeleteProgram(prog);
5518 glUseProgram(0);
5519 } else {
5520 if (!sso_in_use)
5521 glDeleteProgramsARB(1, &prog);
5524 if (pipeline != 0)
5525 glDeleteProgramPipelines(1, &pipeline);
5528 return full_result;
5531 static enum piglit_result
5532 init_test(const char *file)
5534 enum piglit_result result;
5536 result = process_test_script(file);
5537 if (result != PIGLIT_PASS)
5538 return result;
5540 result = link_and_use_shaders();
5541 if (result != PIGLIT_PASS)
5542 return result;
5544 if (sso_in_use)
5545 glBindProgramPipeline(pipeline);
5547 if (link_ok && vertex_data_start != NULL) {
5548 result = program_must_be_in_use();
5549 if (result != PIGLIT_PASS)
5550 return result;
5552 bind_vao_if_supported();
5554 num_vbo_rows = setup_vbo_from_text(prog, vertex_data_start,
5555 vertex_data_end);
5556 vbo_present = true;
5558 setup_ubos();
5559 return PIGLIT_PASS;
5562 static void
5563 recreate_gl_context(char *exec_arg, int param_argc, char **param_argv)
5565 int argc = param_argc + 4;
5566 char **argv = malloc(sizeof(char*) * argc);
5568 if (!argv) {
5569 fprintf(stderr, "%s: malloc failed.\n", __func__);
5570 piglit_report_result(PIGLIT_FAIL);
5573 argv[0] = exec_arg;
5574 memcpy(&argv[1], param_argv, param_argc * sizeof(char*));
5575 argv[argc-3] = "-auto";
5576 argv[argc-2] = "-fbo";
5577 argv[argc-1] = "-report-subtests";
5579 if (gl_fw->destroy)
5580 gl_fw->destroy(gl_fw);
5581 gl_fw = NULL;
5583 exit(main(argc, argv));
5586 static bool
5587 validate_current_gl_context(const char *filename)
5589 struct piglit_gl_test_config config = { 0 };
5591 if (!piglit_gl_test_config_override_size(&config)) {
5592 config.window_width = DEFAULT_WINDOW_WIDTH;
5593 config.window_height = DEFAULT_WINDOW_HEIGHT;
5596 get_required_config(filename, spirv_replaces_glsl, &config);
5598 if (!current_config.supports_gl_compat_version !=
5599 !config.supports_gl_compat_version)
5600 return false;
5602 if (!current_config.supports_gl_core_version !=
5603 !config.supports_gl_core_version)
5604 return false;
5606 if (!current_config.supports_gl_es_version !=
5607 !config.supports_gl_es_version)
5608 return false;
5610 if (current_config.window_width != config.window_width ||
5611 current_config.window_height != config.window_height)
5612 return false;
5614 if (!(current_config.window_visual & PIGLIT_GL_VISUAL_DEPTH) &&
5615 config.window_visual & PIGLIT_GL_VISUAL_DEPTH)
5616 return false;
5618 return true;
5621 void
5622 piglit_init(int argc, char **argv)
5624 int major;
5625 int minor;
5626 bool core = piglit_is_core_profile;
5627 bool es;
5628 enum piglit_result result;
5629 float default_piglit_tolerance[4];
5631 use_get_program_binary =
5632 piglit_strip_arg(&argc, argv, "-get-program-binary") ||
5633 piglit_env_var_as_boolean("SHADER_RUNNER_GET_PROGRAM_BINARY",
5634 false);
5636 report_subtests = piglit_strip_arg(&argc, argv, "-report-subtests");
5637 force_glsl = piglit_strip_arg(&argc, argv, "-glsl");
5638 ignore_missing_uniforms = piglit_strip_arg(&argc, argv, "-ignore-missing-uniforms");
5640 force_no_names = piglit_strip_arg(&argc, argv, "-force-no-names");
5642 if (force_glsl && spirv_replaces_glsl) {
5643 printf("Options -glsl and -spirv can't be used at the same time\n");
5644 piglit_report_result(PIGLIT_FAIL);
5647 if (spirv_replaces_glsl)
5648 force_no_names = true;
5650 if (argc < 2) {
5651 printf("usage: shader_runner <test.shader_test> [-auto] [-fbo] [-png]"
5652 "[-rlimit <AS-limit>] [-samples=<N>] [-khr_no_error] [-compat] [-report-subtests]"
5653 "[-glsl] [-ignore-missing-uniforms] [-force-no-names]\n");
5654 exit(1);
5657 memcpy(default_piglit_tolerance, piglit_tolerance,
5658 sizeof(piglit_tolerance));
5660 piglit_require_GLSL();
5662 version_init(&gl_version, VERSION_GL,
5663 core, !core,
5664 piglit_is_gles(),
5665 piglit_get_gl_version());
5666 piglit_get_glsl_version(&es, &major, &minor);
5667 version_init(&glsl_version, VERSION_GLSL, core, !core, es,
5668 (major * 100) + minor);
5670 #ifdef PIGLIT_USE_OPENGL
5671 if (piglit_get_gl_version() >= 32)
5672 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
5673 &gl_max_vertex_output_components);
5674 if (piglit_get_gl_version() >= 20 ||
5675 piglit_is_extension_supported("GL_ARB_fragment_shader"))
5676 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
5677 &gl_max_fragment_uniform_components);
5678 if (piglit_get_gl_version() >= 20 ||
5679 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5680 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
5681 &gl_max_vertex_uniform_components);
5682 if (piglit_get_gl_version() >= 20 ||
5683 piglit_is_extension_supported("GL_ARB_vertex_shader") ||
5684 piglit_is_extension_supported("GL_ARB_geometry_shader4") ||
5685 piglit_is_extension_supported("GL_EXT_geometry_shader4"))
5686 glGetIntegerv(GL_MAX_VARYING_COMPONENTS,
5687 &gl_max_varying_components);
5688 #else
5689 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
5690 &gl_max_fragment_uniform_components);
5691 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
5692 &gl_max_vertex_uniform_components);
5693 glGetIntegerv(GL_MAX_VARYING_VECTORS,
5694 &gl_max_varying_components);
5695 gl_max_fragment_uniform_components *= 4;
5696 gl_max_vertex_uniform_components *= 4;
5697 gl_max_varying_components *= 4;
5698 #endif
5699 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max_clip_planes);
5701 if (gl_version.num >= 20 ||
5702 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5703 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,
5704 &gl_max_vertex_attribs);
5705 else
5706 gl_max_vertex_attribs = 16;
5708 read_width = render_width = piglit_width;
5709 read_height = render_height = piglit_height;
5711 #ifdef PIGLIT_USE_OPENGL
5712 if (piglit_is_extension_supported("GL_ARB_get_program_binary"))
5713 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
5714 &gl_num_program_binary_formats);
5715 #else
5716 if (piglit_is_extension_supported("GL_OES_get_program_binary"))
5717 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES,
5718 &gl_num_program_binary_formats);
5719 #endif
5721 if (use_get_program_binary) {
5722 if (gl_num_program_binary_formats == 0) {
5723 printf("Trying to use get_program_binary, but "
5724 "GL_NUM_PROGRAM_BINARY == 0\n");
5725 piglit_report_result(PIGLIT_SKIP);
5729 /* Run multiple tests per session. */
5730 if (argc > 2) {
5731 char testname[4096], *ext;
5732 int i, j;
5733 enum piglit_result all = PIGLIT_PASS;
5735 for (i = 1; i < argc; i++) {
5736 const char *hit, *filename = argv[i];
5738 memcpy(piglit_tolerance, default_piglit_tolerance,
5739 sizeof(piglit_tolerance));
5741 for (unsigned i = 0; i < ARRAY_SIZE(specializations); i++) {
5742 free(specializations[i].indices);
5743 free(specializations[i].values);
5745 memset(specializations, 0, sizeof(specializations));
5747 /* Re-initialize the GL context if a different GL config is required. */
5748 if (!validate_current_gl_context(filename))
5749 recreate_gl_context(argv[0], argc - i, argv + i);
5751 /* Clear global variables to defaults. */
5752 test_start = NULL;
5753 assert(num_vertex_shaders == 0);
5754 assert(num_tess_ctrl_shaders == 0);
5755 assert(num_tess_eval_shaders == 0);
5756 assert(num_geometry_shaders == 0);
5757 assert(num_fragment_shaders == 0);
5758 assert(num_compute_shaders == 0);
5759 assert(num_uniform_blocks == 0);
5760 assert(uniform_block_bos == NULL);
5761 assert(uniform_block_indexes == NULL);
5762 geometry_layout_input_type = GL_TRIANGLES;
5763 geometry_layout_output_type = GL_TRIANGLE_STRIP;
5764 geometry_layout_vertices_out = 0;
5765 memset(atomics_bos, 0, sizeof(atomics_bos));
5766 memset(ssbo, 0, sizeof(ssbo));
5767 for (j = 0; j < ARRAY_SIZE(subuniform_locations); j++)
5768 assert(subuniform_locations[j] == NULL);
5769 memset(num_subuniform_locations, 0, sizeof(num_subuniform_locations));
5770 shader_string = NULL;
5771 shader_string_size = 0;
5772 vertex_data_start = NULL;
5773 vertex_data_end = NULL;
5774 prog = 0;
5775 sso_vertex_prog = 0;
5776 sso_tess_control_prog = 0;
5777 sso_tess_eval_prog = 0;
5778 sso_geometry_prog = 0;
5779 sso_fragment_prog = 0;
5780 sso_compute_prog = 0;
5781 num_vbo_rows = 0;
5782 vbo_present = false;
5783 link_ok = false;
5784 prog_in_use = false;
5785 sso_in_use = false;
5786 separable_program = false;
5787 prog_err_info = NULL;
5788 vao = 0;
5790 /* Clear GL states to defaults. */
5791 glClearColor(0, 0, 0, 0);
5792 # if PIGLIT_USE_OPENGL
5793 glClearDepth(1);
5794 # else
5795 glClearDepthf(1.0);
5796 # endif
5797 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
5798 glActiveTexture(GL_TEXTURE0);
5799 glUseProgram(0);
5800 glDisable(GL_DEPTH_TEST);
5801 glBindBuffer(GL_ARRAY_BUFFER, 0);
5802 if (!es)
5803 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
5805 for (int k = 0; k < gl_max_clip_planes; k++) {
5806 static const GLdouble zero[4];
5808 if (!piglit_is_core_profile && !es)
5809 glClipPlane(GL_CLIP_PLANE0 + k, zero);
5810 glDisable(GL_CLIP_PLANE0 + k);
5813 if (!(es) && (gl_version.num >= 20 ||
5814 piglit_is_extension_supported("GL_ARB_vertex_program")))
5815 glDisable(GL_PROGRAM_POINT_SIZE);
5817 for (int i = 0; i < 16; i++)
5818 glDisableVertexAttribArray(i);
5820 if (!piglit_is_core_profile && !es) {
5821 glMatrixMode(GL_PROJECTION);
5822 glLoadIdentity();
5823 glMatrixMode(GL_MODELVIEW);
5824 glLoadIdentity();
5825 glShadeModel(GL_SMOOTH);
5826 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
5829 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
5830 glDisable(GL_VERTEX_PROGRAM_ARB);
5831 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0);
5833 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
5834 glDisable(GL_FRAGMENT_PROGRAM_ARB);
5835 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
5837 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
5838 if (!pipeline)
5839 glGenProgramPipelines(1, &pipeline);
5840 glBindProgramPipeline(0);
5843 if (piglit_is_extension_supported("GL_EXT_provoking_vertex"))
5844 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
5846 # if PIGLIT_USE_OPENGL
5847 if (gl_version.num >= 40 ||
5848 piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
5849 static float ones[] = {1, 1, 1, 1};
5850 glPatchParameteri(GL_PATCH_VERTICES, 3);
5851 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, ones);
5852 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, ones);
5854 # else
5855 /* Ideally one would use the following code:
5857 * if (gl_version.num >= 32) {
5858 * glPatchParameteri(GL_PATCH_VERTICES, 3);
5861 * however, that doesn't work with mesa because those
5862 * symbols apparently need to be exported, but that
5863 * breaks non-gles builds.
5865 * It seems rather unlikely that an implementation
5866 * would have GLES 3.2 support but not
5867 * OES_tessellation_shader.
5869 if (piglit_is_extension_supported("GL_OES_tessellation_shader")) {
5870 glPatchParameteriOES(GL_PATCH_VERTICES_OES, 3);
5872 # endif
5874 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5876 /* Strip the file path. */
5877 hit = strrchr(filename, PIGLIT_PATH_SEP);
5878 if (hit)
5879 strcpy(testname, hit+1);
5880 else
5881 strcpy(testname, filename);
5883 /* Strip the file extension. */
5884 ext = strstr(testname, ".shader_test");
5885 if (ext && !ext[12])
5886 *ext = 0;
5888 /* Print the name before we start the test, that way if
5889 * the test fails we can still resume and know which
5890 * test failed */
5891 printf("PIGLIT TEST: %i - %s\n", test_num, testname);
5892 fprintf(stderr, "PIGLIT TEST: %i - %s\n", test_num, testname);
5893 test_num++;
5895 /* Run the test. */
5896 result = init_test(filename);
5898 if (result == PIGLIT_PASS) {
5899 result = piglit_display();
5901 /* Use subtest when running with more than one test,
5902 * but use regular test result when running with just
5903 * one. This allows the standard process-at-a-time
5904 * mode to keep working.
5906 if (report_subtests) {
5907 piglit_report_subtest_result(
5908 result, "%s", testname);
5909 } else {
5910 piglit_merge_result(&all, result);
5913 /* destroy GL objects? */
5914 teardown_ubos();
5915 teardown_atomics();
5916 teardown_fbos();
5917 teardown_shader_include_paths();
5918 teardown_xfb();
5920 if (!report_subtests)
5921 piglit_report_result(all);
5922 exit(0);
5925 result = init_test(argv[1]);
5926 if (result != PIGLIT_PASS)
5927 piglit_report_result(result);