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
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.
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
;
46 get_required_config(const char *script_name
, bool spirv
,
47 struct piglit_gl_test_config
*config
);
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.
65 get_required_config(argv
[1], spirv_replaces_glsl
, &config
);
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"
78 "attribute vec4 piglit_vertex;\n"
80 "void main() { gl_Position = piglit_vertex; }\n"
83 struct component_version
{
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
;
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
{
195 union { GLuint u
; GLfloat f
; } *values
;
198 static struct specialization_list
199 specializations
[SHADER_TYPES
];
201 static struct texture_binding
{
206 } texture_bindings
[32];
208 static struct resident_handle
{
211 } resident_handles
[32];
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;
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
];
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
);
260 if (glIsImageHandleResidentARB(handle
))
261 glMakeImageHandleNonResidentARB(handle
);
263 resident_handles
[idx
].handle
= 0;
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
];
292 vertex_shader_passthrough
,
294 vertex_shader_specializations
,
297 tess_ctrl_shader_spirv
,
298 tess_ctrl_shader_specializations
,
300 tess_eval_shader_spirv
,
301 tess_eval_shader_specializations
,
303 geometry_shader_spirv
,
304 geometry_shader_specializations
,
307 fragment_shader_spirv
,
308 fragment_shader_specializations
,
311 compute_shader_spirv
,
312 compute_shader_specializations
,
315 shader_include_paths
,
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
),
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
),
406 compare(float ref
, float value
, enum comparison cmp
);
409 compare_uint(GLuint ref
, GLuint value
, enum comparison cmp
);
412 compare_int(GLint ref
, GLint value
, enum comparison cmp
);
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
);
428 version_copy(struct component_version
*dest
, struct component_version
*src
)
430 memcpy(dest
, src
, sizeof(*dest
));
434 version_compare(struct component_version
*a
, struct component_version
*b
, enum comparison cmp
)
436 assert(a
->_tag
== b
->_tag
);
441 return compare(a
->num
, b
->num
, cmp
);
445 * Get the version string.
448 version_string(struct component_version
*v
)
455 snprintf(v
->_string
, sizeof(v
->_string
) - 1, "GL%s %d.%d",
457 v
->num
/ 10, v
->num
% 10);
460 snprintf(v
->_string
, sizeof(v
->_string
) - 1, "GLSL%s %d.%d",
462 v
->num
/ 100, v
->num
% 100);
474 target_to_short_name(GLenum target
)
477 case GL_VERTEX_SHADER
:
479 case GL_FRAGMENT_SHADER
:
481 case GL_TESS_CONTROL_SHADER
:
483 case GL_TESS_EVALUATION_SHADER
:
485 case GL_GEOMETRY_SHADER
:
487 case GL_COMPUTE_SHADER
:
495 static enum piglit_result
496 compile_glsl(GLenum target
)
498 GLuint shader
= glCreateShader(target
);
502 printf("Cannot mix SPIRV and non-SPIRV shaders\n");
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")))
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")))
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"))
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"))
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"))
543 if (!glsl_req_version
.num
) {
544 printf("GLSL version requirement missing\n");
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
);
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
);
578 glCompileShader(shader
);
580 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &ok
);
586 glGetShaderiv(shader
, GL_INFO_LOG_LENGTH
, &size
);
589 glGetShaderInfoLog(shader
, size
, NULL
, info
);
591 fprintf(stderr
, "Failed to compile %s: %s\n",
592 target_to_short_name(target
),
600 case GL_VERTEX_SHADER
:
601 vertex_shaders
[num_vertex_shaders
] = shader
;
602 num_vertex_shaders
++;
604 case GL_TESS_CONTROL_SHADER
:
605 tess_ctrl_shaders
[num_tess_ctrl_shaders
] = shader
;
606 num_tess_ctrl_shaders
++;
608 case GL_TESS_EVALUATION_SHADER
:
609 tess_eval_shaders
[num_tess_eval_shaders
] = shader
;
610 num_tess_eval_shaders
++;
612 case GL_GEOMETRY_SHADER
:
613 geometry_shaders
[num_geometry_shaders
] = shader
;
614 num_geometry_shaders
++;
616 case GL_FRAGMENT_SHADER
:
617 fragment_shaders
[num_fragment_shaders
] = shader
;
618 num_fragment_shaders
++;
620 case GL_COMPUTE_SHADER
:
621 compute_shaders
[num_compute_shaders
] = shader
;
622 num_compute_shaders
++;
629 static enum piglit_result
630 compile_and_bind_program(GLenum target
, const char *start
, int len
)
636 case GL_VERTEX_PROGRAM_ARB
:
637 if (!piglit_is_extension_supported("GL_ARB_vertex_program"))
640 case GL_FRAGMENT_PROGRAM_ARB
:
641 if (!piglit_is_extension_supported("GL_ARB_fragment_program"))
646 source
= malloc(len
+ 1);
647 memcpy(source
, start
, len
);
649 prog
= piglit_compile_program(target
, source
);
652 glBindProgramARB(target
, prog
);
660 program_binary_save_restore(bool script_command
)
664 GLenum binary_format
;
668 if (!script_command
&& !use_get_program_binary
)
671 if (script_command
&& gl_num_program_binary_formats
== 0)
672 piglit_report_result(PIGLIT_SKIP
);
674 glGetProgramiv(prog
, GL_LINK_STATUS
, &ok
);
676 if (script_command
) {
677 fprintf(stderr
, "Can't save/restore program that is "
679 piglit_report_result(PIGLIT_FAIL
);
685 #ifdef PIGLIT_USE_OPENGL
686 glGetProgramiv(prog
, GL_PROGRAM_BINARY_LENGTH
, &binary_length
);
688 glGetProgramiv(prog
, GL_PROGRAM_BINARY_LENGTH_OES
, &binary_length
);
690 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
691 fprintf(stderr
, "glGetProgramiv GL_PROGRAM_BINARY_LENGTH "
693 piglit_report_result(PIGLIT_FAIL
);
696 binary
= malloc(binary_length
);
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
,
707 glGetProgramBinaryOES(prog
, binary_length
, &binary_length
,
708 &binary_format
, binary
);
710 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
711 fprintf(stderr
, "glGetProgramBinary error\n");
713 piglit_report_result(PIGLIT_FAIL
);
716 new_prog
= glCreateProgram();
717 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
719 piglit_report_result(PIGLIT_FAIL
);
722 #ifdef PIGLIT_USE_OPENGL
723 glProgramBinary(new_prog
, binary_format
, binary
, binary_length
);
725 glProgramBinaryOES(new_prog
, binary_format
, binary
, binary_length
);
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
);
736 fprintf(stderr
, "link failure after glProgramBinary\n");
737 piglit_report_result(PIGLIT_FAIL
);
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
);
754 static enum piglit_result
755 specialize_spirv(GLenum target
,
759 printf("Cannot mix SPIR-V and non-SPIR-V shaders\n");
765 const struct specialization_list
*specs
;
768 case GL_VERTEX_SHADER
:
769 specs
= specializations
+ 0;
771 case GL_TESS_CONTROL_SHADER
:
772 specs
= specializations
+ 1;
774 case GL_TESS_EVALUATION_SHADER
:
775 specs
= specializations
+ 2;
777 case GL_GEOMETRY_SHADER
:
778 specs
= specializations
+ 3;
780 case GL_FRAGMENT_SHADER
:
781 specs
= specializations
+ 4;
783 case GL_COMPUTE_SHADER
:
784 specs
= specializations
+ 5;
787 assert(!"Should not get here.");
790 glSpecializeShaderARB(shader
,
794 &specs
->values
[0].u
);
797 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &ok
);
803 glGetShaderiv(shader
, GL_INFO_LOG_LENGTH
, &size
);
804 info
= malloc(MAX2(size
, 1));
807 glGetShaderInfoLog(shader
, size
, NULL
, info
);
809 printf("Failed to specialize %s: %s\n",
810 target_to_short_name(target
), info
);
817 case GL_VERTEX_SHADER
:
818 vertex_shaders
[num_vertex_shaders
] = shader
;
819 num_vertex_shaders
++;
821 case GL_TESS_CONTROL_SHADER
:
822 tess_ctrl_shaders
[num_tess_ctrl_shaders
] = shader
;
823 num_tess_ctrl_shaders
++;
825 case GL_TESS_EVALUATION_SHADER
:
826 tess_eval_shaders
[num_tess_eval_shaders
] = shader
;
827 num_tess_eval_shaders
++;
829 case GL_GEOMETRY_SHADER
:
830 geometry_shaders
[num_geometry_shaders
] = shader
;
831 num_geometry_shaders
++;
833 case GL_FRAGMENT_SHADER
:
834 fragment_shaders
[num_fragment_shaders
] = shader
;
835 num_fragment_shaders
++;
837 case GL_COMPUTE_SHADER
:
838 compute_shaders
[num_compute_shaders
] = shader
;
839 num_compute_shaders
++;
846 static enum piglit_result
847 assemble_spirv(GLenum target
)
849 if (!piglit_is_extension_supported("GL_ARB_gl_spirv")) {
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
;
861 if (*in
== '#' && at_start_of_line
) {
865 shader_string
+ shader_string_size
- in
);
870 at_start_of_line
= *in
== '\n';
875 GLuint shader
= piglit_assemble_spirv(target
,
879 free(stripped_source
);
881 return specialize_spirv(target
, shader
);
884 static enum piglit_result
885 link_sso(GLenum target
)
891 glGetProgramiv(prog
, GL_LINK_STATUS
, &ok
);
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
),
911 if (!program_binary_save_restore(false))
915 case GL_VERTEX_SHADER
:
916 sso_vertex_prog
= prog
;
917 glUseProgramStages(pipeline
, GL_VERTEX_SHADER_BIT
, prog
);
919 case GL_TESS_CONTROL_SHADER
:
920 sso_tess_control_prog
= prog
;
921 glUseProgramStages(pipeline
, GL_TESS_CONTROL_SHADER_BIT
, prog
);
923 case GL_TESS_EVALUATION_SHADER
:
924 sso_tess_eval_prog
= prog
;
925 glUseProgramStages(pipeline
, GL_TESS_EVALUATION_SHADER_BIT
, prog
);
927 case GL_GEOMETRY_SHADER
:
928 sso_geometry_prog
= prog
;
929 glUseProgramStages(pipeline
, GL_GEOMETRY_SHADER_BIT
, prog
);
931 case GL_FRAGMENT_SHADER
:
932 sso_fragment_prog
= prog
;
933 glUseProgramStages(pipeline
, GL_FRAGMENT_SHADER_BIT
, prog
);
935 case GL_COMPUTE_SHADER
:
936 sso_compute_prog
= prog
;
937 glUseProgramStages(pipeline
, GL_COMPUTE_SHADER_BIT
, prog
);
944 * Compare two values given a specified comparison operator
947 compare(float ref
, float value
, enum comparison 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.");
963 compare_double(double ref
, double value
, enum comparison cmp
)
966 case equal
: return fabs(value
- ref
) < DBL_EPSILON
;
967 case not_equal
: return fabs(value
- ref
) >= DBL_EPSILON
;
968 case less
: return value
< ref
;
969 case greater_equal
: return value
>= ref
;
970 case greater
: return value
> ref
;
971 case less_equal
: return value
<= ref
;
974 assert(!"Should not get here.");
979 compare_uint(GLuint ref
, GLuint value
, enum comparison 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.");
995 compare_int(GLint ref
, GLint value
, enum comparison cmp
)
998 case equal
: return value
== ref
;
999 case not_equal
: return value
!= ref
;
1000 case less
: return value
< ref
;
1001 case greater_equal
: return value
>= ref
;
1002 case greater
: return value
> ref
;
1003 case less_equal
: return value
<= ref
;
1006 assert(!"Should not get here.");
1011 compare_uint64(GLuint64 ref
, GLuint64 value
, enum comparison cmp
)
1014 case equal
: return value
== ref
;
1015 case not_equal
: return value
!= ref
;
1016 case less
: return value
< ref
;
1017 case greater_equal
: return value
>= ref
;
1018 case greater
: return value
> ref
;
1019 case less_equal
: return value
<= ref
;
1022 assert(!"Should not get here.");
1027 compare_int64(GLint64 ref
, GLint64 value
, enum comparison cmp
)
1030 case equal
: return value
== ref
;
1031 case not_equal
: return value
!= ref
;
1032 case less
: return value
< ref
;
1033 case greater_equal
: return value
>= ref
;
1034 case greater
: return value
> ref
;
1035 case less_equal
: return value
<= ref
;
1038 assert(!"Should not get here.");
1043 * Get the string representation of a comparison operator
1046 comparison_string(enum comparison cmp
)
1049 case equal
: return "==";
1050 case not_equal
: return "!=";
1051 case less
: return "<";
1052 case greater_equal
: return ">=";
1053 case greater
: return ">";
1054 case less_equal
: return "<=";
1057 assert(!"Should not get here.");
1062 * " ES" before the comparison operator indicates the version
1063 * pertains to GL ES.
1066 parse_version_comparison(const char *line
, enum comparison
*cmp
,
1067 struct component_version
*v
, enum version_tag tag
)
1072 const bool core
= parse_str(line
, "CORE", &line
);
1073 const bool compat
= parse_str(line
, "COMPAT", &line
);
1074 const bool es
= parse_str(line
, "ES", &line
);
1076 REQUIRE(parse_comparison_op(line
, cmp
, &line
),
1077 "Invalid comparison operation at: %s\n", line
);
1079 REQUIRE(parse_uint(line
, &major
, &line
) &&
1080 parse_str(line
, ".", &line
) &&
1081 parse_uint(line
, &minor
, &line
),
1082 "Invalid version string: %s\n", line
);
1084 parse_whitespace(line
, &line
);
1085 if (*line
!= '\n') {
1086 printf("Unexpected characters following version comparison\n");
1087 piglit_report_result(PIGLIT_FAIL
);
1090 /* This hack is so that we can tell the difference between GL versions
1091 * and GLSL versions. All GL versions look like 3.2, and we want the
1092 * integer to be 32. All GLSL versions look like 1.40, and we want
1093 * the integer to be 140.
1095 if (tag
== VERSION_GLSL
) {
1096 full_num
= (major
* 100) + minor
;
1098 full_num
= (major
* 10) + minor
;
1101 version_init(v
, tag
, core
, compat
, es
, full_num
);
1105 * Parse and check a line from the requirement section of the test
1107 static enum piglit_result
1108 process_requirement(const char *line
)
1111 static const struct {
1115 } getint_limits
[] = {
1117 "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
1118 &gl_max_vertex_output_components
,
1119 "vertex output components",
1122 "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
1123 &gl_max_fragment_uniform_components
,
1124 "fragment uniform components",
1127 "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
1128 &gl_max_vertex_uniform_components
,
1129 "vertex uniform components",
1132 "GL_MAX_VERTEX_ATTRIBS",
1133 &gl_max_vertex_attribs
,
1137 "GL_MAX_VARYING_COMPONENTS",
1138 &gl_max_varying_components
,
1139 "varying components",
1142 "GL_NUM_PROGRAM_BINARY_FORMATS",
1143 &gl_num_program_binary_formats
,
1144 "num program binary formats",
1149 /* The INT keyword in the requirements section causes
1150 * shader_runner to read the specified integer value and
1151 * processes the given requirement.
1153 if (parse_str(line
, "INT ", &line
)) {
1154 enum comparison cmp
;
1155 int comparison_value
, gl_int_value
;
1158 REQUIRE(parse_enum_gl(line
, &int_enum
, &line
),
1159 "Invalid comparison enum at: %s\n", line
);
1160 REQUIRE(parse_comparison_op(line
, &cmp
, &line
),
1161 "Invalid comparison operation at: %s\n", line
);
1162 REQUIRE(parse_int(line
, &comparison_value
, &line
),
1163 "Invalid comparison value at: %s\n", line
);
1165 glGetIntegerv(int_enum
, &gl_int_value
);
1166 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
1167 fprintf(stderr
, "Error reading %s\n",
1168 piglit_get_gl_enum_name(int_enum
));
1172 if (!compare(comparison_value
, gl_int_value
, cmp
)) {
1173 printf("Test requires %s %s %i. "
1174 "The driver supports %i.\n",
1175 piglit_get_gl_enum_name(int_enum
),
1176 comparison_string(cmp
),
1185 /* There are five types of requirements that a test can currently
1188 * * Require that some GL extension be supported
1189 * * Require some particular versions of GL
1190 * * Require some particular versions of GLSL
1191 * * Require some particular number of uniform components
1192 * * Require shaders be built as separate shader objects
1194 * The tests for GL and GLSL versions can be equal, not equal,
1195 * less, less-or-equal, greater, or greater-or-equal. Extension tests
1196 * can also require that a particular extension not be supported by
1197 * prepending ! to the extension name.
1199 for (i
= 0; i
< ARRAY_SIZE(getint_limits
); i
++) {
1200 enum comparison cmp
;
1203 if (!parse_str(line
, getint_limits
[i
].name
, &line
))
1206 REQUIRE(parse_comparison_op(line
, &cmp
, &line
),
1207 "Invalid comparison operation at: %s\n", line
);
1209 maxcomp
= atoi(line
);
1210 if (!compare(maxcomp
, *getint_limits
[i
].val
, cmp
)) {
1211 printf("Test requires %s %s %i. "
1212 "The driver supports %i.\n",
1213 getint_limits
[i
].desc
,
1214 comparison_string(cmp
),
1216 *getint_limits
[i
].val
);
1222 if (parse_str(line
, "GL_", NULL
) &&
1223 parse_word_copy(line
, buffer
, sizeof(buffer
), &line
)) {
1224 if (!piglit_is_extension_supported(buffer
)) {
1225 printf("Test requires unsupported extension %s\n", buffer
);
1228 } else if (parse_str(line
, "!", &line
) &&
1229 parse_str(line
, "GL_", NULL
) &&
1230 parse_word_copy(line
, buffer
, sizeof(buffer
), &line
)) {
1231 if (piglit_is_extension_supported(buffer
)) {
1232 printf("Test requires unsupported extension %s\n", buffer
);
1235 } else if (parse_str(line
, "GLSL", &line
)) {
1236 enum comparison cmp
;
1238 parse_version_comparison(line
, &cmp
, &glsl_req_version
,
1241 /* We only allow >= because we potentially use the
1242 * version number to insert a #version directive. */
1243 if (cmp
!= greater_equal
) {
1244 printf("Unsupported GLSL version comparison\n");
1248 if (!version_compare(&glsl_req_version
, &glsl_version
, cmp
)) {
1249 printf("Test requires %s %s. "
1250 "Actual version %s.\n",
1251 comparison_string(cmp
),
1252 version_string(&glsl_req_version
),
1253 version_string(&glsl_version
));
1256 } else if (parse_str(line
, "GL", &line
)) {
1257 enum comparison cmp
;
1258 struct component_version gl_req_version
;
1260 parse_version_comparison(line
, &cmp
, &gl_req_version
,
1263 if (!version_compare(&gl_req_version
, &gl_version
, cmp
)) {
1264 printf("Test requires %s %s. "
1265 "Actual version is %s.\n",
1266 comparison_string(cmp
),
1267 version_string(&gl_req_version
),
1268 version_string(&gl_version
));
1271 } else if (parse_str(line
, "rlimit", &line
)) {
1274 REQUIRE(parse_uint(line
, &lim
, &line
),
1275 "Invalid rlimit argument at: %s\n", line
);
1277 piglit_set_rlimit(lim
);
1278 } else if (parse_str(line
, "SSO", &line
) &&
1279 parse_str(line
, "ENABLED", NULL
)) {
1280 if (separable_program
) {
1281 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1285 const char *const ext_name
= gl_version
.es
1286 ? "GL_EXT_separate_shader_objects"
1287 : "GL_ARB_separate_shader_objects";
1288 const unsigned min_version
= gl_version
.es
1291 if (gl_version
.num
< min_version
)
1292 piglit_require_extension(ext_name
);
1295 glGenProgramPipelines(1, &pipeline
);
1296 } else if (parse_str(line
, "SEPARABLE PROGRAM", &line
) &&
1297 parse_str(line
, "ENABLED", NULL
)) {
1299 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1303 const char *const ext_name
= gl_version
.es
1304 ? "GL_EXT_separate_shader_objects"
1305 : "GL_ARB_separate_shader_objects";
1306 const unsigned min_version
= gl_version
.es
1309 if (gl_version
.num
< min_version
)
1310 piglit_require_extension(ext_name
);
1312 separable_program
= true;
1313 } else if (parse_str(line
, "SPIRV", &line
)) {
1314 spirv_replaces_glsl
= !force_glsl
;
1316 if (parse_str(line
, "ONLY", NULL
)) {
1318 printf("This shader is not compatible with GLSL\n");
1321 } else if (parse_str(line
, "YES", NULL
)) {
1322 /* Empty. Everything already set. Just parsing
1326 printf("Unknown SPIRV line in [require]\n");
1330 if (spirv_replaces_glsl
)
1331 force_no_names
= true;
1338 * Process a line from the [geometry layout] section of a test
1341 process_geometry_layout(const char *line
)
1346 parse_whitespace(line
, &line
);
1348 if (line
[0] == '\0' || line
[0] == '\n') {
1350 } else if (sscanf(line
, "input type %31s", s
) == 1) {
1351 geometry_layout_input_type
= decode_drawing_mode(s
);
1352 } else if (sscanf(line
, "output type %31s", s
) == 1) {
1353 geometry_layout_output_type
= decode_drawing_mode(s
);
1354 } else if (sscanf(line
, "vertices out %d", &x
) == 1) {
1355 geometry_layout_vertices_out
= x
;
1357 printf("Could not parse geometry layout line: %s\n", line
);
1358 piglit_report_result(PIGLIT_FAIL
);
1362 static enum piglit_result
1363 leave_state(enum states state
, const char *line
, const char *script_name
)
1370 if (spirv_replaces_glsl
) {
1371 printf("Running on SPIR-V mode\n");
1373 if (force_no_names
&& !spirv_replaces_glsl
) {
1374 printf("Running on GLSL mode, forcing not using "
1375 "uniform/uniform block names\n");
1380 if (spirv_replaces_glsl
)
1382 shader_string_size
= line
- shader_string
;
1383 return compile_glsl(GL_VERTEX_SHADER
);
1385 case vertex_shader_passthrough
:
1386 if (spirv_replaces_glsl
) {
1387 shader_string
= (char *) passthrough_vertex_shader_source_spv
;
1388 shader_string_size
= strlen(passthrough_vertex_shader_source_spv
);
1390 return assemble_spirv(GL_VERTEX_SHADER
);
1392 return compile_glsl(GL_VERTEX_SHADER
);
1394 case vertex_program
:
1395 return compile_and_bind_program(GL_VERTEX_PROGRAM_ARB
,
1397 line
- shader_string
);
1399 case vertex_shader_spirv
:
1400 if (!spirv_replaces_glsl
)
1402 shader_string_size
= line
- shader_string
;
1403 return assemble_spirv(GL_VERTEX_SHADER
);
1405 case vertex_shader_specializations
:
1408 case tess_ctrl_shader
:
1409 if (spirv_replaces_glsl
)
1411 shader_string_size
= line
- shader_string
;
1412 return compile_glsl(GL_TESS_CONTROL_SHADER
);
1414 case tess_ctrl_shader_spirv
:
1415 if (!spirv_replaces_glsl
)
1417 shader_string_size
= line
- shader_string
;
1418 return assemble_spirv(GL_TESS_CONTROL_SHADER
);
1420 case tess_ctrl_shader_specializations
:
1423 case tess_eval_shader
:
1424 if (spirv_replaces_glsl
)
1426 shader_string_size
= line
- shader_string
;
1427 return compile_glsl(GL_TESS_EVALUATION_SHADER
);
1429 case tess_eval_shader_spirv
:
1430 if (!spirv_replaces_glsl
)
1432 shader_string_size
= line
- shader_string
;
1433 return assemble_spirv(GL_TESS_EVALUATION_SHADER
);
1435 case tess_eval_shader_specializations
:
1438 case geometry_shader
:
1439 if (spirv_replaces_glsl
)
1441 shader_string_size
= line
- shader_string
;
1442 return compile_glsl(GL_GEOMETRY_SHADER
);
1444 case geometry_shader_spirv
:
1445 if (!spirv_replaces_glsl
)
1447 shader_string_size
= line
- shader_string
;
1448 return assemble_spirv(GL_GEOMETRY_SHADER
);
1450 case geometry_shader_specializations
:
1453 case geometry_layout
:
1456 case fragment_shader
:
1457 if (spirv_replaces_glsl
)
1459 shader_string_size
= line
- shader_string
;
1460 return compile_glsl(GL_FRAGMENT_SHADER
);
1462 case fragment_program
:
1463 return compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB
,
1465 line
- shader_string
);
1468 case fragment_shader_spirv
:
1469 if (!spirv_replaces_glsl
)
1471 shader_string_size
= line
- shader_string
;
1472 return assemble_spirv(GL_FRAGMENT_SHADER
);
1474 case fragment_shader_specializations
:
1477 case compute_shader
:
1478 if (spirv_replaces_glsl
)
1480 shader_string_size
= line
- shader_string
;
1481 return compile_glsl(GL_COMPUTE_SHADER
);
1483 case compute_shader_spirv
:
1484 if (!spirv_replaces_glsl
)
1486 shader_string_size
= line
- shader_string
;
1487 return assemble_spirv(GL_COMPUTE_SHADER
);
1489 case compute_shader_specializations
:
1493 vertex_data_end
= line
;
1496 case shader_include
: {
1497 const char *path_end
= strchrnul(shader_string
, '\n');
1499 if (shader_string
== path_end
) {
1500 fprintf(stderr
, "No shader include path provided\n");
1504 if (!piglit_is_extension_supported("GL_ARB_shading_language_include"))
1507 int path_name_len
= path_end
- shader_string
;
1508 glNamedStringARB(GL_SHADER_INCLUDE_ARB
, path_name_len
, shader_string
,
1509 line
- shader_string
- path_name_len
, shader_string
+ path_name_len
);
1511 shader_include_names
[num_shader_includes
] = strndup(shader_string
, path_name_len
);
1512 num_shader_includes
++;
1513 assert(num_shader_includes
<= 256);
1515 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
1516 fprintf(stderr
, "glNamedStringARB error\n");
1523 case shader_include_paths
: {
1524 num_shader_include_paths
= 0;
1525 const char *cursor
= shader_string
;
1527 const char *line_start
= cursor
;
1528 cursor
= strchr(cursor
, '\n');
1530 if (cursor
== line_start
) {
1536 num_shader_include_paths
++;
1537 } while (cursor
&& cursor
< line
);
1539 shader_include_path
= calloc(num_shader_include_paths
, sizeof(char *));
1541 cursor
= shader_string
;
1542 for (unsigned i
= 0; i
< num_shader_include_paths
; i
++) {
1543 char *line_end
= strchr(cursor
, '\n');
1544 unsigned path_len
= line_end
- cursor
- 1;
1545 char *path
= malloc(path_len
+ 1);
1546 path
[path_len
] = '\0';
1548 memcpy(path
, cursor
, path_len
);
1549 shader_include_path
[i
] = path
;
1550 cursor
= line_end
+ 1;
1560 assert(!"Not yet supported.");
1566 static enum piglit_result
1567 process_shader(GLenum target
, unsigned num_shaders
, GLuint
*shaders
)
1569 if (num_shaders
== 0)
1573 prog
= glCreateProgram();
1574 glProgramParameteri(prog
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
1577 for (unsigned i
= 0; i
< num_shaders
; i
++) {
1578 glAttachShader(prog
, shaders
[i
]);
1581 #ifdef PIGLIT_USE_OPENGL
1582 if (geometry_layout_input_type
!= GL_TRIANGLES
) {
1583 glProgramParameteriARB(prog
, GL_GEOMETRY_INPUT_TYPE_ARB
,
1584 geometry_layout_input_type
);
1586 if (geometry_layout_output_type
!= GL_TRIANGLE_STRIP
) {
1587 glProgramParameteriARB(prog
, GL_GEOMETRY_OUTPUT_TYPE_ARB
,
1588 geometry_layout_output_type
);
1590 if (geometry_layout_vertices_out
!= 0) {
1591 glProgramParameteriARB(prog
, GL_GEOMETRY_VERTICES_OUT_ARB
,
1592 geometry_layout_vertices_out
);
1596 /* If the shaders reference piglit_vertex or piglit_tex, bind
1597 * them to some fixed attribute locations so they can be used
1598 * with piglit_draw_rect_tex() in GLES.
1600 glBindAttribLocation(prog
, PIGLIT_ATTRIB_POS
, "piglit_vertex");
1601 glBindAttribLocation(prog
, PIGLIT_ATTRIB_TEX
, "piglit_texcoord");
1604 return link_sso(target
);
1610 static enum piglit_result
1611 link_and_use_shaders(void)
1613 enum piglit_result result
;
1618 if ((num_vertex_shaders
== 0)
1619 && (num_fragment_shaders
== 0)
1620 && (num_tess_ctrl_shaders
== 0)
1621 && (num_tess_eval_shaders
== 0)
1622 && (num_geometry_shaders
== 0)
1623 && (num_compute_shaders
== 0))
1627 prog
= glCreateProgram();
1629 result
= process_shader(GL_VERTEX_SHADER
, num_vertex_shaders
, vertex_shaders
);
1630 if (result
!= PIGLIT_PASS
)
1632 result
= process_shader(GL_TESS_CONTROL_SHADER
, num_tess_ctrl_shaders
, tess_ctrl_shaders
);
1633 if (result
!= PIGLIT_PASS
)
1635 result
= process_shader(GL_TESS_EVALUATION_SHADER
, num_tess_eval_shaders
, tess_eval_shaders
);
1636 if (result
!= PIGLIT_PASS
)
1638 result
= process_shader(GL_GEOMETRY_SHADER
, num_geometry_shaders
, geometry_shaders
);
1639 if (result
!= PIGLIT_PASS
)
1641 result
= process_shader(GL_FRAGMENT_SHADER
, num_fragment_shaders
, fragment_shaders
);
1642 if (result
!= PIGLIT_PASS
)
1644 result
= process_shader(GL_COMPUTE_SHADER
, num_compute_shaders
, compute_shaders
);
1645 if (result
!= PIGLIT_PASS
)
1649 if (separable_program
)
1650 glProgramParameteri(prog
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
1652 glLinkProgram(prog
);
1656 if (!program_binary_save_restore(false))
1658 glGetProgramiv(prog
, GL_LINK_STATUS
, &ok
);
1664 glGetProgramiv(prog
, GL_INFO_LOG_LENGTH
, &size
);
1665 prog_err_info
= malloc(MAX2(size
, 1));
1666 prog_err_info
[0] = 0;
1668 glGetProgramInfoLog(prog
, size
, NULL
, prog_err_info
);
1670 result
= PIGLIT_PASS
;
1683 glGetProgramiv(prog
, GL_INFO_LOG_LENGTH
, &size
);
1684 prog_err_info
= malloc(MAX2(size
, 1));
1685 prog_err_info
[0] = 0;
1687 glGetProgramInfoLog(prog
, size
, NULL
, prog_err_info
);
1691 for (i
= 0; i
< num_vertex_shaders
; i
++) {
1692 glDeleteShader(vertex_shaders
[i
]);
1694 num_vertex_shaders
= 0;
1696 for (i
= 0; i
< num_tess_ctrl_shaders
; i
++) {
1697 glDeleteShader(tess_ctrl_shaders
[i
]);
1699 num_tess_ctrl_shaders
= 0;
1701 for (i
= 0; i
< num_tess_eval_shaders
; i
++) {
1702 glDeleteShader(tess_eval_shaders
[i
]);
1704 num_tess_eval_shaders
= 0;
1706 for (i
= 0; i
< num_geometry_shaders
; i
++) {
1707 glDeleteShader(geometry_shaders
[i
]);
1709 num_geometry_shaders
= 0;
1711 for (i
= 0; i
< num_fragment_shaders
; i
++) {
1712 glDeleteShader(fragment_shaders
[i
]);
1714 num_fragment_shaders
= 0;
1716 for (i
= 0; i
< num_compute_shaders
; i
++) {
1717 glDeleteShader(compute_shaders
[i
]);
1719 num_compute_shaders
= 0;
1724 static enum piglit_result
1725 process_specialization(enum states state
, const char *line
)
1727 const char *end
= strchrnul(line
, '\n');
1729 enum { TYPE_FLOAT
, TYPE_UINT
} type
;
1731 while (line
< end
&& isspace(*line
))
1734 if (line
>= end
|| *line
== '#')
1737 if (parse_str(line
, "uint", &next
))
1739 else if (parse_str(line
, "float", &next
))
1744 struct specialization_list
*list
;
1747 case vertex_shader_specializations
:
1748 list
= specializations
+ 0;
1750 case tess_ctrl_shader_specializations
:
1751 list
= specializations
+ 1;
1753 case tess_eval_shader_specializations
:
1754 list
= specializations
+ 2;
1756 case geometry_shader_specializations
:
1757 list
= specializations
+ 3;
1759 case fragment_shader_specializations
:
1760 list
= specializations
+ 4;
1762 case compute_shader_specializations
:
1763 list
= specializations
+ 5;
1766 assert(!"Should not get here.");
1769 if (list
->n_entries
>= list
->buffer_size
) {
1770 if (list
->buffer_size
== 0)
1771 list
->buffer_size
= 1;
1773 list
->buffer_size
*= 2;
1774 list
->indices
= realloc(list
->indices
,
1775 (sizeof list
->indices
[0]) *
1777 list
->values
= realloc(list
->values
,
1778 (sizeof list
->values
[0]) *
1782 if (parse_uints(next
, list
->indices
+ list
->n_entries
, 1, &next
) != 1)
1787 if (parse_uints(next
,
1788 &list
->values
[list
->n_entries
].u
,
1794 if (parse_floats(next
,
1795 &list
->values
[list
->n_entries
].f
,
1807 fprintf(stderr
, "Invalid specialization line\n");
1811 static enum piglit_result
1812 process_test_script(const char *script_name
)
1816 char *text
= piglit_load_text_file(script_name
, &text_size
);
1817 enum states state
= none
;
1818 const char *line
= text
;
1819 enum piglit_result result
;
1822 printf("could not read file \"%s\"\n", script_name
);
1828 while (line
[0] != '\0') {
1829 if (line
[0] == '[') {
1830 result
= leave_state(state
, line
, script_name
);
1831 if (result
!= PIGLIT_PASS
)
1834 if (parse_str(line
, "[require]", NULL
)) {
1835 state
= requirements
;
1836 } else if (parse_str(line
, "[vertex shader]", NULL
)) {
1837 state
= vertex_shader
;
1838 shader_string
= NULL
;
1839 } else if (parse_str(line
, "[vertex program]", NULL
)) {
1840 state
= vertex_program
;
1841 shader_string
= NULL
;
1842 } else if (parse_str(line
, "[vertex shader passthrough]", NULL
)) {
1843 state
= vertex_shader_passthrough
;
1845 (char *) passthrough_vertex_shader_source
;
1846 shader_string_size
= strlen(shader_string
);
1847 } else if (parse_str(line
, "[vertex shader spirv]", NULL
)) {
1848 state
= vertex_shader_spirv
;
1849 shader_string
= NULL
;
1850 } else if (parse_str(line
, "[vertex shader specializations]", NULL
)) {
1851 state
= vertex_shader_specializations
;
1852 } else if (parse_str(line
, "[tessellation control shader]", NULL
)) {
1853 state
= tess_ctrl_shader
;
1854 shader_string
= NULL
;
1855 } else if (parse_str(line
, "[tessellation control shader spirv]", NULL
)) {
1856 state
= tess_ctrl_shader_spirv
;
1857 shader_string
= NULL
;
1858 } else if (parse_str(line
, "[tessellation control shader specializations]", NULL
)) {
1859 state
= tess_ctrl_shader_specializations
;
1860 } else if (parse_str(line
, "[tessellation evaluation shader]", NULL
)) {
1861 state
= tess_eval_shader
;
1862 shader_string
= NULL
;
1863 } else if (parse_str(line
, "[tessellation evaluation shader spirv]", NULL
)) {
1864 state
= tess_eval_shader_spirv
;
1865 shader_string
= NULL
;
1866 } else if (parse_str(line
, "[tessellation evaluation shader specializations]", NULL
)) {
1867 state
= tess_eval_shader_specializations
;
1868 } else if (parse_str(line
, "[geometry shader]", NULL
)) {
1869 state
= geometry_shader
;
1870 shader_string
= NULL
;
1871 } else if (parse_str(line
, "[geometry shader specializations]", NULL
)) {
1872 state
= geometry_shader_specializations
;
1873 } else if (parse_str(line
, "[geometry shader spirv]", NULL
)) {
1874 state
= geometry_shader_spirv
;
1875 shader_string
= NULL
;
1876 } else if (parse_str(line
, "[geometry shader specializations]", NULL
)) {
1877 state
= geometry_shader_specializations
;
1878 } else if (parse_str(line
, "[geometry layout]", NULL
)) {
1879 state
= geometry_layout
;
1880 shader_string
= NULL
;
1881 } else if (parse_str(line
, "[fragment shader]", NULL
)) {
1882 state
= fragment_shader
;
1883 shader_string
= NULL
;
1884 } else if (parse_str(line
, "[fragment program]", NULL
)) {
1885 state
= fragment_program
;
1886 shader_string
= NULL
;
1887 } else if (parse_str(line
, "[fragment shader specializations]", NULL
)) {
1888 state
= fragment_shader_specializations
;
1889 } else if (parse_str(line
, "[fragment shader spirv]", NULL
)) {
1890 state
= fragment_shader_spirv
;
1891 shader_string
= NULL
;
1892 } else if (parse_str(line
, "[fragment shader specializations]", NULL
)) {
1893 state
= fragment_shader_specializations
;
1894 } else if (parse_str(line
, "[compute shader]", NULL
)) {
1895 state
= compute_shader
;
1896 shader_string
= NULL
;
1897 } else if (parse_str(line
, "[compute shader spirv]", NULL
)) {
1898 state
= compute_shader_spirv
;
1899 shader_string
= NULL
;
1900 } else if (parse_str(line
, "[compute shader specializations]", NULL
)) {
1901 state
= compute_shader_specializations
;
1902 } else if (parse_str(line
, "[vertex data]", NULL
)) {
1903 state
= vertex_data
;
1904 vertex_data_start
= NULL
;
1905 } else if (parse_str(line
, "[shader include]", NULL
)) {
1906 state
= shader_include
;
1907 shader_string
= NULL
;
1908 } else if (parse_str(line
, "[shader include paths]", NULL
)) {
1909 state
= shader_include_paths
;
1910 shader_string
= NULL
;
1911 } else if (parse_str(line
, "[test]", NULL
)) {
1912 test_start
= strchrnul(line
, '\n');
1913 test_start_line_num
= line_num
+ 1;
1914 if (test_start
[0] != '\0')
1919 "Unknown section in test script. "
1920 "Perhaps missing closing ']'?\n");
1926 case vertex_shader_passthrough
:
1930 result
= process_requirement(line
);
1931 if (result
!= PIGLIT_PASS
)
1935 case geometry_layout
:
1936 process_geometry_layout(line
);
1940 case vertex_program
:
1941 case tess_ctrl_shader
:
1942 case tess_eval_shader
:
1943 case geometry_shader
:
1944 case fragment_shader
:
1945 case fragment_program
:
1946 case compute_shader
:
1947 case vertex_shader_spirv
:
1948 case tess_ctrl_shader_spirv
:
1949 case tess_eval_shader_spirv
:
1950 case geometry_shader_spirv
:
1951 case fragment_shader_spirv
:
1952 case compute_shader_spirv
:
1953 case shader_include
:
1954 case shader_include_paths
:
1955 if (shader_string
== NULL
)
1956 shader_string
= (char *) line
;
1959 case vertex_shader_specializations
:
1960 case tess_ctrl_shader_specializations
:
1961 case tess_eval_shader_specializations
:
1962 case geometry_shader_specializations
:
1963 case fragment_shader_specializations
:
1964 case compute_shader_specializations
: {
1965 enum piglit_result result
=
1966 process_specialization(state
, line
);
1967 if (result
!= PIGLIT_PASS
)
1973 if (vertex_data_start
== NULL
)
1974 vertex_data_start
= line
;
1982 line
= strchrnul(line
, '\n');
1983 if (line
[0] != '\0')
1989 return leave_state(state
, line
, script_name
);
1992 struct requirement_parse_results
{
1996 bool found_depthbuffer
;
1997 struct component_version gl_version
;
1998 struct component_version glsl_version
;
2003 parse_required_config(struct requirement_parse_results
*results
,
2004 const char *script_name
)
2007 char *text
= piglit_load_text_file(script_name
, &text_size
);
2008 const char *line
= text
;
2009 bool in_requirement_section
= false;
2011 results
->found_gl
= false;
2012 results
->found_glsl
= false;
2013 results
->found_size
= false;
2014 results
->found_depthbuffer
= false;
2017 printf("could not read file \"%s\"\n", script_name
);
2018 piglit_report_result(PIGLIT_FAIL
);
2021 while (line
[0] != '\0') {
2022 if (line
[0] == '[') {
2023 if (in_requirement_section
)
2026 in_requirement_section
= false;
2029 if (!in_requirement_section
) {
2030 if (parse_str(line
, "[require]", NULL
)) {
2031 in_requirement_section
= true;
2034 if (parse_str(line
, "GL_", NULL
)
2035 || parse_str(line
, "!GL_", NULL
)) {
2037 } else if (parse_str(line
, "GLSL", &line
)) {
2038 enum comparison cmp
;
2039 struct component_version version
;
2041 parse_version_comparison(line
, &cmp
,
2042 &version
, VERSION_GLSL
);
2043 if (cmp
== greater_equal
) {
2044 results
->found_glsl
= true;
2045 version_copy(&results
->glsl_version
, &version
);
2047 } else if (parse_str(line
, "GL", &line
)) {
2048 enum comparison cmp
;
2049 struct component_version version
;
2051 parse_version_comparison(line
, &cmp
,
2052 &version
, VERSION_GL
);
2053 if (cmp
== greater_equal
2056 results
->found_gl
= true;
2057 version_copy(&results
->gl_version
, &version
);
2059 } else if (parse_str(line
, "SIZE", &line
)) {
2060 results
->found_size
= true;
2061 parse_uints(line
, results
->size
, 2, NULL
);
2062 } else if (parse_str(line
, "depthbuffer", NULL
)) {
2063 results
->found_depthbuffer
= true;
2067 line
= strchrnul(line
, '\n');
2068 if (line
[0] != '\0')
2074 if (!in_requirement_section
) {
2075 printf("[require] section missing\n");
2076 piglit_report_result(PIGLIT_FAIL
);
2079 if (results
->found_glsl
&& results
->glsl_version
.es
&& !results
->found_gl
) {
2080 printf("%s", "The test specifies a requirement for GLSL ES, "
2081 "but specifies no GL requirement\n.");
2082 piglit_report_result(PIGLIT_FAIL
);
2088 choose_required_gl_version(struct requirement_parse_results
*parse_results
,
2089 struct component_version
*gl_version
)
2091 if (parse_results
->found_gl
) {
2092 version_copy(gl_version
, &parse_results
->gl_version
);
2094 assert(!parse_results
->found_glsl
|| !parse_results
->glsl_version
.es
);
2095 version_init(gl_version
, VERSION_GL
, false, false, false, 10);
2101 /* Possibly promote the GL version. */
2102 if (parse_results
->found_glsl
2103 && gl_version
->num
< required_gl_version_from_glsl_version(
2104 parse_results
->glsl_version
.num
)) {
2105 gl_version
->num
= required_gl_version_from_glsl_version(
2106 parse_results
->glsl_version
.num
);
2111 * Just determine the GLSL version required by the shader script.
2113 * This function is a bit of a hack that is, unfortunately necessary. A test
2114 * script can require a specific GLSL version or a specific GL version. To
2115 * satisfy this requirement, the piglit framework code needs to know about the
2116 * requirement before creating the context. However, the requirements section
2117 * can contain other requirements, such as minimum number of uniforms.
2119 * The requirements section can't be fully processed until after the context
2120 * is created, but the context can't be created until after the requirements
2121 * section is processed. Do a quick scan over the requirements section to find
2122 * the GL and GLSL version requirements. Use these to guide context creation.
2125 get_required_config(const char *script_name
, bool spirv
,
2126 struct piglit_gl_test_config
*config
)
2128 struct requirement_parse_results parse_results
;
2129 struct component_version required_gl_version
;
2131 parse_required_config(&parse_results
, script_name
);
2132 choose_required_gl_version(&parse_results
, &required_gl_version
);
2135 required_gl_version
.es
= false;
2136 required_gl_version
.core
= true;
2137 required_gl_version
.num
= MAX2(required_gl_version
.num
, 33);
2140 if (parse_results
.found_size
) {
2141 config
->window_width
= parse_results
.size
[0];
2142 config
->window_height
= parse_results
.size
[1];
2145 if (required_gl_version
.es
) {
2146 config
->supports_gl_es_version
= required_gl_version
.num
;
2147 } else if (required_gl_version
.num
>= 31) {
2148 if (!required_gl_version
.compat
)
2149 config
->supports_gl_core_version
= required_gl_version
.num
;
2150 if (!required_gl_version
.core
)
2151 config
->supports_gl_compat_version
= required_gl_version
.num
;
2153 config
->supports_gl_compat_version
= 10;
2156 if (parse_results
.found_depthbuffer
) {
2157 config
->window_visual
|= PIGLIT_GL_VISUAL_DEPTH
;
2162 * Check that the GL implementation supports unsigned uniforms
2163 * (e.g. through glUniform1ui). If not, terminate the test with a
2167 check_unsigned_support(void)
2169 if (gl_version
.num
< 30 && !piglit_is_extension_supported("GL_EXT_gpu_shader4"))
2170 piglit_report_result(PIGLIT_SKIP
);
2174 * Check that the GL implementation supports double uniforms
2175 * (e.g. through glUniform1d). If not, terminate the test with a
2179 check_double_support(void)
2181 if (gl_version
.num
< 40 && !piglit_is_extension_supported("GL_ARB_gpu_shader_fp64"))
2182 piglit_report_result(PIGLIT_SKIP
);
2186 * Check that the GL implementation supports double uniforms
2187 * (e.g. through glUniform1d). If not, terminate the test with a
2191 check_int64_support(void)
2193 if (!piglit_is_extension_supported("GL_ARB_gpu_shader_int64"))
2194 piglit_report_result(PIGLIT_SKIP
);
2198 * Check that the GL implementation supports shader subroutines
2199 * If not, terminate the test with a SKIP.
2202 check_shader_subroutine_support(void)
2204 if (gl_version
.num
< 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
2205 piglit_report_result(PIGLIT_SKIP
);
2209 * Check that the GL implementation supports texture handles.
2210 * If not, terminate the test with a SKIP.
2213 check_texture_handle_support(void)
2215 if (!piglit_is_extension_supported("GL_ARB_bindless_texture"))
2216 piglit_report_result(PIGLIT_SKIP
);
2220 get_indexes_and_offset_from_ubo(char *name
, struct block_info block_data
,
2221 GLuint
*uniform_index_out
,
2222 GLint
*block_index_out
,
2226 * Handles uploads of UBO uniforms by mapping the buffer and storing
2227 * the data. If the uniform is not in a uniform block, returns false.
2230 set_ubo_uniform(char *name
, const char *type
,
2232 struct block_info block_data
)
2234 /* Note: on SPIR-V we can't access to uniform_index as we
2235 * could lack the name. We force that with force_no_names on
2238 GLuint uniform_index
;
2246 uint64_t uint64s
[16];
2249 if (!get_indexes_and_offset_from_ubo(name
, block_data
, &uniform_index
,
2250 &block_index
, &offset
)) {
2254 glBindBuffer(GL_UNIFORM_BUFFER
,
2255 uniform_block_bos
[block_index
]);
2256 data
= glMapBuffer(GL_UNIFORM_BUFFER
, GL_WRITE_ONLY
);
2259 if (parse_str(type
, "float", NULL
)) {
2260 parse_floats(line
, f
, 1, NULL
);
2261 memcpy(data
, f
, sizeof(float));
2262 } else if (parse_str(type
, "int64_t", NULL
)) {
2263 parse_int64s(line
, int64s
, 1, NULL
);
2264 memcpy(data
, int64s
, sizeof(int64_t));
2265 } else if (parse_str(type
, "uint64_t", NULL
)) {
2266 parse_uint64s(line
, uint64s
, 1, NULL
);
2267 memcpy(data
, uint64s
, sizeof(uint64_t));
2268 } else if (parse_str(type
, "int", NULL
)) {
2269 parse_ints(line
, ints
, 1, NULL
);
2270 memcpy(data
, ints
, sizeof(int));
2271 } else if (parse_str(type
, "uint", NULL
)) {
2272 parse_uints(line
, uints
, 1, NULL
);
2273 memcpy(data
, uints
, sizeof(int));
2274 } else if (parse_str(type
, "double", NULL
)) {
2275 parse_doubles(line
, d
, 1, NULL
);
2276 memcpy(data
, d
, sizeof(double));
2277 } else if (parse_str(type
, "vec", NULL
)) {
2278 int elements
= type
[3] - '0';
2279 parse_floats(line
, f
, elements
, NULL
);
2280 memcpy(data
, f
, elements
* sizeof(float));
2281 } else if (parse_str(type
, "ivec", NULL
)) {
2282 int elements
= type
[4] - '0';
2283 parse_ints(line
, ints
, elements
, NULL
);
2284 memcpy(data
, ints
, elements
* sizeof(int));
2285 } else if (parse_str(type
, "uvec", NULL
)) {
2286 int elements
= type
[4] - '0';
2287 parse_uints(line
, uints
, elements
, NULL
);
2288 memcpy(data
, uints
, elements
* sizeof(unsigned));
2289 } else if (parse_str(type
, "i64vec", NULL
)) {
2290 int elements
= type
[6] - '0';
2291 parse_int64s(line
, int64s
, elements
, NULL
);
2292 memcpy(data
, int64s
, elements
* sizeof(int64_t));
2293 } else if (parse_str(type
, "u64vec", NULL
)) {
2294 int elements
= type
[6] - '0';
2295 parse_uint64s(line
, uint64s
, elements
, NULL
);
2296 memcpy(data
, uint64s
, elements
* sizeof(uint64_t));
2297 } else if (parse_str(type
, "dvec", NULL
)) {
2298 int elements
= type
[4] - '0';
2299 parse_doubles(line
, d
, elements
, NULL
);
2300 memcpy(data
, d
, elements
* sizeof(double));
2301 } else if (parse_str(type
, "mat", NULL
)) {
2302 GLint matrix_stride
, row_major
;
2303 int cols
= type
[3] - '0';
2304 int rows
= type
[4] == 'x' ? type
[5] - '0' : cols
;
2306 float *matrixdata
= (float *)data
;
2308 assert(cols
>= 2 && cols
<= 4);
2309 assert(rows
>= 2 && rows
<= 4);
2311 parse_floats(line
, f
, rows
* cols
, NULL
);
2313 if (!force_no_names
) {
2314 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2315 GL_UNIFORM_MATRIX_STRIDE
,
2317 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2318 GL_UNIFORM_IS_ROW_MAJOR
,
2321 matrix_stride
= block_data
.matrix_stride
;
2322 row_major
= block_data
.row_major
;
2325 matrix_stride
/= sizeof(float);
2327 /* Expect the data in the .shader_test file to be listed in
2328 * column-major order no matter what the layout of the data in
2331 for (c
= 0; c
< cols
; c
++) {
2332 for (r
= 0; r
< rows
; r
++) {
2334 matrixdata
[matrix_stride
* r
+ c
] =
2337 matrixdata
[matrix_stride
* c
+ r
] =
2342 } else if (parse_str(type
, "dmat", NULL
)) {
2343 GLint matrix_stride
, row_major
;
2344 int cols
= type
[4] - '0';
2345 int rows
= type
[5] == 'x' ? type
[6] - '0' : cols
;
2347 double *matrixdata
= (double *)data
;
2349 assert(cols
>= 2 && cols
<= 4);
2350 assert(rows
>= 2 && rows
<= 4);
2352 parse_doubles(line
, d
, rows
* cols
, NULL
);
2354 if (!force_no_names
) {
2355 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2356 GL_UNIFORM_MATRIX_STRIDE
,
2358 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2359 GL_UNIFORM_IS_ROW_MAJOR
,
2362 matrix_stride
= block_data
.matrix_stride
;
2363 row_major
= block_data
.row_major
;
2366 matrix_stride
/= sizeof(double);
2368 /* Expect the data in the .shader_test file to be listed in
2369 * column-major order no matter what the layout of the data in
2372 for (c
= 0; c
< cols
; c
++) {
2373 for (r
= 0; r
< rows
; r
++) {
2375 matrixdata
[matrix_stride
* r
+ c
] =
2378 matrixdata
[matrix_stride
* c
+ r
] =
2383 } else if (parse_str(type
, "handle", NULL
)) {
2384 check_unsigned_support();
2385 check_texture_handle_support();
2386 parse_uints(line
, uints
, 1, NULL
);
2387 GLuint64 handle
= get_resident_handle(uints
[0])->handle
;
2388 memcpy(data
, &handle
, sizeof(uint64_t));
2390 printf("unknown uniform type \"%s\" for \"%s\"\n", type
, name
);
2391 piglit_report_result(PIGLIT_FAIL
);
2394 glUnmapBuffer(GL_UNIFORM_BUFFER
);
2400 * Get the uniform_index, block_index and offset of a given
2401 * uniform. By default it gets those values using the uniform name. If
2402 * force_no_names mode is active, it uses the current values stored at
2403 * @block_data. On the latter, uniform index is not filled up.
2406 get_indexes_and_offset_from_ubo(char *name
, struct block_info block_data
,
2407 GLuint
*uniform_index_out
,
2408 GLint
*block_index_out
,
2411 GLuint uniform_index
= 0;
2414 int name_len
= strlen(name
);
2415 GLint array_index
= 0;
2417 if (!num_uniform_blocks
)
2420 if (!force_no_names
) {
2421 /* if the uniform is an array, strip the index, as GL
2422 prevents non-zero indexes from matching a name */
2423 if (name
[name_len
- 1] == ']') {
2426 for (i
= name_len
- 1; (i
> 0) && isdigit(name
[i
-1]); --i
)
2429 array_index
= strtol(&name
[i
], NULL
, 0);
2433 if (name
[i
] != '[') {
2434 printf("cannot parse uniform \"%s\"\n", name
);
2435 piglit_report_result(PIGLIT_FAIL
);
2442 glGetUniformIndices(prog
, 1, (const char **)&name
, &uniform_index
);
2443 if (uniform_index
== GL_INVALID_INDEX
) {
2444 printf("cannot get index of uniform \"%s\"\n", name
);
2445 piglit_report_result(PIGLIT_FAIL
);
2448 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2449 GL_UNIFORM_BLOCK_INDEX
, &block_index
);
2451 if (block_index
== -1)
2455 glGetActiveUniformsiv(prog
, 1, &uniform_index
, GL_UNIFORM_SIZE
, &array_size
);
2457 if (array_index
> array_size
) {
2458 printf("attempt to access beyond uniform \"%s\" array size (%d)\n",
2463 /* if the uniform block is an array, then GetActiveUniformsiv with
2464 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2465 * element in the array.
2467 block_index
+= block_data
.array_index
;
2469 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2470 GL_UNIFORM_OFFSET
, &offset
);
2472 if (name
[name_len
- 1] == ']') {
2475 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2476 GL_UNIFORM_ARRAY_STRIDE
, &stride
);
2477 offset
+= stride
* array_index
;
2480 if (block_data
.binding
< 0) {
2481 printf("if you force to use a explicit ubo binding, you "
2482 "need to provide it when filling the data with "
2483 "\"ubo binding\"\n");
2484 piglit_report_result(PIGLIT_FAIL
);
2487 /* The mapping could be improved using a hash
2488 * table. For now, this is enough.
2490 block_index
= uniform_block_indexes
[block_data
.binding
];
2492 /* if the uniform block is an array, then GetActiveUniformsiv with
2493 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2494 * element in the array.
2496 block_index
+= block_data
.array_index
;
2498 if (block_data
.offset
< 0) {
2499 printf("if you force to use a explicit ubo binding, you "
2500 "need to provide offset when filling the data with "
2501 "\"ubo offset\"\n");
2502 piglit_report_result(PIGLIT_FAIL
);
2504 offset
= block_data
.offset
;
2507 *offset_out
= offset
;
2508 *block_index_out
= block_index
;
2509 *uniform_index_out
= uniform_index
;
2515 set_uniform(const char *line
, struct block_info block_data
)
2517 char name
[512], type
[512];
2523 uint64_t uint64s
[16];
2526 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2527 parse_word_copy(line
, name
, sizeof(name
), &line
),
2528 "Invalid set uniform command at: %s\n", line
);
2530 if (isdigit(name
[0])) {
2531 loc
= strtol(name
, NULL
, 0);
2535 if (set_ubo_uniform(name
, type
, line
, block_data
))
2538 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2539 loc
= glGetUniformLocation(prog
, name
);
2541 if (ignore_missing_uniforms
)
2543 printf("cannot get location of uniform \"%s\"\n",
2545 piglit_report_result(PIGLIT_FAIL
);
2549 if (parse_str(type
, "float", NULL
)) {
2550 parse_floats(line
, f
, 1, NULL
);
2551 glUniform1fv(loc
, 1, f
);
2553 } else if (parse_str(type
, "int64_t", NULL
)) {
2554 check_int64_support();
2555 parse_int64s(line
, int64s
, 1, NULL
);
2556 glUniform1i64vARB(loc
, 1, int64s
);
2558 } else if (parse_str(type
, "uint64_t", NULL
)) {
2559 check_int64_support();
2560 parse_uint64s(line
, uint64s
, 1, NULL
);
2561 glUniform1ui64vARB(loc
, 1, uint64s
);
2563 } else if (parse_str(type
, "int", NULL
)) {
2564 parse_ints(line
, ints
, 1, NULL
);
2565 glUniform1iv(loc
, 1, ints
);
2567 } else if (parse_str(type
, "uint", NULL
)) {
2568 check_unsigned_support();
2569 parse_uints(line
, uints
, 1, NULL
);
2570 glUniform1uiv(loc
, 1, uints
);
2572 } else if (parse_str(type
, "double", NULL
)) {
2573 check_double_support();
2574 parse_doubles(line
, d
, 1, NULL
);
2575 glUniform1dv(loc
, 1, d
);
2577 } else if (parse_str(type
, "vec", NULL
)) {
2580 parse_floats(line
, f
, 2, NULL
);
2581 glUniform2fv(loc
, 1, f
);
2584 parse_floats(line
, f
, 3, NULL
);
2585 glUniform3fv(loc
, 1, f
);
2588 parse_floats(line
, f
, 4, NULL
);
2589 glUniform4fv(loc
, 1, f
);
2592 } else if (parse_str(type
, "ivec", NULL
)) {
2595 parse_ints(line
, ints
, 2, NULL
);
2596 glUniform2iv(loc
, 1, ints
);
2599 parse_ints(line
, ints
, 3, NULL
);
2600 glUniform3iv(loc
, 1, ints
);
2603 parse_ints(line
, ints
, 4, NULL
);
2604 glUniform4iv(loc
, 1, ints
);
2607 } else if (parse_str(type
, "uvec", NULL
)) {
2608 check_unsigned_support();
2611 parse_uints(line
, uints
, 2, NULL
);
2612 glUniform2uiv(loc
, 1, uints
);
2615 parse_uints(line
, uints
, 3, NULL
);
2616 glUniform3uiv(loc
, 1, uints
);
2619 parse_uints(line
, uints
, 4, NULL
);
2620 glUniform4uiv(loc
, 1, uints
);
2623 } else if (parse_str(type
, "dvec", NULL
)) {
2624 check_double_support();
2627 parse_doubles(line
, d
, 2, NULL
);
2628 glUniform2dv(loc
, 1, d
);
2631 parse_doubles(line
, d
, 3, NULL
);
2632 glUniform3dv(loc
, 1, d
);
2635 parse_doubles(line
, d
, 4, NULL
);
2636 glUniform4dv(loc
, 1, d
);
2639 } else if (parse_str(type
, "i64vec", NULL
)) {
2640 check_int64_support();
2643 parse_int64s(line
, int64s
, 2, NULL
);
2644 glUniform2i64vARB(loc
, 1, int64s
);
2647 parse_int64s(line
, int64s
, 3, NULL
);
2648 glUniform3i64vARB(loc
, 1, int64s
);
2651 parse_int64s(line
, int64s
, 4, NULL
);
2652 glUniform4i64vARB(loc
, 1, int64s
);
2655 } else if (parse_str(type
, "u64vec", NULL
)) {
2656 check_int64_support();
2659 parse_uint64s(line
, uint64s
, 2, NULL
);
2660 glUniform2ui64vARB(loc
, 1, uint64s
);
2663 parse_uint64s(line
, uint64s
, 3, NULL
);
2664 glUniform3ui64vARB(loc
, 1, uint64s
);
2667 parse_uint64s(line
, uint64s
, 4, NULL
);
2668 glUniform4ui64vARB(loc
, 1, uint64s
);
2671 } else if (parse_str(type
, "mat", NULL
) && type
[3] != '\0') {
2672 char cols
= type
[3];
2673 char rows
= type
[4] == 'x' ? type
[5] : cols
;
2678 parse_floats(line
, f
, 4, NULL
);
2679 glUniformMatrix2fv(loc
, 1, GL_FALSE
, f
);
2682 parse_floats(line
, f
, 6, NULL
);
2683 glUniformMatrix2x3fv(loc
, 1, GL_FALSE
, f
);
2686 parse_floats(line
, f
, 8, NULL
);
2687 glUniformMatrix2x4fv(loc
, 1, GL_FALSE
, f
);
2693 parse_floats(line
, f
, 6, NULL
);
2694 glUniformMatrix3x2fv(loc
, 1, GL_FALSE
, f
);
2697 parse_floats(line
, f
, 9, NULL
);
2698 glUniformMatrix3fv(loc
, 1, GL_FALSE
, f
);
2701 parse_floats(line
, f
, 12, NULL
);
2702 glUniformMatrix3x4fv(loc
, 1, GL_FALSE
, f
);
2708 parse_floats(line
, f
, 8, NULL
);
2709 glUniformMatrix4x2fv(loc
, 1, GL_FALSE
, f
);
2712 parse_floats(line
, f
, 12, NULL
);
2713 glUniformMatrix4x3fv(loc
, 1, GL_FALSE
, f
);
2716 parse_floats(line
, f
, 16, NULL
);
2717 glUniformMatrix4fv(loc
, 1, GL_FALSE
, f
);
2721 } else if (parse_str(type
, "dmat", NULL
) && type
[4] != '\0') {
2722 char cols
= type
[4];
2723 char rows
= type
[5] == 'x' ? type
[6] : cols
;
2728 parse_doubles(line
, d
, 4, NULL
);
2729 glUniformMatrix2dv(loc
, 1, GL_FALSE
, d
);
2732 parse_doubles(line
, d
, 6, NULL
);
2733 glUniformMatrix2x3dv(loc
, 1, GL_FALSE
, d
);
2736 parse_doubles(line
, d
, 8, NULL
);
2737 glUniformMatrix2x4dv(loc
, 1, GL_FALSE
, d
);
2743 parse_doubles(line
, d
, 6, NULL
);
2744 glUniformMatrix3x2dv(loc
, 1, GL_FALSE
, d
);
2747 parse_doubles(line
, d
, 9, NULL
);
2748 glUniformMatrix3dv(loc
, 1, GL_FALSE
, d
);
2751 parse_doubles(line
, d
, 12, NULL
);
2752 glUniformMatrix3x4dv(loc
, 1, GL_FALSE
, d
);
2758 parse_doubles(line
, d
, 8, NULL
);
2759 glUniformMatrix4x2dv(loc
, 1, GL_FALSE
, d
);
2762 parse_doubles(line
, d
, 12, NULL
);
2763 glUniformMatrix4x3dv(loc
, 1, GL_FALSE
, d
);
2766 parse_doubles(line
, d
, 16, NULL
);
2767 glUniformMatrix4dv(loc
, 1, GL_FALSE
, d
);
2771 } else if (parse_str(type
, "handle", NULL
)) {
2772 check_unsigned_support();
2773 check_texture_handle_support();
2774 parse_uints(line
, uints
, 1, NULL
);
2775 glUniformHandleui64ARB(loc
, get_resident_handle(uints
[0])->handle
);
2779 printf("unknown uniform type \"%s\"\n", type
);
2780 piglit_report_result(PIGLIT_FAIL
);
2786 set_vertex_attrib(const char *line
)
2788 char name
[512], type
[512];
2792 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2793 parse_word_copy(line
, name
, sizeof(name
), &line
),
2794 "Invalid set vertex attrib command at: %s\n", line
);
2796 if (isdigit(name
[0])) {
2797 loc
= strtol(name
, NULL
, 0);
2801 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2802 loc
= glGetAttribLocation(prog
, name
);
2804 if (ignore_missing_uniforms
)
2806 printf("cannot get location of vertex attrib \"%s\"\n",
2808 piglit_report_result(PIGLIT_FAIL
);
2812 if (parse_str(type
, "handle", NULL
)) {
2813 check_unsigned_support();
2814 check_texture_handle_support();
2815 parse_uints(line
, uints
, 1, NULL
);
2816 glVertexAttribL1ui64ARB(loc
, get_resident_handle(uints
[0])->handle
);
2820 printf("unknown vertex attrib type \"%s\"\n", type
);
2821 printf("use [vertex data] instead if possible\n");
2822 piglit_report_result(PIGLIT_FAIL
);
2827 static GLenum
lookup_shader_type(GLuint idx
)
2831 return GL_VERTEX_SHADER
;
2833 return GL_FRAGMENT_SHADER
;
2835 return GL_GEOMETRY_SHADER
;
2837 return GL_TESS_CONTROL_SHADER
;
2839 return GL_TESS_EVALUATION_SHADER
;
2841 return GL_COMPUTE_SHADER
;
2847 static GLenum
get_shader_from_string(const char *name
, int *idx
)
2849 if (parse_str(name
, "GL_VERTEX_SHADER", NULL
)) {
2851 return GL_VERTEX_SHADER
;
2853 if (parse_str(name
, "GL_FRAGMENT_SHADER", NULL
)) {
2855 return GL_FRAGMENT_SHADER
;
2857 if (parse_str(name
, "GL_GEOMETRY_SHADER", NULL
)) {
2859 return GL_GEOMETRY_SHADER
;
2861 if (parse_str(name
, "GL_TESS_CONTROL_SHADER", NULL
)) {
2863 return GL_TESS_CONTROL_SHADER
;
2865 if (parse_str(name
, "GL_TESS_EVALUATION_SHADER", NULL
)) {
2867 return GL_TESS_EVALUATION_SHADER
;
2869 if (parse_str(name
, "GL_COMPUTE_SHADER", NULL
)) {
2871 return GL_COMPUTE_SHADER
;
2877 free_subroutine_uniforms(void)
2880 for (sidx
= 0; sidx
< 4; sidx
++) {
2881 free(subuniform_locations
[sidx
]);
2882 subuniform_locations
[sidx
] = NULL
;
2887 program_subroutine_uniforms(void)
2892 for (sidx
= 0; sidx
< 4; sidx
++) {
2894 if (num_subuniform_locations
[sidx
] == 0)
2897 stype
= lookup_shader_type(sidx
);
2901 glUniformSubroutinesuiv(stype
, num_subuniform_locations
[sidx
], subuniform_locations
[sidx
]);
2906 set_subroutine_uniform(const char *line
)
2917 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2918 parse_word_copy(line
, name
, sizeof(name
), &line
) &&
2919 parse_word_copy(line
, subname
, sizeof(subname
), &line
),
2920 "Invalid set subroutine uniform command at: %s\n", line
);
2922 ptype
= get_shader_from_string(type
, &sidx
);
2924 printf("illegal type in subroutine uniform\n");
2925 piglit_report_result(PIGLIT_FAIL
);
2928 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2930 if (num_subuniform_locations
[sidx
] == 0) {
2931 glGetProgramStageiv(prog
, ptype
, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS
,
2932 &num_subuniform_locations
[sidx
]);
2934 if (num_subuniform_locations
[sidx
] == 0) {
2935 printf("illegal subroutine uniform specified\n");
2936 piglit_report_result(PIGLIT_FAIL
);
2939 subuniform_locations
[sidx
] = calloc(num_subuniform_locations
[sidx
], sizeof(GLuint
));
2940 if (!subuniform_locations
[sidx
])
2941 piglit_report_result(PIGLIT_FAIL
);
2944 loc
= glGetSubroutineUniformLocation(prog
, ptype
, name
);
2946 if (ignore_missing_uniforms
)
2948 printf("cannot get location of subroutine uniform \"%s\"\n",
2950 piglit_report_result(PIGLIT_FAIL
);
2953 idx
= glGetSubroutineIndex(prog
, ptype
, subname
);
2954 if (idx
== GL_INVALID_INDEX
) {
2955 printf("cannot get index of subroutine uniform \"%s\"\n",
2957 piglit_report_result(PIGLIT_FAIL
);
2960 subuniform_locations
[sidx
][loc
] = idx
;
2965 * Query values from current program using glGetProgram.
2967 * Format of the command:
2968 * verify program_query GL_PNAME_ENUM integer
2972 * verify program_query GL_PNAME_ENUM <enum>
2974 * Note: GL_COMPUTE_WORK_GROUP_SIZE is not supported, as is the only
2975 * query that requires a params with more than one component, and we
2976 * want to keep things simple.
2980 verify_program_query(const char *line
)
2982 static const struct string_to_enum all_pnames
[] = {
2983 ENUM_STRING(GL_DELETE_STATUS
),
2984 ENUM_STRING(GL_LINK_STATUS
),
2985 ENUM_STRING(GL_VALIDATE_STATUS
),
2986 ENUM_STRING(GL_INFO_LOG_LENGTH
),
2987 ENUM_STRING(GL_ATTACHED_SHADERS
),
2988 ENUM_STRING(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS
),
2989 ENUM_STRING(GL_ACTIVE_ATTRIBUTES
),
2990 ENUM_STRING(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
),
2991 ENUM_STRING(GL_ACTIVE_UNIFORMS
),
2992 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCKS
),
2993 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
),
2994 ENUM_STRING(GL_ACTIVE_UNIFORM_MAX_LENGTH
),
2995 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE
),
2996 ENUM_STRING(GL_PROGRAM_BINARY_LENGTH
),
2997 ENUM_STRING(GL_TRANSFORM_FEEDBACK_BUFFER_MODE
),
2998 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYINGS
),
2999 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
),
3000 ENUM_STRING(GL_GEOMETRY_VERTICES_OUT
),
3001 ENUM_STRING(GL_GEOMETRY_INPUT_TYPE
),
3002 ENUM_STRING(GL_GEOMETRY_OUTPUT_TYPE
),
3006 static const struct string_to_enum all_possible_param_enums
[] = {
3007 ENUM_STRING(GL_TRUE
),
3008 ENUM_STRING(GL_FALSE
),
3009 ENUM_STRING(GL_SEPARATE_ATTRIBS
),
3010 ENUM_STRING(GL_INTERLEAVED_ATTRIBS
),
3011 ENUM_STRING(GL_POINTS
),
3012 ENUM_STRING(GL_LINES
),
3013 ENUM_STRING(GL_LINES_ADJACENCY
),
3014 ENUM_STRING(GL_TRIANGLES
),
3015 ENUM_STRING(GL_TRIANGLES_ADJACENCY
),
3016 ENUM_STRING(GL_LINE_STRIP
),
3017 ENUM_STRING(GL_TRIANGLE_STRIP
),
3018 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE
),
3026 REQUIRE(parse_enum_tab(all_pnames
, line
,
3028 "Bad glGetProgram pname at: %s\n", line
);
3030 REQUIRE(parse_enum_tab(all_possible_param_enums
, line
, (unsigned *)&expected
, &line
) ||
3031 parse_int(line
, &expected
, &line
),
3032 "Bad expected value at: %s\n", line
);
3034 if (pname
== GL_COMPUTE_WORK_GROUP_SIZE
) {
3035 /* TODO: eventually it would be good to add support for
3036 * this parameter. What it makes different to the rest is
3037 * that it requires a param with more than one component
3039 fprintf(stderr
, "glGetProgram queries with GL_COMPUTE_WORK_GROUP_SIZE "
3040 "not supported yet\n");
3041 piglit_report_result(PIGLIT_FAIL
);
3044 glGetProgramiv(prog
, pname
, &value
);
3046 if (expected
!= value
) {
3047 fprintf(stderr
, "glGetProgram(%s): expected %d, got %d\n",
3048 piglit_get_gl_enum_name(pname
), expected
, value
);
3049 piglit_report_result(PIGLIT_FAIL
);
3054 * Query a uniform using glGetActiveUniformsiv
3056 * Format of the command:
3058 * active uniform uniform_name GL_PNAME_ENUM integer
3062 * active uniform uniform_name GL_PNAME_ENUM GL_TYPE_ENUM
3065 active_uniform(const char *line
)
3067 static const struct string_to_enum all_pnames
[] = {
3068 ENUM_STRING(GL_UNIFORM_TYPE
),
3069 ENUM_STRING(GL_UNIFORM_SIZE
),
3070 ENUM_STRING(GL_UNIFORM_NAME_LENGTH
),
3071 ENUM_STRING(GL_UNIFORM_BLOCK_INDEX
),
3072 ENUM_STRING(GL_UNIFORM_OFFSET
),
3073 ENUM_STRING(GL_UNIFORM_ARRAY_STRIDE
),
3074 ENUM_STRING(GL_UNIFORM_MATRIX_STRIDE
),
3075 ENUM_STRING(GL_UNIFORM_IS_ROW_MAJOR
),
3076 ENUM_STRING(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX
),
3080 const char *rest
= line
;
3086 int num_active_uniforms
;
3088 REQUIRE(parse_word_copy(rest
, name
, sizeof(name
), &rest
),
3089 "Bad uniform name at: %s\n", line
);
3091 REQUIRE(parse_enum_tab(all_pnames
, rest
, &pname
, &rest
),
3092 "Bad glGetUniformsiv pname at: %s\n", line
);
3094 REQUIRE(parse_enum_tab(all_types
, rest
, (unsigned *)&expected
, &rest
) ||
3095 parse_int(rest
, &expected
, &rest
),
3096 "Bad expected value at: %s\n", line
);
3098 glGetProgramiv(prog
, GL_ACTIVE_UNIFORMS
, &num_active_uniforms
);
3099 for (i
= 0; i
< num_active_uniforms
; i
++) {
3106 glGetActiveUniform(prog
, i
, sizeof(name_buf
), &name_len
,
3107 &size
, &type
, name_buf
);
3109 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3110 fprintf(stderr
, "glGetActiveUniform error\n");
3111 piglit_report_result(PIGLIT_FAIL
);
3114 if (strcmp(name
, name_buf
) != 0)
3117 /* If the requested pname is one of the values that
3118 * glGetActiveUniform happens to return, check the value
3119 * returned by that function too.
3122 case GL_UNIFORM_TYPE
:
3126 case GL_UNIFORM_SIZE
:
3130 case GL_UNIFORM_NAME_LENGTH
:
3135 /* This ensures the check below will pass when the
3136 * requested enum is not one of the values already
3137 * returned by glGetActiveUniform.
3143 if (got
!= expected
) {
3145 "glGetActiveUniform(%s, %s): "
3146 "expected %d (0x%04x), got %d (0x%04x)\n",
3147 name
, piglit_get_gl_enum_name(pname
),
3148 expected
, expected
, got
, got
);
3152 /* Set 'got' to some value in case glGetActiveUniformsiv
3153 * doesn't write to it. That should only be able to occur
3154 * when the function raises a GL error, but "should" is kind
3158 glGetActiveUniformsiv(prog
, 1, (GLuint
*) &i
, pname
, &got
);
3160 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3161 fprintf(stderr
, "glGetActiveUniformsiv error\n");
3162 piglit_report_result(PIGLIT_FAIL
);
3165 if (got
!= expected
) {
3167 "glGetActiveUniformsiv(%s, %s): "
3168 "expected %d, got %d\n",
3169 name
, piglit_get_gl_enum_name(pname
),
3175 piglit_report_result(PIGLIT_FAIL
);
3180 fprintf(stderr
, "No active uniform named \"%s\"\n", name
);
3181 piglit_report_result(PIGLIT_FAIL
);
3187 * Confirms if @resource_index is a given resource, within @interface_type.
3189 * In order to identify it, it uses by default @resource_name. If
3190 * force_no_names mode is activated it uses the binding contained at
3191 * @block_data. Note that for the latter, only ubos or ssbos are
3192 * supported as @interface_type.
3194 * @resource_name_buf, @prop and @value_expected are only used for
3195 * some extra checks.
3197 * Return true if @resource_index is the resource within
3198 * @interface_type we search for. false otherwise.
3201 confirm_program_resource(GLenum interface_type
, GLuint resource_index
,
3202 const char *resource_name
, char *resource_name_buf
,
3203 struct block_info block_data
, unsigned prop
,
3206 if (!force_no_names
) {
3207 GLsizei resource_name_len
;
3209 glGetProgramResourceName(prog
, interface_type
, resource_index
,
3210 512, &resource_name_len
,
3213 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3214 fprintf(stderr
, "glGetProgramResourceName error\n");
3215 piglit_report_result(PIGLIT_FAIL
);
3218 if (strcmp(resource_name
, resource_name_buf
) != 0)
3221 /* glGetProgramResourceName does not consider the NULL
3222 * terminator when returning the name length, however,
3223 * glGetProgramResourceiv does. We take that into account
3224 * when doing the comparison.
3226 if (prop
== GL_NAME_LENGTH
&&
3227 resource_name_len
!= (value_expected
- 1)) {
3229 "glGetProgramResourceName(%s, %s, %s): "
3230 "expected length: %d (0x%04x), "
3231 "got length: %d (0x%04x)\n",
3232 piglit_get_gl_enum_name(interface_type
),
3233 resource_name
, piglit_get_gl_enum_name(prop
),
3234 value_expected
- 1, value_expected
- 1,
3235 resource_name_len
, resource_name_len
);
3236 piglit_report_result(PIGLIT_FAIL
);
3239 unsigned binding_prop
= GL_BUFFER_BINDING
;
3240 int current_binding
= 0;
3243 if (interface_type
!= GL_SHADER_STORAGE_BLOCK
&&
3244 interface_type
!= GL_UNIFORM_BLOCK
) {
3246 "active_program_interface queries under force_no_names "
3247 "mode are only supported for GL_SHADER_STORAGE_BLOCK "
3248 "or GL_UNIFORM_BLOCK interfaces\n");
3249 piglit_report_result(PIGLIT_FAIL
);
3252 glGetProgramResourceiv(prog
, interface_type
,
3253 resource_index
, 1, &binding_prop
, 1,
3254 &length
, ¤t_binding
);
3255 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3256 fprintf(stderr
, "glGetProgramResourceiv error\n");
3257 piglit_report_result(PIGLIT_FAIL
);
3260 if (block_data
.binding
!= current_binding
)
3268 * Query an active resource using ARB_program_interface_query functions
3270 * Format of the command:
3272 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM integer
3276 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM GL_TYPE_ENUM
3279 active_program_interface(const char *line
, struct block_info block_data
)
3281 static const struct string_to_enum all_props
[] = {
3282 ENUM_STRING(GL_TYPE
),
3283 ENUM_STRING(GL_ARRAY_SIZE
),
3284 ENUM_STRING(GL_NAME_LENGTH
),
3285 ENUM_STRING(GL_BLOCK_INDEX
),
3286 ENUM_STRING(GL_OFFSET
),
3287 ENUM_STRING(GL_ARRAY_STRIDE
),
3288 ENUM_STRING(GL_MATRIX_STRIDE
),
3289 ENUM_STRING(GL_IS_ROW_MAJOR
),
3290 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER_INDEX
),
3291 ENUM_STRING(GL_BUFFER_BINDING
),
3292 ENUM_STRING(GL_BUFFER_DATA_SIZE
),
3293 ENUM_STRING(GL_NUM_ACTIVE_VARIABLES
),
3294 ENUM_STRING(GL_REFERENCED_BY_VERTEX_SHADER
),
3295 ENUM_STRING(GL_REFERENCED_BY_TESS_CONTROL_SHADER
),
3296 ENUM_STRING(GL_REFERENCED_BY_TESS_EVALUATION_SHADER
),
3297 ENUM_STRING(GL_REFERENCED_BY_GEOMETRY_SHADER
),
3298 ENUM_STRING(GL_REFERENCED_BY_FRAGMENT_SHADER
),
3299 ENUM_STRING(GL_REFERENCED_BY_COMPUTE_SHADER
),
3300 ENUM_STRING(GL_TOP_LEVEL_ARRAY_SIZE
),
3301 ENUM_STRING(GL_TOP_LEVEL_ARRAY_STRIDE
),
3302 ENUM_STRING(GL_LOCATION
),
3303 ENUM_STRING(GL_LOCATION_INDEX
),
3304 ENUM_STRING(GL_LOCATION_COMPONENT
),
3305 ENUM_STRING(GL_IS_PER_PATCH
),
3306 ENUM_STRING(GL_NUM_COMPATIBLE_SUBROUTINES
),
3307 ENUM_STRING(GL_COMPATIBLE_SUBROUTINES
),
3311 static const struct string_to_enum all_program_interface
[] = {
3312 ENUM_STRING(GL_UNIFORM
),
3313 ENUM_STRING(GL_UNIFORM_BLOCK
),
3314 ENUM_STRING(GL_PROGRAM_INPUT
),
3315 ENUM_STRING(GL_PROGRAM_OUTPUT
),
3316 ENUM_STRING(GL_BUFFER_VARIABLE
),
3317 ENUM_STRING(GL_SHADER_STORAGE_BLOCK
),
3318 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER
),
3319 ENUM_STRING(GL_VERTEX_SUBROUTINE
),
3320 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE
),
3321 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE
),
3322 ENUM_STRING(GL_GEOMETRY_SUBROUTINE
),
3323 ENUM_STRING(GL_FRAGMENT_SUBROUTINE
),
3324 ENUM_STRING(GL_COMPUTE_SUBROUTINE
),
3325 ENUM_STRING(GL_VERTEX_SUBROUTINE_UNIFORM
),
3326 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE_UNIFORM
),
3327 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
),
3328 ENUM_STRING(GL_GEOMETRY_SUBROUTINE_UNIFORM
),
3329 ENUM_STRING(GL_FRAGMENT_SUBROUTINE_UNIFORM
),
3330 ENUM_STRING(GL_COMPUTE_SUBROUTINE_UNIFORM
),
3331 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING
),
3337 unsigned prop
, interface_type
;
3340 int num_active_buffers
;
3342 if (!piglit_is_extension_supported("GL_ARB_program_interface_query") &&
3343 piglit_get_gl_version() < 43) {
3345 "GL_ARB_program_interface_query not supported or "
3346 "OpenGL version < 4.3\n");
3350 REQUIRE(parse_enum_tab(all_program_interface
, line
,
3351 &interface_type
, &line
),
3352 "Bad program interface at: %s\n", line
);
3353 REQUIRE(parse_word_copy(line
, name
, sizeof(name
), &line
),
3354 "Bad program resource name at: %s\n", line
);
3355 REQUIRE(parse_enum_tab(all_props
, line
, &prop
, &line
),
3356 "Bad glGetProgramResourceiv pname at: %s\n", line
);
3357 REQUIRE(parse_enum_tab(all_types
, line
, (unsigned *)&expected
, &line
) ||
3358 parse_int(line
, &expected
, &line
),
3359 "Bad expected value at: %s\n", line
);
3361 glGetProgramInterfaceiv(prog
, interface_type
,
3362 GL_ACTIVE_RESOURCES
, &num_active_buffers
);
3363 for (i
= 0; i
< num_active_buffers
; i
++) {
3368 if (!confirm_program_resource(interface_type
, i
, name
, name_buf
,
3369 block_data
, prop
, expected
))
3372 /* Set 'got' to some value in case glGetActiveUniformsiv
3373 * doesn't write to it. That should only be able to occur
3374 * when the function raises a GL error, but "should" is kind
3378 glGetProgramResourceiv(prog
, interface_type
,
3382 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3383 fprintf(stderr
, "glGetProgramResourceiv error\n");
3384 piglit_report_result(PIGLIT_FAIL
);
3387 if (got
!= expected
) {
3389 "glGetProgramResourceiv(%s, %s): "
3390 "expected %d, got %d\n",
3391 name
, piglit_get_gl_enum_name(prop
),
3397 piglit_report_result(PIGLIT_FAIL
);
3402 if (!force_no_names
)
3403 fprintf(stderr
, "No active resource named \"%s\"\n", name
);
3405 fprintf(stderr
, "No active resource with binding %i\n", block_data
.binding
);
3407 piglit_report_result(PIGLIT_FAIL
);
3413 query_index(GLenum query
)
3416 case GL_PRIMITIVES_GENERATED
:
3418 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
3425 * Checks if the GL_QUERY_RESULT of a given query object has the
3428 * Note that right now it only supports the following two queries:
3429 * * GL_PRIMITIVES_GENERATED
3430 * * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
3432 * As right now we are only creating those query objects with xfb
3435 * Format of the command:
3437 * verify query_object GL_PRIMITIVES_GENERATED integer
3441 * verify query_object GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN integer
3443 static enum piglit_result
3444 verify_query_object_result(const char *line
)
3446 static const struct string_to_enum all_targets
[] = {
3447 ENUM_STRING(GL_PRIMITIVES_GENERATED
),
3448 ENUM_STRING(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
),
3457 REQUIRE(parse_enum_tab(all_targets
, line
,
3459 "Bad query object target at: %s\n", line
);
3461 REQUIRE(parse_uint(line
, &expected
, &line
),
3462 "Bad expected value at: %s\n", line
);
3464 /* Previous require already checks if the target is one of the
3467 index
= query_index(target
);
3469 if (queries
[index
]) {
3470 glGetQueryObjectuiv(queries
[index
], GL_QUERY_RESULT
, &value
);
3472 fprintf(stderr
, "query object for target %s is not initialized. "
3473 "Did you forget to call \"xfb draw arrays\"?\n",
3474 piglit_get_gl_enum_name(target
));
3478 if (expected
!= value
) {
3479 fprintf(stderr
, "glGetQueryObjectuiv(GL_QUERY_RESULT) for a %s "
3480 "query object: expected %d, got %d\n",
3481 piglit_get_gl_enum_name(target
), expected
, value
);
3488 set_parameter(const char *line
)
3494 count
= sscanf(line
, "%s %d (%f , %f , %f , %f)",
3495 type
, &index
, &f
[0], &f
[1], &f
[2], &f
[3]);
3497 fprintf(stderr
, "Couldn't parse parameter command:\n%s\n", line
);
3498 piglit_report_result(PIGLIT_FAIL
);
3501 if (parse_str(type
, "env_vp", NULL
)) {
3502 glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB
, index
, f
);
3503 } else if (parse_str(type
, "local_vp", NULL
)) {
3504 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB
, index
, f
);
3505 } else if (parse_str(type
, "env_fp", NULL
)) {
3506 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB
, index
, f
);
3507 } else if (parse_str(type
, "local_fp", NULL
)) {
3508 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB
, index
, f
);
3510 fprintf(stderr
, "Unknown parameter type `%s'\n", type
);
3511 piglit_report_result(PIGLIT_FAIL
);
3516 set_patch_parameter(const char *line
)
3518 #ifdef PIGLIT_USE_OPENGL
3521 const char *const line0
= line
;
3523 if (gl_version
.num
< 40)
3524 piglit_require_extension("GL_ARB_tessellation_shader");
3526 if (parse_str(line
, "vertices ", &line
)) {
3527 count
= sscanf(line
, "%d", &i
);
3529 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3530 piglit_report_result(PIGLIT_FAIL
);
3532 glPatchParameteri(GL_PATCH_VERTICES
, i
);
3533 } else if (parse_str(line
, "default level outer ", &line
)) {
3534 count
= sscanf(line
, "%f %f %f %f", &f
[0], &f
[1], &f
[2], &f
[3]);
3536 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3537 piglit_report_result(PIGLIT_FAIL
);
3539 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL
, f
);
3540 } else if (parse_str(line
, "default level inner ", &line
)) {
3541 count
= sscanf(line
, "%f %f", &f
[0], &f
[1]);
3543 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3544 piglit_report_result(PIGLIT_FAIL
);
3546 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL
, f
);
3548 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line
);
3549 piglit_report_result(PIGLIT_FAIL
);
3552 printf("patch parameters are only available in desktop GL\n");
3553 piglit_report_result(PIGLIT_SKIP
);
3558 set_provoking_vertex(const char *line
)
3560 if (parse_str(line
, "first", NULL
)) {
3561 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT
);
3562 } else if (parse_str(line
, "last", NULL
)) {
3563 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT
);
3565 fprintf(stderr
, "Unknown provoking vertex parameter `%s'\n", line
);
3566 piglit_report_result(PIGLIT_FAIL
);
3570 static const struct string_to_enum enable_table
[] = {
3571 { "GL_CLIP_PLANE0", GL_CLIP_PLANE0
},
3572 { "GL_CLIP_PLANE1", GL_CLIP_PLANE1
},
3573 { "GL_CLIP_PLANE2", GL_CLIP_PLANE2
},
3574 { "GL_CLIP_PLANE3", GL_CLIP_PLANE3
},
3575 { "GL_CLIP_PLANE4", GL_CLIP_PLANE4
},
3576 { "GL_CLIP_PLANE5", GL_CLIP_PLANE5
},
3577 { "GL_CLIP_PLANE6", GL_CLIP_PLANE0
+6 },
3578 { "GL_CLIP_PLANE7", GL_CLIP_PLANE0
+7 },
3579 { "GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE
},
3580 { "GL_PROGRAM_POINT_SIZE", GL_PROGRAM_POINT_SIZE
},
3581 { "GL_DEPTH_TEST", GL_DEPTH_TEST
},
3582 { "GL_DEPTH_CLAMP", GL_DEPTH_CLAMP
},
3587 do_enable_disable(const char *line
, bool enable_flag
)
3590 REQUIRE(parse_enum_tab(enable_table
, line
, &value
, NULL
),
3591 "Bad enable/disable enum at: %s\n", line
);
3599 static const struct string_to_enum hint_target_table
[] = {
3600 ENUM_STRING(GL_LINE_SMOOTH_HINT
),
3601 ENUM_STRING(GL_POLYGON_SMOOTH_HINT
),
3602 ENUM_STRING(GL_TEXTURE_COMPRESSION_HINT
),
3603 ENUM_STRING(GL_FRAGMENT_SHADER_DERIVATIVE_HINT
),
3607 static const struct string_to_enum hint_param_table
[] = {
3608 ENUM_STRING(GL_FASTEST
),
3609 ENUM_STRING(GL_NICEST
),
3610 ENUM_STRING(GL_DONT_CARE
),
3614 static void do_hint(const char *line
)
3616 unsigned target
, param
;
3617 REQUIRE(parse_enum_tab(hint_target_table
, line
, &target
, &line
),
3618 "Bad hint target at: %s\n", line
);
3619 REQUIRE(parse_enum_tab(hint_param_table
, line
, ¶m
, &line
),
3620 "Bad hint param at: %s\n", line
);
3622 glHint(target
, param
);
3626 draw_instanced_rect(int primcount
, float x
, float y
, float w
, float h
)
3630 piglit_require_extension("GL_ARB_draw_instanced");
3636 verts
[1][0] = x
+ w
;
3641 verts
[2][1] = y
+ h
;
3644 verts
[3][0] = x
+ w
;
3645 verts
[3][1] = y
+ h
;
3649 glVertexPointer(4, GL_FLOAT
, 0, verts
);
3650 glEnableClientState(GL_VERTEX_ARRAY
);
3652 glDrawArraysInstanced(GL_TRIANGLE_STRIP
, 0, 4, primcount
);
3654 glDisableClientState(GL_VERTEX_ARRAY
);
3659 decode_drawing_mode(const char *mode_str
)
3663 for (i
= GL_POINTS
; i
<= GL_PATCHES
; ++i
) {
3664 const char *name
= piglit_get_prim_name(i
);
3665 if (0 == strcmp(mode_str
, name
))
3669 printf("unknown drawing mode \"%s\"\n", mode_str
);
3670 piglit_report_result(PIGLIT_FAIL
);
3672 /* Should not be reached, but return 0 to avoid compiler warning */
3677 handle_texparameter(const char *line
)
3679 static const struct string_to_enum compare_funcs
[] = {
3680 { "greater", GL_GREATER
},
3681 { "gequal", GL_GEQUAL
},
3682 { "less", GL_LESS
},
3683 { "lequal", GL_LEQUAL
},
3684 { "equal", GL_EQUAL
},
3685 { "notequal", GL_NOTEQUAL
},
3686 { "never", GL_NEVER
},
3687 { "always", GL_ALWAYS
},
3690 static const struct string_to_enum depth_modes
[] = {
3691 { "intensity", GL_INTENSITY
},
3692 { "luminance", GL_LUMINANCE
},
3693 { "alpha", GL_ALPHA
},
3694 { "red", GL_RED
}, /* Requires GL 3.0 or GL_ARB_texture_rg */
3697 static const struct string_to_enum min_filter_modes
[] = {
3698 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST
},
3699 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST
},
3700 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR
},
3701 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR
},
3702 { "nearest", GL_NEAREST
},
3703 { "linear", GL_LINEAR
},
3706 static const struct string_to_enum mag_filter_modes
[] = {
3707 { "nearest", GL_NEAREST
},
3708 { "linear", GL_LINEAR
},
3711 static const struct string_to_enum wrap_modes
[] = {
3712 { "repeat", GL_REPEAT
},
3713 { "clamp_to_edge", GL_CLAMP_TO_EDGE
},
3714 { "clamp_to_border", GL_CLAMP_TO_BORDER
},
3717 static const struct string_to_enum swizzle_modes
[] = {
3719 { "green", GL_GREEN
},
3720 { "blue", GL_BLUE
},
3721 { "alpha", GL_ALPHA
},
3724 unsigned target
= 0;
3725 GLenum parameter
= GL_NONE
;
3726 const char *parameter_name
= NULL
;
3727 const struct string_to_enum
*strings
= NULL
;
3730 REQUIRE(parse_tex_target(line
, &target
, &line
),
3731 "Bad texture target at: %s\n", line
);
3733 if (parse_str(line
, "compare_func ", &line
)) {
3734 parameter
= GL_TEXTURE_COMPARE_FUNC
;
3735 parameter_name
= "compare_func";
3736 strings
= compare_funcs
;
3737 } else if (parse_str(line
, "depth_mode ", &line
)) {
3738 parameter
= GL_DEPTH_TEXTURE_MODE
;
3739 parameter_name
= "depth_mode";
3740 strings
= depth_modes
;
3741 } else if (parse_str(line
, "min ", &line
)) {
3742 parameter
= GL_TEXTURE_MIN_FILTER
;
3743 parameter_name
= "min";
3744 strings
= min_filter_modes
;
3745 } else if (parse_str(line
, "mag ", &line
)) {
3746 parameter
= GL_TEXTURE_MAG_FILTER
;
3747 parameter_name
= "mag";
3748 strings
= mag_filter_modes
;
3749 } else if (parse_str(line
, "wrap_s ", &line
)) {
3750 parameter
= GL_TEXTURE_WRAP_S
;
3751 parameter_name
= "wrap_s";
3752 strings
= wrap_modes
;
3753 } else if (parse_str(line
, "wrap_t ", &line
)) {
3754 parameter
= GL_TEXTURE_WRAP_T
;
3755 parameter_name
= "wrap_t";
3756 strings
= wrap_modes
;
3757 } else if (parse_str(line
, "wrap_r ", &line
)) {
3758 parameter
= GL_TEXTURE_WRAP_R
;
3759 parameter_name
= "wrap_r";
3760 strings
= wrap_modes
;
3761 } else if (parse_str(line
, "lod_bias ", &line
)) {
3762 #ifdef PIGLIT_USE_OPENGL
3763 glTexParameterf(target
, GL_TEXTURE_LOD_BIAS
,
3764 strtod(line
, NULL
));
3767 printf("lod_bias feature is only available in desktop GL\n");
3768 piglit_report_result(PIGLIT_SKIP
);
3770 } else if (parse_str(line
, "max_level ", &line
)) {
3771 glTexParameteri(target
, GL_TEXTURE_MAX_LEVEL
,
3772 strtol(line
, NULL
, 10));
3774 } else if (parse_str(line
, "base_level ", &line
)) {
3775 glTexParameteri(target
, GL_TEXTURE_BASE_LEVEL
,
3776 strtol(line
, NULL
, 10));
3778 } else if (parse_str(line
, "border_color ", &line
)) {
3781 count
= sscanf(line
, "%f %f %f %f", &bc
[0], &bc
[1], &bc
[2], &bc
[3]);
3783 fprintf(stderr
, "Could not parse border_color texture parameter.\n");
3784 piglit_report_result(PIGLIT_FAIL
);
3786 glTexParameterfv(target
, GL_TEXTURE_BORDER_COLOR
, bc
);
3788 } else if (parse_str(line
, "swizzle_r ", &line
)) {
3789 parameter
= GL_TEXTURE_SWIZZLE_R
;
3790 parameter_name
= "swizzle_r";
3791 strings
= swizzle_modes
;
3793 fprintf(stderr
, "unknown texture parameter in `%s'\n", line
);
3794 piglit_report_result(PIGLIT_FAIL
);
3797 REQUIRE(parse_enum_tab(strings
, line
, &value
, &line
),
3798 "Bad %s at: %s\n", parameter_name
, line
);
3800 glTexParameteri(target
, parameter
, value
);
3803 static const struct string_to_enum viewport_swizzle_table
[] = {
3804 { "POSITIVE_X", GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV
},
3805 { "NEGATIVE_X", GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV
},
3806 { "POSITIVE_Y", GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV
},
3807 { "NEGATIVE_Y", GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV
},
3808 { "POSITIVE_Z", GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV
},
3809 { "NEGATIVE_Z", GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV
},
3810 { "POSITIVE_W", GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV
},
3811 { "NEGATIVE_W", GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV
},
3816 handle_viewport_swizzle(const char *line
)
3821 viewport
= strtol(line
, (char **)&line
, 0);
3822 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &x
, &line
),
3823 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3824 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &y
, &line
),
3825 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3826 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &z
, &line
),
3827 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3828 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &w
, &line
),
3829 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3831 glViewportSwizzleNV(viewport
, x
, y
, z
, w
);
3839 if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
3840 piglit_get_gl_version() < 31) {
3845 /* probably running an ARB_vertex/fragment_program test */
3849 glGetProgramiv(prog
, GL_ACTIVE_UNIFORM_BLOCKS
, &num_uniform_blocks
);
3850 if (num_uniform_blocks
== 0)
3853 uniform_block_bos
= calloc(num_uniform_blocks
, sizeof(GLuint
));
3854 glGenBuffers(num_uniform_blocks
, uniform_block_bos
);
3857 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
, &max_ubos
);
3858 uniform_block_indexes
= calloc(max_ubos
, sizeof(int));
3860 for (i
= 0; i
< num_uniform_blocks
; i
++) {
3864 glGetActiveUniformBlockiv(prog
, i
, GL_UNIFORM_BLOCK_DATA_SIZE
,
3867 glBindBuffer(GL_UNIFORM_BUFFER
, uniform_block_bos
[i
]);
3868 glBufferData(GL_UNIFORM_BUFFER
, size
, NULL
, GL_STATIC_DRAW
);
3870 if (!force_no_names
) {
3871 glUniformBlockBinding(prog
, i
, i
);
3872 uniform_block_indexes
[i
] = i
;
3875 glGetActiveUniformBlockiv(prog
, i
, GL_UNIFORM_BLOCK_BINDING
,
3877 uniform_block_indexes
[binding
] = i
;
3880 glBindBufferBase(GL_UNIFORM_BUFFER
, binding
, uniform_block_bos
[i
]);
3887 if (draw_fbo
!= 0 &&
3888 draw_fbo
!= piglit_winsys_fbo
)
3889 glDeleteFramebuffers(1, &draw_fbo
);
3891 if (read_fbo
!= 0 &&
3892 read_fbo
!= piglit_winsys_fbo
&&
3893 read_fbo
!= draw_fbo
)
3894 glDeleteFramebuffers(1, &read_fbo
);
3903 if (num_uniform_blocks
== 0) {
3907 glDeleteBuffers(num_uniform_blocks
, uniform_block_bos
);
3908 free(uniform_block_bos
);
3909 uniform_block_bos
= NULL
;
3910 free(uniform_block_indexes
);
3911 uniform_block_indexes
= NULL
;
3912 num_uniform_blocks
= 0;
3916 teardown_atomics(void)
3918 for (unsigned i
= 0; i
< ARRAY_SIZE(atomics_bos
); ++i
) {
3920 glDeleteBuffers(1, &atomics_bos
[i
]);
3925 teardown_shader_include_paths(void)
3927 for (unsigned i
= 0; i
< num_shader_include_paths
; i
++)
3928 free(shader_include_path
[i
]);
3930 for (unsigned i
= 0; i
< num_shader_includes
; i
++) {
3931 glDeleteNamedStringARB(-1, shader_include_names
[i
]);
3932 free(shader_include_names
[i
]);
3935 num_shader_includes
= 0;
3936 num_shader_include_paths
= 0;
3937 free(shader_include_path
);
3938 shader_include_path
= NULL
;
3944 glDeleteBuffers(MAX_XFB_BUFFERS
, xfb
);
3946 glDeleteQueries(1, &queries
[query_index(GL_PRIMITIVES_GENERATED
)]);
3947 glDeleteQueries(1, &queries
[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
)]);
3948 queries
[query_index(GL_PRIMITIVES_GENERATED
)] = 0;
3949 queries
[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
)] = 0;
3952 static enum piglit_result
3953 program_must_be_in_use(void)
3956 fprintf(stderr
, "Failed to link:\n%s\n", prog_err_info
);
3958 } else if (!prog_in_use
) {
3959 fprintf(stderr
, "Failed to use program: %s\n", prog_err_info
);
3966 bind_vao_if_supported()
3968 if (vao
== 0 && piglit_is_core_profile
) {
3969 glGenVertexArrays(1, &vao
);
3970 glBindVertexArray(vao
);
3974 static enum piglit_result
3975 draw_arrays_common(int first
, size_t count
)
3977 enum piglit_result result
= program_must_be_in_use();
3979 printf("draw arrays 'first' must be >= 0\n");
3980 piglit_report_result(PIGLIT_FAIL
);
3981 } else if (vbo_present
&&
3982 (size_t) first
>= num_vbo_rows
) {
3983 printf("draw arrays 'first' must be < %lu\n",
3984 (unsigned long) num_vbo_rows
);
3985 piglit_report_result(PIGLIT_FAIL
);
3988 printf("draw arrays 'count' must be > 0\n");
3989 piglit_report_result(PIGLIT_FAIL
);
3990 } else if (vbo_present
&&
3991 count
> num_vbo_rows
- (size_t) first
) {
3992 printf("draw arrays cannot draw beyond %lu\n",
3993 (unsigned long) num_vbo_rows
);
3994 piglit_report_result(PIGLIT_FAIL
);
3996 bind_vao_if_supported();
4000 static const struct string_to_enum light_table
[] = {
4001 ENUM_STRING(GL_AMBIENT
),
4002 ENUM_STRING(GL_DIFFUSE
),
4003 ENUM_STRING(GL_SPECULAR
),
4004 ENUM_STRING(GL_POSITION
),
4005 ENUM_STRING(GL_SPOT_DIRECTION
),
4006 ENUM_STRING(GL_SPOT_EXPONENT
),
4007 ENUM_STRING(GL_SPOT_CUTOFF
),
4008 ENUM_STRING(GL_CONSTANT_ATTENUATION
),
4009 ENUM_STRING(GL_LINEAR_ATTENUATION
),
4010 ENUM_STRING(GL_QUADRATIC_ATTENUATION
),
4015 set_light(const char *line
)
4020 REQUIRE(parse_int(line
, &index
, &line
),
4021 "Bad light index at: %s\n", line
);
4023 REQUIRE(parse_enum_tab(light_table
, line
, &attrib
, &line
),
4024 "Bad light enum at: %s\n", line
);
4026 if (parse_str(line
, "float", &line
)) {
4030 REQUIRE((n
= parse_floats(line
, f
, 16, NULL
)) > 0,
4031 "No float found for light %s\n", line
);
4034 glLightf(GL_LIGHT0
+ index
, attrib
, f
[0]);
4036 glLightfv(GL_LIGHT0
+ index
, attrib
, f
);
4037 } else if (parse_str(line
, "int", &line
)) {
4041 REQUIRE((n
= parse_ints(line
, i
, 16, NULL
)) > 0,
4042 "No int found for light %s\n", line
);
4045 glLighti(GL_LIGHT0
+ index
, attrib
, i
[0]);
4047 glLightiv(GL_LIGHT0
+ index
, attrib
, i
);
4049 printf("Invalid light value type \"%s\"\n", line
);
4050 piglit_report_result(PIGLIT_FAIL
);
4055 probe_atomic_counter(unsigned buffer_num
, GLint counter_num
, const char *op
,
4056 uint32_t value
, bool uses_layout_qualifiers
)
4060 enum comparison cmp
;
4063 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4064 "Invalid comparison operation at: %s\n", op
);
4066 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER
, atomics_bos
[buffer_num
]);
4067 p
= glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER
,
4068 uses_layout_qualifiers
? counter_num
: counter_num
* sizeof(uint32_t),
4069 sizeof(uint32_t), GL_MAP_READ_BIT
);
4072 printf("Couldn't map atomic counter to verify expected value.\n");
4077 result
= compare_uint(value
, observed
, cmp
);
4080 if (uses_layout_qualifiers
)
4081 printf("Atomic counter (binding = %d, offset = %d) test failed: "
4082 "Reference %s Observed\n",
4083 buffer_num
, counter_num
, comparison_string(cmp
));
4085 printf("Atomic counter %d test failed: Reference %s Observed\n",
4086 counter_num
, comparison_string(cmp
));
4087 printf(" Reference: %u\n", value
);
4088 printf(" Observed: %u\n", observed
);
4089 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER
);
4093 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER
);
4098 probe_ssbo_uint(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, uint32_t value
)
4102 enum comparison cmp
;
4105 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4106 "Invalid comparison operation at: %s\n", op
);
4108 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4109 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4110 sizeof(uint32_t), GL_MAP_READ_BIT
);
4113 printf("Couldn't map ssbo to verify expected value.\n");
4118 result
= compare_uint(value
, observed
, cmp
);
4121 printf("SSBO %d test failed: Reference %s Observed\n",
4122 ssbo_offset
, comparison_string(cmp
));
4123 printf(" Reference: %u\n", value
);
4124 printf(" Observed: %u\n", observed
);
4125 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4129 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4134 probe_ssbo_uint64(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, uint64_t value
)
4138 enum comparison cmp
;
4141 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4142 "Invalid comparison operation at: %s\n", op
);
4144 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4145 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4146 sizeof(uint64_t), GL_MAP_READ_BIT
);
4149 printf("Couldn't map ssbo to verify expected value.\n");
4154 result
= compare_uint64(value
, observed
, cmp
);
4157 printf("SSBO %d test failed: Reference %s Observed\n",
4158 ssbo_offset
, comparison_string(cmp
));
4159 printf(" Reference: %lu\n", value
);
4160 printf(" Observed: %lu\n", observed
);
4161 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4165 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4170 probe_ssbo_int(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, int32_t value
)
4174 enum comparison cmp
;
4177 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4178 "Invalid comparison operation at: %s\n", op
);
4180 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4181 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4182 sizeof(uint32_t), GL_MAP_READ_BIT
);
4185 printf("Couldn't map ssbo to verify expected value.\n");
4190 result
= compare_int(value
, observed
, cmp
);
4193 printf("SSBO %d test failed: Reference %s Observed\n",
4194 ssbo_offset
, comparison_string(cmp
));
4195 printf(" Reference: %d\n", value
);
4196 printf(" Observed: %d\n", observed
);
4197 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4201 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4206 probe_ssbo_int64(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, int64_t value
)
4210 enum comparison cmp
;
4213 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4214 "Invalid comparison operation at: %s\n", op
);
4216 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4217 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4218 sizeof(uint64_t), GL_MAP_READ_BIT
);
4221 printf("Couldn't map ssbo to verify expected value.\n");
4226 result
= compare_int64(value
, observed
, cmp
);
4229 printf("SSBO %d test failed: Reference %s Observed\n",
4230 ssbo_offset
, comparison_string(cmp
));
4231 printf(" Reference: %ld\n", value
);
4232 printf(" Observed: %ld\n", observed
);
4233 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4237 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4242 probe_ssbo_double(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, double value
)
4246 enum comparison cmp
;
4249 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4250 "Invalid comparison operation at: %s\n", op
);
4252 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4253 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4254 sizeof(double), GL_MAP_READ_BIT
);
4257 printf("Couldn't map ssbo to verify expected value.\n");
4262 result
= compare_double(value
, observed
, cmp
);
4265 printf("SSBO %d test failed: Reference %s Observed\n",
4266 ssbo_offset
, comparison_string(cmp
));
4267 printf(" Reference: %g\n", value
);
4268 printf(" Observed: %g\n", observed
);
4269 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4273 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4278 probe_ssbo_float(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, float value
)
4282 enum comparison cmp
;
4285 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4286 "Invalid comparison operation at: %s\n", op
);
4288 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4289 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4290 sizeof(float), GL_MAP_READ_BIT
);
4293 printf("Couldn't map ssbo to verify expected value.\n");
4298 result
= compare_double(value
, observed
, cmp
);
4301 printf("SSBO %d test failed: Reference %s Observed\n",
4302 ssbo_offset
, comparison_string(cmp
));
4303 printf(" Reference: %g\n", value
);
4304 printf(" Observed: %g\n", observed
);
4305 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4309 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4313 GLenum
piglit_xfb_primitive_mode(GLenum draw_arrays_mode
)
4315 switch (draw_arrays_mode
) {
4321 case GL_LINES_ADJACENCY
:
4322 case GL_LINE_STRIP_ADJACENCY
:
4325 case GL_TRIANGLE_STRIP
:
4326 case GL_TRIANGLE_FAN
:
4327 case GL_TRIANGLES_ADJACENCY
:
4328 case GL_TRIANGLE_STRIP_ADJACENCY
:
4329 return GL_TRIANGLES
;
4332 printf("glDrawArrays mode %s not supported for a transform feedback operation\n",
4333 piglit_get_gl_enum_name(draw_arrays_mode
));
4334 piglit_report_result(PIGLIT_FAIL
);
4338 begin_query(GLenum query_type
)
4340 unsigned idx
= query_index(query_type
);
4341 if (queries
[idx
] == 0)
4342 glGenQueries(1, &queries
[idx
]);
4343 glBeginQuery(query_type
, queries
[idx
]);
4347 piglit_xfb_draw_arrays(GLenum mode
, int first
, size_t count
)
4349 GLenum primitive_mode
= piglit_xfb_primitive_mode(mode
);
4351 begin_query(GL_PRIMITIVES_GENERATED
);
4352 begin_query(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
4354 glEnable(GL_RASTERIZER_DISCARD
);
4356 /* We don't need to call glBindBufferBase here, it is done on
4357 * the "xfb buffer object" command
4360 glBeginTransformFeedback(primitive_mode
);
4361 glDrawArrays(mode
, first
, count
);
4362 glEndTransformFeedback();
4364 glDisable(GL_RASTERIZER_DISCARD
);
4368 glEndQuery(GL_PRIMITIVES_GENERATED
);
4369 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
4373 probe_xfb_float(GLuint buf
, unsigned n
, float expected
)
4377 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, buf
);
4378 p
= glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, n
* sizeof(float),
4379 sizeof(float), GL_MAP_READ_BIT
);
4381 printf("Couldn't map xfb buffer %u\n", buf
);
4384 result
= fabsf(expected
- *p
) < piglit_tolerance
[0];
4386 printf("xfb buffer %i[%i]: %f, Expected: %f\n",
4387 buf
, n
, *p
, expected
);
4390 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
4395 probe_xfb_double(GLuint buf
, unsigned n
, double expected
)
4400 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, buf
);
4401 p
= glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, n
* sizeof(double),
4402 sizeof(double), GL_MAP_READ_BIT
);
4404 printf("Couldn't map xfb buffer %u\n", buf
);
4407 result
= fabs(expected
- *p
) < piglit_tolerance
[0];
4409 printf("xfb buffer %i[%i]: %lf, Expected: %lf\n",
4410 buf
, n
, *p
, expected
);
4413 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
4418 piglit_display(void)
4420 const char *line
, *next_line
, *rest
;
4422 enum piglit_result full_result
= PIGLIT_PASS
;
4423 GLbitfield clear_bits
= 0;
4424 bool link_error_expected
= false;
4426 struct block_info block_data
= {0, -1, -1, -1, -1};
4428 if (test_start
== NULL
)
4431 next_line
= test_start
;
4432 line_num
= test_start_line_num
;
4433 while (next_line
[0] != '\0') {
4436 int x
, y
, z
, w
, h
, l
, tex
, level
;
4437 unsigned ux
, uy
, uz
;
4440 char s
[300]; // 300 for safety
4441 enum piglit_result result
= PIGLIT_PASS
;
4443 parse_whitespace(next_line
, &line
);
4445 next_line
= strchrnul(next_line
, '\n');
4447 /* Duplicate the line to make it null terminated */
4448 line
= strndup(line
, next_line
- line
);
4450 /* If strchrnul found a newline, then skip it */
4451 if (next_line
[0] != '\0')
4454 if (line
[0] == '\0') {
4455 } else if (sscanf(line
, "active shader program %s", s
) == 1) {
4456 switch (get_shader_from_string(s
, &x
)) {
4457 case GL_VERTEX_SHADER
:
4458 glActiveShaderProgram(pipeline
, sso_vertex_prog
);
4460 case GL_TESS_CONTROL_SHADER
:
4461 glActiveShaderProgram(pipeline
, sso_tess_control_prog
);
4463 case GL_TESS_EVALUATION_SHADER
:
4464 glActiveShaderProgram(pipeline
, sso_tess_eval_prog
);
4466 case GL_GEOMETRY_SHADER
:
4467 glActiveShaderProgram(pipeline
, sso_geometry_prog
);
4469 case GL_FRAGMENT_SHADER
:
4470 glActiveShaderProgram(pipeline
, sso_fragment_prog
);
4472 case GL_COMPUTE_SHADER
:
4473 glActiveShaderProgram(pipeline
, sso_compute_prog
);
4476 } else if (sscanf(line
, "atomic counter buffer %u %u", &x
, &y
) == 2) {
4477 GLuint
*atomics_buf
= calloc(y
, sizeof(GLuint
));
4478 glGenBuffers(1, &atomics_bos
[x
]);
4479 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, x
, atomics_bos
[x
]);
4480 glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
4481 sizeof(GLuint
) * y
, atomics_buf
,
4484 } else if (sscanf(line
, "atomic counters %d", &x
) == 1) {
4485 GLuint
*atomics_buf
= calloc(x
, sizeof(GLuint
));
4486 glGenBuffers(1, &atomics_bos
[0]);
4487 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, atomics_bos
[0]);
4488 glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
4490 atomics_buf
, GL_STATIC_DRAW
);
4492 } else if (sscanf(line
, "atomic counter %u %u %u", &x
, &y
, &z
) == 3) {
4493 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, x
, atomics_bos
[x
]);
4494 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER
,
4495 sizeof(GLuint
) * y
, sizeof(GLuint
),
4497 } else if (parse_str(line
, "clear color ", &rest
)) {
4498 parse_floats(rest
, c
, 4, NULL
);
4499 glClearColor(c
[0], c
[1], c
[2], c
[3]);
4500 clear_bits
|= GL_COLOR_BUFFER_BIT
;
4501 } else if (parse_str(line
, "clear depth ", &rest
)) {
4502 parse_floats(rest
, c
, 1, NULL
);
4504 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
4505 } else if (parse_str(line
, "clear", NULL
)) {
4506 glClear(clear_bits
);
4507 } else if (sscanf(line
,
4508 "clip plane %d %lf %lf %lf %lf",
4509 &x
, &d
[0], &d
[1], &d
[2], &d
[3]) == 5) {
4510 if (x
< 0 || x
>= gl_max_clip_planes
) {
4511 printf("clip plane id %d out of range\n", x
);
4512 piglit_report_result(PIGLIT_FAIL
);
4514 glClipPlane(GL_CLIP_PLANE0
+ x
, d
);
4515 #ifdef PIGLIT_USE_OPENGL
4516 } else if (parse_str(line
, "color ", &rest
)) {
4517 parse_floats(rest
, c
, 4, NULL
);
4518 assert(!piglit_is_core_profile
);
4521 } else if (sscanf(line
,
4524 result
= program_must_be_in_use();
4525 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4526 glDispatchCompute(x
, y
, z
);
4527 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4528 } else if (sscanf(line
,
4529 "compute group size %d %d %d %d %d %d",
4530 &x
, &y
, &z
, &w
, &h
, &l
) == 6) {
4531 result
= program_must_be_in_use();
4532 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4533 glDispatchComputeGroupSizeARB(x
, y
, z
, w
, h
, l
);
4534 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4535 } else if (parse_str(line
, "draw rect tex ", &rest
)) {
4536 result
= program_must_be_in_use();
4537 program_subroutine_uniforms();
4538 parse_floats(rest
, c
, 8, NULL
);
4539 piglit_draw_rect_tex(c
[0], c
[1], c
[2], c
[3],
4540 c
[4], c
[5], c
[6], c
[7]);
4541 } else if (parse_str(line
, "draw rect ortho patch ", &rest
)) {
4542 result
= program_must_be_in_use();
4543 program_subroutine_uniforms();
4544 parse_floats(rest
, c
, 4, NULL
);
4546 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4547 -1.0 + 2.0 * (c
[1] / piglit_height
),
4548 2.0 * (c
[2] / piglit_width
),
4549 2.0 * (c
[3] / piglit_height
), true, 1);
4550 } else if (parse_str(line
, "draw rect ortho ", &rest
)) {
4551 result
= program_must_be_in_use();
4552 program_subroutine_uniforms();
4553 parse_floats(rest
, c
, 4, NULL
);
4555 piglit_draw_rect(-1.0 + 2.0 * (c
[0] / piglit_width
),
4556 -1.0 + 2.0 * (c
[1] / piglit_height
),
4557 2.0 * (c
[2] / piglit_width
),
4558 2.0 * (c
[3] / piglit_height
));
4559 } else if (parse_str(line
, "draw rect patch ", &rest
)) {
4560 result
= program_must_be_in_use();
4561 parse_floats(rest
, c
, 4, NULL
);
4562 piglit_draw_rect_custom(c
[0], c
[1], c
[2], c
[3], true, 1);
4563 } else if (parse_str(line
, "draw rect ", &rest
)) {
4564 result
= program_must_be_in_use();
4565 program_subroutine_uniforms();
4566 parse_floats(rest
, c
, 4, NULL
);
4567 piglit_draw_rect(c
[0], c
[1], c
[2], c
[3]);
4568 } else if (parse_str(line
, "draw instanced rect ortho patch ", &rest
)) {
4571 result
= program_must_be_in_use();
4572 sscanf(rest
, "%d %f %f %f %f",
4574 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4575 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4576 -1.0 + 2.0 * (c
[1] / piglit_height
),
4577 2.0 * (c
[2] / piglit_width
),
4578 2.0 * (c
[3] / piglit_height
), true,
4580 } else if (parse_str(line
, "draw instanced rect ortho ", &rest
)) {
4583 result
= program_must_be_in_use();
4584 sscanf(rest
, "%d %f %f %f %f",
4586 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4587 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4588 -1.0 + 2.0 * (c
[1] / piglit_height
),
4589 2.0 * (c
[2] / piglit_width
),
4590 2.0 * (c
[3] / piglit_height
), false,
4592 } else if (parse_str(line
, "draw instanced rect ", &rest
)) {
4595 result
= program_must_be_in_use();
4596 sscanf(rest
, "%d %f %f %f %f",
4598 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4599 draw_instanced_rect(primcount
, c
[0], c
[1], c
[2], c
[3]);
4600 } else if (sscanf(line
, "draw arrays instanced %31s %d %d %d", s
, &x
, &y
, &z
) == 4) {
4601 GLenum mode
= decode_drawing_mode(s
);
4603 size_t count
= (size_t) y
;
4604 size_t primcount
= (size_t) z
;
4605 draw_arrays_common(first
, count
);
4606 glDrawArraysInstanced(mode
, first
, count
, primcount
);
4607 } else if (sscanf(line
, "draw arrays %31s %d %d", s
, &x
, &y
) == 3) {
4608 GLenum mode
= decode_drawing_mode(s
);
4610 size_t count
= (size_t) y
;
4611 result
= draw_arrays_common(first
, count
);
4612 glDrawArrays(mode
, first
, count
);
4613 } else if (parse_str(line
, "disable ", &rest
)) {
4614 do_enable_disable(rest
, false);
4615 } else if (parse_str(line
, "enable ", &rest
)) {
4616 do_enable_disable(rest
, true);
4617 } else if (sscanf(line
, "depthfunc %31s", s
) == 1) {
4618 glDepthFunc(piglit_get_gl_enum_from_name(s
));
4619 } else if (parse_str(line
, "fb ", &rest
)) {
4620 const GLenum target
=
4621 parse_str(rest
, "draw ", &rest
) ? GL_DRAW_FRAMEBUFFER
:
4622 parse_str(rest
, "read ", &rest
) ? GL_READ_FRAMEBUFFER
:
4626 if (parse_str(rest
, "tex 2d ", &rest
)) {
4627 GLenum attachments
[32];
4628 unsigned num_attachments
= 0;
4630 glGenFramebuffers(1, &fbo
);
4631 glBindFramebuffer(target
, fbo
);
4633 while (parse_int(rest
, &tex
, &rest
)) {
4634 attachments
[num_attachments
] =
4635 GL_COLOR_ATTACHMENT0
+ num_attachments
;
4636 glFramebufferTexture2D(
4637 target
, attachments
[num_attachments
],
4639 get_texture_binding(tex
)->obj
, 0);
4641 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4643 "glFramebufferTexture2D error\n");
4644 piglit_report_result(PIGLIT_FAIL
);
4650 if (target
!= GL_READ_FRAMEBUFFER
)
4651 glDrawBuffers(num_attachments
, attachments
);
4653 w
= get_texture_binding(tex
)->width
;
4654 h
= get_texture_binding(tex
)->height
;
4656 } else if (parse_str(rest
, "tex slice ", &rest
)) {
4659 REQUIRE(parse_tex_target(rest
, &tex_target
, &rest
) &&
4660 parse_int(rest
, &tex
, &rest
) &&
4661 parse_int(rest
, &l
, &rest
) &&
4662 parse_int(rest
, &z
, &rest
),
4663 "Framebuffer binding command not "
4664 "understood at: %s\n", rest
);
4666 const GLuint tex_obj
= get_texture_binding(tex
)->obj
;
4668 glGenFramebuffers(1, &fbo
);
4669 glBindFramebuffer(target
, fbo
);
4671 if (tex_target
== GL_TEXTURE_1D
) {
4673 "Invalid layer index provided "
4674 "in command: %s\n", line
);
4675 glFramebufferTexture1D(
4676 target
, GL_COLOR_ATTACHMENT0
,
4677 tex_target
, tex_obj
, l
);
4679 } else if (tex_target
== GL_TEXTURE_2D
||
4680 tex_target
== GL_TEXTURE_RECTANGLE
||
4681 tex_target
== GL_TEXTURE_2D_MULTISAMPLE
) {
4683 "Invalid layer index provided "
4684 "in command: %s\n", line
);
4685 glFramebufferTexture2D(
4686 target
, GL_COLOR_ATTACHMENT0
,
4687 tex_target
, tex_obj
, l
);
4689 } else if (tex_target
== GL_TEXTURE_CUBE_MAP
) {
4690 static const GLenum cubemap_targets
[] = {
4691 GL_TEXTURE_CUBE_MAP_POSITIVE_X
,
4692 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
,
4693 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
,
4694 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
,
4695 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
,
4696 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4698 REQUIRE(z
< ARRAY_SIZE(cubemap_targets
),
4699 "Invalid layer index provided "
4700 "in command: %s\n", line
);
4701 tex_target
= cubemap_targets
[z
];
4703 glFramebufferTexture2D(
4704 target
, GL_COLOR_ATTACHMENT0
,
4705 tex_target
, tex_obj
, l
);
4708 glFramebufferTextureLayer(
4709 target
, GL_COLOR_ATTACHMENT0
,
4713 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4714 fprintf(stderr
, "Error binding texture "
4715 "attachment for command: %s\n",
4717 piglit_report_result(PIGLIT_FAIL
);
4720 w
= MAX2(1, get_texture_binding(tex
)->width
>> l
);
4721 h
= MAX2(1, get_texture_binding(tex
)->height
>> l
);
4723 } else if (sscanf(rest
, "tex layered %d", &tex
) == 1) {
4724 glGenFramebuffers(1, &fbo
);
4725 glBindFramebuffer(target
, fbo
);
4727 glFramebufferTexture(
4728 target
, GL_COLOR_ATTACHMENT0
,
4729 get_texture_binding(tex
)->obj
, 0);
4730 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4732 "glFramebufferTexture error\n");
4733 piglit_report_result(PIGLIT_FAIL
);
4736 w
= get_texture_binding(tex
)->width
;
4737 h
= get_texture_binding(tex
)->height
;
4739 } else if (parse_str(rest
, "ms ", &rest
)) {
4744 REQUIRE(parse_enum_gl(rest
, &format
, &rest
) &&
4745 parse_int(rest
, &w
, &rest
) &&
4746 parse_int(rest
, &h
, &rest
) &&
4747 parse_int(rest
, &samples
, &rest
),
4748 "Framebuffer binding command not "
4749 "understood at: %s\n", rest
);
4751 glGenFramebuffers(1, &fbo
);
4752 glBindFramebuffer(target
, fbo
);
4754 glGenRenderbuffers(1, &rb
);
4755 glBindRenderbuffer(GL_RENDERBUFFER
, rb
);
4757 glRenderbufferStorageMultisample(GL_RENDERBUFFER
, samples
,
4760 glFramebufferRenderbuffer(target
,
4761 GL_COLOR_ATTACHMENT0
,
4762 GL_RENDERBUFFER
, rb
);
4764 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4765 fprintf(stderr
, "glFramebufferRenderbuffer error\n");
4766 piglit_report_result(PIGLIT_FAIL
);
4769 } else if (parse_str(rest
, "winsys", &rest
)) {
4770 fbo
= piglit_winsys_fbo
;
4771 glBindFramebuffer(target
, fbo
);
4772 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4773 fprintf(stderr
, "glBindFramebuffer error\n");
4774 piglit_report_result(PIGLIT_FAIL
);
4781 fprintf(stderr
, "Unknown fb bind subcommand "
4783 piglit_report_result(PIGLIT_FAIL
);
4786 const GLenum status
= glCheckFramebufferStatus(target
);
4787 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
4788 fprintf(stderr
, "incomplete fbo (status 0x%x)\n",
4790 piglit_report_result(PIGLIT_FAIL
);
4793 if (target
!= GL_READ_FRAMEBUFFER
) {
4797 /* Delete the previous draw FB in case
4798 * it's no longer reachable.
4800 if (draw_fbo
!= 0 &&
4801 draw_fbo
!= piglit_winsys_fbo
&&
4802 draw_fbo
!= (target
== GL_DRAW_FRAMEBUFFER
?
4804 glDeleteFramebuffers(1, &draw_fbo
);
4809 if (target
!= GL_DRAW_FRAMEBUFFER
) {
4813 /* Delete the previous read FB in case
4814 * it's no longer reachable.
4816 if (read_fbo
!= 0 &&
4817 read_fbo
!= piglit_winsys_fbo
&&
4818 read_fbo
!= (target
== GL_READ_FRAMEBUFFER
?
4820 glDeleteFramebuffers(1, &read_fbo
);
4825 } else if (parse_str(line
, "blit ", &rest
)) {
4826 static const struct string_to_enum buffers
[] = {
4827 { "color", GL_COLOR_BUFFER_BIT
},
4828 { "depth", GL_DEPTH_BUFFER_BIT
},
4829 { "stencil", GL_STENCIL_BUFFER_BIT
},
4832 static const struct string_to_enum filters
[] = {
4833 { "linear", GL_LINEAR
},
4834 { "nearest", GL_NEAREST
},
4837 unsigned buffer
, filter
;
4839 REQUIRE(parse_enum_tab(buffers
, rest
, &buffer
, &rest
) &&
4840 parse_enum_tab(filters
, rest
, &filter
, &rest
),
4841 "FB blit command not understood at: %s\n",
4844 glBlitFramebuffer(0, 0, read_width
, read_height
,
4845 0, 0, render_width
, render_height
,
4848 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4849 fprintf(stderr
, "glBlitFramebuffer error\n");
4850 piglit_report_result(PIGLIT_FAIL
);
4853 } else if (parse_str(line
, "frustum", &rest
)) {
4854 parse_floats(rest
, c
, 6, NULL
);
4855 piglit_frustum_projection(false, c
[0], c
[1], c
[2],
4857 } else if (parse_str(line
, "hint", &rest
)) {
4859 } else if (sscanf(line
,
4860 "image texture %d %31s",
4862 const GLenum img_fmt
= piglit_get_gl_enum_from_name(s
);
4863 glBindImageTexture(tex
, get_texture_binding(tex
)->obj
, 0,
4864 GL_FALSE
, 0, GL_READ_WRITE
, img_fmt
);
4865 } else if (sscanf(line
, "memory barrier %s", s
) == 1) {
4866 glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s
));
4867 } else if (parse_str(line
, "blend barrier", NULL
)) {
4869 } else if (parse_str(line
, "fbfetch barrier", NULL
)) {
4870 glFramebufferFetchBarrierEXT();
4871 } else if (sscanf(line
, "ortho %f %f %f %f",
4872 c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 4) {
4873 piglit_gen_ortho_projection(c
[0], c
[1], c
[2], c
[3],
4875 } else if (parse_str(line
, "ortho", NULL
)) {
4876 piglit_ortho_projection(render_width
, render_height
,
4878 } else if (sscanf(line
, "viewport indexed %u %f %f %f %f",
4879 &x
, c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 5) {
4880 glViewportIndexedfv(x
, c
);
4881 } else if (parse_str(line
, "probe rgba ", &rest
)) {
4882 parse_floats(rest
, c
, 6, NULL
);
4883 if (!piglit_probe_pixel_rgba((int) c
[0], (int) c
[1],
4885 result
= PIGLIT_FAIL
;
4887 } else if (parse_str(line
, "probe depth ", &rest
)) {
4888 parse_floats(rest
, c
, 3, NULL
);
4889 if (!piglit_probe_pixel_depth((int) c
[0], (int) c
[1],
4891 result
= PIGLIT_FAIL
;
4893 } else if (sscanf(line
,
4894 "probe atomic counter buffer %u %u %s %u",
4895 &ux
, &uy
, s
, &uz
) == 4) {
4896 if (!probe_atomic_counter(ux
, uy
, s
, uz
, true)) {
4897 result
= PIGLIT_FAIL
;
4899 } else if (sscanf(line
,
4900 "probe atomic counter %u %s %u",
4901 &ux
, s
, &uy
) == 3) {
4902 if (!probe_atomic_counter(0, ux
, s
, uy
, false)) {
4903 result
= PIGLIT_FAIL
;
4905 } else if (sscanf(line
, "probe ssbo uint %d %d %s 0x%x",
4906 &x
, &y
, s
, &z
) == 4) {
4907 if (!probe_ssbo_uint(x
, y
, s
, z
))
4908 result
= PIGLIT_FAIL
;
4909 } else if (sscanf(line
, "probe ssbo uint %d %d %s %d",
4910 &x
, &y
, s
, &z
) == 4) {
4911 if (!probe_ssbo_uint(x
, y
, s
, z
))
4912 result
= PIGLIT_FAIL
;
4913 } else if (sscanf(line
, "probe ssbo uint64 %d %d %s %lu",
4914 &x
, &y
, s
, &luz
) == 4) {
4915 if (!probe_ssbo_uint64(x
, y
, s
, luz
))
4916 result
= PIGLIT_FAIL
;
4917 } else if (sscanf(line
, "probe ssbo int %d %d %s %d",
4918 &x
, &y
, s
, &z
) == 4) {
4919 if (!probe_ssbo_int(x
, y
, s
, z
))
4920 result
= PIGLIT_FAIL
;
4921 } else if (sscanf(line
, "probe ssbo int64 %d %d %s %ld",
4922 &x
, &y
, s
, &lz
) == 4) {
4923 if (!probe_ssbo_int64(x
, y
, s
, lz
))
4924 result
= PIGLIT_FAIL
;
4925 } else if (sscanf(line
, "probe ssbo double %d %d %s %lf",
4926 &x
, &y
, s
, &d
[0]) == 4) {
4927 if (!probe_ssbo_double(x
, y
, s
, d
[0]))
4928 result
= PIGLIT_FAIL
;
4929 } else if (sscanf(line
, "probe ssbo float %d %d %s %f",
4930 &x
, &y
, s
, &c
[0]) == 4) {
4931 if (!probe_ssbo_float(x
, y
, s
, c
[0]))
4932 result
= PIGLIT_FAIL
;
4933 } else if (sscanf(line
,
4934 "relative probe rgba ( %f , %f ) "
4935 "( %f , %f , %f , %f )",
4937 c
+ 2, c
+ 3, c
+ 4, c
+ 5) == 6) {
4938 x
= c
[0] * read_width
;
4939 y
= c
[1] * read_height
;
4940 if (x
>= read_width
)
4942 if (y
>= read_height
)
4943 y
= read_height
- 1;
4945 if (!piglit_probe_pixel_rgba(x
, y
, &c
[2])) {
4946 result
= PIGLIT_FAIL
;
4948 } else if (parse_str(line
, "probe rgb ", &rest
)) {
4949 parse_floats(rest
, c
, 5, NULL
);
4950 if (!piglit_probe_pixel_rgb((int) c
[0], (int) c
[1],
4952 result
= PIGLIT_FAIL
;
4954 } else if (sscanf(line
,
4955 "relative probe rgb ( %f , %f ) "
4958 c
+ 2, c
+ 3, c
+ 4) == 5) {
4959 x
= c
[0] * read_width
;
4960 y
= c
[1] * read_height
;
4961 if (x
>= read_width
)
4963 if (y
>= read_height
)
4964 y
= read_height
- 1;
4966 if (!piglit_probe_pixel_rgb(x
, y
, &c
[2])) {
4967 result
= PIGLIT_FAIL
;
4969 } else if (sscanf(line
, "probe rect rgba "
4970 "( %d , %d , %d , %d ) "
4971 "( %f , %f , %f , %f )",
4973 c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 8) {
4974 if (!piglit_probe_rect_rgba(x
, y
, w
, h
, c
)) {
4975 result
= PIGLIT_FAIL
;
4977 } else if (sscanf(line
, "relative probe rect rgb "
4978 "( %f , %f , %f , %f ) "
4980 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4981 c
+ 4, c
+ 5, c
+ 6) == 7) {
4982 x
= c
[0] * read_width
;
4983 y
= c
[1] * read_height
;
4984 w
= c
[2] * read_width
;
4985 h
= c
[3] * read_height
;
4987 if (!piglit_probe_rect_rgb(x
, y
, w
, h
, &c
[4])) {
4988 result
= PIGLIT_FAIL
;
4990 } else if (sscanf(line
, "relative probe rect rgba "
4991 "( %f , %f , %f , %f ) "
4992 "( %f , %f , %f , %f )",
4993 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4994 c
+ 4, c
+ 5, c
+ 6, c
+ 7) == 8) {
4995 x
= c
[0] * read_width
;
4996 y
= c
[1] * read_height
;
4997 w
= c
[2] * read_width
;
4998 h
= c
[3] * read_height
;
5000 if (!piglit_probe_rect_rgba(x
, y
, w
, h
, &c
[4])) {
5001 result
= PIGLIT_FAIL
;
5003 } else if (sscanf(line
, "relative probe rect rgba int "
5004 "( %f , %f , %f , %f ) "
5005 "( %d , %d , %d , %d )",
5006 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
5007 &x
, &y
, &z
, &w
) == 8) {
5008 const int expected
[] = { x
, y
, z
, w
};
5009 if (!piglit_probe_rect_rgba_int(c
[0] * read_width
,
5014 result
= PIGLIT_FAIL
;
5016 } else if (parse_str(line
, "polygon mode ", &rest
)) {
5019 REQUIRE(parse_enum_gl(rest
, &face
, &rest
) &&
5020 parse_enum_gl(rest
, &mode
, &rest
),
5021 "Polygon mode command not understood at %s\n",
5024 glPolygonMode(face
, mode
);
5026 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
5027 fprintf(stderr
, "glPolygonMode error\n");
5028 piglit_report_result(PIGLIT_FAIL
);
5030 } else if (parse_str(line
, "probe all rgba ", &rest
)) {
5031 parse_floats(rest
, c
, 4, NULL
);
5032 if (result
!= PIGLIT_FAIL
&&
5033 !piglit_probe_rect_rgba(0, 0, read_width
,
5035 result
= PIGLIT_FAIL
;
5036 } else if (parse_str(line
, "probe warn all rgba ", &rest
)) {
5037 parse_floats(rest
, c
, 4, NULL
);
5038 if (result
== PIGLIT_PASS
&&
5039 !piglit_probe_rect_rgba(0, 0, read_width
,
5041 result
= PIGLIT_WARN
;
5042 } else if (parse_str(line
, "probe all rgb", &rest
)) {
5043 parse_floats(rest
, c
, 3, NULL
);
5044 if (result
!= PIGLIT_FAIL
&&
5045 !piglit_probe_rect_rgb(0, 0, read_width
,
5047 result
= PIGLIT_FAIL
;
5048 } else if (parse_str(line
, "tolerance", &rest
)) {
5049 parse_floats(rest
, piglit_tolerance
, 4, NULL
);
5050 } else if (parse_str(line
, "shade model smooth", NULL
)) {
5051 glShadeModel(GL_SMOOTH
);
5052 } else if (parse_str(line
, "shade model flat", NULL
)) {
5053 glShadeModel(GL_FLAT
);
5054 } else if (sscanf(line
, "ssbo %d %d", &x
, &y
) == 2) {
5055 GLuint
*ssbo_init
= calloc(y
, 1);
5056 glGenBuffers(1, &ssbo
[x
]);
5057 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, x
, ssbo
[x
]);
5058 glBufferData(GL_SHADER_STORAGE_BUFFER
, y
,
5059 ssbo_init
, GL_DYNAMIC_DRAW
);
5062 else if (sscanf(line
, "xfb buffer object %u %u", &ux
, &uy
) == 2) {
5063 GLuint
*xfb_init
= calloc(uy
, 1);
5064 if (ux
< 0 || ux
>= MAX_XFB_BUFFERS
) {
5065 printf("xfb buffer id %d out of range\n", ux
);
5066 piglit_report_result(PIGLIT_FAIL
);
5068 glGenBuffers(1, &xfb
[ux
]);
5069 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, ux
, xfb
[ux
]);
5070 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, uy
,
5071 xfb_init
, GL_STREAM_READ
);
5073 } else if (sscanf(line
, "xfb draw arrays %31s %d %d", s
, &x
, &y
) == 3) {
5074 GLenum mode
= decode_drawing_mode(s
);
5076 size_t count
= (size_t) y
;
5077 result
= draw_arrays_common(first
, count
);
5078 piglit_xfb_draw_arrays(mode
, first
, count
);
5079 } else if (sscanf(line
, "probe xfb buffer float %u %u %f",
5080 &ux
, &uy
, &c
[0]) == 3) {
5081 if (!probe_xfb_float(xfb
[ux
], uy
, c
[0]))
5082 result
= PIGLIT_FAIL
;
5083 } else if (sscanf(line
, "probe xfb buffer double %u %u %lf",
5084 &ux
, &uy
, &d
[0]) == 3) {
5085 if (!probe_xfb_double(xfb
[ux
], uy
, d
[0]))
5086 result
= PIGLIT_FAIL
;
5087 } else if (sscanf(line
, "ssbo %d subdata float %d %f", &x
, &y
, &c
[0]) == 3) {
5088 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
5089 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, y
, 4, &c
[0]);
5090 } else if (sscanf(line
, "ssbo %d subdata double %d %s", &x
, &y
, s
) == 3) {
5091 parse_doubles(s
, &d
[0], 1, NULL
);
5092 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
5093 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, y
, sizeof(double), &d
[0]);
5094 } else if (sscanf(line
, "ssbo %d subdata int64 %ld %s", &x
, &ly
, s
) == 3) {
5095 parse_int64s(s
, &lz
, 1, NULL
);
5096 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
5097 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, ly
, sizeof(int64_t), &lz
);
5098 } else if (sscanf(line
, "ssbo %d subdata uint64 %lu %s", &x
, &luy
, s
) == 3) {
5099 parse_uint64s(s
, &luz
, 1, NULL
);
5100 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
5101 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, luy
, sizeof(uint64_t), &luz
);
5102 } else if (sscanf(line
, "ssbo %d subdata int %d %s", &x
, &y
, s
) == 3) {
5103 parse_ints(s
, &z
, 1, NULL
);
5104 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
5105 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, y
, 4, &z
);
5106 } else if (sscanf(line
, "texture rgbw %d ( %d", &tex
, &w
) == 2) {
5107 GLenum int_fmt
= GL_RGBA
;
5110 "texture rgbw %d ( %d , %d ) %31s",
5112 if (num_scanned
< 3) {
5114 "invalid texture rgbw command!\n");
5115 piglit_report_result(PIGLIT_FAIL
);
5118 if (num_scanned
>= 4) {
5119 int_fmt
= piglit_get_gl_enum_from_name(s
);
5122 glActiveTexture(GL_TEXTURE0
+ tex
);
5123 int handle
= piglit_rgbw_texture(
5124 int_fmt
, w
, h
, GL_FALSE
, GL_FALSE
,
5125 (piglit_is_gles() ? GL_UNSIGNED_BYTE
:
5126 GL_UNSIGNED_NORMALIZED
));
5127 set_texture_binding(tex
, handle
, w
, h
, 1);
5129 if (!piglit_is_core_profile
&&
5130 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5131 glEnable(GL_TEXTURE_2D
);
5133 } else if (sscanf(line
, "resident texture %d", &tex
) == 1) {
5136 glBindTexture(GL_TEXTURE_2D
, 0);
5138 handle
= glGetTextureHandleARB(get_texture_binding(tex
)->obj
);
5139 glMakeTextureHandleResidentARB(handle
);
5141 set_resident_handle(tex
, handle
, true);
5143 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
5145 "glMakeTextureHandleResidentARB error\n");
5146 piglit_report_result(PIGLIT_FAIL
);
5148 } else if (sscanf(line
, "resident texture 1D %d", &tex
) == 1) {
5151 glBindTexture(GL_TEXTURE_1D
, 0);
5153 handle
= glGetTextureHandleARB(get_texture_binding(tex
)->obj
);
5154 glMakeTextureHandleResidentARB(handle
);
5156 set_resident_handle(tex
, handle
, true);
5158 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
5160 "glMakeTextureHandleResidentARB error\n");
5161 piglit_report_result(PIGLIT_FAIL
);
5163 } else if (sscanf(line
, "resident image texture %d %31s",
5165 const GLenum img_fmt
= piglit_get_gl_enum_from_name(s
);
5168 glBindTexture(GL_TEXTURE_2D
, 0);
5170 handle
= glGetImageHandleARB(get_texture_binding(tex
)->obj
,
5171 0, GL_FALSE
, 0, img_fmt
);
5172 glMakeImageHandleResidentARB(handle
, GL_READ_WRITE
);
5174 set_resident_handle(tex
, handle
, false);
5176 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
5178 "glMakeImageHandleResidentARB error\n");
5179 piglit_report_result(PIGLIT_FAIL
);
5181 } else if (parse_str(line
, "texture integer ", &rest
)) {
5185 sscanf(rest
, "%d ( %d , %d ) ( %d, %d ) %31s",
5186 &tex
, &w
, &h
, &b
, &a
, s
);
5187 if (num_scanned
< 6) {
5189 "invalid texture integer command!\n");
5190 piglit_report_result(PIGLIT_FAIL
);
5193 int_fmt
= piglit_get_gl_enum_from_name(s
);
5195 glActiveTexture(GL_TEXTURE0
+ tex
);
5196 const GLuint handle
=
5197 piglit_integer_texture(int_fmt
, w
, h
, b
, a
);
5198 set_texture_binding(tex
, handle
, w
, h
, 1);
5200 } else if (sscanf(line
, "texture miptree %d", &tex
) == 1) {
5201 glActiveTexture(GL_TEXTURE0
+ tex
);
5202 const GLuint handle
= piglit_miptree_texture();
5203 set_texture_binding(tex
, handle
, 8, 8, 1);
5205 if (!piglit_is_core_profile
&&
5206 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5207 glEnable(GL_TEXTURE_2D
);
5208 } else if (sscanf(line
,
5209 "texture checkerboard %d %d ( %d , %d ) "
5210 "( %f , %f , %f , %f ) "
5211 "( %f , %f , %f , %f )",
5212 &tex
, &level
, &w
, &h
,
5213 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
5214 c
+ 4, c
+ 5, c
+ 6, c
+ 7) == 12) {
5215 glActiveTexture(GL_TEXTURE0
+ tex
);
5216 const GLuint handle
= piglit_checkerboard_texture(
5217 0, level
, w
, h
, w
/ 2, h
/ 2, c
+ 0, c
+ 4);
5218 set_texture_binding(tex
, handle
, w
, h
, 1);
5220 if (!piglit_is_core_profile
&&
5221 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5222 glEnable(GL_TEXTURE_2D
);
5223 } else if (sscanf(line
,
5224 "texture quads %d %d ( %d , %d ) ( %d , %d ) "
5225 "( %f , %f , %f , %f ) "
5226 "( %f , %f , %f , %f ) "
5227 "( %f , %f , %f , %f ) "
5228 "( %f , %f , %f , %f )",
5229 &tex
, &level
, &w
, &h
, &x
, &y
,
5230 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
5231 c
+ 4, c
+ 5, c
+ 6, c
+ 7,
5232 c
+ 8, c
+ 9, c
+ 10, c
+ 11,
5233 c
+ 12, c
+ 13, c
+ 14, c
+ 15) == 22) {
5234 glActiveTexture(GL_TEXTURE0
+ tex
);
5235 const GLuint handle
= piglit_quads_texture(
5236 0, level
, w
, h
, x
, y
, c
+ 0, c
+ 4, c
+ 8, c
+ 12);
5237 set_texture_binding(tex
, handle
, w
, h
, 1);
5239 if (!piglit_is_core_profile
&&
5240 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5241 glEnable(GL_TEXTURE_2D
);
5242 } else if (sscanf(line
,
5243 "texture junk 2DArray %d ( %d , %d , %d )",
5244 &tex
, &w
, &h
, &l
) == 4) {
5246 glActiveTexture(GL_TEXTURE0
+ tex
);
5247 glGenTextures(1, &texobj
);
5248 glBindTexture(GL_TEXTURE_2D_ARRAY
, texobj
);
5249 glTexImage3D(GL_TEXTURE_2D_ARRAY
, 0, GL_RGBA
,
5250 w
, h
, l
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, 0);
5251 set_texture_binding(tex
, texobj
, w
, h
, l
);
5253 } else if (parse_str(line
, "texture storage ", &rest
)) {
5254 GLenum target
, format
;
5258 REQUIRE(parse_int(rest
, &tex
, &rest
) &&
5259 parse_tex_target(rest
, &target
, &rest
) &&
5260 parse_enum_gl(rest
, &format
, &rest
) &&
5261 parse_str(rest
, "(", &rest
) &&
5262 parse_int(rest
, &l
, &rest
) &&
5263 parse_int(rest
, &w
, &rest
),
5264 "Texture storage command not understood "
5267 glActiveTexture(GL_TEXTURE0
+ tex
);
5268 glGenTextures(1, &tex_obj
);
5269 glBindTexture(target
, tex_obj
);
5271 if (!parse_int(rest
, &h
, &rest
))
5272 glTexStorage1D(target
, l
, format
, w
);
5273 else if (!parse_int(rest
, &d
, &rest
))
5274 glTexStorage2D(target
, l
, format
, w
, h
);
5276 glTexStorage3D(target
, l
, format
, w
, h
, d
);
5278 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
5279 fprintf(stderr
, "glTexStorage error\n");
5280 piglit_report_result(PIGLIT_FAIL
);
5283 if (target
== GL_TEXTURE_1D_ARRAY
)
5284 set_texture_binding(tex
, tex_obj
, w
, 1, h
);
5286 set_texture_binding(tex
, tex_obj
, w
, h
, d
);
5288 #ifdef PIGLIT_USE_OPENGL
5289 } else if (sscanf(line
,
5290 "texture rgbw 1D %d",
5292 glActiveTexture(GL_TEXTURE0
+ tex
);
5293 const GLuint handle
= piglit_rgbw_texture_1d();
5294 set_texture_binding(tex
, handle
, 4, 1, 1);
5297 } else if (sscanf(line
,
5298 "texture rgbw 3D %d",
5300 glActiveTexture(GL_TEXTURE0
+ tex
);
5301 const GLuint handle
= piglit_rgbw_texture_3d();
5302 set_texture_binding(tex
, handle
, 2, 2, 2);
5304 } else if (sscanf(line
,
5305 "texture rgbw 2DArray %d ( %d , %d , %d )",
5306 &tex
, &w
, &h
, &l
) == 4) {
5307 glActiveTexture(GL_TEXTURE0
+ tex
);
5308 const GLuint handle
= piglit_array_texture(
5309 GL_TEXTURE_2D_ARRAY
, GL_RGBA
, w
, h
, l
, GL_FALSE
);
5310 set_texture_binding(tex
, handle
, w
, h
, l
);
5312 } else if (sscanf(line
,
5313 "texture rgbw 1DArray %d ( %d , %d )",
5314 &tex
, &w
, &l
) == 3) {
5315 glActiveTexture(GL_TEXTURE0
+ tex
);
5317 const GLuint handle
= piglit_array_texture(
5318 GL_TEXTURE_1D_ARRAY
, GL_RGBA
, w
, h
, l
, GL_FALSE
);
5319 set_texture_binding(tex
, handle
, w
, 1, l
);
5321 } else if (sscanf(line
,
5322 "texture shadow2D %d ( %d , %d )",
5323 &tex
, &w
, &h
) == 3) {
5324 glActiveTexture(GL_TEXTURE0
+ tex
);
5325 const GLuint handle
= piglit_depth_texture(
5326 GL_TEXTURE_2D
, GL_DEPTH_COMPONENT
,
5328 glTexParameteri(GL_TEXTURE_2D
,
5329 GL_TEXTURE_COMPARE_MODE
,
5330 GL_COMPARE_R_TO_TEXTURE
);
5331 glTexParameteri(GL_TEXTURE_2D
,
5332 GL_TEXTURE_COMPARE_FUNC
,
5334 set_texture_binding(tex
, handle
, w
, h
, 1);
5336 if (!piglit_is_core_profile
&&
5337 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5338 glEnable(GL_TEXTURE_2D
);
5339 } else if (sscanf(line
,
5340 "texture shadowRect %d ( %d , %d )",
5341 &tex
, &w
, &h
) == 3) {
5342 glActiveTexture(GL_TEXTURE0
+ tex
);
5343 const GLuint handle
= piglit_depth_texture(
5344 GL_TEXTURE_RECTANGLE
, GL_DEPTH_COMPONENT
,
5346 glTexParameteri(GL_TEXTURE_RECTANGLE
,
5347 GL_TEXTURE_COMPARE_MODE
,
5348 GL_COMPARE_R_TO_TEXTURE
);
5349 glTexParameteri(GL_TEXTURE_RECTANGLE
,
5350 GL_TEXTURE_COMPARE_FUNC
,
5352 set_texture_binding(tex
, handle
, w
, h
, 1);
5353 } else if (sscanf(line
,
5354 "texture shadow1D %d ( %d )",
5356 glActiveTexture(GL_TEXTURE0
+ tex
);
5357 const GLuint handle
= piglit_depth_texture(
5358 GL_TEXTURE_1D
, GL_DEPTH_COMPONENT
,
5360 glTexParameteri(GL_TEXTURE_1D
,
5361 GL_TEXTURE_COMPARE_MODE
,
5362 GL_COMPARE_R_TO_TEXTURE
);
5363 glTexParameteri(GL_TEXTURE_1D
,
5364 GL_TEXTURE_COMPARE_FUNC
,
5366 set_texture_binding(tex
, handle
, w
, 1, 1);
5367 } else if (sscanf(line
,
5368 "texture shadow1DArray %d ( %d , %d )",
5369 &tex
, &w
, &l
) == 3) {
5370 glActiveTexture(GL_TEXTURE0
+ tex
);
5371 const GLuint handle
= piglit_depth_texture(
5372 GL_TEXTURE_1D_ARRAY
, GL_DEPTH_COMPONENT
,
5374 glTexParameteri(GL_TEXTURE_1D_ARRAY
,
5375 GL_TEXTURE_COMPARE_MODE
,
5376 GL_COMPARE_R_TO_TEXTURE
);
5377 glTexParameteri(GL_TEXTURE_1D_ARRAY
,
5378 GL_TEXTURE_COMPARE_FUNC
,
5380 set_texture_binding(tex
, handle
, w
, 1, l
);
5381 } else if (sscanf(line
,
5382 "texture shadow2DArray %d ( %d , %d , %d )",
5383 &tex
, &w
, &h
, &l
) == 4) {
5384 glActiveTexture(GL_TEXTURE0
+ tex
);
5385 const GLuint handle
= piglit_depth_texture(
5386 GL_TEXTURE_2D_ARRAY
, GL_DEPTH_COMPONENT
,
5388 glTexParameteri(GL_TEXTURE_2D_ARRAY
,
5389 GL_TEXTURE_COMPARE_MODE
,
5390 GL_COMPARE_R_TO_TEXTURE
);
5391 glTexParameteri(GL_TEXTURE_2D_ARRAY
,
5392 GL_TEXTURE_COMPARE_FUNC
,
5394 set_texture_binding(tex
, handle
, w
, h
, l
);
5395 } else if (sscanf(line
, "texcoord %d ( %f , %f , %f , %f )",
5396 &x
, c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 5) {
5397 glMultiTexCoord4fv(GL_TEXTURE0
+ x
, c
);
5398 } else if (parse_str(line
, "texparameter ", &rest
)) {
5399 handle_texparameter(rest
);
5400 } else if (parse_str(line
, "uniform ", &rest
)) {
5401 result
= program_must_be_in_use();
5402 set_uniform(rest
, block_data
);
5403 } else if (parse_str(line
, "subuniform ", &rest
)) {
5404 result
= program_must_be_in_use();
5405 check_shader_subroutine_support();
5406 set_subroutine_uniform(rest
);
5407 } else if (parse_str(line
, "parameter ", &rest
)) {
5408 set_parameter(rest
);
5409 } else if (parse_str(line
, "patch parameter ", &rest
)) {
5410 set_patch_parameter(rest
);
5411 } else if (parse_str(line
, "program binary save restore", &rest
)) {
5412 program_binary_save_restore(true);
5413 } else if (parse_str(line
, "provoking vertex ", &rest
)) {
5414 set_provoking_vertex(rest
);
5415 } else if (parse_str(line
, "link error", &rest
)) {
5416 link_error_expected
= true;
5418 printf("shader link error expected, but it was successful!\n");
5419 piglit_report_result(PIGLIT_FAIL
);
5421 fprintf(stderr
, "Failed to link:\n%s\n", prog_err_info
);
5423 } else if (parse_str(line
, "link success", &rest
)) {
5424 result
= program_must_be_in_use();
5425 } else if (parse_str(line
, "ubo array index ", &rest
)) {
5426 /* we allow "ubo array index" in order to not
5427 * change existing tests using ubo array index
5429 parse_ints(rest
, &block_data
.array_index
, 1, NULL
);
5430 } else if (parse_str(line
, "block array index ", &rest
)) {
5431 parse_ints(rest
, &block_data
.array_index
, 1, NULL
);
5432 } else if (parse_str(line
, "block binding ", &rest
)) {
5433 parse_ints(rest
, &block_data
.binding
, 1, NULL
);
5434 } else if (parse_str(line
, "block offset ", &rest
)) {
5435 parse_ints(rest
, &block_data
.offset
, 1, NULL
);
5436 } else if (parse_str(line
, "block matrix stride", &rest
)) {
5437 parse_ints(rest
, &block_data
.matrix_stride
, 1, NULL
);
5438 } else if (parse_str(line
, "block row major", &rest
)) {
5439 parse_ints(rest
, &block_data
.row_major
, 1, NULL
);
5440 } else if (parse_str(line
, "active uniform ", &rest
)) {
5441 active_uniform(rest
);
5442 } else if (parse_str(line
, "verify program_query", &rest
)) {
5443 verify_program_query(rest
);
5444 } else if (parse_str(line
, "verify program_interface_query ", &rest
)) {
5445 active_program_interface(rest
, block_data
);
5446 } else if (parse_str(line
, "verify query_object", &rest
)) {
5447 result
= verify_query_object_result(rest
);
5448 } else if (parse_str(line
, "vertex attrib ", &rest
)) {
5449 set_vertex_attrib(rest
);
5450 } else if (parse_str(line
, "newlist ", &rest
)) {
5453 REQUIRE(parse_enum_gl(rest
, &mode
, &rest
),
5454 "NewList mode command not understood at %s\n",
5457 list
= glGenLists(1);
5458 glNewList(list
, mode
);
5459 } else if (parse_str(line
, "endlist", NULL
)) {
5461 } else if (parse_str(line
, "calllist", NULL
)) {
5463 } else if (parse_str(line
, "deletelist", NULL
)) {
5464 glDeleteLists(list
, 1);
5465 } else if (parse_str(line
, "viewport swizzle ", &rest
)) {
5466 handle_viewport_swizzle(rest
);
5467 } else if (parse_str(line
, "light ", &rest
)) {
5469 } else if ((line
[0] != '\n') && (line
[0] != '\0')
5470 && (line
[0] != '#')) {
5471 printf("unknown command \"%s\"\n", line
);
5472 piglit_report_result(PIGLIT_FAIL
);
5477 if (result
!= PIGLIT_PASS
) {
5478 printf("Test failure on line %u\n", line_num
);
5479 full_result
= result
;
5485 if (!link_ok
&& !link_error_expected
) {
5486 full_result
= program_must_be_in_use();
5489 piglit_present_results();
5491 if (piglit_automatic
) {
5494 /* Free our resources, useful for valgrinding. */
5495 free_subroutine_uniforms();
5497 for (i
= 0; i
< ARRAY_SIZE(resident_handles
); i
++)
5498 clear_resident_handle(i
);
5500 for (i
= 0; i
< ARRAY_SIZE(texture_bindings
); i
++)
5501 clear_texture_binding(i
);
5504 glDeleteProgram(prog
);
5508 glDeleteProgramsARB(1, &prog
);
5512 glDeleteProgramPipelines(1, &pipeline
);
5518 static enum piglit_result
5519 init_test(const char *file
)
5521 enum piglit_result result
;
5523 result
= process_test_script(file
);
5524 if (result
!= PIGLIT_PASS
)
5527 result
= link_and_use_shaders();
5528 if (result
!= PIGLIT_PASS
)
5532 glBindProgramPipeline(pipeline
);
5534 if (link_ok
&& vertex_data_start
!= NULL
) {
5535 result
= program_must_be_in_use();
5536 if (result
!= PIGLIT_PASS
)
5539 bind_vao_if_supported();
5541 num_vbo_rows
= setup_vbo_from_text(prog
, vertex_data_start
,
5550 recreate_gl_context(char *exec_arg
, int param_argc
, char **param_argv
)
5552 int argc
= param_argc
+ 4;
5553 char **argv
= malloc(sizeof(char*) * argc
);
5556 fprintf(stderr
, "%s: malloc failed.\n", __func__
);
5557 piglit_report_result(PIGLIT_FAIL
);
5561 memcpy(&argv
[1], param_argv
, param_argc
* sizeof(char*));
5562 argv
[argc
-3] = "-auto";
5563 argv
[argc
-2] = "-fbo";
5564 argv
[argc
-1] = "-report-subtests";
5567 gl_fw
->destroy(gl_fw
);
5570 exit(main(argc
, argv
));
5574 validate_current_gl_context(const char *filename
)
5576 struct piglit_gl_test_config config
= { 0 };
5578 if (!piglit_gl_test_config_override_size(&config
)) {
5579 config
.window_width
= DEFAULT_WINDOW_WIDTH
;
5580 config
.window_height
= DEFAULT_WINDOW_HEIGHT
;
5583 get_required_config(filename
, spirv_replaces_glsl
, &config
);
5585 if (!current_config
.supports_gl_compat_version
!=
5586 !config
.supports_gl_compat_version
)
5589 if (!current_config
.supports_gl_core_version
!=
5590 !config
.supports_gl_core_version
)
5593 if (!current_config
.supports_gl_es_version
!=
5594 !config
.supports_gl_es_version
)
5597 if (current_config
.window_width
!= config
.window_width
||
5598 current_config
.window_height
!= config
.window_height
)
5601 if (!(current_config
.window_visual
& PIGLIT_GL_VISUAL_DEPTH
) &&
5602 config
.window_visual
& PIGLIT_GL_VISUAL_DEPTH
)
5609 piglit_init(int argc
, char **argv
)
5613 bool core
= piglit_is_core_profile
;
5615 enum piglit_result result
;
5616 float default_piglit_tolerance
[4];
5618 use_get_program_binary
=
5619 piglit_strip_arg(&argc
, argv
, "-get-program-binary") ||
5620 piglit_env_var_as_boolean("SHADER_RUNNER_GET_PROGRAM_BINARY",
5623 report_subtests
= piglit_strip_arg(&argc
, argv
, "-report-subtests");
5624 force_glsl
= piglit_strip_arg(&argc
, argv
, "-glsl");
5625 ignore_missing_uniforms
= piglit_strip_arg(&argc
, argv
, "-ignore-missing-uniforms");
5627 force_no_names
= piglit_strip_arg(&argc
, argv
, "-force-no-names");
5629 if (force_glsl
&& spirv_replaces_glsl
) {
5630 printf("Options -glsl and -spirv can't be used at the same time\n");
5631 piglit_report_result(PIGLIT_FAIL
);
5634 if (spirv_replaces_glsl
)
5635 force_no_names
= true;
5638 printf("usage: shader_runner <test.shader_test> [-glsl] [-force-no-names]\n");
5642 memcpy(default_piglit_tolerance
, piglit_tolerance
,
5643 sizeof(piglit_tolerance
));
5645 piglit_require_GLSL();
5647 version_init(&gl_version
, VERSION_GL
,
5650 piglit_get_gl_version());
5651 piglit_get_glsl_version(&es
, &major
, &minor
);
5652 version_init(&glsl_version
, VERSION_GLSL
, core
, !core
, es
,
5653 (major
* 100) + minor
);
5655 #ifdef PIGLIT_USE_OPENGL
5656 if (piglit_get_gl_version() >= 32)
5657 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
5658 &gl_max_vertex_output_components
);
5659 if (piglit_get_gl_version() >= 20 ||
5660 piglit_is_extension_supported("GL_ARB_fragment_shader"))
5661 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
5662 &gl_max_fragment_uniform_components
);
5663 if (piglit_get_gl_version() >= 20 ||
5664 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5665 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
5666 &gl_max_vertex_uniform_components
);
5667 if (piglit_get_gl_version() >= 20 ||
5668 piglit_is_extension_supported("GL_ARB_vertex_shader") ||
5669 piglit_is_extension_supported("GL_ARB_geometry_shader4") ||
5670 piglit_is_extension_supported("GL_EXT_geometry_shader4"))
5671 glGetIntegerv(GL_MAX_VARYING_COMPONENTS
,
5672 &gl_max_varying_components
);
5674 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
5675 &gl_max_fragment_uniform_components
);
5676 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
5677 &gl_max_vertex_uniform_components
);
5678 glGetIntegerv(GL_MAX_VARYING_VECTORS
,
5679 &gl_max_varying_components
);
5680 gl_max_fragment_uniform_components
*= 4;
5681 gl_max_vertex_uniform_components
*= 4;
5682 gl_max_varying_components
*= 4;
5684 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max_clip_planes
);
5686 if (gl_version
.num
>= 20 ||
5687 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5688 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS
,
5689 &gl_max_vertex_attribs
);
5691 gl_max_vertex_attribs
= 16;
5693 read_width
= render_width
= piglit_width
;
5694 read_height
= render_height
= piglit_height
;
5696 #ifdef PIGLIT_USE_OPENGL
5697 if (piglit_is_extension_supported("GL_ARB_get_program_binary"))
5698 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
5699 &gl_num_program_binary_formats
);
5701 if (piglit_is_extension_supported("GL_OES_get_program_binary"))
5702 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES
,
5703 &gl_num_program_binary_formats
);
5706 if (use_get_program_binary
) {
5707 if (gl_num_program_binary_formats
== 0) {
5708 printf("Trying to use get_program_binary, but "
5709 "GL_NUM_PROGRAM_BINARY == 0\n");
5710 piglit_report_result(PIGLIT_SKIP
);
5714 /* Run multiple tests per session. */
5716 char testname
[4096], *ext
;
5718 enum piglit_result all
= PIGLIT_PASS
;
5720 for (i
= 1; i
< argc
; i
++) {
5721 const char *hit
, *filename
= argv
[i
];
5723 memcpy(piglit_tolerance
, default_piglit_tolerance
,
5724 sizeof(piglit_tolerance
));
5726 for (unsigned i
= 0; i
< ARRAY_SIZE(specializations
); i
++) {
5727 free(specializations
[i
].indices
);
5728 free(specializations
[i
].values
);
5730 memset(specializations
, 0, sizeof(specializations
));
5732 /* Re-initialize the GL context if a different GL config is required. */
5733 if (!validate_current_gl_context(filename
))
5734 recreate_gl_context(argv
[0], argc
- i
, argv
+ i
);
5736 /* Clear global variables to defaults. */
5738 assert(num_vertex_shaders
== 0);
5739 assert(num_tess_ctrl_shaders
== 0);
5740 assert(num_tess_eval_shaders
== 0);
5741 assert(num_geometry_shaders
== 0);
5742 assert(num_fragment_shaders
== 0);
5743 assert(num_compute_shaders
== 0);
5744 assert(num_uniform_blocks
== 0);
5745 assert(uniform_block_bos
== NULL
);
5746 assert(uniform_block_indexes
== NULL
);
5747 geometry_layout_input_type
= GL_TRIANGLES
;
5748 geometry_layout_output_type
= GL_TRIANGLE_STRIP
;
5749 geometry_layout_vertices_out
= 0;
5750 memset(atomics_bos
, 0, sizeof(atomics_bos
));
5751 memset(ssbo
, 0, sizeof(ssbo
));
5752 for (j
= 0; j
< ARRAY_SIZE(subuniform_locations
); j
++)
5753 assert(subuniform_locations
[j
] == NULL
);
5754 memset(num_subuniform_locations
, 0, sizeof(num_subuniform_locations
));
5755 shader_string
= NULL
;
5756 shader_string_size
= 0;
5757 vertex_data_start
= NULL
;
5758 vertex_data_end
= NULL
;
5760 sso_vertex_prog
= 0;
5761 sso_tess_control_prog
= 0;
5762 sso_tess_eval_prog
= 0;
5763 sso_geometry_prog
= 0;
5764 sso_fragment_prog
= 0;
5765 sso_compute_prog
= 0;
5767 vbo_present
= false;
5769 prog_in_use
= false;
5771 separable_program
= false;
5772 prog_err_info
= NULL
;
5775 /* Clear GL states to defaults. */
5776 glClearColor(0, 0, 0, 0);
5777 # if PIGLIT_USE_OPENGL
5782 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
5783 glActiveTexture(GL_TEXTURE0
);
5785 glDisable(GL_DEPTH_TEST
);
5786 glBindBuffer(GL_ARRAY_BUFFER
, 0);
5788 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
5790 for (int k
= 0; k
< gl_max_clip_planes
; k
++) {
5791 static const GLdouble zero
[4];
5793 if (!piglit_is_core_profile
&& !es
)
5794 glClipPlane(GL_CLIP_PLANE0
+ k
, zero
);
5795 glDisable(GL_CLIP_PLANE0
+ k
);
5798 if (!(es
) && (gl_version
.num
>= 20 ||
5799 piglit_is_extension_supported("GL_ARB_vertex_program")))
5800 glDisable(GL_PROGRAM_POINT_SIZE
);
5802 for (int i
= 0; i
< 16; i
++)
5803 glDisableVertexAttribArray(i
);
5805 if (!piglit_is_core_profile
&& !es
) {
5806 glMatrixMode(GL_PROJECTION
);
5808 glMatrixMode(GL_MODELVIEW
);
5810 glShadeModel(GL_SMOOTH
);
5811 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE
);
5814 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
5815 glDisable(GL_VERTEX_PROGRAM_ARB
);
5816 glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, 0);
5818 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
5819 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
5820 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, 0);
5822 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
5824 glGenProgramPipelines(1, &pipeline
);
5825 glBindProgramPipeline(0);
5828 if (piglit_is_extension_supported("GL_EXT_provoking_vertex"))
5829 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT
);
5831 # if PIGLIT_USE_OPENGL
5832 if (gl_version
.num
>= 40 ||
5833 piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
5834 static float ones
[] = {1, 1, 1, 1};
5835 glPatchParameteri(GL_PATCH_VERTICES
, 3);
5836 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL
, ones
);
5837 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL
, ones
);
5840 /* Ideally one would use the following code:
5842 * if (gl_version.num >= 32) {
5843 * glPatchParameteri(GL_PATCH_VERTICES, 3);
5846 * however, that doesn't work with mesa because those
5847 * symbols apparently need to be exported, but that
5848 * breaks non-gles builds.
5850 * It seems rather unlikely that an implementation
5851 * would have GLES 3.2 support but not
5852 * OES_tessellation_shader.
5854 if (piglit_is_extension_supported("GL_OES_tessellation_shader")) {
5855 glPatchParameteriOES(GL_PATCH_VERTICES_OES
, 3);
5859 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
5861 /* Strip the file path. */
5862 hit
= strrchr(filename
, PIGLIT_PATH_SEP
);
5864 strcpy(testname
, hit
+1);
5866 strcpy(testname
, filename
);
5868 /* Strip the file extension. */
5869 ext
= strstr(testname
, ".shader_test");
5870 if (ext
&& !ext
[12])
5873 /* Print the name before we start the test, that way if
5874 * the test fails we can still resume and know which
5876 printf("PIGLIT TEST: %i - %s\n", test_num
, testname
);
5877 fprintf(stderr
, "PIGLIT TEST: %i - %s\n", test_num
, testname
);
5881 result
= init_test(filename
);
5883 if (result
== PIGLIT_PASS
) {
5884 result
= piglit_display();
5886 /* Use subtest when running with more than one test,
5887 * but use regular test result when running with just
5888 * one. This allows the standard process-at-a-time
5889 * mode to keep working.
5891 if (report_subtests
) {
5892 piglit_report_subtest_result(
5893 result
, "%s", testname
);
5895 piglit_merge_result(&all
, result
);
5898 /* destroy GL objects? */
5902 teardown_shader_include_paths();
5905 if (!report_subtests
)
5906 piglit_report_result(all
);
5910 result
= init_test(argv
[1]);
5911 if (result
!= PIGLIT_PASS
)
5912 piglit_report_result(result
);