glsl-array-bounds: set out-of-bounds array index inside shader
[piglit.git] / tests / shaders / shader_runner.c
blobeb34c5a0a641497c5b60fa81e08e42185693869f
1 /*
2 * Copyright © 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #include <stdbool.h>
25 #include <string.h>
26 #include <ctype.h>
28 #include "piglit-util.h"
29 #include "piglit-util-gl.h"
30 #include "piglit-vbo.h"
31 #include "piglit-framework-gl/piglit_gl_framework.h"
32 #include "piglit-subprocess.h"
34 #include "shader_runner_gles_workarounds.h"
35 #include "parser_utils.h"
37 #include "shader_runner_vs_passthrough_spv.h"
39 #define DEFAULT_WINDOW_WIDTH 250
40 #define DEFAULT_WINDOW_HEIGHT 250
42 static bool spirv_replaces_glsl = false;
43 static struct piglit_gl_test_config current_config;
45 static void
46 get_required_config(const char *script_name, bool spirv,
47 struct piglit_gl_test_config *config);
48 static GLenum
49 decode_drawing_mode(const char *mode_str);
51 PIGLIT_GL_TEST_CONFIG_BEGIN
53 if (!piglit_gl_test_config_override_size(&config)) {
54 config.window_width = DEFAULT_WINDOW_WIDTH;
55 config.window_height = DEFAULT_WINDOW_HEIGHT;
57 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
58 config.khr_no_error_support = PIGLIT_NO_ERRORS;
60 /* By default SPIR-V mode is false. It will not be enabled
61 * unless the script includes SPIRV YES or SPIRV ONLY lines at
62 * [require] section, so it will be handled later.
64 if (argc > 1) {
65 get_required_config(argv[1], spirv_replaces_glsl, &config);
66 } else {
67 config.supports_gl_compat_version = 10;
70 current_config = config;
72 PIGLIT_GL_TEST_CONFIG_END
74 static const char passthrough_vertex_shader_source[] =
75 "#if __VERSION__ >= 130\n"
76 "in vec4 piglit_vertex;\n"
77 "#else\n"
78 "attribute vec4 piglit_vertex;\n"
79 "#endif\n"
80 "void main() { gl_Position = piglit_vertex; }\n"
83 struct component_version {
84 enum version_tag {
85 VERSION_GL,
86 VERSION_GLSL,
87 } _tag;
89 bool core;
90 bool compat;
91 bool es;
92 unsigned num;
93 char _string[100];
96 struct block_info {
97 int array_index;
98 int binding;
99 int offset;
100 int matrix_stride;
101 int row_major; /* int as we don't have a parse_bool */
104 #define ENUM_STRING(e) { #e, e }
106 extern float piglit_tolerance[4];
108 static int test_num = 1;
109 static struct component_version gl_version;
110 static struct component_version glsl_version;
111 static struct component_version glsl_req_version;
112 static int gl_max_vertex_output_components;
113 static int gl_max_fragment_uniform_components;
114 static int gl_max_vertex_uniform_components;
115 static int gl_max_vertex_attribs;
116 static int gl_max_varying_components;
117 static int gl_max_clip_planes;
118 static int gl_num_program_binary_formats = 0;
120 static const char *test_start = NULL;
121 static unsigned test_start_line_num = 0;
123 static GLuint vertex_shaders[256];
124 static unsigned num_vertex_shaders = 0;
125 static GLuint tess_ctrl_shaders[256];
126 static unsigned num_tess_ctrl_shaders = 0;
127 static GLuint tess_eval_shaders[256];
128 static unsigned num_tess_eval_shaders = 0;
129 static GLuint geometry_shaders[256];
130 static unsigned num_geometry_shaders = 0;
131 static GLuint fragment_shaders[256];
132 static unsigned num_fragment_shaders = 0;
133 static GLuint compute_shaders[256];
134 static unsigned num_compute_shaders = 0;
135 static int num_uniform_blocks;
136 static GLuint *uniform_block_bos;
137 static int *uniform_block_indexes; /* ubo block index, indexed by ubo binding */
138 static GLenum geometry_layout_input_type = GL_TRIANGLES;
139 static GLenum geometry_layout_output_type = GL_TRIANGLE_STRIP;
140 static GLint geometry_layout_vertices_out = 0;
141 static GLuint atomics_bos[8];
142 static GLuint ssbo[32];
143 static unsigned num_shader_include_paths = 0;
144 static char **shader_include_path;
145 static char *shader_include_names[256];
146 static unsigned num_shader_includes = 0;
148 #define MAX_XFB_BUFFERS 4 /* Same value used at nir_xfb_info */
149 static GLuint xfb[MAX_XFB_BUFFERS];
151 #define MAX_QUERIES 2
152 static GLuint queries[MAX_QUERIES];
154 #define SHADER_TYPES 6
155 static GLuint *subuniform_locations[SHADER_TYPES];
156 static int num_subuniform_locations[SHADER_TYPES];
157 static char *shader_string;
158 static GLint shader_string_size;
159 static const char *vertex_data_start = NULL;
160 static const char *vertex_data_end = NULL;
161 static GLuint prog;
162 static GLuint sso_vertex_prog;
163 static GLuint sso_tess_control_prog;
164 static GLuint sso_tess_eval_prog;
165 static GLuint sso_geometry_prog;
166 static GLuint sso_fragment_prog;
167 static GLuint sso_compute_prog;
168 static GLuint pipeline = 0;
169 static size_t num_vbo_rows = 0;
170 static bool vbo_present = false;
171 static bool link_ok = false;
172 static bool prog_in_use = false;
173 static bool sso_in_use = false;
174 static bool separable_program = false;
175 static bool glsl_in_use = false;
176 static bool force_glsl = false;
177 static bool spirv_in_use = false;
178 static bool force_no_names = false;
179 static GLchar *prog_err_info = NULL;
180 static GLuint vao = 0;
181 static GLuint draw_fbo, read_fbo;
182 static GLint render_width, render_height;
183 static GLint read_width, read_height;
185 static bool use_get_program_binary = false;
187 static bool ignore_missing_uniforms = false;
189 static bool report_subtests = false;
191 struct specialization_list {
192 size_t buffer_size;
193 size_t n_entries;
194 GLuint *indices;
195 union { GLuint u; GLfloat f; } *values;
198 static struct specialization_list
199 specializations[SHADER_TYPES];
201 static struct texture_binding {
202 GLuint obj;
203 unsigned width;
204 unsigned height;
205 unsigned layers;
206 } texture_bindings[32];
208 static struct resident_handle {
209 GLuint64 handle;
210 bool is_tex;
211 } resident_handles[32];
213 static void
214 clear_texture_binding(unsigned idx)
216 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
217 "Invalid texture index %d\n", idx);
219 if (texture_bindings[idx].obj) {
220 glDeleteTextures(1, &texture_bindings[idx].obj);
221 texture_bindings[idx].obj = 0;
225 static void
226 set_texture_binding(unsigned idx, GLuint obj, unsigned w, unsigned h, unsigned l)
228 clear_texture_binding(idx);
230 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
231 "Invalid texture index %d\n", idx);
232 texture_bindings[idx].obj = obj;
233 texture_bindings[idx].width = w;
234 texture_bindings[idx].height = h;
235 texture_bindings[idx].layers = l;
238 static const struct texture_binding *
239 get_texture_binding(unsigned idx)
241 REQUIRE(idx < ARRAY_SIZE(texture_bindings),
242 "Invalid texture index %d\n", idx);
243 REQUIRE(texture_bindings[idx].obj,
244 "No texture bound at %d\n", idx);
245 return &texture_bindings[idx];
248 static void
249 clear_resident_handle(unsigned idx)
251 REQUIRE(idx < ARRAY_SIZE(resident_handles),
252 "Invalid resident handle index %d\n", idx);
254 if (resident_handles[idx].handle) {
255 GLuint64 handle = resident_handles[idx].handle;
256 if (resident_handles[idx].is_tex) {
257 if (glIsTextureHandleResidentARB(handle))
258 glMakeTextureHandleNonResidentARB(handle);
259 } else {
260 if (glIsImageHandleResidentARB(handle))
261 glMakeImageHandleNonResidentARB(handle);
263 resident_handles[idx].handle = 0;
267 static void
268 set_resident_handle(unsigned idx, GLuint64 handle, bool is_tex)
270 clear_resident_handle(idx);
272 REQUIRE(idx < ARRAY_SIZE(resident_handles),
273 "Invalid resident handle index %d\n", idx);
274 resident_handles[idx].handle = handle;
275 resident_handles[idx].is_tex = is_tex;
278 static const struct resident_handle *
279 get_resident_handle(unsigned idx)
281 REQUIRE(idx < ARRAY_SIZE(resident_handles),
282 "Invalid resident handle index %d\n", idx);
283 REQUIRE(resident_handles[idx].handle,
284 "No resident handle at %d\n", idx);
285 return &resident_handles[idx];
288 enum states {
289 none = 0,
290 requirements,
291 vertex_shader,
292 vertex_shader_passthrough,
293 vertex_shader_spirv,
294 vertex_shader_specializations,
295 vertex_program,
296 tess_ctrl_shader,
297 tess_ctrl_shader_spirv,
298 tess_ctrl_shader_specializations,
299 tess_eval_shader,
300 tess_eval_shader_spirv,
301 tess_eval_shader_specializations,
302 geometry_shader,
303 geometry_shader_spirv,
304 geometry_shader_specializations,
305 geometry_layout,
306 fragment_shader,
307 fragment_shader_spirv,
308 fragment_shader_specializations,
309 fragment_program,
310 compute_shader,
311 compute_shader_spirv,
312 compute_shader_specializations,
313 vertex_data,
314 shader_include,
315 shader_include_paths,
316 test,
319 static const struct string_to_enum all_types[] = {
320 ENUM_STRING(GL_FLOAT),
321 ENUM_STRING(GL_FLOAT_VEC2),
322 ENUM_STRING(GL_FLOAT_VEC3),
323 ENUM_STRING(GL_FLOAT_VEC4),
324 ENUM_STRING(GL_DOUBLE),
325 ENUM_STRING(GL_DOUBLE_VEC2),
326 ENUM_STRING(GL_DOUBLE_VEC3),
327 ENUM_STRING(GL_DOUBLE_VEC4),
328 ENUM_STRING(GL_INT),
329 ENUM_STRING(GL_INT_VEC2),
330 ENUM_STRING(GL_INT_VEC3),
331 ENUM_STRING(GL_INT_VEC4),
332 ENUM_STRING(GL_UNSIGNED_INT),
333 ENUM_STRING(GL_UNSIGNED_INT_VEC2),
334 ENUM_STRING(GL_UNSIGNED_INT_VEC3),
335 ENUM_STRING(GL_UNSIGNED_INT_VEC4),
336 ENUM_STRING(GL_INT64_ARB),
337 ENUM_STRING(GL_INT64_VEC2_ARB),
338 ENUM_STRING(GL_INT64_VEC3_ARB),
339 ENUM_STRING(GL_INT64_VEC4_ARB),
340 ENUM_STRING(GL_UNSIGNED_INT64_ARB),
341 ENUM_STRING(GL_UNSIGNED_INT64_VEC2_ARB),
342 ENUM_STRING(GL_UNSIGNED_INT64_VEC3_ARB),
343 ENUM_STRING(GL_UNSIGNED_INT64_VEC4_ARB),
344 ENUM_STRING(GL_BOOL),
345 ENUM_STRING(GL_BOOL_VEC2),
346 ENUM_STRING(GL_BOOL_VEC3),
347 ENUM_STRING(GL_BOOL_VEC4),
348 ENUM_STRING(GL_FLOAT_MAT2),
349 ENUM_STRING(GL_FLOAT_MAT3),
350 ENUM_STRING(GL_FLOAT_MAT4),
351 ENUM_STRING(GL_FLOAT_MAT2x3),
352 ENUM_STRING(GL_FLOAT_MAT2x4),
353 ENUM_STRING(GL_FLOAT_MAT3x2),
354 ENUM_STRING(GL_FLOAT_MAT3x4),
355 ENUM_STRING(GL_FLOAT_MAT4x2),
356 ENUM_STRING(GL_FLOAT_MAT4x3),
357 ENUM_STRING(GL_DOUBLE_MAT2),
358 ENUM_STRING(GL_DOUBLE_MAT3),
359 ENUM_STRING(GL_DOUBLE_MAT4),
360 ENUM_STRING(GL_DOUBLE_MAT2x3),
361 ENUM_STRING(GL_DOUBLE_MAT2x4),
362 ENUM_STRING(GL_DOUBLE_MAT3x2),
363 ENUM_STRING(GL_DOUBLE_MAT3x4),
364 ENUM_STRING(GL_DOUBLE_MAT4x2),
365 ENUM_STRING(GL_DOUBLE_MAT4x3),
366 ENUM_STRING(GL_SAMPLER_1D),
367 ENUM_STRING(GL_SAMPLER_2D),
368 ENUM_STRING(GL_SAMPLER_3D),
369 ENUM_STRING(GL_SAMPLER_CUBE),
370 ENUM_STRING(GL_SAMPLER_1D_SHADOW),
371 ENUM_STRING(GL_SAMPLER_2D_SHADOW),
372 ENUM_STRING(GL_SAMPLER_1D_ARRAY),
373 ENUM_STRING(GL_SAMPLER_2D_ARRAY),
374 ENUM_STRING(GL_SAMPLER_1D_ARRAY_SHADOW),
375 ENUM_STRING(GL_SAMPLER_2D_ARRAY_SHADOW),
376 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE),
377 ENUM_STRING(GL_SAMPLER_2D_MULTISAMPLE_ARRAY),
378 ENUM_STRING(GL_SAMPLER_CUBE_SHADOW),
379 ENUM_STRING(GL_SAMPLER_BUFFER),
380 ENUM_STRING(GL_SAMPLER_2D_RECT),
381 ENUM_STRING(GL_SAMPLER_2D_RECT_SHADOW),
382 ENUM_STRING(GL_INT_SAMPLER_1D),
383 ENUM_STRING(GL_INT_SAMPLER_2D),
384 ENUM_STRING(GL_INT_SAMPLER_3D),
385 ENUM_STRING(GL_INT_SAMPLER_CUBE),
386 ENUM_STRING(GL_INT_SAMPLER_1D_ARRAY),
387 ENUM_STRING(GL_INT_SAMPLER_2D_ARRAY),
388 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE),
389 ENUM_STRING(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
390 ENUM_STRING(GL_INT_SAMPLER_BUFFER),
391 ENUM_STRING(GL_INT_SAMPLER_2D_RECT),
392 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D),
393 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D),
394 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_3D),
395 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_CUBE),
396 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY),
397 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY),
398 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE),
399 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY),
400 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_BUFFER),
401 ENUM_STRING(GL_UNSIGNED_INT_SAMPLER_2D_RECT),
402 { NULL, 0 }
405 static bool
406 compare(float ref, float value, enum comparison cmp);
408 static bool
409 compare_uint(GLuint ref, GLuint value, enum comparison cmp);
411 static bool
412 compare_int(GLint ref, GLint value, enum comparison cmp);
414 static void
415 version_init(struct component_version *v, enum version_tag tag, bool core, bool compat, bool es, unsigned num)
417 assert(tag == VERSION_GL || tag == VERSION_GLSL);
419 v->_tag = tag;
420 v->core = core;
421 v->compat = compat;
422 v->es = es;
423 v->num = num;
424 v->_string[0] = 0;
427 static void
428 version_copy(struct component_version *dest, struct component_version *src)
430 memcpy(dest, src, sizeof(*dest));
433 static bool
434 version_compare(struct component_version *a, struct component_version *b, enum comparison cmp)
436 assert(a->_tag == b->_tag);
438 if (a->es != b->es)
439 return false;
441 return compare(a->num, b->num, cmp);
445 * Get the version string.
447 static const char*
448 version_string(struct component_version *v)
450 if (v->_string[0])
451 return v->_string;
453 switch (v->_tag) {
454 case VERSION_GL:
455 snprintf(v->_string, sizeof(v->_string) - 1, "GL%s %d.%d",
456 v->es ? " ES" : "",
457 v->num / 10, v->num % 10);
458 break;
459 case VERSION_GLSL:
460 snprintf(v->_string, sizeof(v->_string) - 1, "GLSL%s %d.%d",
461 v->es ? " ES" : "",
462 v->num / 100, v->num % 100);
463 break;
464 default:
465 assert(false);
466 break;
469 return v->_string;
473 static const char *
474 target_to_short_name(GLenum target)
476 switch (target) {
477 case GL_VERTEX_SHADER:
478 return "VS";
479 case GL_FRAGMENT_SHADER:
480 return "FS";
481 case GL_TESS_CONTROL_SHADER:
482 return "TCS";
483 case GL_TESS_EVALUATION_SHADER:
484 return "TES";
485 case GL_GEOMETRY_SHADER:
486 return "GS";
487 case GL_COMPUTE_SHADER:
488 return "CS";
489 default:
490 return "???";
495 static enum piglit_result
496 compile_glsl(GLenum target)
498 GLuint shader = glCreateShader(target);
499 GLint ok;
501 if (spirv_in_use) {
502 printf("Cannot mix SPIRV and non-SPIRV shaders\n");
503 return PIGLIT_FAIL;
506 glsl_in_use = true;
508 switch (target) {
509 case GL_VERTEX_SHADER:
510 if (piglit_get_gl_version() < 20 &&
511 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
512 piglit_is_extension_supported("GL_ARB_vertex_shader")))
513 return PIGLIT_SKIP;
514 break;
515 case GL_FRAGMENT_SHADER:
516 if (piglit_get_gl_version() < 20 &&
517 !(piglit_is_extension_supported("GL_ARB_shader_objects") &&
518 piglit_is_extension_supported("GL_ARB_fragment_shader")))
519 return PIGLIT_SKIP;
520 break;
521 case GL_TESS_CONTROL_SHADER:
522 case GL_TESS_EVALUATION_SHADER:
523 if (gl_version.num < (gl_version.es ? 32 : 40))
524 if (!piglit_is_extension_supported(gl_version.es ?
525 "GL_OES_tessellation_shader" :
526 "GL_ARB_tessellation_shader"))
527 return PIGLIT_SKIP;
528 break;
529 case GL_GEOMETRY_SHADER:
530 if (gl_version.num < 32)
531 if (!piglit_is_extension_supported(gl_version.es ?
532 "GL_OES_geometry_shader" :
533 "GL_ARB_geometry_shader4"))
534 return PIGLIT_SKIP;
535 break;
536 case GL_COMPUTE_SHADER:
537 if (gl_version.num < (gl_version.es ? 31 : 43))
538 if (!piglit_is_extension_supported("GL_ARB_compute_shader"))
539 return PIGLIT_SKIP;
540 break;
543 if (!glsl_req_version.num) {
544 printf("GLSL version requirement missing\n");
545 return PIGLIT_FAIL;
548 if (!strstr(shader_string, "#version ")) {
549 char *shader_strings[2];
550 char version_string[100];
551 GLint shader_string_sizes[2];
553 /* Add a #version directive based on the GLSL requirement. */
554 sprintf(version_string, "#version %d", glsl_req_version.num);
555 if (glsl_req_version.es && glsl_req_version.num != 100) {
556 strcat(version_string, " es");
558 strcat(version_string, "\n");
559 shader_strings[0] = version_string;
560 shader_string_sizes[0] = strlen(version_string);
561 shader_strings[1] = shader_string;
562 shader_string_sizes[1] = shader_string_size;
564 glShaderSource(shader, 2,
565 (const GLchar **) shader_strings,
566 shader_string_sizes);
568 } else {
569 glShaderSource(shader, 1,
570 (const GLchar **) &shader_string,
571 &shader_string_size);
574 if (num_shader_include_paths) {
575 glCompileShaderIncludeARB(shader, num_shader_include_paths,
576 (const char **) shader_include_path, NULL);
577 } else
578 glCompileShader(shader);
580 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
582 if (!ok) {
583 GLchar *info;
584 GLint size;
586 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
587 info = malloc(size);
589 glGetShaderInfoLog(shader, size, NULL, info);
591 fprintf(stderr, "Failed to compile %s: %s\n",
592 target_to_short_name(target),
593 info);
595 free(info);
596 return PIGLIT_FAIL;
599 switch (target) {
600 case GL_VERTEX_SHADER:
601 vertex_shaders[num_vertex_shaders] = shader;
602 num_vertex_shaders++;
603 break;
604 case GL_TESS_CONTROL_SHADER:
605 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
606 num_tess_ctrl_shaders++;
607 break;
608 case GL_TESS_EVALUATION_SHADER:
609 tess_eval_shaders[num_tess_eval_shaders] = shader;
610 num_tess_eval_shaders++;
611 break;
612 case GL_GEOMETRY_SHADER:
613 geometry_shaders[num_geometry_shaders] = shader;
614 num_geometry_shaders++;
615 break;
616 case GL_FRAGMENT_SHADER:
617 fragment_shaders[num_fragment_shaders] = shader;
618 num_fragment_shaders++;
619 break;
620 case GL_COMPUTE_SHADER:
621 compute_shaders[num_compute_shaders] = shader;
622 num_compute_shaders++;
623 break;
625 return PIGLIT_PASS;
629 static enum piglit_result
630 compile_and_bind_program(GLenum target, const char *start, int len)
632 GLuint prog;
633 char *source;
635 switch (target) {
636 case GL_VERTEX_PROGRAM_ARB:
637 if (!piglit_is_extension_supported("GL_ARB_vertex_program"))
638 return PIGLIT_SKIP;
639 break;
640 case GL_FRAGMENT_PROGRAM_ARB:
641 if (!piglit_is_extension_supported("GL_ARB_fragment_program"))
642 return PIGLIT_SKIP;
643 break;
646 source = malloc(len + 1);
647 memcpy(source, start, len);
648 source[len] = 0;
649 prog = piglit_compile_program(target, source);
651 glEnable(target);
652 glBindProgramARB(target, prog);
653 link_ok = true;
654 prog_in_use = true;
656 return PIGLIT_PASS;
659 static bool
660 program_binary_save_restore(bool script_command)
662 GLint binary_length;
663 void *binary;
664 GLenum binary_format;
665 GLint ok;
666 GLuint new_prog;
668 if (!script_command && !use_get_program_binary)
669 return true;
671 if (script_command && gl_num_program_binary_formats == 0)
672 piglit_report_result(PIGLIT_SKIP);
674 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
675 if (!ok) {
676 if (script_command) {
677 fprintf(stderr, "Can't save/restore program that is "
678 "not linked!\n");
679 piglit_report_result(PIGLIT_FAIL);
680 } else {
681 return true;
685 #ifdef PIGLIT_USE_OPENGL
686 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &binary_length);
687 #else
688 glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH_OES, &binary_length);
689 #endif
690 if (!piglit_check_gl_error(GL_NO_ERROR)) {
691 fprintf(stderr, "glGetProgramiv GL_PROGRAM_BINARY_LENGTH "
692 "error\n");
693 piglit_report_result(PIGLIT_FAIL);
696 binary = malloc(binary_length);
697 if (!binary) {
698 fprintf(stderr, "Failed to allocate buffer for "
699 "GetProgramBinary\n");
700 piglit_report_result(PIGLIT_FAIL);
703 #ifdef PIGLIT_USE_OPENGL
704 glGetProgramBinary(prog, binary_length, &binary_length, &binary_format,
705 binary);
706 #else
707 glGetProgramBinaryOES(prog, binary_length, &binary_length,
708 &binary_format, binary);
709 #endif
710 if (!piglit_check_gl_error(GL_NO_ERROR)) {
711 fprintf(stderr, "glGetProgramBinary error\n");
712 free(binary);
713 piglit_report_result(PIGLIT_FAIL);
716 new_prog = glCreateProgram();
717 if (!piglit_check_gl_error(GL_NO_ERROR)) {
718 free(binary);
719 piglit_report_result(PIGLIT_FAIL);
722 #ifdef PIGLIT_USE_OPENGL
723 glProgramBinary(new_prog, binary_format, binary, binary_length);
724 #else
725 glProgramBinaryOES(new_prog, binary_format, binary, binary_length);
726 #endif
727 free(binary);
728 if (!piglit_check_gl_error(GL_NO_ERROR)) {
729 fprintf(stderr, "glProgramBinary error "
730 "(should not happend according to spec.)\n");
731 piglit_report_result(PIGLIT_FAIL);
734 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
735 if (!ok) {
736 fprintf(stderr, "link failure after glProgramBinary\n");
737 piglit_report_result(PIGLIT_FAIL);
740 if (prog_in_use) {
741 glUseProgram(new_prog);
742 if (!piglit_check_gl_error(GL_NO_ERROR))
743 piglit_report_result(PIGLIT_FAIL);
746 glDeleteProgram(prog);
747 if (!piglit_check_gl_error(GL_NO_ERROR))
748 piglit_report_result(PIGLIT_FAIL);
749 prog = new_prog;
751 return true;
754 static enum piglit_result
755 specialize_spirv(GLenum target,
756 GLuint shader)
758 if (glsl_in_use) {
759 printf("Cannot mix SPIR-V and non-SPIR-V shaders\n");
760 return PIGLIT_FAIL;
763 spirv_in_use = true;
765 const struct specialization_list *specs;
767 switch (target) {
768 case GL_VERTEX_SHADER:
769 specs = specializations + 0;
770 break;
771 case GL_TESS_CONTROL_SHADER:
772 specs = specializations + 1;
773 break;
774 case GL_TESS_EVALUATION_SHADER:
775 specs = specializations + 2;
776 break;
777 case GL_GEOMETRY_SHADER:
778 specs = specializations + 3;
779 break;
780 case GL_FRAGMENT_SHADER:
781 specs = specializations + 4;
782 break;
783 case GL_COMPUTE_SHADER:
784 specs = specializations + 5;
785 break;
786 default:
787 assert(!"Should not get here.");
790 glSpecializeShaderARB(shader,
791 "main",
792 specs->n_entries,
793 specs->indices,
794 &specs->values[0].u);
796 GLint ok;
797 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
799 if (!ok) {
800 GLchar *info;
801 GLint size;
803 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
804 info = malloc(MAX2(size, 1));
805 info[0] = 0;
807 glGetShaderInfoLog(shader, size, NULL, info);
809 printf("Failed to specialize %s: %s\n",
810 target_to_short_name(target), info);
812 free(info);
813 return PIGLIT_FAIL;
816 switch (target) {
817 case GL_VERTEX_SHADER:
818 vertex_shaders[num_vertex_shaders] = shader;
819 num_vertex_shaders++;
820 break;
821 case GL_TESS_CONTROL_SHADER:
822 tess_ctrl_shaders[num_tess_ctrl_shaders] = shader;
823 num_tess_ctrl_shaders++;
824 break;
825 case GL_TESS_EVALUATION_SHADER:
826 tess_eval_shaders[num_tess_eval_shaders] = shader;
827 num_tess_eval_shaders++;
828 break;
829 case GL_GEOMETRY_SHADER:
830 geometry_shaders[num_geometry_shaders] = shader;
831 num_geometry_shaders++;
832 break;
833 case GL_FRAGMENT_SHADER:
834 fragment_shaders[num_fragment_shaders] = shader;
835 num_fragment_shaders++;
836 break;
837 case GL_COMPUTE_SHADER:
838 compute_shaders[num_compute_shaders] = shader;
839 num_compute_shaders++;
840 break;
843 return PIGLIT_PASS;
846 static enum piglit_result
847 assemble_spirv(GLenum target)
849 if (!piglit_is_extension_supported("GL_ARB_gl_spirv")) {
850 return PIGLIT_SKIP;
853 /* Strip comments from the source */
854 char *stripped_source = malloc(shader_string_size);
855 char *p = stripped_source;
856 bool at_start_of_line = true;
858 for (const char *in = shader_string;
859 in < shader_string + shader_string_size;
860 in++) {
861 if (*in == '#' && at_start_of_line) {
862 const char *end;
863 end = memchr(in,
864 '\n',
865 shader_string + shader_string_size - in);
866 if (end == NULL)
867 break;
868 in = end;
869 } else {
870 at_start_of_line = *in == '\n';
871 *(p++) = *in;
875 GLuint shader = piglit_assemble_spirv(target,
876 p - stripped_source,
877 stripped_source);
879 free(stripped_source);
881 return specialize_spirv(target, shader);
884 static enum piglit_result
885 link_sso(GLenum target)
887 GLint ok;
889 glLinkProgram(prog);
891 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
892 if (ok) {
893 link_ok = true;
894 } else {
895 GLint size;
897 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
898 prog_err_info = malloc(MAX2(size, 1));
899 prog_err_info[0] = 0;
901 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
903 fprintf(stderr, "SSO glLinkProgram(%s) failed: %s\n",
904 target_to_short_name(target),
905 prog_err_info);
907 free(prog_err_info);
908 return PIGLIT_FAIL;
911 if (!program_binary_save_restore(false))
912 return PIGLIT_FAIL;
914 switch (target) {
915 case GL_VERTEX_SHADER:
916 sso_vertex_prog = prog;
917 glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, prog);
918 break;
919 case GL_TESS_CONTROL_SHADER:
920 sso_tess_control_prog = prog;
921 glUseProgramStages(pipeline, GL_TESS_CONTROL_SHADER_BIT, prog);
922 break;
923 case GL_TESS_EVALUATION_SHADER:
924 sso_tess_eval_prog = prog;
925 glUseProgramStages(pipeline, GL_TESS_EVALUATION_SHADER_BIT, prog);
926 break;
927 case GL_GEOMETRY_SHADER:
928 sso_geometry_prog = prog;
929 glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, prog);
930 break;
931 case GL_FRAGMENT_SHADER:
932 sso_fragment_prog = prog;
933 glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, prog);
934 break;
935 case GL_COMPUTE_SHADER:
936 sso_compute_prog = prog;
937 glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, prog);
938 break;
940 return PIGLIT_PASS;
944 * Compare two values given a specified comparison operator
946 static bool
947 compare(float ref, float value, enum comparison cmp)
949 switch (cmp) {
950 case equal: return value == ref;
951 case not_equal: return value != ref;
952 case less: return value < ref;
953 case greater_equal: return value >= ref;
954 case greater: return value > ref;
955 case less_equal: return value <= ref;
958 assert(!"Should not get here.");
959 return false;
962 static bool
963 compare_uint(GLuint ref, GLuint value, enum comparison cmp)
965 switch (cmp) {
966 case equal: return value == ref;
967 case not_equal: return value != ref;
968 case less: return value < ref;
969 case greater_equal: return value >= ref;
970 case greater: return value > ref;
971 case less_equal: return value <= ref;
974 assert(!"Should not get here.");
975 return false;
978 static bool
979 compare_int(GLint ref, GLint value, enum comparison cmp)
981 switch (cmp) {
982 case equal: return value == ref;
983 case not_equal: return value != ref;
984 case less: return value < ref;
985 case greater_equal: return value >= ref;
986 case greater: return value > ref;
987 case less_equal: return value <= ref;
990 assert(!"Should not get here.");
991 return false;
995 * Get the string representation of a comparison operator
997 static const char *
998 comparison_string(enum comparison cmp)
1000 switch (cmp) {
1001 case equal: return "==";
1002 case not_equal: return "!=";
1003 case less: return "<";
1004 case greater_equal: return ">=";
1005 case greater: return ">";
1006 case less_equal: return "<=";
1009 assert(!"Should not get here.");
1010 return false;
1014 * " ES" before the comparison operator indicates the version
1015 * pertains to GL ES.
1017 static void
1018 parse_version_comparison(const char *line, enum comparison *cmp,
1019 struct component_version *v, enum version_tag tag)
1021 unsigned major;
1022 unsigned minor;
1023 unsigned full_num;
1024 const bool core = parse_str(line, "CORE", &line);
1025 const bool compat = parse_str(line, "COMPAT", &line);
1026 const bool es = parse_str(line, "ES", &line);
1028 REQUIRE(parse_comparison_op(line, cmp, &line),
1029 "Invalid comparison operation at: %s\n", line);
1031 REQUIRE(parse_uint(line, &major, &line) &&
1032 parse_str(line, ".", &line) &&
1033 parse_uint(line, &minor, &line),
1034 "Invalid version string: %s\n", line);
1036 parse_whitespace(line, &line);
1037 if (*line != '\n') {
1038 printf("Unexpected characters following version comparison\n");
1039 piglit_report_result(PIGLIT_FAIL);
1042 /* This hack is so that we can tell the difference between GL versions
1043 * and GLSL versions. All GL versions look like 3.2, and we want the
1044 * integer to be 32. All GLSL versions look like 1.40, and we want
1045 * the integer to be 140.
1047 if (tag == VERSION_GLSL) {
1048 full_num = (major * 100) + minor;
1049 } else {
1050 full_num = (major * 10) + minor;
1053 version_init(v, tag, core, compat, es, full_num);
1057 * Parse and check a line from the requirement section of the test
1059 static enum piglit_result
1060 process_requirement(const char *line)
1062 char buffer[4096];
1063 static const struct {
1064 const char *name;
1065 int *val;
1066 const char *desc;
1067 } getint_limits[] = {
1069 "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
1070 &gl_max_vertex_output_components,
1071 "vertex output components",
1074 "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
1075 &gl_max_fragment_uniform_components,
1076 "fragment uniform components",
1079 "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
1080 &gl_max_vertex_uniform_components,
1081 "vertex uniform components",
1084 "GL_MAX_VERTEX_ATTRIBS",
1085 &gl_max_vertex_attribs,
1086 "vertex attribs",
1089 "GL_MAX_VARYING_COMPONENTS",
1090 &gl_max_varying_components,
1091 "varying components",
1094 "GL_NUM_PROGRAM_BINARY_FORMATS",
1095 &gl_num_program_binary_formats,
1096 "num program binary formats",
1099 unsigned i;
1101 /* The INT keyword in the requirements section causes
1102 * shader_runner to read the specified integer value and
1103 * processes the given requirement.
1105 if (parse_str(line, "INT ", &line)) {
1106 enum comparison cmp;
1107 int comparison_value, gl_int_value;
1108 unsigned int_enum;
1110 REQUIRE(parse_enum_gl(line, &int_enum, &line),
1111 "Invalid comparison enum at: %s\n", line);
1112 REQUIRE(parse_comparison_op(line, &cmp, &line),
1113 "Invalid comparison operation at: %s\n", line);
1114 REQUIRE(parse_int(line, &comparison_value, &line),
1115 "Invalid comparison value at: %s\n", line);
1117 glGetIntegerv(int_enum, &gl_int_value);
1118 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1119 fprintf(stderr, "Error reading %s\n",
1120 piglit_get_gl_enum_name(int_enum));
1121 return PIGLIT_FAIL;
1124 if (!compare(comparison_value, gl_int_value, cmp)) {
1125 printf("Test requires %s %s %i. "
1126 "The driver supports %i.\n",
1127 piglit_get_gl_enum_name(int_enum),
1128 comparison_string(cmp),
1129 comparison_value,
1130 gl_int_value);
1131 return PIGLIT_SKIP;
1134 return PIGLIT_PASS;
1137 /* There are five types of requirements that a test can currently
1138 * have:
1140 * * Require that some GL extension be supported
1141 * * Require some particular versions of GL
1142 * * Require some particular versions of GLSL
1143 * * Require some particular number of uniform components
1144 * * Require shaders be built as separate shader objects
1146 * The tests for GL and GLSL versions can be equal, not equal,
1147 * less, less-or-equal, greater, or greater-or-equal. Extension tests
1148 * can also require that a particular extension not be supported by
1149 * prepending ! to the extension name.
1151 for (i = 0; i < ARRAY_SIZE(getint_limits); i++) {
1152 enum comparison cmp;
1153 int maxcomp;
1155 if (!parse_str(line, getint_limits[i].name, &line))
1156 continue;
1158 REQUIRE(parse_comparison_op(line, &cmp, &line),
1159 "Invalid comparison operation at: %s\n", line);
1161 maxcomp = atoi(line);
1162 if (!compare(maxcomp, *getint_limits[i].val, cmp)) {
1163 printf("Test requires %s %s %i. "
1164 "The driver supports %i.\n",
1165 getint_limits[i].desc,
1166 comparison_string(cmp),
1167 maxcomp,
1168 *getint_limits[i].val);
1169 return PIGLIT_SKIP;
1171 return PIGLIT_PASS;
1174 if (parse_str(line, "GL_", NULL) &&
1175 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1176 if (!piglit_is_extension_supported(buffer)) {
1177 printf("Test requires unsupported extension %s\n", buffer);
1178 return PIGLIT_SKIP;
1180 } else if (parse_str(line, "!", &line) &&
1181 parse_str(line, "GL_", NULL) &&
1182 parse_word_copy(line, buffer, sizeof(buffer), &line)) {
1183 if (piglit_is_extension_supported(buffer)) {
1184 printf("Test requires unsupported extension %s\n", buffer);
1185 return PIGLIT_SKIP;
1187 } else if (parse_str(line, "GLSL", &line)) {
1188 enum comparison cmp;
1190 parse_version_comparison(line, &cmp, &glsl_req_version,
1191 VERSION_GLSL);
1193 /* We only allow >= because we potentially use the
1194 * version number to insert a #version directive. */
1195 if (cmp != greater_equal) {
1196 printf("Unsupported GLSL version comparison\n");
1197 return PIGLIT_FAIL;
1200 if (!version_compare(&glsl_req_version, &glsl_version, cmp)) {
1201 printf("Test requires %s %s. "
1202 "Actual version %s.\n",
1203 comparison_string(cmp),
1204 version_string(&glsl_req_version),
1205 version_string(&glsl_version));
1206 return PIGLIT_SKIP;
1208 } else if (parse_str(line, "GL", &line)) {
1209 enum comparison cmp;
1210 struct component_version gl_req_version;
1212 parse_version_comparison(line, &cmp, &gl_req_version,
1213 VERSION_GL);
1215 if (!version_compare(&gl_req_version, &gl_version, cmp)) {
1216 printf("Test requires %s %s. "
1217 "Actual version is %s.\n",
1218 comparison_string(cmp),
1219 version_string(&gl_req_version),
1220 version_string(&gl_version));
1221 return PIGLIT_SKIP;
1223 } else if (parse_str(line, "rlimit", &line)) {
1224 unsigned lim;
1226 REQUIRE(parse_uint(line, &lim, &line),
1227 "Invalid rlimit argument at: %s\n", line);
1229 piglit_set_rlimit(lim);
1230 } else if (parse_str(line, "SSO", &line) &&
1231 parse_str(line, "ENABLED", NULL)) {
1232 if (separable_program) {
1233 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1234 return PIGLIT_FAIL;
1237 const char *const ext_name = gl_version.es
1238 ? "GL_EXT_separate_shader_objects"
1239 : "GL_ARB_separate_shader_objects";
1240 const unsigned min_version = gl_version.es
1241 ? 31 : 41;
1243 if (gl_version.num < min_version)
1244 piglit_require_extension(ext_name);
1246 sso_in_use = true;
1247 glGenProgramPipelines(1, &pipeline);
1248 } else if (parse_str(line, "SEPARABLE PROGRAM", &line) &&
1249 parse_str(line, "ENABLED", NULL)) {
1250 if (sso_in_use) {
1251 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1252 return PIGLIT_FAIL;
1255 const char *const ext_name = gl_version.es
1256 ? "GL_EXT_separate_shader_objects"
1257 : "GL_ARB_separate_shader_objects";
1258 const unsigned min_version = gl_version.es
1259 ? 31 : 41;
1261 if (gl_version.num < min_version)
1262 piglit_require_extension(ext_name);
1264 separable_program = true;
1265 } else if (parse_str(line, "SPIRV", &line)) {
1266 spirv_replaces_glsl = !force_glsl;
1268 if (parse_str(line, "ONLY", NULL)) {
1269 if (force_glsl) {
1270 printf("This shader is not compatible with GLSL\n");
1271 return PIGLIT_SKIP;
1273 } else if (parse_str(line, "YES", NULL)) {
1274 /* Empty. Everything already set. Just parsing
1275 * correct options
1277 } else {
1278 printf("Unknown SPIRV line in [require]\n");
1279 return PIGLIT_FAIL;
1282 if (spirv_replaces_glsl)
1283 force_no_names = true;
1285 return PIGLIT_PASS;
1290 * Process a line from the [geometry layout] section of a test
1292 static void
1293 process_geometry_layout(const char *line)
1295 char s[32];
1296 int x;
1298 parse_whitespace(line, &line);
1300 if (line[0] == '\0' || line[0] == '\n') {
1301 return;
1302 } else if (sscanf(line, "input type %31s", s) == 1) {
1303 geometry_layout_input_type = decode_drawing_mode(s);
1304 } else if (sscanf(line, "output type %31s", s) == 1) {
1305 geometry_layout_output_type = decode_drawing_mode(s);
1306 } else if (sscanf(line, "vertices out %d", &x) == 1) {
1307 geometry_layout_vertices_out = x;
1308 } else {
1309 printf("Could not parse geometry layout line: %s\n", line);
1310 piglit_report_result(PIGLIT_FAIL);
1314 static enum piglit_result
1315 leave_state(enum states state, const char *line, const char *script_name)
1317 switch (state) {
1318 case none:
1319 break;
1321 case requirements:
1322 if (spirv_replaces_glsl) {
1323 printf("Running on SPIR-V mode\n");
1325 if (force_no_names && !spirv_replaces_glsl) {
1326 printf("Running on GLSL mode, forcing not using "
1327 "uniform/uniform block names\n");
1329 break;
1331 case vertex_shader:
1332 if (spirv_replaces_glsl)
1333 break;
1334 shader_string_size = line - shader_string;
1335 return compile_glsl(GL_VERTEX_SHADER);
1337 case vertex_shader_passthrough:
1338 if (spirv_replaces_glsl) {
1339 shader_string = (char *) passthrough_vertex_shader_source_spv;
1340 shader_string_size = strlen(passthrough_vertex_shader_source_spv);
1342 return assemble_spirv(GL_VERTEX_SHADER);
1344 return compile_glsl(GL_VERTEX_SHADER);
1346 case vertex_program:
1347 return compile_and_bind_program(GL_VERTEX_PROGRAM_ARB,
1348 shader_string,
1349 line - shader_string);
1351 case vertex_shader_spirv:
1352 if (!spirv_replaces_glsl)
1353 break;
1354 shader_string_size = line - shader_string;
1355 return assemble_spirv(GL_VERTEX_SHADER);
1357 case vertex_shader_specializations:
1358 break;
1360 case tess_ctrl_shader:
1361 if (spirv_replaces_glsl)
1362 break;
1363 shader_string_size = line - shader_string;
1364 return compile_glsl(GL_TESS_CONTROL_SHADER);
1366 case tess_ctrl_shader_spirv:
1367 if (!spirv_replaces_glsl)
1368 break;
1369 shader_string_size = line - shader_string;
1370 return assemble_spirv(GL_TESS_CONTROL_SHADER);
1372 case tess_ctrl_shader_specializations:
1373 break;
1375 case tess_eval_shader:
1376 if (spirv_replaces_glsl)
1377 break;
1378 shader_string_size = line - shader_string;
1379 return compile_glsl(GL_TESS_EVALUATION_SHADER);
1381 case tess_eval_shader_spirv:
1382 if (!spirv_replaces_glsl)
1383 break;
1384 shader_string_size = line - shader_string;
1385 return assemble_spirv(GL_TESS_EVALUATION_SHADER);
1387 case tess_eval_shader_specializations:
1388 break;
1390 case geometry_shader:
1391 if (spirv_replaces_glsl)
1392 break;
1393 shader_string_size = line - shader_string;
1394 return compile_glsl(GL_GEOMETRY_SHADER);
1396 case geometry_shader_spirv:
1397 if (!spirv_replaces_glsl)
1398 break;
1399 shader_string_size = line - shader_string;
1400 return assemble_spirv(GL_GEOMETRY_SHADER);
1402 case geometry_shader_specializations:
1403 break;
1405 case geometry_layout:
1406 break;
1408 case fragment_shader:
1409 if (spirv_replaces_glsl)
1410 break;
1411 shader_string_size = line - shader_string;
1412 return compile_glsl(GL_FRAGMENT_SHADER);
1414 case fragment_program:
1415 return compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB,
1416 shader_string,
1417 line - shader_string);
1418 break;
1420 case fragment_shader_spirv:
1421 if (!spirv_replaces_glsl)
1422 break;
1423 shader_string_size = line - shader_string;
1424 return assemble_spirv(GL_FRAGMENT_SHADER);
1426 case fragment_shader_specializations:
1427 break;
1429 case compute_shader:
1430 if (spirv_replaces_glsl)
1431 break;
1432 shader_string_size = line - shader_string;
1433 return compile_glsl(GL_COMPUTE_SHADER);
1435 case compute_shader_spirv:
1436 if (!spirv_replaces_glsl)
1437 break;
1438 shader_string_size = line - shader_string;
1439 return assemble_spirv(GL_COMPUTE_SHADER);
1441 case compute_shader_specializations:
1442 break;
1444 case vertex_data:
1445 vertex_data_end = line;
1446 break;
1448 case shader_include: {
1449 const char *path_end = strchrnul(shader_string, '\n');
1451 if (shader_string == path_end) {
1452 fprintf(stderr, "No shader include path provided\n");
1453 return PIGLIT_FAIL;
1456 if (!piglit_is_extension_supported("GL_ARB_shading_language_include"))
1457 return PIGLIT_SKIP;
1459 int path_name_len = path_end - shader_string;
1460 glNamedStringARB(GL_SHADER_INCLUDE_ARB, path_name_len, shader_string,
1461 line - shader_string - path_name_len, shader_string + path_name_len);
1463 shader_include_names[num_shader_includes] = strndup(shader_string, path_name_len);
1464 num_shader_includes++;
1465 assert(num_shader_includes <= 256);
1467 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1468 fprintf(stderr, "glNamedStringARB error\n");
1469 return PIGLIT_FAIL;
1472 break;
1475 case shader_include_paths: {
1476 num_shader_include_paths = 0;
1477 const char *cursor = shader_string;
1478 do {
1479 const char *line_start = cursor;
1480 cursor = strchr(cursor, '\n');
1482 if (cursor == line_start) {
1483 cursor++;
1484 continue;
1487 cursor++;
1488 num_shader_include_paths++;
1489 } while (cursor && cursor < line);
1491 shader_include_path = calloc(num_shader_include_paths, sizeof(char *));
1493 cursor = shader_string;
1494 for (unsigned i = 0; i < num_shader_include_paths; i++) {
1495 char *line_end = strchr(cursor, '\n');
1496 unsigned path_len = line_end - cursor - 1;
1497 char *path = malloc(path_len + 1);
1498 path[path_len] = '\0';
1500 memcpy(path, cursor, path_len);
1501 shader_include_path[i] = path;
1502 cursor = line_end + 1;
1505 break;
1508 case test:
1509 break;
1511 default:
1512 assert(!"Not yet supported.");
1514 return PIGLIT_PASS;
1518 static enum piglit_result
1519 process_shader(GLenum target, unsigned num_shaders, GLuint *shaders)
1521 if (num_shaders == 0)
1522 return PIGLIT_PASS;
1524 if (sso_in_use) {
1525 prog = glCreateProgram();
1526 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1529 for (unsigned i = 0; i < num_shaders; i++) {
1530 glAttachShader(prog, shaders[i]);
1533 #ifdef PIGLIT_USE_OPENGL
1534 if (geometry_layout_input_type != GL_TRIANGLES) {
1535 glProgramParameteriARB(prog, GL_GEOMETRY_INPUT_TYPE_ARB,
1536 geometry_layout_input_type);
1538 if (geometry_layout_output_type != GL_TRIANGLE_STRIP) {
1539 glProgramParameteriARB(prog, GL_GEOMETRY_OUTPUT_TYPE_ARB,
1540 geometry_layout_output_type);
1542 if (geometry_layout_vertices_out != 0) {
1543 glProgramParameteriARB(prog, GL_GEOMETRY_VERTICES_OUT_ARB,
1544 geometry_layout_vertices_out);
1546 #endif
1548 /* If the shaders reference piglit_vertex or piglit_tex, bind
1549 * them to some fixed attribute locations so they can be used
1550 * with piglit_draw_rect_tex() in GLES.
1552 glBindAttribLocation(prog, PIGLIT_ATTRIB_POS, "piglit_vertex");
1553 glBindAttribLocation(prog, PIGLIT_ATTRIB_TEX, "piglit_texcoord");
1555 if (sso_in_use) {
1556 return link_sso(target);
1558 return PIGLIT_PASS;
1562 static enum piglit_result
1563 link_and_use_shaders(void)
1565 enum piglit_result result;
1566 unsigned i;
1567 GLenum err;
1568 GLint ok;
1570 if ((num_vertex_shaders == 0)
1571 && (num_fragment_shaders == 0)
1572 && (num_tess_ctrl_shaders == 0)
1573 && (num_tess_eval_shaders == 0)
1574 && (num_geometry_shaders == 0)
1575 && (num_compute_shaders == 0))
1576 return PIGLIT_PASS;
1578 if (!sso_in_use)
1579 prog = glCreateProgram();
1581 result = process_shader(GL_VERTEX_SHADER, num_vertex_shaders, vertex_shaders);
1582 if (result != PIGLIT_PASS)
1583 goto cleanup;
1584 result = process_shader(GL_TESS_CONTROL_SHADER, num_tess_ctrl_shaders, tess_ctrl_shaders);
1585 if (result != PIGLIT_PASS)
1586 goto cleanup;
1587 result = process_shader(GL_TESS_EVALUATION_SHADER, num_tess_eval_shaders, tess_eval_shaders);
1588 if (result != PIGLIT_PASS)
1589 goto cleanup;
1590 result = process_shader(GL_GEOMETRY_SHADER, num_geometry_shaders, geometry_shaders);
1591 if (result != PIGLIT_PASS)
1592 goto cleanup;
1593 result = process_shader(GL_FRAGMENT_SHADER, num_fragment_shaders, fragment_shaders);
1594 if (result != PIGLIT_PASS)
1595 goto cleanup;
1596 result = process_shader(GL_COMPUTE_SHADER, num_compute_shaders, compute_shaders);
1597 if (result != PIGLIT_PASS)
1598 goto cleanup;
1600 if (!sso_in_use) {
1601 if (separable_program)
1602 glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
1604 glLinkProgram(prog);
1607 if (!sso_in_use) {
1608 if (!program_binary_save_restore(false))
1609 return PIGLIT_FAIL;
1610 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
1611 if (ok) {
1612 link_ok = true;
1613 } else {
1614 GLint size;
1616 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1617 prog_err_info = malloc(MAX2(size, 1));
1618 prog_err_info[0] = 0;
1620 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1622 result = PIGLIT_PASS;
1623 goto cleanup;
1626 glUseProgram(prog);
1629 err = glGetError();
1630 if (!err) {
1631 prog_in_use = true;
1632 } else {
1633 GLint size;
1635 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
1636 prog_err_info = malloc(MAX2(size, 1));
1637 prog_err_info[0] = 0;
1639 glGetProgramInfoLog(prog, size, NULL, prog_err_info);
1642 cleanup:
1643 for (i = 0; i < num_vertex_shaders; i++) {
1644 glDeleteShader(vertex_shaders[i]);
1646 num_vertex_shaders = 0;
1648 for (i = 0; i < num_tess_ctrl_shaders; i++) {
1649 glDeleteShader(tess_ctrl_shaders[i]);
1651 num_tess_ctrl_shaders = 0;
1653 for (i = 0; i < num_tess_eval_shaders; i++) {
1654 glDeleteShader(tess_eval_shaders[i]);
1656 num_tess_eval_shaders = 0;
1658 for (i = 0; i < num_geometry_shaders; i++) {
1659 glDeleteShader(geometry_shaders[i]);
1661 num_geometry_shaders = 0;
1663 for (i = 0; i < num_fragment_shaders; i++) {
1664 glDeleteShader(fragment_shaders[i]);
1666 num_fragment_shaders = 0;
1668 for (i = 0; i < num_compute_shaders; i++) {
1669 glDeleteShader(compute_shaders[i]);
1671 num_compute_shaders = 0;
1673 return result;
1676 static enum piglit_result
1677 process_specialization(enum states state, const char *line)
1679 const char *end = strchrnul(line, '\n');
1680 const char *next;
1681 enum { TYPE_FLOAT, TYPE_UINT } type;
1683 while (line < end && isspace(*line))
1684 line++;
1686 if (line >= end || *line == '#')
1687 return PIGLIT_PASS;
1689 if (parse_str(line, "uint", &next))
1690 type = TYPE_UINT;
1691 else if (parse_str(line, "float", &next))
1692 type = TYPE_FLOAT;
1693 else
1694 goto invalid;
1696 struct specialization_list *list;
1698 switch (state) {
1699 case vertex_shader_specializations:
1700 list = specializations + 0;
1701 break;
1702 case tess_ctrl_shader_specializations:
1703 list = specializations + 1;
1704 break;
1705 case tess_eval_shader_specializations:
1706 list = specializations + 2;
1707 break;
1708 case geometry_shader_specializations:
1709 list = specializations + 3;
1710 break;
1711 case fragment_shader_specializations:
1712 list = specializations + 4;
1713 break;
1714 case compute_shader_specializations:
1715 list = specializations + 5;
1716 break;
1717 default:
1718 assert(!"Should not get here.");
1721 if (list->n_entries >= list->buffer_size) {
1722 if (list->buffer_size == 0)
1723 list->buffer_size = 1;
1724 else
1725 list->buffer_size *= 2;
1726 list->indices = realloc(list->indices,
1727 (sizeof list->indices[0]) *
1728 list->buffer_size);
1729 list->values = realloc(list->values,
1730 (sizeof list->values[0]) *
1731 list->buffer_size);
1734 if (parse_uints(next, list->indices + list->n_entries, 1, &next) != 1)
1735 goto invalid;
1737 switch (type) {
1738 case TYPE_UINT:
1739 if (parse_uints(next,
1740 &list->values[list->n_entries].u,
1742 &next) != 1)
1743 goto invalid;
1744 break;
1745 case TYPE_FLOAT:
1746 if (parse_floats(next,
1747 &list->values[list->n_entries].f,
1749 &next) != 1)
1750 goto invalid;
1751 break;
1754 list->n_entries++;
1756 return PIGLIT_PASS;
1758 invalid:
1759 fprintf(stderr, "Invalid specialization line\n");
1760 return PIGLIT_FAIL;
1763 static enum piglit_result
1764 process_test_script(const char *script_name)
1766 unsigned text_size;
1767 unsigned line_num;
1768 char *text = piglit_load_text_file(script_name, &text_size);
1769 enum states state = none;
1770 const char *line = text;
1771 enum piglit_result result;
1773 if (line == NULL) {
1774 printf("could not read file \"%s\"\n", script_name);
1775 return PIGLIT_FAIL;
1778 line_num = 1;
1780 while (line[0] != '\0') {
1781 if (line[0] == '[') {
1782 result = leave_state(state, line, script_name);
1783 if (result != PIGLIT_PASS)
1784 return result;
1786 if (parse_str(line, "[require]", NULL)) {
1787 state = requirements;
1788 } else if (parse_str(line, "[vertex shader]", NULL)) {
1789 state = vertex_shader;
1790 shader_string = NULL;
1791 } else if (parse_str(line, "[vertex program]", NULL)) {
1792 state = vertex_program;
1793 shader_string = NULL;
1794 } else if (parse_str(line, "[vertex shader passthrough]", NULL)) {
1795 state = vertex_shader_passthrough;
1796 shader_string =
1797 (char *) passthrough_vertex_shader_source;
1798 shader_string_size = strlen(shader_string);
1799 } else if (parse_str(line, "[vertex shader spirv]", NULL)) {
1800 state = vertex_shader_spirv;
1801 shader_string = NULL;
1802 } else if (parse_str(line, "[vertex shader specializations]", NULL)) {
1803 state = vertex_shader_specializations;
1804 } else if (parse_str(line, "[tessellation control shader]", NULL)) {
1805 state = tess_ctrl_shader;
1806 shader_string = NULL;
1807 } else if (parse_str(line, "[tessellation control shader spirv]", NULL)) {
1808 state = tess_ctrl_shader_spirv;
1809 shader_string = NULL;
1810 } else if (parse_str(line, "[tessellation control shader specializations]", NULL)) {
1811 state = tess_ctrl_shader_specializations;
1812 } else if (parse_str(line, "[tessellation evaluation shader]", NULL)) {
1813 state = tess_eval_shader;
1814 shader_string = NULL;
1815 } else if (parse_str(line, "[tessellation evaluation shader spirv]", NULL)) {
1816 state = tess_eval_shader_spirv;
1817 shader_string = NULL;
1818 } else if (parse_str(line, "[tessellation evaluation shader specializations]", NULL)) {
1819 state = tess_eval_shader_specializations;
1820 } else if (parse_str(line, "[geometry shader]", NULL)) {
1821 state = geometry_shader;
1822 shader_string = NULL;
1823 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1824 state = geometry_shader_specializations;
1825 } else if (parse_str(line, "[geometry shader spirv]", NULL)) {
1826 state = geometry_shader_spirv;
1827 shader_string = NULL;
1828 } else if (parse_str(line, "[geometry shader specializations]", NULL)) {
1829 state = geometry_shader_specializations;
1830 } else if (parse_str(line, "[geometry layout]", NULL)) {
1831 state = geometry_layout;
1832 shader_string = NULL;
1833 } else if (parse_str(line, "[fragment shader]", NULL)) {
1834 state = fragment_shader;
1835 shader_string = NULL;
1836 } else if (parse_str(line, "[fragment program]", NULL)) {
1837 state = fragment_program;
1838 shader_string = NULL;
1839 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1840 state = fragment_shader_specializations;
1841 } else if (parse_str(line, "[fragment shader spirv]", NULL)) {
1842 state = fragment_shader_spirv;
1843 shader_string = NULL;
1844 } else if (parse_str(line, "[fragment shader specializations]", NULL)) {
1845 state = fragment_shader_specializations;
1846 } else if (parse_str(line, "[compute shader]", NULL)) {
1847 state = compute_shader;
1848 shader_string = NULL;
1849 } else if (parse_str(line, "[compute shader spirv]", NULL)) {
1850 state = compute_shader_spirv;
1851 shader_string = NULL;
1852 } else if (parse_str(line, "[compute shader specializations]", NULL)) {
1853 state = compute_shader_specializations;
1854 } else if (parse_str(line, "[vertex data]", NULL)) {
1855 state = vertex_data;
1856 vertex_data_start = NULL;
1857 } else if (parse_str(line, "[shader include]", NULL)) {
1858 state = shader_include;
1859 shader_string = NULL;
1860 } else if (parse_str(line, "[shader include paths]", NULL)) {
1861 state = shader_include_paths;
1862 shader_string = NULL;
1863 } else if (parse_str(line, "[test]", NULL)) {
1864 test_start = strchrnul(line, '\n');
1865 test_start_line_num = line_num + 1;
1866 if (test_start[0] != '\0')
1867 test_start++;
1868 return PIGLIT_PASS;
1869 } else {
1870 fprintf(stderr,
1871 "Unknown section in test script. "
1872 "Perhaps missing closing ']'?\n");
1873 return PIGLIT_FAIL;
1875 } else {
1876 switch (state) {
1877 case none:
1878 case vertex_shader_passthrough:
1879 break;
1881 case requirements:
1882 result = process_requirement(line);
1883 if (result != PIGLIT_PASS)
1884 return result;
1885 break;
1887 case geometry_layout:
1888 process_geometry_layout(line);
1889 break;
1891 case vertex_shader:
1892 case vertex_program:
1893 case tess_ctrl_shader:
1894 case tess_eval_shader:
1895 case geometry_shader:
1896 case fragment_shader:
1897 case fragment_program:
1898 case compute_shader:
1899 case vertex_shader_spirv:
1900 case tess_ctrl_shader_spirv:
1901 case tess_eval_shader_spirv:
1902 case geometry_shader_spirv:
1903 case fragment_shader_spirv:
1904 case compute_shader_spirv:
1905 case shader_include:
1906 case shader_include_paths:
1907 if (shader_string == NULL)
1908 shader_string = (char *) line;
1909 break;
1911 case vertex_shader_specializations:
1912 case tess_ctrl_shader_specializations:
1913 case tess_eval_shader_specializations:
1914 case geometry_shader_specializations:
1915 case fragment_shader_specializations:
1916 case compute_shader_specializations: {
1917 enum piglit_result result =
1918 process_specialization(state, line);
1919 if (result != PIGLIT_PASS)
1920 return result;
1921 break;
1924 case vertex_data:
1925 if (vertex_data_start == NULL)
1926 vertex_data_start = line;
1927 break;
1929 case test:
1930 break;
1934 line = strchrnul(line, '\n');
1935 if (line[0] != '\0')
1936 line++;
1938 line_num++;
1941 return leave_state(state, line, script_name);
1944 struct requirement_parse_results {
1945 bool found_gl;
1946 bool found_glsl;
1947 bool found_size;
1948 bool found_depthbuffer;
1949 struct component_version gl_version;
1950 struct component_version glsl_version;
1951 unsigned size[2];
1954 static void
1955 parse_required_config(struct requirement_parse_results *results,
1956 const char *script_name)
1958 unsigned text_size;
1959 char *text = piglit_load_text_file(script_name, &text_size);
1960 const char *line = text;
1961 bool in_requirement_section = false;
1963 results->found_gl = false;
1964 results->found_glsl = false;
1965 results->found_size = false;
1966 results->found_depthbuffer = false;
1968 if (line == NULL) {
1969 printf("could not read file \"%s\"\n", script_name);
1970 piglit_report_result(PIGLIT_FAIL);
1973 while (line[0] != '\0') {
1974 if (line[0] == '[') {
1975 if (in_requirement_section)
1976 break;
1977 else
1978 in_requirement_section = false;
1981 if (!in_requirement_section) {
1982 if (parse_str(line, "[require]", NULL)) {
1983 in_requirement_section = true;
1985 } else {
1986 if (parse_str(line, "GL_", NULL)
1987 || parse_str(line, "!GL_", NULL)) {
1988 /* empty */
1989 } else if (parse_str(line, "GLSL", &line)) {
1990 enum comparison cmp;
1991 struct component_version version;
1993 parse_version_comparison(line, &cmp,
1994 &version, VERSION_GLSL);
1995 if (cmp == greater_equal) {
1996 results->found_glsl = true;
1997 version_copy(&results->glsl_version, &version);
1999 } else if (parse_str(line, "GL", &line)) {
2000 enum comparison cmp;
2001 struct component_version version;
2003 parse_version_comparison(line, &cmp,
2004 &version, VERSION_GL);
2005 if (cmp == greater_equal
2006 || cmp == greater
2007 || cmp == equal) {
2008 results->found_gl = true;
2009 version_copy(&results->gl_version, &version);
2011 } else if (parse_str(line, "SIZE", &line)) {
2012 results->found_size = true;
2013 parse_uints(line, results->size, 2, NULL);
2014 } else if (parse_str(line, "depthbuffer", NULL)) {
2015 results->found_depthbuffer = true;
2019 line = strchrnul(line, '\n');
2020 if (line[0] != '\0')
2021 line++;
2024 free(text);
2026 if (!in_requirement_section) {
2027 printf("[require] section missing\n");
2028 piglit_report_result(PIGLIT_FAIL);
2031 if (results->found_glsl && results->glsl_version.es && !results->found_gl) {
2032 printf("%s", "The test specifies a requirement for GLSL ES, "
2033 "but specifies no GL requirement\n.");
2034 piglit_report_result(PIGLIT_FAIL);
2039 static void
2040 choose_required_gl_version(struct requirement_parse_results *parse_results,
2041 struct component_version *gl_version)
2043 if (parse_results->found_gl) {
2044 version_copy(gl_version, &parse_results->gl_version);
2045 } else {
2046 assert(!parse_results->found_glsl || !parse_results->glsl_version.es);
2047 version_init(gl_version, VERSION_GL, false, false, false, 10);
2050 if (gl_version->es)
2051 return;
2053 /* Possibly promote the GL version. */
2054 if (parse_results->found_glsl
2055 && gl_version->num < required_gl_version_from_glsl_version(
2056 parse_results->glsl_version.num)) {
2057 gl_version->num = required_gl_version_from_glsl_version(
2058 parse_results->glsl_version.num);
2063 * Just determine the GLSL version required by the shader script.
2065 * This function is a bit of a hack that is, unfortunately necessary. A test
2066 * script can require a specific GLSL version or a specific GL version. To
2067 * satisfy this requirement, the piglit framework code needs to know about the
2068 * requirement before creating the context. However, the requirements section
2069 * can contain other requirements, such as minimum number of uniforms.
2071 * The requirements section can't be fully processed until after the context
2072 * is created, but the context can't be created until after the requirements
2073 * section is processed. Do a quick scan over the requirements section to find
2074 * the GL and GLSL version requirements. Use these to guide context creation.
2076 static void
2077 get_required_config(const char *script_name, bool spirv,
2078 struct piglit_gl_test_config *config)
2080 struct requirement_parse_results parse_results;
2081 struct component_version required_gl_version;
2083 parse_required_config(&parse_results, script_name);
2084 choose_required_gl_version(&parse_results, &required_gl_version);
2086 if (spirv) {
2087 required_gl_version.es = false;
2088 required_gl_version.core = true;
2089 required_gl_version.num = MAX2(required_gl_version.num, 33);
2092 if (parse_results.found_size) {
2093 config->window_width = parse_results.size[0];
2094 config->window_height = parse_results.size[1];
2097 if (required_gl_version.es) {
2098 config->supports_gl_es_version = required_gl_version.num;
2099 } else if (required_gl_version.num >= 31) {
2100 if (!required_gl_version.compat)
2101 config->supports_gl_core_version = required_gl_version.num;
2102 if (!required_gl_version.core)
2103 config->supports_gl_compat_version = required_gl_version.num;
2104 } else {
2105 config->supports_gl_compat_version = 10;
2108 if (parse_results.found_depthbuffer) {
2109 config->window_visual |= PIGLIT_GL_VISUAL_DEPTH;
2114 * Check that the GL implementation supports unsigned uniforms
2115 * (e.g. through glUniform1ui). If not, terminate the test with a
2116 * SKIP.
2118 static void
2119 check_unsigned_support(void)
2121 if (gl_version.num < 30 && !piglit_is_extension_supported("GL_EXT_gpu_shader4"))
2122 piglit_report_result(PIGLIT_SKIP);
2126 * Check that the GL implementation supports double uniforms
2127 * (e.g. through glUniform1d). If not, terminate the test with a
2128 * SKIP.
2130 static void
2131 check_double_support(void)
2133 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_gpu_shader_fp64"))
2134 piglit_report_result(PIGLIT_SKIP);
2138 * Check that the GL implementation supports double uniforms
2139 * (e.g. through glUniform1d). If not, terminate the test with a
2140 * SKIP.
2142 static void
2143 check_int64_support(void)
2145 if (!piglit_is_extension_supported("GL_ARB_gpu_shader_int64"))
2146 piglit_report_result(PIGLIT_SKIP);
2150 * Check that the GL implementation supports shader subroutines
2151 * If not, terminate the test with a SKIP.
2153 static void
2154 check_shader_subroutine_support(void)
2156 if (gl_version.num < 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
2157 piglit_report_result(PIGLIT_SKIP);
2161 * Check that the GL implementation supports texture handles.
2162 * If not, terminate the test with a SKIP.
2164 static void
2165 check_texture_handle_support(void)
2167 if (!piglit_is_extension_supported("GL_ARB_bindless_texture"))
2168 piglit_report_result(PIGLIT_SKIP);
2171 static bool
2172 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2173 GLuint *uniform_index_out,
2174 GLint *block_index_out,
2175 GLint *offset_out);
2178 * Handles uploads of UBO uniforms by mapping the buffer and storing
2179 * the data. If the uniform is not in a uniform block, returns false.
2181 static bool
2182 set_ubo_uniform(char *name, const char *type,
2183 const char *line,
2184 struct block_info block_data)
2186 /* Note: on SPIR-V we can't access to uniform_index as we
2187 * could lack the name. We force that with force_no_names on
2188 * GLSL
2190 GLuint uniform_index;
2191 GLint block_index;
2192 GLint offset;
2193 char *data;
2194 float f[16];
2195 double d[16];
2196 int ints[16];
2197 unsigned uints[16];
2198 uint64_t uint64s[16];
2199 int64_t int64s[16];
2201 if (!get_indexes_and_offset_from_ubo(name, block_data, &uniform_index,
2202 &block_index, &offset)) {
2203 return false;
2206 glBindBuffer(GL_UNIFORM_BUFFER,
2207 uniform_block_bos[block_index]);
2208 data = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
2209 data += offset;
2211 if (parse_str(type, "float", NULL)) {
2212 parse_floats(line, f, 1, NULL);
2213 memcpy(data, f, sizeof(float));
2214 } else if (parse_str(type, "int64_t", NULL)) {
2215 parse_int64s(line, int64s, 1, NULL);
2216 memcpy(data, int64s, sizeof(int64_t));
2217 } else if (parse_str(type, "uint64_t", NULL)) {
2218 parse_uint64s(line, uint64s, 1, NULL);
2219 memcpy(data, uint64s, sizeof(uint64_t));
2220 } else if (parse_str(type, "int", NULL)) {
2221 parse_ints(line, ints, 1, NULL);
2222 memcpy(data, ints, sizeof(int));
2223 } else if (parse_str(type, "uint", NULL)) {
2224 parse_uints(line, uints, 1, NULL);
2225 memcpy(data, uints, sizeof(int));
2226 } else if (parse_str(type, "double", NULL)) {
2227 parse_doubles(line, d, 1, NULL);
2228 memcpy(data, d, sizeof(double));
2229 } else if (parse_str(type, "vec", NULL)) {
2230 int elements = type[3] - '0';
2231 parse_floats(line, f, elements, NULL);
2232 memcpy(data, f, elements * sizeof(float));
2233 } else if (parse_str(type, "ivec", NULL)) {
2234 int elements = type[4] - '0';
2235 parse_ints(line, ints, elements, NULL);
2236 memcpy(data, ints, elements * sizeof(int));
2237 } else if (parse_str(type, "uvec", NULL)) {
2238 int elements = type[4] - '0';
2239 parse_uints(line, uints, elements, NULL);
2240 memcpy(data, uints, elements * sizeof(unsigned));
2241 } else if (parse_str(type, "i64vec", NULL)) {
2242 int elements = type[6] - '0';
2243 parse_int64s(line, int64s, elements, NULL);
2244 memcpy(data, int64s, elements * sizeof(int64_t));
2245 } else if (parse_str(type, "u64vec", NULL)) {
2246 int elements = type[6] - '0';
2247 parse_uint64s(line, uint64s, elements, NULL);
2248 memcpy(data, uint64s, elements * sizeof(uint64_t));
2249 } else if (parse_str(type, "dvec", NULL)) {
2250 int elements = type[4] - '0';
2251 parse_doubles(line, d, elements, NULL);
2252 memcpy(data, d, elements * sizeof(double));
2253 } else if (parse_str(type, "mat", NULL)) {
2254 GLint matrix_stride, row_major;
2255 int cols = type[3] - '0';
2256 int rows = type[4] == 'x' ? type[5] - '0' : cols;
2257 int r, c;
2258 float *matrixdata = (float *)data;
2260 assert(cols >= 2 && cols <= 4);
2261 assert(rows >= 2 && rows <= 4);
2263 parse_floats(line, f, rows * cols, NULL);
2265 if (!force_no_names) {
2266 glGetActiveUniformsiv(prog, 1, &uniform_index,
2267 GL_UNIFORM_MATRIX_STRIDE,
2268 &matrix_stride);
2269 glGetActiveUniformsiv(prog, 1, &uniform_index,
2270 GL_UNIFORM_IS_ROW_MAJOR,
2271 &row_major);
2272 } else {
2273 matrix_stride = block_data.matrix_stride;
2274 row_major = block_data.row_major;
2277 matrix_stride /= sizeof(float);
2279 /* Expect the data in the .shader_test file to be listed in
2280 * column-major order no matter what the layout of the data in
2281 * the UBO will be.
2283 for (c = 0; c < cols; c++) {
2284 for (r = 0; r < rows; r++) {
2285 if (row_major) {
2286 matrixdata[matrix_stride * r + c] =
2287 f[c * rows + r];
2288 } else {
2289 matrixdata[matrix_stride * c + r] =
2290 f[c * rows + r];
2294 } else if (parse_str(type, "dmat", NULL)) {
2295 GLint matrix_stride, row_major;
2296 int cols = type[4] - '0';
2297 int rows = type[5] == 'x' ? type[6] - '0' : cols;
2298 int r, c;
2299 double *matrixdata = (double *)data;
2301 assert(cols >= 2 && cols <= 4);
2302 assert(rows >= 2 && rows <= 4);
2304 parse_doubles(line, d, rows * cols, NULL);
2306 if (!force_no_names) {
2307 glGetActiveUniformsiv(prog, 1, &uniform_index,
2308 GL_UNIFORM_MATRIX_STRIDE,
2309 &matrix_stride);
2310 glGetActiveUniformsiv(prog, 1, &uniform_index,
2311 GL_UNIFORM_IS_ROW_MAJOR,
2312 &row_major);
2313 } else {
2314 matrix_stride = block_data.matrix_stride;
2315 row_major = block_data.row_major;
2318 matrix_stride /= sizeof(double);
2320 /* Expect the data in the .shader_test file to be listed in
2321 * column-major order no matter what the layout of the data in
2322 * the UBO will be.
2324 for (c = 0; c < cols; c++) {
2325 for (r = 0; r < rows; r++) {
2326 if (row_major) {
2327 matrixdata[matrix_stride * r + c] =
2328 d[c * rows + r];
2329 } else {
2330 matrixdata[matrix_stride * c + r] =
2331 d[c * rows + r];
2335 } else if (parse_str(type, "handle", NULL)) {
2336 check_unsigned_support();
2337 check_texture_handle_support();
2338 parse_uints(line, uints, 1, NULL);
2339 GLuint64 handle = get_resident_handle(uints[0])->handle;
2340 memcpy(data, &handle, sizeof(uint64_t));
2341 } else {
2342 printf("unknown uniform type \"%s\" for \"%s\"\n", type, name);
2343 piglit_report_result(PIGLIT_FAIL);
2346 glUnmapBuffer(GL_UNIFORM_BUFFER);
2348 return true;
2352 * Get the uniform_index, block_index and offset of a given
2353 * uniform. By default it gets those values using the uniform name. If
2354 * force_no_names mode is active, it uses the current values stored at
2355 * @block_data. On the latter, uniform index is not filled up.
2357 static bool
2358 get_indexes_and_offset_from_ubo(char *name, struct block_info block_data,
2359 GLuint *uniform_index_out,
2360 GLint *block_index_out,
2361 GLint *offset_out)
2363 GLuint uniform_index = 0;
2364 GLint block_index;
2365 GLint offset;
2366 int name_len = strlen(name);
2367 GLint array_index = 0;
2369 if (!num_uniform_blocks)
2370 return false;
2372 if (!force_no_names) {
2373 /* if the uniform is an array, strip the index, as GL
2374 prevents non-zero indexes from matching a name */
2375 if (name[name_len - 1] == ']') {
2376 int i;
2378 for (i = name_len - 1; (i > 0) && isdigit(name[i-1]); --i)
2379 /* empty */;
2381 array_index = strtol(&name[i], NULL, 0);
2383 if (i) {
2384 i--;
2385 if (name[i] != '[') {
2386 printf("cannot parse uniform \"%s\"\n", name);
2387 piglit_report_result(PIGLIT_FAIL);
2389 name[i] = 0;
2394 glGetUniformIndices(prog, 1, (const char **)&name, &uniform_index);
2395 if (uniform_index == GL_INVALID_INDEX) {
2396 printf("cannot get index of uniform \"%s\"\n", name);
2397 piglit_report_result(PIGLIT_FAIL);
2400 glGetActiveUniformsiv(prog, 1, &uniform_index,
2401 GL_UNIFORM_BLOCK_INDEX, &block_index);
2403 if (block_index == -1)
2404 return false;
2406 /* if the uniform block is an array, then GetActiveUniformsiv with
2407 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2408 * element in the array.
2410 block_index += block_data.array_index;
2412 glGetActiveUniformsiv(prog, 1, &uniform_index,
2413 GL_UNIFORM_OFFSET, &offset);
2415 if (name[name_len - 1] == ']') {
2416 GLint stride;
2418 glGetActiveUniformsiv(prog, 1, &uniform_index,
2419 GL_UNIFORM_ARRAY_STRIDE, &stride);
2420 offset += stride * array_index;
2422 } else {
2423 if (block_data.binding < 0) {
2424 printf("if you force to use a explicit ubo binding, you "
2425 "need to provide it when filling the data with "
2426 "\"ubo binding\"\n");
2427 piglit_report_result(PIGLIT_FAIL);
2430 /* The mapping could be improved using a hash
2431 * table. For now, this is enough.
2433 block_index = uniform_block_indexes[block_data.binding];
2435 /* if the uniform block is an array, then GetActiveUniformsiv with
2436 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2437 * element in the array.
2439 block_index += block_data.array_index;
2441 if (block_data.offset < 0) {
2442 printf("if you force to use a explicit ubo binding, you "
2443 "need to provide offset when filling the data with "
2444 "\"ubo offset\"\n");
2445 piglit_report_result(PIGLIT_FAIL);
2447 offset = block_data.offset;
2450 *offset_out = offset;
2451 *block_index_out = block_index;
2452 *uniform_index_out = uniform_index;
2454 return true;
2457 static void
2458 set_uniform(const char *line, struct block_info block_data)
2460 char name[512], type[512];
2461 float f[16];
2462 double d[16];
2463 int ints[16];
2464 unsigned uints[16];
2465 int64_t int64s[16];
2466 uint64_t uint64s[16];
2467 GLint loc;
2469 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2470 parse_word_copy(line, name, sizeof(name), &line),
2471 "Invalid set uniform command at: %s\n", line);
2473 if (isdigit(name[0])) {
2474 loc = strtol(name, NULL, 0);
2475 } else {
2476 GLuint prog;
2478 if (set_ubo_uniform(name, type, line, block_data))
2479 return;
2481 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2482 loc = glGetUniformLocation(prog, name);
2483 if (loc < 0) {
2484 if (ignore_missing_uniforms)
2485 return;
2486 printf("cannot get location of uniform \"%s\"\n",
2487 name);
2488 piglit_report_result(PIGLIT_FAIL);
2492 if (parse_str(type, "float", NULL)) {
2493 parse_floats(line, f, 1, NULL);
2494 glUniform1fv(loc, 1, f);
2495 return;
2496 } else if (parse_str(type, "int64_t", NULL)) {
2497 check_int64_support();
2498 parse_int64s(line, int64s, 1, NULL);
2499 glUniform1i64vARB(loc, 1, int64s);
2500 return;
2501 } else if (parse_str(type, "uint64_t", NULL)) {
2502 check_int64_support();
2503 parse_uint64s(line, uint64s, 1, NULL);
2504 glUniform1ui64vARB(loc, 1, uint64s);
2505 return;
2506 } else if (parse_str(type, "int", NULL)) {
2507 parse_ints(line, ints, 1, NULL);
2508 glUniform1iv(loc, 1, ints);
2509 return;
2510 } else if (parse_str(type, "uint", NULL)) {
2511 check_unsigned_support();
2512 parse_uints(line, uints, 1, NULL);
2513 glUniform1uiv(loc, 1, uints);
2514 return;
2515 } else if (parse_str(type, "double", NULL)) {
2516 check_double_support();
2517 parse_doubles(line, d, 1, NULL);
2518 glUniform1dv(loc, 1, d);
2519 return;
2520 } else if (parse_str(type, "vec", NULL)) {
2521 switch (type[3]) {
2522 case '2':
2523 parse_floats(line, f, 2, NULL);
2524 glUniform2fv(loc, 1, f);
2525 return;
2526 case '3':
2527 parse_floats(line, f, 3, NULL);
2528 glUniform3fv(loc, 1, f);
2529 return;
2530 case '4':
2531 parse_floats(line, f, 4, NULL);
2532 glUniform4fv(loc, 1, f);
2533 return;
2535 } else if (parse_str(type, "ivec", NULL)) {
2536 switch (type[4]) {
2537 case '2':
2538 parse_ints(line, ints, 2, NULL);
2539 glUniform2iv(loc, 1, ints);
2540 return;
2541 case '3':
2542 parse_ints(line, ints, 3, NULL);
2543 glUniform3iv(loc, 1, ints);
2544 return;
2545 case '4':
2546 parse_ints(line, ints, 4, NULL);
2547 glUniform4iv(loc, 1, ints);
2548 return;
2550 } else if (parse_str(type, "uvec", NULL)) {
2551 check_unsigned_support();
2552 switch (type[4]) {
2553 case '2':
2554 parse_uints(line, uints, 2, NULL);
2555 glUniform2uiv(loc, 1, uints);
2556 return;
2557 case '3':
2558 parse_uints(line, uints, 3, NULL);
2559 glUniform3uiv(loc, 1, uints);
2560 return;
2561 case '4':
2562 parse_uints(line, uints, 4, NULL);
2563 glUniform4uiv(loc, 1, uints);
2564 return;
2566 } else if (parse_str(type, "dvec", NULL)) {
2567 check_double_support();
2568 switch (type[4]) {
2569 case '2':
2570 parse_doubles(line, d, 2, NULL);
2571 glUniform2dv(loc, 1, d);
2572 return;
2573 case '3':
2574 parse_doubles(line, d, 3, NULL);
2575 glUniform3dv(loc, 1, d);
2576 return;
2577 case '4':
2578 parse_doubles(line, d, 4, NULL);
2579 glUniform4dv(loc, 1, d);
2580 return;
2582 } else if (parse_str(type, "i64vec", NULL)) {
2583 check_int64_support();
2584 switch (type[6]) {
2585 case '2':
2586 parse_int64s(line, int64s, 2, NULL);
2587 glUniform2i64vARB(loc, 1, int64s);
2588 return;
2589 case '3':
2590 parse_int64s(line, int64s, 3, NULL);
2591 glUniform3i64vARB(loc, 1, int64s);
2592 return;
2593 case '4':
2594 parse_int64s(line, int64s, 4, NULL);
2595 glUniform4i64vARB(loc, 1, int64s);
2596 return;
2598 } else if (parse_str(type, "u64vec", NULL)) {
2599 check_int64_support();
2600 switch (type[6]) {
2601 case '2':
2602 parse_uint64s(line, uint64s, 2, NULL);
2603 glUniform2ui64vARB(loc, 1, uint64s);
2604 return;
2605 case '3':
2606 parse_uint64s(line, uint64s, 3, NULL);
2607 glUniform3ui64vARB(loc, 1, uint64s);
2608 return;
2609 case '4':
2610 parse_uint64s(line, uint64s, 4, NULL);
2611 glUniform4ui64vARB(loc, 1, uint64s);
2612 return;
2614 } else if (parse_str(type, "mat", NULL) && type[3] != '\0') {
2615 char cols = type[3];
2616 char rows = type[4] == 'x' ? type[5] : cols;
2617 switch (cols) {
2618 case '2':
2619 switch (rows) {
2620 case '2':
2621 parse_floats(line, f, 4, NULL);
2622 glUniformMatrix2fv(loc, 1, GL_FALSE, f);
2623 return;
2624 case '3':
2625 parse_floats(line, f, 6, NULL);
2626 glUniformMatrix2x3fv(loc, 1, GL_FALSE, f);
2627 return;
2628 case '4':
2629 parse_floats(line, f, 8, NULL);
2630 glUniformMatrix2x4fv(loc, 1, GL_FALSE, f);
2631 return;
2633 case '3':
2634 switch (rows) {
2635 case '2':
2636 parse_floats(line, f, 6, NULL);
2637 glUniformMatrix3x2fv(loc, 1, GL_FALSE, f);
2638 return;
2639 case '3':
2640 parse_floats(line, f, 9, NULL);
2641 glUniformMatrix3fv(loc, 1, GL_FALSE, f);
2642 return;
2643 case '4':
2644 parse_floats(line, f, 12, NULL);
2645 glUniformMatrix3x4fv(loc, 1, GL_FALSE, f);
2646 return;
2648 case '4':
2649 switch (rows) {
2650 case '2':
2651 parse_floats(line, f, 8, NULL);
2652 glUniformMatrix4x2fv(loc, 1, GL_FALSE, f);
2653 return;
2654 case '3':
2655 parse_floats(line, f, 12, NULL);
2656 glUniformMatrix4x3fv(loc, 1, GL_FALSE, f);
2657 return;
2658 case '4':
2659 parse_floats(line, f, 16, NULL);
2660 glUniformMatrix4fv(loc, 1, GL_FALSE, f);
2661 return;
2664 } else if (parse_str(type, "dmat", NULL) && type[4] != '\0') {
2665 char cols = type[4];
2666 char rows = type[5] == 'x' ? type[6] : cols;
2667 switch (cols) {
2668 case '2':
2669 switch (rows) {
2670 case '2':
2671 parse_doubles(line, d, 4, NULL);
2672 glUniformMatrix2dv(loc, 1, GL_FALSE, d);
2673 return;
2674 case '3':
2675 parse_doubles(line, d, 6, NULL);
2676 glUniformMatrix2x3dv(loc, 1, GL_FALSE, d);
2677 return;
2678 case '4':
2679 parse_doubles(line, d, 8, NULL);
2680 glUniformMatrix2x4dv(loc, 1, GL_FALSE, d);
2681 return;
2683 case '3':
2684 switch (rows) {
2685 case '2':
2686 parse_doubles(line, d, 6, NULL);
2687 glUniformMatrix3x2dv(loc, 1, GL_FALSE, d);
2688 return;
2689 case '3':
2690 parse_doubles(line, d, 9, NULL);
2691 glUniformMatrix3dv(loc, 1, GL_FALSE, d);
2692 return;
2693 case '4':
2694 parse_doubles(line, d, 12, NULL);
2695 glUniformMatrix3x4dv(loc, 1, GL_FALSE, d);
2696 return;
2698 case '4':
2699 switch (rows) {
2700 case '2':
2701 parse_doubles(line, d, 8, NULL);
2702 glUniformMatrix4x2dv(loc, 1, GL_FALSE, d);
2703 return;
2704 case '3':
2705 parse_doubles(line, d, 12, NULL);
2706 glUniformMatrix4x3dv(loc, 1, GL_FALSE, d);
2707 return;
2708 case '4':
2709 parse_doubles(line, d, 16, NULL);
2710 glUniformMatrix4dv(loc, 1, GL_FALSE, d);
2711 return;
2714 } else if (parse_str(type, "handle", NULL)) {
2715 check_unsigned_support();
2716 check_texture_handle_support();
2717 parse_uints(line, uints, 1, NULL);
2718 glUniformHandleui64ARB(loc, get_resident_handle(uints[0])->handle);
2719 return;
2722 printf("unknown uniform type \"%s\"\n", type);
2723 piglit_report_result(PIGLIT_FAIL);
2725 return;
2728 static void
2729 set_vertex_attrib(const char *line)
2731 char name[512], type[512];
2732 uint32_t uints[16];
2733 GLint loc;
2735 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2736 parse_word_copy(line, name, sizeof(name), &line),
2737 "Invalid set vertex attrib command at: %s\n", line);
2739 if (isdigit(name[0])) {
2740 loc = strtol(name, NULL, 0);
2741 } else {
2742 GLuint prog;
2744 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2745 loc = glGetAttribLocation(prog, name);
2746 if (loc < 0) {
2747 if (ignore_missing_uniforms)
2748 return;
2749 printf("cannot get location of vertex attrib \"%s\"\n",
2750 name);
2751 piglit_report_result(PIGLIT_FAIL);
2755 if (parse_str(type, "handle", NULL)) {
2756 check_unsigned_support();
2757 check_texture_handle_support();
2758 parse_uints(line, uints, 1, NULL);
2759 glVertexAttribL1ui64ARB(loc, get_resident_handle(uints[0])->handle);
2760 return;
2763 printf("unknown vertex attrib type \"%s\"\n", type);
2764 printf("use [vertex data] instead if possible\n");
2765 piglit_report_result(PIGLIT_FAIL);
2767 return;
2770 static GLenum lookup_shader_type(GLuint idx)
2772 switch (idx) {
2773 case 0:
2774 return GL_VERTEX_SHADER;
2775 case 1:
2776 return GL_FRAGMENT_SHADER;
2777 case 2:
2778 return GL_GEOMETRY_SHADER;
2779 case 3:
2780 return GL_TESS_CONTROL_SHADER;
2781 case 4:
2782 return GL_TESS_EVALUATION_SHADER;
2783 case 5:
2784 return GL_COMPUTE_SHADER;
2785 default:
2786 return 0;
2790 static GLenum get_shader_from_string(const char *name, int *idx)
2792 if (parse_str(name, "GL_VERTEX_SHADER", NULL)) {
2793 *idx = 0;
2794 return GL_VERTEX_SHADER;
2796 if (parse_str(name, "GL_FRAGMENT_SHADER", NULL)) {
2797 *idx = 1;
2798 return GL_FRAGMENT_SHADER;
2800 if (parse_str(name, "GL_GEOMETRY_SHADER", NULL)) {
2801 *idx = 2;
2802 return GL_GEOMETRY_SHADER;
2804 if (parse_str(name, "GL_TESS_CONTROL_SHADER", NULL)) {
2805 *idx = 3;
2806 return GL_TESS_CONTROL_SHADER;
2808 if (parse_str(name, "GL_TESS_EVALUATION_SHADER", NULL)) {
2809 *idx = 4;
2810 return GL_TESS_EVALUATION_SHADER;
2812 if (parse_str(name, "GL_COMPUTE_SHADER", NULL)) {
2813 *idx = 5;
2814 return GL_COMPUTE_SHADER;
2816 return 0;
2819 static void
2820 free_subroutine_uniforms(void)
2822 int sidx;
2823 for (sidx = 0; sidx < 4; sidx++) {
2824 free(subuniform_locations[sidx]);
2825 subuniform_locations[sidx] = NULL;
2829 static void
2830 program_subroutine_uniforms(void)
2832 int sidx;
2833 int stype;
2835 for (sidx = 0; sidx < 4; sidx++) {
2837 if (num_subuniform_locations[sidx] == 0)
2838 continue;
2840 stype = lookup_shader_type(sidx);
2841 if (!stype)
2842 continue;
2844 glUniformSubroutinesuiv(stype, num_subuniform_locations[sidx], subuniform_locations[sidx]);
2848 static void
2849 set_subroutine_uniform(const char *line)
2851 GLuint prog;
2852 char type[512];
2853 char name[512];
2854 char subname[512];
2855 GLint loc;
2856 GLuint idx;
2857 GLenum ptype = 0;
2858 int sidx = 0;
2860 REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
2861 parse_word_copy(line, name, sizeof(name), &line) &&
2862 parse_word_copy(line, subname, sizeof(subname), &line),
2863 "Invalid set subroutine uniform command at: %s\n", line);
2865 ptype = get_shader_from_string(type, &sidx);
2866 if (ptype == 0) {
2867 printf("illegal type in subroutine uniform\n");
2868 piglit_report_result(PIGLIT_FAIL);
2871 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
2873 if (num_subuniform_locations[sidx] == 0) {
2874 glGetProgramStageiv(prog, ptype, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
2875 &num_subuniform_locations[sidx]);
2877 if (num_subuniform_locations[sidx] == 0) {
2878 printf("illegal subroutine uniform specified\n");
2879 piglit_report_result(PIGLIT_FAIL);
2882 subuniform_locations[sidx] = calloc(num_subuniform_locations[sidx], sizeof(GLuint));
2883 if (!subuniform_locations[sidx])
2884 piglit_report_result(PIGLIT_FAIL);
2887 loc = glGetSubroutineUniformLocation(prog, ptype, name);
2888 if (loc < 0) {
2889 if (ignore_missing_uniforms)
2890 return;
2891 printf("cannot get location of subroutine uniform \"%s\"\n",
2892 name);
2893 piglit_report_result(PIGLIT_FAIL);
2896 idx = glGetSubroutineIndex(prog, ptype, subname);
2897 if (idx == GL_INVALID_INDEX) {
2898 printf("cannot get index of subroutine uniform \"%s\"\n",
2899 subname);
2900 piglit_report_result(PIGLIT_FAIL);
2903 subuniform_locations[sidx][loc] = idx;
2904 return;
2908 * Query values from current program using glGetProgram.
2910 * Format of the command:
2911 * verify program_query GL_PNAME_ENUM integer
2913 * or
2915 * verify program_query GL_PNAME_ENUM <enum>
2917 * Note: GL_COMPUTE_WORK_GROUP_SIZE is not supported, as is the only
2918 * query that requires a params with more than one component, and we
2919 * want to keep things simple.
2922 static void
2923 verify_program_query(const char *line)
2925 static const struct string_to_enum all_pnames[] = {
2926 ENUM_STRING(GL_DELETE_STATUS),
2927 ENUM_STRING(GL_LINK_STATUS),
2928 ENUM_STRING(GL_VALIDATE_STATUS),
2929 ENUM_STRING(GL_INFO_LOG_LENGTH),
2930 ENUM_STRING(GL_ATTACHED_SHADERS),
2931 ENUM_STRING(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS),
2932 ENUM_STRING(GL_ACTIVE_ATTRIBUTES),
2933 ENUM_STRING(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH),
2934 ENUM_STRING(GL_ACTIVE_UNIFORMS),
2935 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCKS),
2936 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH),
2937 ENUM_STRING(GL_ACTIVE_UNIFORM_MAX_LENGTH),
2938 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
2939 ENUM_STRING(GL_PROGRAM_BINARY_LENGTH),
2940 ENUM_STRING(GL_TRANSFORM_FEEDBACK_BUFFER_MODE),
2941 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYINGS),
2942 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH),
2943 ENUM_STRING(GL_GEOMETRY_VERTICES_OUT),
2944 ENUM_STRING(GL_GEOMETRY_INPUT_TYPE),
2945 ENUM_STRING(GL_GEOMETRY_OUTPUT_TYPE),
2946 { NULL, 0 }
2949 static const struct string_to_enum all_possible_param_enums[] = {
2950 ENUM_STRING(GL_TRUE),
2951 ENUM_STRING(GL_FALSE),
2952 ENUM_STRING(GL_SEPARATE_ATTRIBS),
2953 ENUM_STRING(GL_INTERLEAVED_ATTRIBS),
2954 ENUM_STRING(GL_POINTS),
2955 ENUM_STRING(GL_LINES),
2956 ENUM_STRING(GL_LINES_ADJACENCY),
2957 ENUM_STRING(GL_TRIANGLES),
2958 ENUM_STRING(GL_TRIANGLES_ADJACENCY),
2959 ENUM_STRING(GL_LINE_STRIP),
2960 ENUM_STRING(GL_TRIANGLE_STRIP),
2961 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE),
2962 { NULL, 0 }
2965 unsigned pname;
2966 int expected;
2967 int value;
2969 REQUIRE(parse_enum_tab(all_pnames, line,
2970 &pname, &line),
2971 "Bad glGetProgram pname at: %s\n", line);
2973 REQUIRE(parse_enum_tab(all_possible_param_enums, line, (unsigned *)&expected, &line) ||
2974 parse_int(line, &expected, &line),
2975 "Bad expected value at: %s\n", line);
2977 if (pname == GL_COMPUTE_WORK_GROUP_SIZE) {
2978 /* TODO: eventually it would be good to add support for
2979 * this parameter. What it makes different to the rest is
2980 * that it requires a param with more than one component
2982 fprintf(stderr, "glGetProgram queries with GL_COMPUTE_WORK_GROUP_SIZE "
2983 "not supported yet\n");
2984 piglit_report_result(PIGLIT_FAIL);
2987 glGetProgramiv(prog, pname, &value);
2989 if (expected != value) {
2990 fprintf(stderr, "glGetProgram(%s): expected %d, got %d\n",
2991 piglit_get_gl_enum_name(pname), expected, value);
2992 piglit_report_result(PIGLIT_FAIL);
2997 * Query a uniform using glGetActiveUniformsiv
2999 * Format of the command:
3001 * active uniform uniform_name GL_PNAME_ENUM integer
3003 * or
3005 * active uniform uniform_name GL_PNAME_ENUM GL_TYPE_ENUM
3007 static void
3008 active_uniform(const char *line)
3010 static const struct string_to_enum all_pnames[] = {
3011 ENUM_STRING(GL_UNIFORM_TYPE),
3012 ENUM_STRING(GL_UNIFORM_SIZE),
3013 ENUM_STRING(GL_UNIFORM_NAME_LENGTH),
3014 ENUM_STRING(GL_UNIFORM_BLOCK_INDEX),
3015 ENUM_STRING(GL_UNIFORM_OFFSET),
3016 ENUM_STRING(GL_UNIFORM_ARRAY_STRIDE),
3017 ENUM_STRING(GL_UNIFORM_MATRIX_STRIDE),
3018 ENUM_STRING(GL_UNIFORM_IS_ROW_MAJOR),
3019 ENUM_STRING(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX),
3020 { NULL, 0 }
3023 const char *rest = line;
3024 char name[512];
3025 char name_buf[512];
3026 unsigned pname;
3027 int expected;
3028 int i;
3029 int num_active_uniforms;
3031 REQUIRE(parse_word_copy(rest, name, sizeof(name), &rest),
3032 "Bad uniform name at: %s\n", line);
3034 REQUIRE(parse_enum_tab(all_pnames, rest, &pname, &rest),
3035 "Bad glGetUniformsiv pname at: %s\n", line);
3037 REQUIRE(parse_enum_tab(all_types, rest, (unsigned *)&expected, &rest) ||
3038 parse_int(rest, &expected, &rest),
3039 "Bad expected value at: %s\n", line);
3041 glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
3042 for (i = 0; i < num_active_uniforms; i++) {
3043 GLint got;
3044 GLint size;
3045 GLenum type;
3046 GLsizei name_len;
3047 bool pass = true;
3049 glGetActiveUniform(prog, i, sizeof(name_buf), &name_len,
3050 &size, &type, name_buf);
3052 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3053 fprintf(stderr, "glGetActiveUniform error\n");
3054 piglit_report_result(PIGLIT_FAIL);
3057 if (strcmp(name, name_buf) != 0)
3058 continue;
3060 /* If the requested pname is one of the values that
3061 * glGetActiveUniform happens to return, check the value
3062 * returned by that function too.
3064 switch (pname) {
3065 case GL_UNIFORM_TYPE:
3066 got = (GLint) type;
3067 break;
3069 case GL_UNIFORM_SIZE:
3070 got = size;
3071 break;
3073 case GL_UNIFORM_NAME_LENGTH:
3074 got = name_len;
3075 break;
3077 default:
3078 /* This ensures the check below will pass when the
3079 * requested enum is not one of the values already
3080 * returned by glGetActiveUniform.
3082 got = expected;
3083 break;
3086 if (got != expected) {
3087 fprintf(stderr,
3088 "glGetActiveUniform(%s, %s): "
3089 "expected %d (0x%04x), got %d (0x%04x)\n",
3090 name, piglit_get_gl_enum_name(pname),
3091 expected, expected, got, got);
3092 pass = false;
3095 /* Set 'got' to some value in case glGetActiveUniformsiv
3096 * doesn't write to it. That should only be able to occur
3097 * when the function raises a GL error, but "should" is kind
3098 * of a funny word.
3100 got = ~expected;
3101 glGetActiveUniformsiv(prog, 1, (GLuint *) &i, pname, &got);
3103 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3104 fprintf(stderr, "glGetActiveUniformsiv error\n");
3105 piglit_report_result(PIGLIT_FAIL);
3108 if (got != expected) {
3109 fprintf(stderr,
3110 "glGetActiveUniformsiv(%s, %s): "
3111 "expected %d, got %d\n",
3112 name, piglit_get_gl_enum_name(pname),
3113 expected, got);
3114 pass = false;
3117 if (!pass)
3118 piglit_report_result(PIGLIT_FAIL);
3120 return;
3123 fprintf(stderr, "No active uniform named \"%s\"\n", name);
3124 piglit_report_result(PIGLIT_FAIL);
3125 return;
3130 * Confirms if @resource_index is a given resource, within @interface_type.
3132 * In order to identify it, it uses by default @resource_name. If
3133 * force_no_names mode is activated it uses the binding contained at
3134 * @block_data. Note that for the latter, only ubos or ssbos are
3135 * supported as @interface_type.
3137 * @resource_name_buf, @prop and @value_expected are only used for
3138 * some extra checks.
3140 * Return true if @resource_index is the resource within
3141 * @interface_type we search for. false otherwise.
3143 static bool
3144 confirm_program_resource(GLenum interface_type, GLuint resource_index,
3145 const char *resource_name, char *resource_name_buf,
3146 struct block_info block_data, unsigned prop,
3147 int value_expected)
3149 if (!force_no_names) {
3150 GLsizei resource_name_len;
3152 glGetProgramResourceName(prog, interface_type, resource_index,
3153 512, &resource_name_len,
3154 resource_name_buf);
3156 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3157 fprintf(stderr, "glGetProgramResourceName error\n");
3158 piglit_report_result(PIGLIT_FAIL);
3161 if (strcmp(resource_name, resource_name_buf) != 0)
3162 return false;
3164 /* glGetProgramResourceName does not consider the NULL
3165 * terminator when returning the name length, however,
3166 * glGetProgramResourceiv does. We take that into account
3167 * when doing the comparison.
3169 if (prop == GL_NAME_LENGTH &&
3170 resource_name_len != (value_expected - 1)) {
3171 fprintf(stderr,
3172 "glGetProgramResourceName(%s, %s, %s): "
3173 "expected length: %d (0x%04x), "
3174 "got length: %d (0x%04x)\n",
3175 piglit_get_gl_enum_name(interface_type),
3176 resource_name, piglit_get_gl_enum_name(prop),
3177 value_expected - 1, value_expected - 1,
3178 resource_name_len, resource_name_len);
3179 piglit_report_result(PIGLIT_FAIL);
3181 } else {
3182 unsigned binding_prop = GL_BUFFER_BINDING;
3183 int current_binding = 0;
3184 GLint length;
3186 if (interface_type != GL_SHADER_STORAGE_BLOCK &&
3187 interface_type != GL_UNIFORM_BLOCK) {
3188 fprintf(stderr,
3189 "active_program_interface queries under force_no_names "
3190 "mode are only supported for GL_SHADER_STORAGE_BLOCK "
3191 "or GL_UNIFORM_BLOCK interfaces\n");
3192 piglit_report_result(PIGLIT_FAIL);
3195 glGetProgramResourceiv(prog, interface_type,
3196 resource_index, 1, &binding_prop, 1,
3197 &length, &current_binding);
3198 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3199 fprintf(stderr, "glGetProgramResourceiv error\n");
3200 piglit_report_result(PIGLIT_FAIL);
3203 if (block_data.binding != current_binding)
3204 return false;
3207 return true;
3211 * Query an active resource using ARB_program_interface_query functions
3213 * Format of the command:
3215 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM integer
3217 * or
3219 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM GL_TYPE_ENUM
3221 static void
3222 active_program_interface(const char *line, struct block_info block_data)
3224 static const struct string_to_enum all_props[] = {
3225 ENUM_STRING(GL_TYPE),
3226 ENUM_STRING(GL_ARRAY_SIZE),
3227 ENUM_STRING(GL_NAME_LENGTH),
3228 ENUM_STRING(GL_BLOCK_INDEX),
3229 ENUM_STRING(GL_OFFSET),
3230 ENUM_STRING(GL_ARRAY_STRIDE),
3231 ENUM_STRING(GL_MATRIX_STRIDE),
3232 ENUM_STRING(GL_IS_ROW_MAJOR),
3233 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER_INDEX),
3234 ENUM_STRING(GL_BUFFER_BINDING),
3235 ENUM_STRING(GL_BUFFER_DATA_SIZE),
3236 ENUM_STRING(GL_NUM_ACTIVE_VARIABLES),
3237 ENUM_STRING(GL_REFERENCED_BY_VERTEX_SHADER),
3238 ENUM_STRING(GL_REFERENCED_BY_TESS_CONTROL_SHADER),
3239 ENUM_STRING(GL_REFERENCED_BY_TESS_EVALUATION_SHADER),
3240 ENUM_STRING(GL_REFERENCED_BY_GEOMETRY_SHADER),
3241 ENUM_STRING(GL_REFERENCED_BY_FRAGMENT_SHADER),
3242 ENUM_STRING(GL_REFERENCED_BY_COMPUTE_SHADER),
3243 ENUM_STRING(GL_TOP_LEVEL_ARRAY_SIZE),
3244 ENUM_STRING(GL_TOP_LEVEL_ARRAY_STRIDE),
3245 ENUM_STRING(GL_LOCATION),
3246 ENUM_STRING(GL_LOCATION_INDEX),
3247 ENUM_STRING(GL_LOCATION_COMPONENT),
3248 ENUM_STRING(GL_IS_PER_PATCH),
3249 ENUM_STRING(GL_NUM_COMPATIBLE_SUBROUTINES),
3250 ENUM_STRING(GL_COMPATIBLE_SUBROUTINES),
3251 { NULL, 0 }
3254 static const struct string_to_enum all_program_interface[] = {
3255 ENUM_STRING(GL_UNIFORM),
3256 ENUM_STRING(GL_UNIFORM_BLOCK),
3257 ENUM_STRING(GL_PROGRAM_INPUT),
3258 ENUM_STRING(GL_PROGRAM_OUTPUT),
3259 ENUM_STRING(GL_BUFFER_VARIABLE),
3260 ENUM_STRING(GL_SHADER_STORAGE_BLOCK),
3261 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER),
3262 ENUM_STRING(GL_VERTEX_SUBROUTINE),
3263 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE),
3264 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE),
3265 ENUM_STRING(GL_GEOMETRY_SUBROUTINE),
3266 ENUM_STRING(GL_FRAGMENT_SUBROUTINE),
3267 ENUM_STRING(GL_COMPUTE_SUBROUTINE),
3268 ENUM_STRING(GL_VERTEX_SUBROUTINE_UNIFORM),
3269 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE_UNIFORM),
3270 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE_UNIFORM),
3271 ENUM_STRING(GL_GEOMETRY_SUBROUTINE_UNIFORM),
3272 ENUM_STRING(GL_FRAGMENT_SUBROUTINE_UNIFORM),
3273 ENUM_STRING(GL_COMPUTE_SUBROUTINE_UNIFORM),
3274 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING),
3275 { NULL, 0 }
3278 char name[512];
3279 char name_buf[512];
3280 unsigned prop, interface_type;
3281 int expected;
3282 int i;
3283 int num_active_buffers;
3285 if (!piglit_is_extension_supported("GL_ARB_program_interface_query") &&
3286 piglit_get_gl_version() < 43) {
3287 fprintf(stderr,
3288 "GL_ARB_program_interface_query not supported or "
3289 "OpenGL version < 4.3\n");
3290 return;
3293 REQUIRE(parse_enum_tab(all_program_interface, line,
3294 &interface_type, &line),
3295 "Bad program interface at: %s\n", line);
3296 REQUIRE(parse_word_copy(line, name, sizeof(name), &line),
3297 "Bad program resource name at: %s\n", line);
3298 REQUIRE(parse_enum_tab(all_props, line, &prop, &line),
3299 "Bad glGetProgramResourceiv pname at: %s\n", line);
3300 REQUIRE(parse_enum_tab(all_types, line, (unsigned *)&expected, &line) ||
3301 parse_int(line, &expected, &line),
3302 "Bad expected value at: %s\n", line);
3304 glGetProgramInterfaceiv(prog, interface_type,
3305 GL_ACTIVE_RESOURCES, &num_active_buffers);
3306 for (i = 0; i < num_active_buffers; i++) {
3307 GLint got;
3308 GLint length;
3309 bool pass = true;
3311 if (!confirm_program_resource(interface_type, i, name, name_buf,
3312 block_data, prop, expected))
3313 continue;
3315 /* Set 'got' to some value in case glGetActiveUniformsiv
3316 * doesn't write to it. That should only be able to occur
3317 * when the function raises a GL error, but "should" is kind
3318 * of a funny word.
3320 got = ~expected;
3321 glGetProgramResourceiv(prog, interface_type,
3322 i, 1, &prop, 1,
3323 &length, &got);
3325 if (!piglit_check_gl_error(GL_NO_ERROR)) {
3326 fprintf(stderr, "glGetProgramResourceiv error\n");
3327 piglit_report_result(PIGLIT_FAIL);
3330 if (got != expected) {
3331 fprintf(stderr,
3332 "glGetProgramResourceiv(%s, %s): "
3333 "expected %d, got %d\n",
3334 name, piglit_get_gl_enum_name(prop),
3335 expected, got);
3336 pass = false;
3339 if (!pass)
3340 piglit_report_result(PIGLIT_FAIL);
3342 return;
3345 if (!force_no_names)
3346 fprintf(stderr, "No active resource named \"%s\"\n", name);
3347 else
3348 fprintf(stderr, "No active resource with binding %i\n", block_data.binding);
3350 piglit_report_result(PIGLIT_FAIL);
3351 return;
3355 static unsigned
3356 query_index(GLenum query)
3358 switch (query) {
3359 case GL_PRIMITIVES_GENERATED:
3360 return 0;
3361 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
3362 return 1;
3363 default:
3364 return 0;
3368 * Checks if the GL_QUERY_RESULT of a given query object has the
3369 * expected value.
3371 * Note that right now it only supports the following two queries:
3372 * * GL_PRIMITIVES_GENERATED
3373 * * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
3375 * As right now we are only creating those query objects with xfb
3376 * rendering.
3378 * Format of the command:
3380 * verify query_object GL_PRIMITIVES_GENERATED integer
3382 * or
3384 * verify query_object GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN integer
3386 static enum piglit_result
3387 verify_query_object_result(const char *line)
3389 static const struct string_to_enum all_targets[] = {
3390 ENUM_STRING(GL_PRIMITIVES_GENERATED),
3391 ENUM_STRING(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
3392 { NULL, 0 }
3395 unsigned target;
3396 unsigned expected;
3397 unsigned value = 0;
3398 unsigned index = 0;
3400 REQUIRE(parse_enum_tab(all_targets, line,
3401 &target, &line),
3402 "Bad query object target at: %s\n", line);
3404 REQUIRE(parse_uint(line, &expected, &line),
3405 "Bad expected value at: %s\n", line);
3407 /* Previous require already checks if the target is one of the
3408 * supported ones.
3410 index = query_index(target);
3412 if (queries[index]) {
3413 glGetQueryObjectuiv(queries[index], GL_QUERY_RESULT, &value);
3414 } else {
3415 fprintf(stderr, "query object for target %s is not initialized. "
3416 "Did you forget to call \"xfb draw arrays\"?\n",
3417 piglit_get_gl_enum_name(target));
3418 return PIGLIT_FAIL;
3421 if (expected != value) {
3422 fprintf(stderr, "glGetQueryObjectuiv(GL_QUERY_RESULT) for a %s "
3423 "query object: expected %d, got %d\n",
3424 piglit_get_gl_enum_name(target), expected, value);
3425 return PIGLIT_FAIL;
3427 return PIGLIT_PASS;
3430 static void
3431 set_parameter(const char *line)
3433 float f[4];
3434 int index, count;
3435 char type[1024];
3437 count = sscanf(line, "%s %d (%f , %f , %f , %f)",
3438 type, &index, &f[0], &f[1], &f[2], &f[3]);
3439 if (count != 6) {
3440 fprintf(stderr, "Couldn't parse parameter command:\n%s\n", line);
3441 piglit_report_result(PIGLIT_FAIL);
3444 if (parse_str(type, "env_vp", NULL)) {
3445 glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3446 } else if (parse_str(type, "local_vp", NULL)) {
3447 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
3448 } else if (parse_str(type, "env_fp", NULL)) {
3449 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3450 } else if (parse_str(type, "local_fp", NULL)) {
3451 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
3452 } else {
3453 fprintf(stderr, "Unknown parameter type `%s'\n", type);
3454 piglit_report_result(PIGLIT_FAIL);
3458 static void
3459 set_patch_parameter(const char *line)
3461 #ifdef PIGLIT_USE_OPENGL
3462 float f[4];
3463 int i, count;
3464 const char *const line0 = line;
3466 if (gl_version.num < 40)
3467 piglit_require_extension("GL_ARB_tessellation_shader");
3469 if (parse_str(line, "vertices ", &line)) {
3470 count = sscanf(line, "%d", &i);
3471 if (count != 1) {
3472 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3473 piglit_report_result(PIGLIT_FAIL);
3475 glPatchParameteri(GL_PATCH_VERTICES, i);
3476 } else if (parse_str(line, "default level outer ", &line)) {
3477 count = sscanf(line, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
3478 if (count != 4) {
3479 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3480 piglit_report_result(PIGLIT_FAIL);
3482 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, f);
3483 } else if (parse_str(line, "default level inner ", &line)) {
3484 count = sscanf(line, "%f %f", &f[0], &f[1]);
3485 if (count != 2) {
3486 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
3487 piglit_report_result(PIGLIT_FAIL);
3489 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, f);
3490 } else {
3491 fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line);
3492 piglit_report_result(PIGLIT_FAIL);
3494 #else
3495 printf("patch parameters are only available in desktop GL\n");
3496 piglit_report_result(PIGLIT_SKIP);
3497 #endif
3500 static void
3501 set_provoking_vertex(const char *line)
3503 if (parse_str(line, "first", NULL)) {
3504 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT);
3505 } else if (parse_str(line, "last", NULL)) {
3506 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
3507 } else {
3508 fprintf(stderr, "Unknown provoking vertex parameter `%s'\n", line);
3509 piglit_report_result(PIGLIT_FAIL);
3513 static const struct string_to_enum enable_table[] = {
3514 { "GL_CLIP_PLANE0", GL_CLIP_PLANE0 },
3515 { "GL_CLIP_PLANE1", GL_CLIP_PLANE1 },
3516 { "GL_CLIP_PLANE2", GL_CLIP_PLANE2 },
3517 { "GL_CLIP_PLANE3", GL_CLIP_PLANE3 },
3518 { "GL_CLIP_PLANE4", GL_CLIP_PLANE4 },
3519 { "GL_CLIP_PLANE5", GL_CLIP_PLANE5 },
3520 { "GL_CLIP_PLANE6", GL_CLIP_PLANE0+6 },
3521 { "GL_CLIP_PLANE7", GL_CLIP_PLANE0+7 },
3522 { "GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE },
3523 { "GL_PROGRAM_POINT_SIZE", GL_PROGRAM_POINT_SIZE },
3524 { "GL_DEPTH_TEST", GL_DEPTH_TEST },
3525 { "GL_DEPTH_CLAMP", GL_DEPTH_CLAMP },
3526 { NULL, 0 }
3529 static void
3530 do_enable_disable(const char *line, bool enable_flag)
3532 GLenum value;
3533 REQUIRE(parse_enum_tab(enable_table, line, &value, NULL),
3534 "Bad enable/disable enum at: %s\n", line);
3536 if (enable_flag)
3537 glEnable(value);
3538 else
3539 glDisable(value);
3542 static const struct string_to_enum hint_target_table[] = {
3543 ENUM_STRING(GL_LINE_SMOOTH_HINT),
3544 ENUM_STRING(GL_POLYGON_SMOOTH_HINT),
3545 ENUM_STRING(GL_TEXTURE_COMPRESSION_HINT),
3546 ENUM_STRING(GL_FRAGMENT_SHADER_DERIVATIVE_HINT),
3547 { NULL, 0 }
3550 static const struct string_to_enum hint_param_table[] = {
3551 ENUM_STRING(GL_FASTEST),
3552 ENUM_STRING(GL_NICEST),
3553 ENUM_STRING(GL_DONT_CARE),
3554 { NULL, 0 }
3557 static void do_hint(const char *line)
3559 unsigned target, param;
3560 REQUIRE(parse_enum_tab(hint_target_table, line, &target, &line),
3561 "Bad hint target at: %s\n", line);
3562 REQUIRE(parse_enum_tab(hint_param_table, line, &param, &line),
3563 "Bad hint param at: %s\n", line);
3565 glHint(target, param);
3568 static void
3569 draw_instanced_rect(int primcount, float x, float y, float w, float h)
3571 float verts[4][4];
3573 piglit_require_extension("GL_ARB_draw_instanced");
3575 verts[0][0] = x;
3576 verts[0][1] = y;
3577 verts[0][2] = 0.0;
3578 verts[0][3] = 1.0;
3579 verts[1][0] = x + w;
3580 verts[1][1] = y;
3581 verts[1][2] = 0.0;
3582 verts[1][3] = 1.0;
3583 verts[2][0] = x;
3584 verts[2][1] = y + h;
3585 verts[2][2] = 0.0;
3586 verts[2][3] = 1.0;
3587 verts[3][0] = x + w;
3588 verts[3][1] = y + h;
3589 verts[3][2] = 0.0;
3590 verts[3][3] = 1.0;
3592 glVertexPointer(4, GL_FLOAT, 0, verts);
3593 glEnableClientState(GL_VERTEX_ARRAY);
3595 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, primcount);
3597 glDisableClientState(GL_VERTEX_ARRAY);
3601 static GLenum
3602 decode_drawing_mode(const char *mode_str)
3604 int i;
3606 for (i = GL_POINTS; i <= GL_PATCHES; ++i) {
3607 const char *name = piglit_get_prim_name(i);
3608 if (0 == strcmp(mode_str, name))
3609 return i;
3612 printf("unknown drawing mode \"%s\"\n", mode_str);
3613 piglit_report_result(PIGLIT_FAIL);
3615 /* Should not be reached, but return 0 to avoid compiler warning */
3616 return 0;
3619 static void
3620 handle_texparameter(const char *line)
3622 static const struct string_to_enum compare_funcs[] = {
3623 { "greater", GL_GREATER },
3624 { "gequal", GL_GEQUAL },
3625 { "less", GL_LESS },
3626 { "lequal", GL_LEQUAL },
3627 { "equal", GL_EQUAL },
3628 { "notequal", GL_NOTEQUAL },
3629 { "never", GL_NEVER },
3630 { "always", GL_ALWAYS },
3631 { NULL, 0 },
3633 static const struct string_to_enum depth_modes[] = {
3634 { "intensity", GL_INTENSITY },
3635 { "luminance", GL_LUMINANCE },
3636 { "alpha", GL_ALPHA },
3637 { "red", GL_RED }, /* Requires GL 3.0 or GL_ARB_texture_rg */
3638 { NULL, 0 },
3640 static const struct string_to_enum min_filter_modes[] = {
3641 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
3642 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
3643 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
3644 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR },
3645 { "nearest", GL_NEAREST },
3646 { "linear", GL_LINEAR },
3647 { NULL, 0 }
3649 static const struct string_to_enum mag_filter_modes[] = {
3650 { "nearest", GL_NEAREST },
3651 { "linear", GL_LINEAR },
3652 { NULL, 0 }
3654 static const struct string_to_enum wrap_modes[] = {
3655 { "repeat", GL_REPEAT },
3656 { "clamp_to_edge", GL_CLAMP_TO_EDGE },
3657 { "clamp_to_border", GL_CLAMP_TO_BORDER },
3658 { NULL, 0 }
3660 static const struct string_to_enum swizzle_modes[] = {
3661 { "red", GL_RED },
3662 { "green", GL_GREEN },
3663 { "blue", GL_BLUE },
3664 { "alpha", GL_ALPHA },
3665 { NULL, 0 }
3667 unsigned target = 0;
3668 GLenum parameter = GL_NONE;
3669 const char *parameter_name = NULL;
3670 const struct string_to_enum *strings = NULL;
3671 unsigned value;
3673 REQUIRE(parse_tex_target(line, &target, &line),
3674 "Bad texture target at: %s\n", line);
3676 if (parse_str(line, "compare_func ", &line)) {
3677 parameter = GL_TEXTURE_COMPARE_FUNC;
3678 parameter_name = "compare_func";
3679 strings = compare_funcs;
3680 } else if (parse_str(line, "depth_mode ", &line)) {
3681 parameter = GL_DEPTH_TEXTURE_MODE;
3682 parameter_name = "depth_mode";
3683 strings = depth_modes;
3684 } else if (parse_str(line, "min ", &line)) {
3685 parameter = GL_TEXTURE_MIN_FILTER;
3686 parameter_name = "min";
3687 strings = min_filter_modes;
3688 } else if (parse_str(line, "mag ", &line)) {
3689 parameter = GL_TEXTURE_MAG_FILTER;
3690 parameter_name = "mag";
3691 strings = mag_filter_modes;
3692 } else if (parse_str(line, "wrap_s ", &line)) {
3693 parameter = GL_TEXTURE_WRAP_S;
3694 parameter_name = "wrap_s";
3695 strings = wrap_modes;
3696 } else if (parse_str(line, "wrap_t ", &line)) {
3697 parameter = GL_TEXTURE_WRAP_T;
3698 parameter_name = "wrap_t";
3699 strings = wrap_modes;
3700 } else if (parse_str(line, "wrap_r ", &line)) {
3701 parameter = GL_TEXTURE_WRAP_R;
3702 parameter_name = "wrap_r";
3703 strings = wrap_modes;
3704 } else if (parse_str(line, "lod_bias ", &line)) {
3705 #ifdef PIGLIT_USE_OPENGL
3706 glTexParameterf(target, GL_TEXTURE_LOD_BIAS,
3707 strtod(line, NULL));
3708 return;
3709 #else
3710 printf("lod_bias feature is only available in desktop GL\n");
3711 piglit_report_result(PIGLIT_SKIP);
3712 #endif
3713 } else if (parse_str(line, "max_level ", &line)) {
3714 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL,
3715 strtol(line, NULL, 10));
3716 return;
3717 } else if (parse_str(line, "base_level ", &line)) {
3718 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL,
3719 strtol(line, NULL, 10));
3720 return;
3721 } else if (parse_str(line, "border_color ", &line)) {
3722 float bc[4];
3723 int count;
3724 count = sscanf(line, "%f %f %f %f", &bc[0], &bc[1], &bc[2], &bc[3]);
3725 if (count != 4) {
3726 fprintf(stderr, "Could not parse border_color texture parameter.\n");
3727 piglit_report_result(PIGLIT_FAIL);
3729 glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bc);
3730 return;
3731 } else if (parse_str(line, "swizzle_r ", &line)) {
3732 parameter = GL_TEXTURE_SWIZZLE_R;
3733 parameter_name = "swizzle_r";
3734 strings = swizzle_modes;
3735 } else {
3736 fprintf(stderr, "unknown texture parameter in `%s'\n", line);
3737 piglit_report_result(PIGLIT_FAIL);
3740 REQUIRE(parse_enum_tab(strings, line, &value, &line),
3741 "Bad %s at: %s\n", parameter_name, line);
3743 glTexParameteri(target, parameter, value);
3746 static const struct string_to_enum viewport_swizzle_table[] = {
3747 { "POSITIVE_X", GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV },
3748 { "NEGATIVE_X", GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV },
3749 { "POSITIVE_Y", GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV },
3750 { "NEGATIVE_Y", GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV },
3751 { "POSITIVE_Z", GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV },
3752 { "NEGATIVE_Z", GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV },
3753 { "POSITIVE_W", GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV },
3754 { "NEGATIVE_W", GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV },
3755 { NULL, 0 }
3758 static void
3759 handle_viewport_swizzle(const char *line)
3761 unsigned viewport;
3762 GLenum x, y, z, w;
3764 viewport = strtol(line, (char **)&line, 0);
3765 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &x, &line),
3766 "Bad ViewportSwizzle swizzle at: %s\n", line);
3767 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &y, &line),
3768 "Bad ViewportSwizzle swizzle at: %s\n", line);
3769 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &z, &line),
3770 "Bad ViewportSwizzle swizzle at: %s\n", line);
3771 REQUIRE(parse_enum_tab(viewport_swizzle_table, line, &w, &line),
3772 "Bad ViewportSwizzle swizzle at: %s\n", line);
3774 glViewportSwizzleNV(viewport, x, y, z, w);
3777 static void
3778 setup_ubos(void)
3780 int i;
3782 if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
3783 piglit_get_gl_version() < 31) {
3784 return;
3787 if (prog == 0) {
3788 /* probably running an ARB_vertex/fragment_program test */
3789 return;
3792 glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &num_uniform_blocks);
3793 if (num_uniform_blocks == 0)
3794 return;
3796 uniform_block_bos = calloc(num_uniform_blocks, sizeof(GLuint));
3797 glGenBuffers(num_uniform_blocks, uniform_block_bos);
3799 int max_ubos;
3800 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_ubos);
3801 uniform_block_indexes = calloc(max_ubos, sizeof(int));
3803 for (i = 0; i < num_uniform_blocks; i++) {
3804 GLint size;
3805 GLint binding;
3807 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_DATA_SIZE,
3808 &size);
3810 glBindBuffer(GL_UNIFORM_BUFFER, uniform_block_bos[i]);
3811 glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
3813 if (!force_no_names) {
3814 glUniformBlockBinding(prog, i, i);
3815 uniform_block_indexes[i] = i;
3816 binding = i;
3817 } else {
3818 glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_BINDING,
3819 &binding);
3820 uniform_block_indexes[binding] = i;
3823 glBindBufferBase(GL_UNIFORM_BUFFER, binding, uniform_block_bos[i]);
3827 static void
3828 teardown_fbos(void)
3830 if (draw_fbo != 0 &&
3831 draw_fbo != piglit_winsys_fbo)
3832 glDeleteFramebuffers(1, &draw_fbo);
3834 if (read_fbo != 0 &&
3835 read_fbo != piglit_winsys_fbo &&
3836 read_fbo != draw_fbo)
3837 glDeleteFramebuffers(1, &read_fbo);
3839 draw_fbo = 0;
3840 read_fbo = 0;
3843 static void
3844 teardown_ubos(void)
3846 if (num_uniform_blocks == 0) {
3847 return;
3850 glDeleteBuffers(num_uniform_blocks, uniform_block_bos);
3851 free(uniform_block_bos);
3852 uniform_block_bos = NULL;
3853 free(uniform_block_indexes);
3854 uniform_block_indexes = NULL;
3855 num_uniform_blocks = 0;
3858 static void
3859 teardown_atomics(void)
3861 for (unsigned i = 0; i < ARRAY_SIZE(atomics_bos); ++i) {
3862 if (atomics_bos[i])
3863 glDeleteBuffers(1, &atomics_bos[i]);
3867 static void
3868 teardown_shader_include_paths(void)
3870 for (unsigned i = 0; i < num_shader_include_paths; i++)
3871 free(shader_include_path[i]);
3873 for (unsigned i = 0; i < num_shader_includes; i++) {
3874 glDeleteNamedStringARB(-1, shader_include_names[i]);
3875 free(shader_include_names[i]);
3878 num_shader_includes = 0;
3879 num_shader_include_paths = 0;
3880 free(shader_include_path);
3881 shader_include_path = NULL;
3884 static void
3885 teardown_xfb(void)
3887 glDeleteBuffers(MAX_XFB_BUFFERS, xfb);
3889 glDeleteQueries(1, &queries[query_index(GL_PRIMITIVES_GENERATED)]);
3890 glDeleteQueries(1, &queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)]);
3891 queries[query_index(GL_PRIMITIVES_GENERATED)] = 0;
3892 queries[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)] = 0;
3895 static enum piglit_result
3896 program_must_be_in_use(void)
3898 if (!link_ok) {
3899 fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
3900 return PIGLIT_FAIL;
3901 } else if (!prog_in_use) {
3902 fprintf(stderr, "Failed to use program: %s\n", prog_err_info);
3903 return PIGLIT_FAIL;
3905 return PIGLIT_PASS;
3908 static void
3909 bind_vao_if_supported()
3911 if (vao == 0 && piglit_is_core_profile) {
3912 glGenVertexArrays(1, &vao);
3913 glBindVertexArray(vao);
3917 static enum piglit_result
3918 draw_arrays_common(int first, size_t count)
3920 enum piglit_result result = program_must_be_in_use();
3921 if (first < 0) {
3922 printf("draw arrays 'first' must be >= 0\n");
3923 piglit_report_result(PIGLIT_FAIL);
3924 } else if (vbo_present &&
3925 (size_t) first >= num_vbo_rows) {
3926 printf("draw arrays 'first' must be < %lu\n",
3927 (unsigned long) num_vbo_rows);
3928 piglit_report_result(PIGLIT_FAIL);
3930 if (count <= 0) {
3931 printf("draw arrays 'count' must be > 0\n");
3932 piglit_report_result(PIGLIT_FAIL);
3933 } else if (vbo_present &&
3934 count > num_vbo_rows - (size_t) first) {
3935 printf("draw arrays cannot draw beyond %lu\n",
3936 (unsigned long) num_vbo_rows);
3937 piglit_report_result(PIGLIT_FAIL);
3939 bind_vao_if_supported();
3940 return result;
3943 static bool
3944 probe_atomic_counter(unsigned buffer_num, GLint counter_num, const char *op,
3945 uint32_t value, bool uses_layout_qualifiers)
3947 uint32_t *p;
3948 uint32_t observed;
3949 enum comparison cmp;
3950 bool result;
3952 REQUIRE(parse_comparison_op(op, &cmp, NULL),
3953 "Invalid comparison operation at: %s\n", op);
3955 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomics_bos[buffer_num]);
3956 p = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER,
3957 uses_layout_qualifiers ? counter_num : counter_num * sizeof(uint32_t),
3958 sizeof(uint32_t), GL_MAP_READ_BIT);
3960 if (!p) {
3961 printf("Couldn't map atomic counter to verify expected value.\n");
3962 return false;
3965 observed = *p;
3966 result = compare_uint(value, observed, cmp);
3968 if (!result) {
3969 if (uses_layout_qualifiers)
3970 printf("Atomic counter (binding = %d, offset = %d) test failed: "
3971 "Reference %s Observed\n",
3972 buffer_num, counter_num, comparison_string(cmp));
3973 else
3974 printf("Atomic counter %d test failed: Reference %s Observed\n",
3975 counter_num, comparison_string(cmp));
3976 printf(" Reference: %u\n", value);
3977 printf(" Observed: %u\n", observed);
3978 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3979 return false;
3982 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3983 return true;
3986 static bool
3987 probe_ssbo_uint(GLint ssbo_index, GLint ssbo_offset, const char *op, uint32_t value)
3989 uint32_t *p;
3990 uint32_t observed;
3991 enum comparison cmp;
3992 bool result;
3994 REQUIRE(parse_comparison_op(op, &cmp, NULL),
3995 "Invalid comparison operation at: %s\n", op);
3997 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
3998 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
3999 sizeof(uint32_t), GL_MAP_READ_BIT);
4001 if (!p) {
4002 printf("Couldn't map ssbo to verify expected value.\n");
4003 return false;
4006 observed = *p;
4007 result = compare_uint(value, observed, cmp);
4009 if (!result) {
4010 printf("SSBO %d test failed: Reference %s Observed\n",
4011 ssbo_offset, comparison_string(cmp));
4012 printf(" Reference: %u\n", value);
4013 printf(" Observed: %u\n", observed);
4014 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4015 return false;
4018 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4019 return true;
4022 static bool
4023 probe_ssbo_int(GLint ssbo_index, GLint ssbo_offset, const char *op, int32_t value)
4025 int32_t *p;
4026 int32_t observed;
4027 enum comparison cmp;
4028 bool result;
4030 REQUIRE(parse_comparison_op(op, &cmp, NULL),
4031 "Invalid comparison operation at: %s\n", op);
4033 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
4034 p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
4035 sizeof(uint32_t), GL_MAP_READ_BIT);
4037 if (!p) {
4038 printf("Couldn't map ssbo to verify expected value.\n");
4039 return false;
4042 observed = *p;
4043 result = compare_int(value, observed, cmp);
4045 if (!result) {
4046 printf("SSBO %d test failed: Reference %s Observed\n",
4047 ssbo_offset, comparison_string(cmp));
4048 printf(" Reference: %d\n", value);
4049 printf(" Observed: %d\n", observed);
4050 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4051 return false;
4054 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4055 return true;
4058 GLenum piglit_xfb_primitive_mode(GLenum draw_arrays_mode)
4060 switch (draw_arrays_mode) {
4061 case GL_POINTS:
4062 return GL_POINTS;
4063 case GL_LINES:
4064 case GL_LINE_LOOP:
4065 case GL_LINE_STRIP:
4066 case GL_LINES_ADJACENCY:
4067 case GL_LINE_STRIP_ADJACENCY:
4068 return GL_LINES;
4069 case GL_TRIANGLES:
4070 case GL_TRIANGLE_STRIP:
4071 case GL_TRIANGLE_FAN:
4072 case GL_TRIANGLES_ADJACENCY:
4073 case GL_TRIANGLE_STRIP_ADJACENCY:
4074 return GL_TRIANGLES;
4077 printf("glDrawArrays mode %s not supported for a transform feedback operation\n",
4078 piglit_get_gl_enum_name(draw_arrays_mode));
4079 piglit_report_result(PIGLIT_FAIL);
4082 static void
4083 begin_query(GLenum query_type)
4085 unsigned idx = query_index(query_type);
4086 if (queries[idx] == 0)
4087 glGenQueries(1, &queries[idx]);
4088 glBeginQuery(query_type, queries[idx]);
4091 static void
4092 piglit_xfb_draw_arrays(GLenum mode, int first, size_t count)
4094 GLenum primitive_mode = piglit_xfb_primitive_mode(mode);
4096 begin_query(GL_PRIMITIVES_GENERATED);
4097 begin_query(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4099 glEnable(GL_RASTERIZER_DISCARD);
4101 /* We don't need to call glBindBufferBase here, it is done on
4102 * the "xfb buffer object" command
4105 glBeginTransformFeedback(primitive_mode);
4106 glDrawArrays(mode, first, count);
4107 glEndTransformFeedback();
4109 glDisable(GL_RASTERIZER_DISCARD);
4111 glFlush();
4113 glEndQuery(GL_PRIMITIVES_GENERATED);
4114 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4117 static bool
4118 probe_xfb_float(GLuint buf, unsigned n, float expected)
4120 float *p;
4121 bool result;
4122 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4123 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(float),
4124 sizeof(float), GL_MAP_READ_BIT);
4125 if (!p) {
4126 printf("Couldn't map xfb buffer %u\n", buf);
4127 return false;
4129 result = fabsf(expected - *p) < piglit_tolerance[0];
4130 if (!result) {
4131 printf("xfb buffer %i[%i]: %f, Expected: %f\n",
4132 buf, n, *p, expected);
4135 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4136 return result;
4139 static bool
4140 probe_xfb_double(GLuint buf, unsigned n, double expected)
4142 double *p;
4143 bool result;
4145 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
4146 p = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, n * sizeof(double),
4147 sizeof(double), GL_MAP_READ_BIT);
4148 if (!p) {
4149 printf("Couldn't map xfb buffer %u\n", buf);
4150 return false;
4152 result = fabs(expected - *p) < piglit_tolerance[0];
4153 if (!result) {
4154 printf("xfb buffer %i[%i]: %lf, Expected: %lf\n",
4155 buf, n, *p, expected);
4158 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4159 return result;
4162 enum piglit_result
4163 piglit_display(void)
4165 const char *line, *next_line, *rest;
4166 unsigned line_num;
4167 enum piglit_result full_result = PIGLIT_PASS;
4168 GLbitfield clear_bits = 0;
4169 bool link_error_expected = false;
4170 unsigned list = 0;
4171 struct block_info block_data = {0, -1, -1, -1, -1};
4173 if (test_start == NULL)
4174 return PIGLIT_PASS;
4176 next_line = test_start;
4177 line_num = test_start_line_num;
4178 while (next_line[0] != '\0') {
4179 float c[32];
4180 double d[4];
4181 int x, y, z, w, h, l, tex, level;
4182 unsigned ux, uy, uz;
4183 char s[300]; // 300 for safety
4184 enum piglit_result result = PIGLIT_PASS;
4186 parse_whitespace(next_line, &line);
4188 next_line = strchrnul(next_line, '\n');
4190 /* Duplicate the line to make it null terminated */
4191 line = strndup(line, next_line - line);
4193 /* If strchrnul found a newline, then skip it */
4194 if (next_line[0] != '\0')
4195 next_line++;
4197 if (line[0] == '\0') {
4198 } else if (sscanf(line, "active shader program %s", s) == 1) {
4199 switch (get_shader_from_string(s, &x)) {
4200 case GL_VERTEX_SHADER:
4201 glActiveShaderProgram(pipeline, sso_vertex_prog);
4202 break;
4203 case GL_TESS_CONTROL_SHADER:
4204 glActiveShaderProgram(pipeline, sso_tess_control_prog);
4205 break;
4206 case GL_TESS_EVALUATION_SHADER:
4207 glActiveShaderProgram(pipeline, sso_tess_eval_prog);
4208 break;
4209 case GL_GEOMETRY_SHADER:
4210 glActiveShaderProgram(pipeline, sso_geometry_prog);
4211 break;
4212 case GL_FRAGMENT_SHADER:
4213 glActiveShaderProgram(pipeline, sso_fragment_prog);
4214 break;
4215 case GL_COMPUTE_SHADER:
4216 glActiveShaderProgram(pipeline, sso_compute_prog);
4217 break;
4219 } else if (sscanf(line, "atomic counter buffer %u %u", &x, &y) == 2) {
4220 GLuint *atomics_buf = calloc(y, sizeof(GLuint));
4221 glGenBuffers(1, &atomics_bos[x]);
4222 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4223 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4224 sizeof(GLuint) * y, atomics_buf,
4225 GL_STATIC_DRAW);
4226 free(atomics_buf);
4227 } else if (sscanf(line, "atomic counters %d", &x) == 1) {
4228 GLuint *atomics_buf = calloc(x, sizeof(GLuint));
4229 glGenBuffers(1, &atomics_bos[0]);
4230 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomics_bos[0]);
4231 glBufferData(GL_ATOMIC_COUNTER_BUFFER,
4232 sizeof(GLuint) * x,
4233 atomics_buf, GL_STATIC_DRAW);
4234 free(atomics_buf);
4235 } else if (sscanf(line, "atomic counter %u %u %u", &x, &y, &z) == 3) {
4236 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, x, atomics_bos[x]);
4237 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER,
4238 sizeof(GLuint) * y, sizeof(GLuint),
4239 &z);
4240 } else if (parse_str(line, "clear color ", &rest)) {
4241 parse_floats(rest, c, 4, NULL);
4242 glClearColor(c[0], c[1], c[2], c[3]);
4243 clear_bits |= GL_COLOR_BUFFER_BIT;
4244 } else if (parse_str(line, "clear depth ", &rest)) {
4245 parse_floats(rest, c, 1, NULL);
4246 glClearDepth(c[0]);
4247 clear_bits |= GL_DEPTH_BUFFER_BIT;
4248 } else if (parse_str(line, "clear", NULL)) {
4249 glClear(clear_bits);
4250 } else if (sscanf(line,
4251 "clip plane %d %lf %lf %lf %lf",
4252 &x, &d[0], &d[1], &d[2], &d[3]) == 5) {
4253 if (x < 0 || x >= gl_max_clip_planes) {
4254 printf("clip plane id %d out of range\n", x);
4255 piglit_report_result(PIGLIT_FAIL);
4257 glClipPlane(GL_CLIP_PLANE0 + x, d);
4258 #ifdef PIGLIT_USE_OPENGL
4259 } else if (parse_str(line, "color ", &rest)) {
4260 parse_floats(rest, c, 4, NULL);
4261 assert(!piglit_is_core_profile);
4262 glColor4fv(c);
4263 #endif
4264 } else if (sscanf(line,
4265 "compute %d %d %d",
4266 &x, &y, &z) == 3) {
4267 result = program_must_be_in_use();
4268 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4269 glDispatchCompute(x, y, z);
4270 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4271 } else if (sscanf(line,
4272 "compute group size %d %d %d %d %d %d",
4273 &x, &y, &z, &w, &h, &l) == 6) {
4274 result = program_must_be_in_use();
4275 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4276 glDispatchComputeGroupSizeARB(x, y, z, w, h, l);
4277 glMemoryBarrier(GL_ALL_BARRIER_BITS);
4278 } else if (parse_str(line, "draw rect tex ", &rest)) {
4279 result = program_must_be_in_use();
4280 program_subroutine_uniforms();
4281 parse_floats(rest, c, 8, NULL);
4282 piglit_draw_rect_tex(c[0], c[1], c[2], c[3],
4283 c[4], c[5], c[6], c[7]);
4284 } else if (parse_str(line, "draw rect ortho patch ", &rest)) {
4285 result = program_must_be_in_use();
4286 program_subroutine_uniforms();
4287 parse_floats(rest, c, 4, NULL);
4289 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4290 -1.0 + 2.0 * (c[1] / piglit_height),
4291 2.0 * (c[2] / piglit_width),
4292 2.0 * (c[3] / piglit_height), true, 1);
4293 } else if (parse_str(line, "draw rect ortho ", &rest)) {
4294 result = program_must_be_in_use();
4295 program_subroutine_uniforms();
4296 parse_floats(rest, c, 4, NULL);
4298 piglit_draw_rect(-1.0 + 2.0 * (c[0] / piglit_width),
4299 -1.0 + 2.0 * (c[1] / piglit_height),
4300 2.0 * (c[2] / piglit_width),
4301 2.0 * (c[3] / piglit_height));
4302 } else if (parse_str(line, "draw rect patch ", &rest)) {
4303 result = program_must_be_in_use();
4304 parse_floats(rest, c, 4, NULL);
4305 piglit_draw_rect_custom(c[0], c[1], c[2], c[3], true, 1);
4306 } else if (parse_str(line, "draw rect ", &rest)) {
4307 result = program_must_be_in_use();
4308 program_subroutine_uniforms();
4309 parse_floats(rest, c, 4, NULL);
4310 piglit_draw_rect(c[0], c[1], c[2], c[3]);
4311 } else if (parse_str(line, "draw instanced rect ortho patch ", &rest)) {
4312 int instance_count;
4314 result = program_must_be_in_use();
4315 sscanf(rest, "%d %f %f %f %f",
4316 &instance_count,
4317 c + 0, c + 1, c + 2, c + 3);
4318 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4319 -1.0 + 2.0 * (c[1] / piglit_height),
4320 2.0 * (c[2] / piglit_width),
4321 2.0 * (c[3] / piglit_height), true,
4322 instance_count);
4323 } else if (parse_str(line, "draw instanced rect ortho ", &rest)) {
4324 int instance_count;
4326 result = program_must_be_in_use();
4327 sscanf(rest, "%d %f %f %f %f",
4328 &instance_count,
4329 c + 0, c + 1, c + 2, c + 3);
4330 piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
4331 -1.0 + 2.0 * (c[1] / piglit_height),
4332 2.0 * (c[2] / piglit_width),
4333 2.0 * (c[3] / piglit_height), false,
4334 instance_count);
4335 } else if (parse_str(line, "draw instanced rect ", &rest)) {
4336 int primcount;
4338 result = program_must_be_in_use();
4339 sscanf(rest, "%d %f %f %f %f",
4340 &primcount,
4341 c + 0, c + 1, c + 2, c + 3);
4342 draw_instanced_rect(primcount, c[0], c[1], c[2], c[3]);
4343 } else if (sscanf(line, "draw arrays instanced %31s %d %d %d", s, &x, &y, &z) == 4) {
4344 GLenum mode = decode_drawing_mode(s);
4345 int first = x;
4346 size_t count = (size_t) y;
4347 size_t primcount = (size_t) z;
4348 draw_arrays_common(first, count);
4349 glDrawArraysInstanced(mode, first, count, primcount);
4350 } else if (sscanf(line, "draw arrays %31s %d %d", s, &x, &y) == 3) {
4351 GLenum mode = decode_drawing_mode(s);
4352 int first = x;
4353 size_t count = (size_t) y;
4354 result = draw_arrays_common(first, count);
4355 glDrawArrays(mode, first, count);
4356 } else if (parse_str(line, "disable ", &rest)) {
4357 do_enable_disable(rest, false);
4358 } else if (parse_str(line, "enable ", &rest)) {
4359 do_enable_disable(rest, true);
4360 } else if (sscanf(line, "depthfunc %31s", s) == 1) {
4361 glDepthFunc(piglit_get_gl_enum_from_name(s));
4362 } else if (parse_str(line, "fb ", &rest)) {
4363 const GLenum target =
4364 parse_str(rest, "draw ", &rest) ? GL_DRAW_FRAMEBUFFER :
4365 parse_str(rest, "read ", &rest) ? GL_READ_FRAMEBUFFER :
4366 GL_FRAMEBUFFER;
4367 GLuint fbo = 0;
4369 if (parse_str(rest, "tex 2d ", &rest)) {
4370 GLenum attachments[32];
4371 unsigned num_attachments = 0;
4373 glGenFramebuffers(1, &fbo);
4374 glBindFramebuffer(target, fbo);
4376 while (parse_int(rest, &tex, &rest)) {
4377 attachments[num_attachments] =
4378 GL_COLOR_ATTACHMENT0 + num_attachments;
4379 glFramebufferTexture2D(
4380 target, attachments[num_attachments],
4381 GL_TEXTURE_2D,
4382 get_texture_binding(tex)->obj, 0);
4384 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4385 fprintf(stderr,
4386 "glFramebufferTexture2D error\n");
4387 piglit_report_result(PIGLIT_FAIL);
4390 num_attachments++;
4393 if (target != GL_READ_FRAMEBUFFER)
4394 glDrawBuffers(num_attachments, attachments);
4396 w = get_texture_binding(tex)->width;
4397 h = get_texture_binding(tex)->height;
4399 } else if (parse_str(rest, "tex slice ", &rest)) {
4400 GLenum tex_target;
4402 REQUIRE(parse_tex_target(rest, &tex_target, &rest) &&
4403 parse_int(rest, &tex, &rest) &&
4404 parse_int(rest, &l, &rest) &&
4405 parse_int(rest, &z, &rest),
4406 "Framebuffer binding command not "
4407 "understood at: %s\n", rest);
4409 const GLuint tex_obj = get_texture_binding(tex)->obj;
4411 glGenFramebuffers(1, &fbo);
4412 glBindFramebuffer(target, fbo);
4414 if (tex_target == GL_TEXTURE_1D) {
4415 REQUIRE(z == 0,
4416 "Invalid layer index provided "
4417 "in command: %s\n", line);
4418 glFramebufferTexture1D(
4419 target, GL_COLOR_ATTACHMENT0,
4420 tex_target, tex_obj, l);
4422 } else if (tex_target == GL_TEXTURE_2D ||
4423 tex_target == GL_TEXTURE_RECTANGLE ||
4424 tex_target == GL_TEXTURE_2D_MULTISAMPLE) {
4425 REQUIRE(z == 0,
4426 "Invalid layer index provided "
4427 "in command: %s\n", line);
4428 glFramebufferTexture2D(
4429 target, GL_COLOR_ATTACHMENT0,
4430 tex_target, tex_obj, l);
4432 } else if (tex_target == GL_TEXTURE_CUBE_MAP) {
4433 static const GLenum cubemap_targets[] = {
4434 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
4435 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4436 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
4437 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4438 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
4439 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4441 REQUIRE(z < ARRAY_SIZE(cubemap_targets),
4442 "Invalid layer index provided "
4443 "in command: %s\n", line);
4444 tex_target = cubemap_targets[z];
4446 glFramebufferTexture2D(
4447 target, GL_COLOR_ATTACHMENT0,
4448 tex_target, tex_obj, l);
4450 } else {
4451 glFramebufferTextureLayer(
4452 target, GL_COLOR_ATTACHMENT0,
4453 tex_obj, l, z);
4456 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4457 fprintf(stderr, "Error binding texture "
4458 "attachment for command: %s\n",
4459 line);
4460 piglit_report_result(PIGLIT_FAIL);
4463 w = MAX2(1, get_texture_binding(tex)->width >> l);
4464 h = MAX2(1, get_texture_binding(tex)->height >> l);
4466 } else if (sscanf(rest, "tex layered %d", &tex) == 1) {
4467 glGenFramebuffers(1, &fbo);
4468 glBindFramebuffer(target, fbo);
4470 glFramebufferTexture(
4471 target, GL_COLOR_ATTACHMENT0,
4472 get_texture_binding(tex)->obj, 0);
4473 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4474 fprintf(stderr,
4475 "glFramebufferTexture error\n");
4476 piglit_report_result(PIGLIT_FAIL);
4479 w = get_texture_binding(tex)->width;
4480 h = get_texture_binding(tex)->height;
4482 } else if (parse_str(rest, "ms ", &rest)) {
4483 GLuint rb;
4484 GLenum format;
4485 int samples;
4487 REQUIRE(parse_enum_gl(rest, &format, &rest) &&
4488 parse_int(rest, &w, &rest) &&
4489 parse_int(rest, &h, &rest) &&
4490 parse_int(rest, &samples, &rest),
4491 "Framebuffer binding command not "
4492 "understood at: %s\n", rest);
4494 glGenFramebuffers(1, &fbo);
4495 glBindFramebuffer(target, fbo);
4497 glGenRenderbuffers(1, &rb);
4498 glBindRenderbuffer(GL_RENDERBUFFER, rb);
4500 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
4501 format, w, h);
4503 glFramebufferRenderbuffer(target,
4504 GL_COLOR_ATTACHMENT0,
4505 GL_RENDERBUFFER, rb);
4507 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4508 fprintf(stderr, "glFramebufferRenderbuffer error\n");
4509 piglit_report_result(PIGLIT_FAIL);
4512 } else if (parse_str(rest, "winsys", &rest)) {
4513 fbo = piglit_winsys_fbo;
4514 glBindFramebuffer(target, fbo);
4515 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4516 fprintf(stderr, "glBindFramebuffer error\n");
4517 piglit_report_result(PIGLIT_FAIL);
4520 w = piglit_width;
4521 h = piglit_height;
4523 } else {
4524 fprintf(stderr, "Unknown fb bind subcommand "
4525 "\"%s\"\n", rest);
4526 piglit_report_result(PIGLIT_FAIL);
4529 const GLenum status = glCheckFramebufferStatus(target);
4530 if (status != GL_FRAMEBUFFER_COMPLETE) {
4531 fprintf(stderr, "incomplete fbo (status 0x%x)\n",
4532 status);
4533 piglit_report_result(PIGLIT_FAIL);
4536 if (target != GL_READ_FRAMEBUFFER) {
4537 render_width = w;
4538 render_height = h;
4540 /* Delete the previous draw FB in case
4541 * it's no longer reachable.
4543 if (draw_fbo != 0 &&
4544 draw_fbo != piglit_winsys_fbo &&
4545 draw_fbo != (target == GL_DRAW_FRAMEBUFFER ?
4546 read_fbo : 0))
4547 glDeleteFramebuffers(1, &draw_fbo);
4549 draw_fbo = fbo;
4552 if (target != GL_DRAW_FRAMEBUFFER) {
4553 read_width = w;
4554 read_height = h;
4556 /* Delete the previous read FB in case
4557 * it's no longer reachable.
4559 if (read_fbo != 0 &&
4560 read_fbo != piglit_winsys_fbo &&
4561 read_fbo != (target == GL_READ_FRAMEBUFFER ?
4562 draw_fbo : 0))
4563 glDeleteFramebuffers(1, &read_fbo);
4565 read_fbo = fbo;
4568 } else if (parse_str(line, "blit ", &rest)) {
4569 static const struct string_to_enum buffers[] = {
4570 { "color", GL_COLOR_BUFFER_BIT },
4571 { "depth", GL_DEPTH_BUFFER_BIT },
4572 { "stencil", GL_STENCIL_BUFFER_BIT },
4573 { NULL }
4575 static const struct string_to_enum filters[] = {
4576 { "linear", GL_LINEAR },
4577 { "nearest", GL_NEAREST },
4578 { NULL }
4580 unsigned buffer, filter;
4582 REQUIRE(parse_enum_tab(buffers, rest, &buffer, &rest) &&
4583 parse_enum_tab(filters, rest, &filter, &rest),
4584 "FB blit command not understood at: %s\n",
4585 rest);
4587 glBlitFramebuffer(0, 0, read_width, read_height,
4588 0, 0, render_width, render_height,
4589 buffer, filter);
4591 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4592 fprintf(stderr, "glBlitFramebuffer error\n");
4593 piglit_report_result(PIGLIT_FAIL);
4596 } else if (parse_str(line, "frustum", &rest)) {
4597 parse_floats(rest, c, 6, NULL);
4598 piglit_frustum_projection(false, c[0], c[1], c[2],
4599 c[3], c[4], c[5]);
4600 } else if (parse_str(line, "hint", &rest)) {
4601 do_hint(rest);
4602 } else if (sscanf(line,
4603 "image texture %d %31s",
4604 &tex, s) == 2) {
4605 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
4606 glBindImageTexture(tex, get_texture_binding(tex)->obj, 0,
4607 GL_FALSE, 0, GL_READ_WRITE, img_fmt);
4608 } else if (sscanf(line, "memory barrier %s", s) == 1) {
4609 glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s));
4610 } else if (parse_str(line, "blend barrier", NULL)) {
4611 glBlendBarrier();
4612 } else if (parse_str(line, "fbfetch barrier", NULL)) {
4613 glFramebufferFetchBarrierEXT();
4614 } else if (sscanf(line, "ortho %f %f %f %f",
4615 c + 0, c + 1, c + 2, c + 3) == 4) {
4616 piglit_gen_ortho_projection(c[0], c[1], c[2], c[3],
4617 -1, 1, GL_FALSE);
4618 } else if (parse_str(line, "ortho", NULL)) {
4619 piglit_ortho_projection(render_width, render_height,
4620 GL_FALSE);
4621 } else if (sscanf(line, "viewport indexed %u %f %f %f %f",
4622 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
4623 glViewportIndexedfv(x, c);
4624 } else if (parse_str(line, "probe rgba ", &rest)) {
4625 parse_floats(rest, c, 6, NULL);
4626 if (!piglit_probe_pixel_rgba((int) c[0], (int) c[1],
4627 & c[2])) {
4628 result = PIGLIT_FAIL;
4630 } else if (parse_str(line, "probe depth ", &rest)) {
4631 parse_floats(rest, c, 3, NULL);
4632 if (!piglit_probe_pixel_depth((int) c[0], (int) c[1],
4633 c[2])) {
4634 result = PIGLIT_FAIL;
4636 } else if (sscanf(line,
4637 "probe atomic counter buffer %u %u %s %u",
4638 &ux, &uy, s, &uz) == 4) {
4639 if (!probe_atomic_counter(ux, uy, s, uz, true)) {
4640 result = PIGLIT_FAIL;
4642 } else if (sscanf(line,
4643 "probe atomic counter %u %s %u",
4644 &ux, s, &uy) == 3) {
4645 if (!probe_atomic_counter(0, ux, s, uy, false)) {
4646 result = PIGLIT_FAIL;
4648 } else if (sscanf(line, "probe ssbo uint %d %d %s 0x%x",
4649 &x, &y, s, &z) == 4) {
4650 if (!probe_ssbo_uint(x, y, s, z))
4651 result = PIGLIT_FAIL;
4652 } else if (sscanf(line, "probe ssbo uint %d %d %s %d",
4653 &x, &y, s, &z) == 4) {
4654 if (!probe_ssbo_uint(x, y, s, z))
4655 result = PIGLIT_FAIL;
4656 } else if (sscanf(line, "probe ssbo int %d %d %s %d",
4657 &x, &y, s, &z) == 4) {
4658 if (!probe_ssbo_int(x, y, s, z))
4659 result = PIGLIT_FAIL;
4660 } else if (sscanf(line,
4661 "relative probe rgba ( %f , %f ) "
4662 "( %f , %f , %f , %f )",
4663 c + 0, c + 1,
4664 c + 2, c + 3, c + 4, c + 5) == 6) {
4665 x = c[0] * read_width;
4666 y = c[1] * read_height;
4667 if (x >= read_width)
4668 x = read_width - 1;
4669 if (y >= read_height)
4670 y = read_height - 1;
4672 if (!piglit_probe_pixel_rgba(x, y, &c[2])) {
4673 result = PIGLIT_FAIL;
4675 } else if (parse_str(line, "probe rgb ", &rest)) {
4676 parse_floats(rest, c, 5, NULL);
4677 if (!piglit_probe_pixel_rgb((int) c[0], (int) c[1],
4678 & c[2])) {
4679 result = PIGLIT_FAIL;
4681 } else if (sscanf(line,
4682 "relative probe rgb ( %f , %f ) "
4683 "( %f , %f , %f )",
4684 c + 0, c + 1,
4685 c + 2, c + 3, c + 4) == 5) {
4686 x = c[0] * read_width;
4687 y = c[1] * read_height;
4688 if (x >= read_width)
4689 x = read_width - 1;
4690 if (y >= read_height)
4691 y = read_height - 1;
4693 if (!piglit_probe_pixel_rgb(x, y, &c[2])) {
4694 result = PIGLIT_FAIL;
4696 } else if (sscanf(line, "probe rect rgba "
4697 "( %d , %d , %d , %d ) "
4698 "( %f , %f , %f , %f )",
4699 &x, &y, &w, &h,
4700 c + 0, c + 1, c + 2, c + 3) == 8) {
4701 if (!piglit_probe_rect_rgba(x, y, w, h, c)) {
4702 result = PIGLIT_FAIL;
4704 } else if (sscanf(line, "relative probe rect rgb "
4705 "( %f , %f , %f , %f ) "
4706 "( %f , %f , %f )",
4707 c + 0, c + 1, c + 2, c + 3,
4708 c + 4, c + 5, c + 6) == 7) {
4709 x = c[0] * read_width;
4710 y = c[1] * read_height;
4711 w = c[2] * read_width;
4712 h = c[3] * read_height;
4714 if (!piglit_probe_rect_rgb(x, y, w, h, &c[4])) {
4715 result = PIGLIT_FAIL;
4717 } else if (sscanf(line, "relative probe rect rgba "
4718 "( %f , %f , %f , %f ) "
4719 "( %f , %f , %f , %f )",
4720 c + 0, c + 1, c + 2, c + 3,
4721 c + 4, c + 5, c + 6, c + 7) == 8) {
4722 x = c[0] * read_width;
4723 y = c[1] * read_height;
4724 w = c[2] * read_width;
4725 h = c[3] * read_height;
4727 if (!piglit_probe_rect_rgba(x, y, w, h, &c[4])) {
4728 result = PIGLIT_FAIL;
4730 } else if (sscanf(line, "relative probe rect rgba int "
4731 "( %f , %f , %f , %f ) "
4732 "( %d , %d , %d , %d )",
4733 c + 0, c + 1, c + 2, c + 3,
4734 &x, &y, &z, &w) == 8) {
4735 const int expected[] = { x, y, z, w };
4736 if (!piglit_probe_rect_rgba_int(c[0] * read_width,
4737 c[1] * read_height,
4738 c[2] * read_width,
4739 c[3] * read_height,
4740 expected))
4741 result = PIGLIT_FAIL;
4743 } else if (parse_str(line, "polygon mode ", &rest)) {
4744 GLenum face, mode;
4746 REQUIRE(parse_enum_gl(rest, &face, &rest) &&
4747 parse_enum_gl(rest, &mode, &rest),
4748 "Polygon mode command not understood at %s\n",
4749 rest);
4751 glPolygonMode(face, mode);
4753 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4754 fprintf(stderr, "glPolygonMode error\n");
4755 piglit_report_result(PIGLIT_FAIL);
4757 } else if (parse_str(line, "probe all rgba ", &rest)) {
4758 parse_floats(rest, c, 4, NULL);
4759 if (result != PIGLIT_FAIL &&
4760 !piglit_probe_rect_rgba(0, 0, read_width,
4761 read_height, c))
4762 result = PIGLIT_FAIL;
4763 } else if (parse_str(line, "probe warn all rgba ", &rest)) {
4764 parse_floats(rest, c, 4, NULL);
4765 if (result == PIGLIT_PASS &&
4766 !piglit_probe_rect_rgba(0, 0, read_width,
4767 read_height, c))
4768 result = PIGLIT_WARN;
4769 } else if (parse_str(line, "probe all rgb", &rest)) {
4770 parse_floats(rest, c, 3, NULL);
4771 if (result != PIGLIT_FAIL &&
4772 !piglit_probe_rect_rgb(0, 0, read_width,
4773 read_height, c))
4774 result = PIGLIT_FAIL;
4775 } else if (parse_str(line, "tolerance", &rest)) {
4776 parse_floats(rest, piglit_tolerance, 4, NULL);
4777 } else if (parse_str(line, "shade model smooth", NULL)) {
4778 glShadeModel(GL_SMOOTH);
4779 } else if (parse_str(line, "shade model flat", NULL)) {
4780 glShadeModel(GL_FLAT);
4781 } else if (sscanf(line, "ssbo %d %d", &x, &y) == 2) {
4782 GLuint *ssbo_init = calloc(y, 1);
4783 glGenBuffers(1, &ssbo[x]);
4784 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, x, ssbo[x]);
4785 glBufferData(GL_SHADER_STORAGE_BUFFER, y,
4786 ssbo_init, GL_DYNAMIC_DRAW);
4787 free(ssbo_init);
4789 else if (sscanf(line, "xfb buffer object %u %u", &ux, &uy) == 2) {
4790 GLuint *xfb_init = calloc(uy, 1);
4791 if (ux < 0 || ux >= MAX_XFB_BUFFERS) {
4792 printf("xfb buffer id %d out of range\n", ux);
4793 piglit_report_result(PIGLIT_FAIL);
4795 glGenBuffers(1, &xfb[ux]);
4796 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, ux, xfb[ux]);
4797 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, uy,
4798 xfb_init, GL_STREAM_READ);
4799 free(xfb_init);
4800 } else if (sscanf(line, "xfb draw arrays %31s %d %d", s, &x, &y) == 3) {
4801 GLenum mode = decode_drawing_mode(s);
4802 int first = x;
4803 size_t count = (size_t) y;
4804 result = draw_arrays_common(first, count);
4805 piglit_xfb_draw_arrays(mode, first, count);
4806 } else if (sscanf(line, "probe xfb buffer float %u %u %f",
4807 &ux, &uy, &c[0]) == 3) {
4808 if (!probe_xfb_float(xfb[ux], uy, c[0]))
4809 result = PIGLIT_FAIL;
4810 } else if (sscanf(line, "probe xfb buffer double %u %u %lf",
4811 &ux, &uy, &d[0]) == 3) {
4812 if (!probe_xfb_double(xfb[ux], uy, d[0]))
4813 result = PIGLIT_FAIL;
4814 } else if (sscanf(line, "ssbo %d subdata float %d %f", &x, &y, &c[0]) == 3) {
4815 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
4816 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &c[0]);
4817 } else if (sscanf(line, "ssbo %d subdata int %d %s", &x, &y, s) == 3) {
4818 parse_ints(s, &z, 1, NULL);
4819 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[x]);
4820 glBufferSubData(GL_SHADER_STORAGE_BUFFER, y, 4, &z);
4821 } else if (sscanf(line, "texture rgbw %d ( %d", &tex, &w) == 2) {
4822 GLenum int_fmt = GL_RGBA;
4823 int num_scanned =
4824 sscanf(line,
4825 "texture rgbw %d ( %d , %d ) %31s",
4826 &tex, &w, &h, s);
4827 if (num_scanned < 3) {
4828 fprintf(stderr,
4829 "invalid texture rgbw command!\n");
4830 piglit_report_result(PIGLIT_FAIL);
4833 if (num_scanned >= 4) {
4834 int_fmt = piglit_get_gl_enum_from_name(s);
4837 glActiveTexture(GL_TEXTURE0 + tex);
4838 int handle = piglit_rgbw_texture(
4839 int_fmt, w, h, GL_FALSE, GL_FALSE,
4840 (piglit_is_gles() ? GL_UNSIGNED_BYTE :
4841 GL_UNSIGNED_NORMALIZED));
4842 set_texture_binding(tex, handle, w, h, 1);
4844 if (!piglit_is_core_profile &&
4845 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4846 glEnable(GL_TEXTURE_2D);
4848 } else if (sscanf(line, "resident texture %d", &tex) == 1) {
4849 GLuint64 handle;
4851 glBindTexture(GL_TEXTURE_2D, 0);
4853 handle = glGetTextureHandleARB(get_texture_binding(tex)->obj);
4854 glMakeTextureHandleResidentARB(handle);
4856 set_resident_handle(tex, handle, true);
4858 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4859 fprintf(stderr,
4860 "glMakeTextureHandleResidentARB error\n");
4861 piglit_report_result(PIGLIT_FAIL);
4863 } else if (sscanf(line, "resident image texture %d %31s",
4864 &tex, s) == 2) {
4865 const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
4866 GLuint64 handle;
4868 glBindTexture(GL_TEXTURE_2D, 0);
4870 handle = glGetImageHandleARB(get_texture_binding(tex)->obj,
4871 0, GL_FALSE, 0, img_fmt);
4872 glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
4874 set_resident_handle(tex, handle, false);
4876 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4877 fprintf(stderr,
4878 "glMakeImageHandleResidentARB error\n");
4879 piglit_report_result(PIGLIT_FAIL);
4881 } else if (parse_str(line, "texture integer ", &rest)) {
4882 GLenum int_fmt;
4883 int b, a;
4884 int num_scanned =
4885 sscanf(rest, "%d ( %d , %d ) ( %d, %d ) %31s",
4886 &tex, &w, &h, &b, &a, s);
4887 if (num_scanned < 6) {
4888 fprintf(stderr,
4889 "invalid texture integer command!\n");
4890 piglit_report_result(PIGLIT_FAIL);
4893 int_fmt = piglit_get_gl_enum_from_name(s);
4895 glActiveTexture(GL_TEXTURE0 + tex);
4896 const GLuint handle =
4897 piglit_integer_texture(int_fmt, w, h, b, a);
4898 set_texture_binding(tex, handle, w, h, 1);
4900 } else if (sscanf(line, "texture miptree %d", &tex) == 1) {
4901 glActiveTexture(GL_TEXTURE0 + tex);
4902 const GLuint handle = piglit_miptree_texture();
4903 set_texture_binding(tex, handle, 8, 8, 1);
4905 if (!piglit_is_core_profile &&
4906 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4907 glEnable(GL_TEXTURE_2D);
4908 } else if (sscanf(line,
4909 "texture checkerboard %d %d ( %d , %d ) "
4910 "( %f , %f , %f , %f ) "
4911 "( %f , %f , %f , %f )",
4912 &tex, &level, &w, &h,
4913 c + 0, c + 1, c + 2, c + 3,
4914 c + 4, c + 5, c + 6, c + 7) == 12) {
4915 glActiveTexture(GL_TEXTURE0 + tex);
4916 const GLuint handle = piglit_checkerboard_texture(
4917 0, level, w, h, w / 2, h / 2, c + 0, c + 4);
4918 set_texture_binding(tex, handle, w, h, 1);
4920 if (!piglit_is_core_profile &&
4921 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4922 glEnable(GL_TEXTURE_2D);
4923 } else if (sscanf(line,
4924 "texture quads %d %d ( %d , %d ) ( %d , %d ) "
4925 "( %f , %f , %f , %f ) "
4926 "( %f , %f , %f , %f ) "
4927 "( %f , %f , %f , %f ) "
4928 "( %f , %f , %f , %f )",
4929 &tex, &level, &w, &h, &x, &y,
4930 c + 0, c + 1, c + 2, c + 3,
4931 c + 4, c + 5, c + 6, c + 7,
4932 c + 8, c + 9, c + 10, c + 11,
4933 c + 12, c + 13, c + 14, c + 15) == 22) {
4934 glActiveTexture(GL_TEXTURE0 + tex);
4935 const GLuint handle = piglit_quads_texture(
4936 0, level, w, h, x, y, c + 0, c + 4, c + 8, c + 12);
4937 set_texture_binding(tex, handle, w, h, 1);
4939 if (!piglit_is_core_profile &&
4940 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4941 glEnable(GL_TEXTURE_2D);
4942 } else if (sscanf(line,
4943 "texture junk 2DArray %d ( %d , %d , %d )",
4944 &tex, &w, &h, &l) == 4) {
4945 GLuint texobj;
4946 glActiveTexture(GL_TEXTURE0 + tex);
4947 glGenTextures(1, &texobj);
4948 glBindTexture(GL_TEXTURE_2D_ARRAY, texobj);
4949 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA,
4950 w, h, l, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
4951 set_texture_binding(tex, texobj, w, h, l);
4953 } else if (parse_str(line, "texture storage ", &rest)) {
4954 GLenum target, format;
4955 GLuint tex_obj;
4956 int d = h = w = 1;
4958 REQUIRE(parse_int(rest, &tex, &rest) &&
4959 parse_tex_target(rest, &target, &rest) &&
4960 parse_enum_gl(rest, &format, &rest) &&
4961 parse_str(rest, "(", &rest) &&
4962 parse_int(rest, &l, &rest) &&
4963 parse_int(rest, &w, &rest),
4964 "Texture storage command not understood "
4965 "at: %s\n", rest);
4967 glActiveTexture(GL_TEXTURE0 + tex);
4968 glGenTextures(1, &tex_obj);
4969 glBindTexture(target, tex_obj);
4971 if (!parse_int(rest, &h, &rest))
4972 glTexStorage1D(target, l, format, w);
4973 else if (!parse_int(rest, &d, &rest))
4974 glTexStorage2D(target, l, format, w, h);
4975 else
4976 glTexStorage3D(target, l, format, w, h, d);
4978 if (!piglit_check_gl_error(GL_NO_ERROR)) {
4979 fprintf(stderr, "glTexStorage error\n");
4980 piglit_report_result(PIGLIT_FAIL);
4983 if (target == GL_TEXTURE_1D_ARRAY)
4984 set_texture_binding(tex, tex_obj, w, 1, h);
4985 else
4986 set_texture_binding(tex, tex_obj, w, h, d);
4988 #ifdef PIGLIT_USE_OPENGL
4989 } else if (sscanf(line,
4990 "texture rgbw 1D %d",
4991 &tex) == 1) {
4992 glActiveTexture(GL_TEXTURE0 + tex);
4993 const GLuint handle = piglit_rgbw_texture_1d();
4994 set_texture_binding(tex, handle, 4, 1, 1);
4995 #endif
4997 } else if (sscanf(line,
4998 "texture rgbw 3D %d",
4999 &tex) == 1) {
5000 glActiveTexture(GL_TEXTURE0 + tex);
5001 const GLuint handle = piglit_rgbw_texture_3d();
5002 set_texture_binding(tex, handle, 2, 2, 2);
5004 } else if (sscanf(line,
5005 "texture rgbw 2DArray %d ( %d , %d , %d )",
5006 &tex, &w, &h, &l) == 4) {
5007 glActiveTexture(GL_TEXTURE0 + tex);
5008 const GLuint handle = piglit_array_texture(
5009 GL_TEXTURE_2D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5010 set_texture_binding(tex, handle, w, h, l);
5012 } else if (sscanf(line,
5013 "texture rgbw 1DArray %d ( %d , %d )",
5014 &tex, &w, &l) == 3) {
5015 glActiveTexture(GL_TEXTURE0 + tex);
5016 h = 1;
5017 const GLuint handle = piglit_array_texture(
5018 GL_TEXTURE_1D_ARRAY, GL_RGBA, w, h, l, GL_FALSE);
5019 set_texture_binding(tex, handle, w, 1, l);
5021 } else if (sscanf(line,
5022 "texture shadow2D %d ( %d , %d )",
5023 &tex, &w, &h) == 3) {
5024 glActiveTexture(GL_TEXTURE0 + tex);
5025 const GLuint handle = piglit_depth_texture(
5026 GL_TEXTURE_2D, GL_DEPTH_COMPONENT,
5027 w, h, 1, GL_FALSE);
5028 glTexParameteri(GL_TEXTURE_2D,
5029 GL_TEXTURE_COMPARE_MODE,
5030 GL_COMPARE_R_TO_TEXTURE);
5031 glTexParameteri(GL_TEXTURE_2D,
5032 GL_TEXTURE_COMPARE_FUNC,
5033 GL_GREATER);
5034 set_texture_binding(tex, handle, w, h, 1);
5036 if (!piglit_is_core_profile &&
5037 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5038 glEnable(GL_TEXTURE_2D);
5039 } else if (sscanf(line,
5040 "texture shadowRect %d ( %d , %d )",
5041 &tex, &w, &h) == 3) {
5042 glActiveTexture(GL_TEXTURE0 + tex);
5043 const GLuint handle = piglit_depth_texture(
5044 GL_TEXTURE_RECTANGLE, GL_DEPTH_COMPONENT,
5045 w, h, 1, GL_FALSE);
5046 glTexParameteri(GL_TEXTURE_RECTANGLE,
5047 GL_TEXTURE_COMPARE_MODE,
5048 GL_COMPARE_R_TO_TEXTURE);
5049 glTexParameteri(GL_TEXTURE_RECTANGLE,
5050 GL_TEXTURE_COMPARE_FUNC,
5051 GL_GREATER);
5052 set_texture_binding(tex, handle, w, h, 1);
5053 } else if (sscanf(line,
5054 "texture shadow1D %d ( %d )",
5055 &tex, &w) == 2) {
5056 glActiveTexture(GL_TEXTURE0 + tex);
5057 const GLuint handle = piglit_depth_texture(
5058 GL_TEXTURE_1D, GL_DEPTH_COMPONENT,
5059 w, 1, 1, GL_FALSE);
5060 glTexParameteri(GL_TEXTURE_1D,
5061 GL_TEXTURE_COMPARE_MODE,
5062 GL_COMPARE_R_TO_TEXTURE);
5063 glTexParameteri(GL_TEXTURE_1D,
5064 GL_TEXTURE_COMPARE_FUNC,
5065 GL_GREATER);
5066 set_texture_binding(tex, handle, w, 1, 1);
5067 } else if (sscanf(line,
5068 "texture shadow1DArray %d ( %d , %d )",
5069 &tex, &w, &l) == 3) {
5070 glActiveTexture(GL_TEXTURE0 + tex);
5071 const GLuint handle = piglit_depth_texture(
5072 GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT,
5073 w, l, 1, GL_FALSE);
5074 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5075 GL_TEXTURE_COMPARE_MODE,
5076 GL_COMPARE_R_TO_TEXTURE);
5077 glTexParameteri(GL_TEXTURE_1D_ARRAY,
5078 GL_TEXTURE_COMPARE_FUNC,
5079 GL_GREATER);
5080 set_texture_binding(tex, handle, w, 1, l);
5081 } else if (sscanf(line,
5082 "texture shadow2DArray %d ( %d , %d , %d )",
5083 &tex, &w, &h, &l) == 4) {
5084 glActiveTexture(GL_TEXTURE0 + tex);
5085 const GLuint handle = piglit_depth_texture(
5086 GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT,
5087 w, h, l, GL_FALSE);
5088 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5089 GL_TEXTURE_COMPARE_MODE,
5090 GL_COMPARE_R_TO_TEXTURE);
5091 glTexParameteri(GL_TEXTURE_2D_ARRAY,
5092 GL_TEXTURE_COMPARE_FUNC,
5093 GL_GREATER);
5094 set_texture_binding(tex, handle, w, h, l);
5095 } else if (sscanf(line, "texcoord %d ( %f , %f , %f , %f )",
5096 &x, c + 0, c + 1, c + 2, c + 3) == 5) {
5097 glMultiTexCoord4fv(GL_TEXTURE0 + x, c);
5098 } else if (parse_str(line, "texparameter ", &rest)) {
5099 handle_texparameter(rest);
5100 } else if (parse_str(line, "uniform ", &rest)) {
5101 result = program_must_be_in_use();
5102 set_uniform(rest, block_data);
5103 } else if (parse_str(line, "subuniform ", &rest)) {
5104 result = program_must_be_in_use();
5105 check_shader_subroutine_support();
5106 set_subroutine_uniform(rest);
5107 } else if (parse_str(line, "parameter ", &rest)) {
5108 set_parameter(rest);
5109 } else if (parse_str(line, "patch parameter ", &rest)) {
5110 set_patch_parameter(rest);
5111 } else if (parse_str(line, "program binary save restore", &rest)) {
5112 program_binary_save_restore(true);
5113 } else if (parse_str(line, "provoking vertex ", &rest)) {
5114 set_provoking_vertex(rest);
5115 } else if (parse_str(line, "link error", &rest)) {
5116 link_error_expected = true;
5117 if (link_ok) {
5118 printf("shader link error expected, but it was successful!\n");
5119 piglit_report_result(PIGLIT_FAIL);
5120 } else {
5121 fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
5123 } else if (parse_str(line, "link success", &rest)) {
5124 result = program_must_be_in_use();
5125 } else if (parse_str(line, "ubo array index ", &rest)) {
5126 /* we allow "ubo array index" in order to not
5127 * change existing tests using ubo array index
5129 parse_ints(rest, &block_data.array_index, 1, NULL);
5130 } else if (parse_str(line, "block array index ", &rest)) {
5131 parse_ints(rest, &block_data.array_index, 1, NULL);
5132 } else if (parse_str(line, "block binding ", &rest)) {
5133 parse_ints(rest, &block_data.binding, 1, NULL);
5134 } else if (parse_str(line, "block offset ", &rest)) {
5135 parse_ints(rest, &block_data.offset, 1, NULL);
5136 } else if (parse_str(line, "block matrix stride", &rest)) {
5137 parse_ints(rest, &block_data.matrix_stride, 1, NULL);
5138 } else if (parse_str(line, "block row major", &rest)) {
5139 parse_ints(rest, &block_data.row_major, 1, NULL);
5140 } else if (parse_str(line, "active uniform ", &rest)) {
5141 active_uniform(rest);
5142 } else if (parse_str(line, "verify program_query", &rest)) {
5143 verify_program_query(rest);
5144 } else if (parse_str(line, "verify program_interface_query ", &rest)) {
5145 active_program_interface(rest, block_data);
5146 } else if (parse_str(line, "verify query_object", &rest)) {
5147 result = verify_query_object_result(rest);
5148 } else if (parse_str(line, "vertex attrib ", &rest)) {
5149 set_vertex_attrib(rest);
5150 } else if (parse_str(line, "newlist ", &rest)) {
5151 GLenum mode;
5153 REQUIRE(parse_enum_gl(rest, &mode, &rest),
5154 "NewList mode command not understood at %s\n",
5155 rest);
5157 list = glGenLists(1);
5158 glNewList(list, mode);
5159 } else if (parse_str(line, "endlist", NULL)) {
5160 glEndList();
5161 } else if (parse_str(line, "calllist", NULL)) {
5162 glCallList(list);
5163 } else if (parse_str(line, "deletelist", NULL)) {
5164 glDeleteLists(list, 1);
5165 } else if (parse_str(line, "viewport swizzle ", &rest)) {
5166 handle_viewport_swizzle(rest);
5167 } else if ((line[0] != '\n') && (line[0] != '\0')
5168 && (line[0] != '#')) {
5169 printf("unknown command \"%s\"\n", line);
5170 piglit_report_result(PIGLIT_FAIL);
5173 free((void*) line);
5175 if (result != PIGLIT_PASS) {
5176 printf("Test failure on line %u\n", line_num);
5177 full_result = result;
5180 line_num++;
5183 if (!link_ok && !link_error_expected) {
5184 full_result = program_must_be_in_use();
5187 piglit_present_results();
5189 if (piglit_automatic) {
5190 unsigned i;
5192 /* Free our resources, useful for valgrinding. */
5193 free_subroutine_uniforms();
5195 for (i = 0; i < ARRAY_SIZE(resident_handles); i++)
5196 clear_resident_handle(i);
5198 for (i = 0; i < ARRAY_SIZE(texture_bindings); i++)
5199 clear_texture_binding(i);
5201 if (prog != 0) {
5202 glDeleteProgram(prog);
5203 glUseProgram(0);
5204 } else {
5205 if (!sso_in_use)
5206 glDeleteProgramsARB(1, &prog);
5209 if (pipeline != 0)
5210 glDeleteProgramPipelines(1, &pipeline);
5213 return full_result;
5216 static enum piglit_result
5217 init_test(const char *file)
5219 enum piglit_result result;
5221 result = process_test_script(file);
5222 if (result != PIGLIT_PASS)
5223 return result;
5225 result = link_and_use_shaders();
5226 if (result != PIGLIT_PASS)
5227 return result;
5229 if (sso_in_use)
5230 glBindProgramPipeline(pipeline);
5232 if (link_ok && vertex_data_start != NULL) {
5233 result = program_must_be_in_use();
5234 if (result != PIGLIT_PASS)
5235 return result;
5237 bind_vao_if_supported();
5239 num_vbo_rows = setup_vbo_from_text(prog, vertex_data_start,
5240 vertex_data_end);
5241 vbo_present = true;
5243 setup_ubos();
5244 return PIGLIT_PASS;
5247 static void
5248 recreate_gl_context(char *exec_arg, int param_argc, char **param_argv)
5250 int argc = param_argc + 4;
5251 char **argv = malloc(sizeof(char*) * argc);
5253 if (!argv) {
5254 fprintf(stderr, "%s: malloc failed.\n", __func__);
5255 piglit_report_result(PIGLIT_FAIL);
5258 argv[0] = exec_arg;
5259 memcpy(&argv[1], param_argv, param_argc * sizeof(char*));
5260 argv[argc-3] = "-auto";
5261 argv[argc-2] = "-fbo";
5262 argv[argc-1] = "-report-subtests";
5264 if (gl_fw->destroy)
5265 gl_fw->destroy(gl_fw);
5266 gl_fw = NULL;
5268 exit(main(argc, argv));
5271 static bool
5272 validate_current_gl_context(const char *filename)
5274 struct piglit_gl_test_config config = { 0 };
5276 if (!piglit_gl_test_config_override_size(&config)) {
5277 config.window_width = DEFAULT_WINDOW_WIDTH;
5278 config.window_height = DEFAULT_WINDOW_HEIGHT;
5281 get_required_config(filename, spirv_replaces_glsl, &config);
5283 if (!current_config.supports_gl_compat_version !=
5284 !config.supports_gl_compat_version)
5285 return false;
5287 if (!current_config.supports_gl_core_version !=
5288 !config.supports_gl_core_version)
5289 return false;
5291 if (!current_config.supports_gl_es_version !=
5292 !config.supports_gl_es_version)
5293 return false;
5295 if (current_config.window_width != config.window_width ||
5296 current_config.window_height != config.window_height)
5297 return false;
5299 if (!(current_config.window_visual & PIGLIT_GL_VISUAL_DEPTH) &&
5300 config.window_visual & PIGLIT_GL_VISUAL_DEPTH)
5301 return false;
5303 return true;
5306 void
5307 piglit_init(int argc, char **argv)
5309 int major;
5310 int minor;
5311 bool core = piglit_is_core_profile;
5312 bool es;
5313 enum piglit_result result;
5314 float default_piglit_tolerance[4];
5316 use_get_program_binary =
5317 piglit_strip_arg(&argc, argv, "-get-program-binary") ||
5318 piglit_env_var_as_boolean("SHADER_RUNNER_GET_PROGRAM_BINARY",
5319 false);
5321 report_subtests = piglit_strip_arg(&argc, argv, "-report-subtests");
5322 force_glsl = piglit_strip_arg(&argc, argv, "-glsl");
5323 ignore_missing_uniforms = piglit_strip_arg(&argc, argv, "-ignore-missing-uniforms");
5325 force_no_names = piglit_strip_arg(&argc, argv, "-force-no-names");
5327 if (force_glsl && spirv_replaces_glsl) {
5328 printf("Options -glsl and -spirv can't be used at the same time\n");
5329 piglit_report_result(PIGLIT_FAIL);
5332 if (spirv_replaces_glsl)
5333 force_no_names = true;
5335 if (argc < 2) {
5336 printf("usage: shader_runner <test.shader_test> [-glsl] [-force-no-names]\n");
5337 exit(1);
5340 memcpy(default_piglit_tolerance, piglit_tolerance,
5341 sizeof(piglit_tolerance));
5343 piglit_require_GLSL();
5345 version_init(&gl_version, VERSION_GL,
5346 core, !core,
5347 piglit_is_gles(),
5348 piglit_get_gl_version());
5349 piglit_get_glsl_version(&es, &major, &minor);
5350 version_init(&glsl_version, VERSION_GLSL, core, !core, es,
5351 (major * 100) + minor);
5353 #ifdef PIGLIT_USE_OPENGL
5354 if (piglit_get_gl_version() >= 32)
5355 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
5356 &gl_max_vertex_output_components);
5357 if (piglit_get_gl_version() >= 20 ||
5358 piglit_is_extension_supported("GL_ARB_fragment_shader"))
5359 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
5360 &gl_max_fragment_uniform_components);
5361 if (piglit_get_gl_version() >= 20 ||
5362 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5363 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
5364 &gl_max_vertex_uniform_components);
5365 if (piglit_get_gl_version() >= 20 ||
5366 piglit_is_extension_supported("GL_ARB_vertex_shader") ||
5367 piglit_is_extension_supported("GL_ARB_geometry_shader4") ||
5368 piglit_is_extension_supported("GL_EXT_geometry_shader4"))
5369 glGetIntegerv(GL_MAX_VARYING_COMPONENTS,
5370 &gl_max_varying_components);
5371 #else
5372 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
5373 &gl_max_fragment_uniform_components);
5374 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
5375 &gl_max_vertex_uniform_components);
5376 glGetIntegerv(GL_MAX_VARYING_VECTORS,
5377 &gl_max_varying_components);
5378 gl_max_fragment_uniform_components *= 4;
5379 gl_max_vertex_uniform_components *= 4;
5380 gl_max_varying_components *= 4;
5381 #endif
5382 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max_clip_planes);
5384 if (gl_version.num >= 20 ||
5385 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5386 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,
5387 &gl_max_vertex_attribs);
5388 else
5389 gl_max_vertex_attribs = 16;
5391 read_width = render_width = piglit_width;
5392 read_height = render_height = piglit_height;
5394 #ifdef PIGLIT_USE_OPENGL
5395 if (piglit_is_extension_supported("GL_ARB_get_program_binary"))
5396 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
5397 &gl_num_program_binary_formats);
5398 #else
5399 if (piglit_is_extension_supported("GL_OES_get_program_binary"))
5400 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES,
5401 &gl_num_program_binary_formats);
5402 #endif
5404 if (use_get_program_binary) {
5405 if (gl_num_program_binary_formats == 0) {
5406 printf("Trying to use get_program_binary, but "
5407 "GL_NUM_PROGRAM_BINARY == 0\n");
5408 piglit_report_result(PIGLIT_SKIP);
5412 /* Automatic mode can run multiple tests per session. */
5413 if (report_subtests) {
5414 char testname[4096], *ext;
5415 int i, j;
5417 for (i = 1; i < argc; i++) {
5418 const char *hit, *filename = argv[i];
5420 memcpy(piglit_tolerance, default_piglit_tolerance,
5421 sizeof(piglit_tolerance));
5423 /* Re-initialize the GL context if a different GL config is required. */
5424 if (!validate_current_gl_context(filename))
5425 recreate_gl_context(argv[0], argc - i, argv + i);
5427 /* Clear global variables to defaults. */
5428 test_start = NULL;
5429 assert(num_vertex_shaders == 0);
5430 assert(num_tess_ctrl_shaders == 0);
5431 assert(num_tess_eval_shaders == 0);
5432 assert(num_geometry_shaders == 0);
5433 assert(num_fragment_shaders == 0);
5434 assert(num_compute_shaders == 0);
5435 assert(num_uniform_blocks == 0);
5436 assert(uniform_block_bos == NULL);
5437 assert(uniform_block_indexes == NULL);
5438 geometry_layout_input_type = GL_TRIANGLES;
5439 geometry_layout_output_type = GL_TRIANGLE_STRIP;
5440 geometry_layout_vertices_out = 0;
5441 memset(atomics_bos, 0, sizeof(atomics_bos));
5442 memset(ssbo, 0, sizeof(ssbo));
5443 for (j = 0; j < ARRAY_SIZE(subuniform_locations); j++)
5444 assert(subuniform_locations[j] == NULL);
5445 memset(num_subuniform_locations, 0, sizeof(num_subuniform_locations));
5446 shader_string = NULL;
5447 shader_string_size = 0;
5448 vertex_data_start = NULL;
5449 vertex_data_end = NULL;
5450 prog = 0;
5451 sso_vertex_prog = 0;
5452 sso_tess_control_prog = 0;
5453 sso_tess_eval_prog = 0;
5454 sso_geometry_prog = 0;
5455 sso_fragment_prog = 0;
5456 sso_compute_prog = 0;
5457 num_vbo_rows = 0;
5458 vbo_present = false;
5459 link_ok = false;
5460 prog_in_use = false;
5461 sso_in_use = false;
5462 separable_program = false;
5463 prog_err_info = NULL;
5464 vao = 0;
5466 /* Clear GL states to defaults. */
5467 glClearColor(0, 0, 0, 0);
5468 # if PIGLIT_USE_OPENGL
5469 glClearDepth(1);
5470 # else
5471 glClearDepthf(1.0);
5472 # endif
5473 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
5474 glActiveTexture(GL_TEXTURE0);
5475 glUseProgram(0);
5476 glDisable(GL_DEPTH_TEST);
5477 glBindBuffer(GL_ARRAY_BUFFER, 0);
5479 for (int k = 0; k < gl_max_clip_planes; k++) {
5480 static const GLdouble zero[4];
5482 if (!piglit_is_core_profile && !es)
5483 glClipPlane(GL_CLIP_PLANE0 + k, zero);
5484 glDisable(GL_CLIP_PLANE0 + k);
5487 if (!(es) && (gl_version.num >= 20 ||
5488 piglit_is_extension_supported("GL_ARB_vertex_program")))
5489 glDisable(GL_PROGRAM_POINT_SIZE);
5491 for (int i = 0; i < 16; i++)
5492 glDisableVertexAttribArray(i);
5494 if (!piglit_is_core_profile && !es) {
5495 glMatrixMode(GL_PROJECTION);
5496 glLoadIdentity();
5497 glMatrixMode(GL_MODELVIEW);
5498 glLoadIdentity();
5499 glShadeModel(GL_SMOOTH);
5500 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
5503 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
5504 glDisable(GL_VERTEX_PROGRAM_ARB);
5505 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0);
5507 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
5508 glDisable(GL_FRAGMENT_PROGRAM_ARB);
5509 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
5511 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
5512 if (!pipeline)
5513 glGenProgramPipelines(1, &pipeline);
5514 glBindProgramPipeline(0);
5517 if (piglit_is_extension_supported("GL_EXT_provoking_vertex"))
5518 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
5520 # if PIGLIT_USE_OPENGL
5521 if (gl_version.num >= 40 ||
5522 piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
5523 static float ones[] = {1, 1, 1, 1};
5524 glPatchParameteri(GL_PATCH_VERTICES, 3);
5525 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, ones);
5526 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, ones);
5528 # else
5529 /* Ideally one would use the following code:
5531 * if (gl_version.num >= 32) {
5532 * glPatchParameteri(GL_PATCH_VERTICES, 3);
5535 * however, that doesn't work with mesa because those
5536 * symbols apparently need to be exported, but that
5537 * breaks non-gles builds.
5539 * It seems rather unlikely that an implementation
5540 * would have GLES 3.2 support but not
5541 * OES_tessellation_shader.
5543 if (piglit_is_extension_supported("GL_OES_tessellation_shader")) {
5544 glPatchParameteriOES(GL_PATCH_VERTICES_OES, 3);
5546 # endif
5548 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5550 /* Strip the file path. */
5551 hit = strrchr(filename, PIGLIT_PATH_SEP);
5552 if (hit)
5553 strcpy(testname, hit+1);
5554 else
5555 strcpy(testname, filename);
5557 /* Strip the file extension. */
5558 ext = strstr(testname, ".shader_test");
5559 if (ext && !ext[12])
5560 *ext = 0;
5562 /* Print the name before we start the test, that way if
5563 * the test fails we can still resume and know which
5564 * test failed */
5565 printf("PIGLIT TEST: %i - %s\n", test_num, testname);
5566 fprintf(stderr, "PIGLIT TEST: %i - %s\n", test_num, testname);
5567 test_num++;
5569 /* Run the test. */
5570 result = init_test(filename);
5572 if (result == PIGLIT_PASS) {
5573 result = piglit_display();
5575 /* Use subtest when running with more than one test,
5576 * but use regular test result when running with just
5577 * one. This allows the standard process-at-a-time
5578 * mode to keep working.
5580 if (report_subtests) {
5581 piglit_report_subtest_result(
5582 result, "%s", testname);
5583 } else {
5584 piglit_report_result(result);
5587 /* destroy GL objects? */
5588 teardown_ubos();
5589 teardown_atomics();
5590 teardown_fbos();
5591 teardown_shader_include_paths();
5592 teardown_xfb();
5594 exit(0);
5597 result = init_test(argv[1]);
5598 if (result != PIGLIT_PASS)
5599 piglit_report_result(result);