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_uint(GLuint ref
, GLuint value
, enum comparison cmp
)
966 case equal
: return value
== ref
;
967 case not_equal
: return value
!= ref
;
968 case less
: return value
< ref
;
969 case greater_equal
: return value
>= ref
;
970 case greater
: return value
> ref
;
971 case less_equal
: return value
<= ref
;
974 assert(!"Should not get here.");
979 compare_int(GLint ref
, GLint 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 * Get the string representation of a comparison operator
998 comparison_string(enum comparison cmp
)
1001 case equal
: return "==";
1002 case not_equal
: return "!=";
1003 case less
: return "<";
1004 case greater_equal
: return ">=";
1005 case greater
: return ">";
1006 case less_equal
: return "<=";
1009 assert(!"Should not get here.");
1014 * " ES" before the comparison operator indicates the version
1015 * pertains to GL ES.
1018 parse_version_comparison(const char *line
, enum comparison
*cmp
,
1019 struct component_version
*v
, enum version_tag tag
)
1024 const bool core
= parse_str(line
, "CORE", &line
);
1025 const bool compat
= parse_str(line
, "COMPAT", &line
);
1026 const bool es
= parse_str(line
, "ES", &line
);
1028 REQUIRE(parse_comparison_op(line
, cmp
, &line
),
1029 "Invalid comparison operation at: %s\n", line
);
1031 REQUIRE(parse_uint(line
, &major
, &line
) &&
1032 parse_str(line
, ".", &line
) &&
1033 parse_uint(line
, &minor
, &line
),
1034 "Invalid version string: %s\n", line
);
1036 parse_whitespace(line
, &line
);
1037 if (*line
!= '\n') {
1038 printf("Unexpected characters following version comparison\n");
1039 piglit_report_result(PIGLIT_FAIL
);
1042 /* This hack is so that we can tell the difference between GL versions
1043 * and GLSL versions. All GL versions look like 3.2, and we want the
1044 * integer to be 32. All GLSL versions look like 1.40, and we want
1045 * the integer to be 140.
1047 if (tag
== VERSION_GLSL
) {
1048 full_num
= (major
* 100) + minor
;
1050 full_num
= (major
* 10) + minor
;
1053 version_init(v
, tag
, core
, compat
, es
, full_num
);
1057 * Parse and check a line from the requirement section of the test
1059 static enum piglit_result
1060 process_requirement(const char *line
)
1063 static const struct {
1067 } getint_limits
[] = {
1069 "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
1070 &gl_max_vertex_output_components
,
1071 "vertex output components",
1074 "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
1075 &gl_max_fragment_uniform_components
,
1076 "fragment uniform components",
1079 "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
1080 &gl_max_vertex_uniform_components
,
1081 "vertex uniform components",
1084 "GL_MAX_VERTEX_ATTRIBS",
1085 &gl_max_vertex_attribs
,
1089 "GL_MAX_VARYING_COMPONENTS",
1090 &gl_max_varying_components
,
1091 "varying components",
1094 "GL_NUM_PROGRAM_BINARY_FORMATS",
1095 &gl_num_program_binary_formats
,
1096 "num program binary formats",
1101 /* The INT keyword in the requirements section causes
1102 * shader_runner to read the specified integer value and
1103 * processes the given requirement.
1105 if (parse_str(line
, "INT ", &line
)) {
1106 enum comparison cmp
;
1107 int comparison_value
, gl_int_value
;
1110 REQUIRE(parse_enum_gl(line
, &int_enum
, &line
),
1111 "Invalid comparison enum at: %s\n", line
);
1112 REQUIRE(parse_comparison_op(line
, &cmp
, &line
),
1113 "Invalid comparison operation at: %s\n", line
);
1114 REQUIRE(parse_int(line
, &comparison_value
, &line
),
1115 "Invalid comparison value at: %s\n", line
);
1117 glGetIntegerv(int_enum
, &gl_int_value
);
1118 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
1119 fprintf(stderr
, "Error reading %s\n",
1120 piglit_get_gl_enum_name(int_enum
));
1124 if (!compare(comparison_value
, gl_int_value
, cmp
)) {
1125 printf("Test requires %s %s %i. "
1126 "The driver supports %i.\n",
1127 piglit_get_gl_enum_name(int_enum
),
1128 comparison_string(cmp
),
1137 /* There are five types of requirements that a test can currently
1140 * * Require that some GL extension be supported
1141 * * Require some particular versions of GL
1142 * * Require some particular versions of GLSL
1143 * * Require some particular number of uniform components
1144 * * Require shaders be built as separate shader objects
1146 * The tests for GL and GLSL versions can be equal, not equal,
1147 * less, less-or-equal, greater, or greater-or-equal. Extension tests
1148 * can also require that a particular extension not be supported by
1149 * prepending ! to the extension name.
1151 for (i
= 0; i
< ARRAY_SIZE(getint_limits
); i
++) {
1152 enum comparison cmp
;
1155 if (!parse_str(line
, getint_limits
[i
].name
, &line
))
1158 REQUIRE(parse_comparison_op(line
, &cmp
, &line
),
1159 "Invalid comparison operation at: %s\n", line
);
1161 maxcomp
= atoi(line
);
1162 if (!compare(maxcomp
, *getint_limits
[i
].val
, cmp
)) {
1163 printf("Test requires %s %s %i. "
1164 "The driver supports %i.\n",
1165 getint_limits
[i
].desc
,
1166 comparison_string(cmp
),
1168 *getint_limits
[i
].val
);
1174 if (parse_str(line
, "GL_", NULL
) &&
1175 parse_word_copy(line
, buffer
, sizeof(buffer
), &line
)) {
1176 if (!piglit_is_extension_supported(buffer
)) {
1177 printf("Test requires unsupported extension %s\n", buffer
);
1180 } else if (parse_str(line
, "!", &line
) &&
1181 parse_str(line
, "GL_", NULL
) &&
1182 parse_word_copy(line
, buffer
, sizeof(buffer
), &line
)) {
1183 if (piglit_is_extension_supported(buffer
)) {
1184 printf("Test requires unsupported extension %s\n", buffer
);
1187 } else if (parse_str(line
, "GLSL", &line
)) {
1188 enum comparison cmp
;
1190 parse_version_comparison(line
, &cmp
, &glsl_req_version
,
1193 /* We only allow >= because we potentially use the
1194 * version number to insert a #version directive. */
1195 if (cmp
!= greater_equal
) {
1196 printf("Unsupported GLSL version comparison\n");
1200 if (!version_compare(&glsl_req_version
, &glsl_version
, cmp
)) {
1201 printf("Test requires %s %s. "
1202 "Actual version %s.\n",
1203 comparison_string(cmp
),
1204 version_string(&glsl_req_version
),
1205 version_string(&glsl_version
));
1208 } else if (parse_str(line
, "GL", &line
)) {
1209 enum comparison cmp
;
1210 struct component_version gl_req_version
;
1212 parse_version_comparison(line
, &cmp
, &gl_req_version
,
1215 if (!version_compare(&gl_req_version
, &gl_version
, cmp
)) {
1216 printf("Test requires %s %s. "
1217 "Actual version is %s.\n",
1218 comparison_string(cmp
),
1219 version_string(&gl_req_version
),
1220 version_string(&gl_version
));
1223 } else if (parse_str(line
, "rlimit", &line
)) {
1226 REQUIRE(parse_uint(line
, &lim
, &line
),
1227 "Invalid rlimit argument at: %s\n", line
);
1229 piglit_set_rlimit(lim
);
1230 } else if (parse_str(line
, "SSO", &line
) &&
1231 parse_str(line
, "ENABLED", NULL
)) {
1232 if (separable_program
) {
1233 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1237 const char *const ext_name
= gl_version
.es
1238 ? "GL_EXT_separate_shader_objects"
1239 : "GL_ARB_separate_shader_objects";
1240 const unsigned min_version
= gl_version
.es
1243 if (gl_version
.num
< min_version
)
1244 piglit_require_extension(ext_name
);
1247 glGenProgramPipelines(1, &pipeline
);
1248 } else if (parse_str(line
, "SEPARABLE PROGRAM", &line
) &&
1249 parse_str(line
, "ENABLED", NULL
)) {
1251 printf("SSO and SEPARABLE PROGRAM directives are incompatible.\n");
1255 const char *const ext_name
= gl_version
.es
1256 ? "GL_EXT_separate_shader_objects"
1257 : "GL_ARB_separate_shader_objects";
1258 const unsigned min_version
= gl_version
.es
1261 if (gl_version
.num
< min_version
)
1262 piglit_require_extension(ext_name
);
1264 separable_program
= true;
1265 } else if (parse_str(line
, "SPIRV", &line
)) {
1266 spirv_replaces_glsl
= !force_glsl
;
1268 if (parse_str(line
, "ONLY", NULL
)) {
1270 printf("This shader is not compatible with GLSL\n");
1273 } else if (parse_str(line
, "YES", NULL
)) {
1274 /* Empty. Everything already set. Just parsing
1278 printf("Unknown SPIRV line in [require]\n");
1282 if (spirv_replaces_glsl
)
1283 force_no_names
= true;
1290 * Process a line from the [geometry layout] section of a test
1293 process_geometry_layout(const char *line
)
1298 parse_whitespace(line
, &line
);
1300 if (line
[0] == '\0' || line
[0] == '\n') {
1302 } else if (sscanf(line
, "input type %31s", s
) == 1) {
1303 geometry_layout_input_type
= decode_drawing_mode(s
);
1304 } else if (sscanf(line
, "output type %31s", s
) == 1) {
1305 geometry_layout_output_type
= decode_drawing_mode(s
);
1306 } else if (sscanf(line
, "vertices out %d", &x
) == 1) {
1307 geometry_layout_vertices_out
= x
;
1309 printf("Could not parse geometry layout line: %s\n", line
);
1310 piglit_report_result(PIGLIT_FAIL
);
1314 static enum piglit_result
1315 leave_state(enum states state
, const char *line
, const char *script_name
)
1322 if (spirv_replaces_glsl
) {
1323 printf("Running on SPIR-V mode\n");
1325 if (force_no_names
&& !spirv_replaces_glsl
) {
1326 printf("Running on GLSL mode, forcing not using "
1327 "uniform/uniform block names\n");
1332 if (spirv_replaces_glsl
)
1334 shader_string_size
= line
- shader_string
;
1335 return compile_glsl(GL_VERTEX_SHADER
);
1337 case vertex_shader_passthrough
:
1338 if (spirv_replaces_glsl
) {
1339 shader_string
= (char *) passthrough_vertex_shader_source_spv
;
1340 shader_string_size
= strlen(passthrough_vertex_shader_source_spv
);
1342 return assemble_spirv(GL_VERTEX_SHADER
);
1344 return compile_glsl(GL_VERTEX_SHADER
);
1346 case vertex_program
:
1347 return compile_and_bind_program(GL_VERTEX_PROGRAM_ARB
,
1349 line
- shader_string
);
1351 case vertex_shader_spirv
:
1352 if (!spirv_replaces_glsl
)
1354 shader_string_size
= line
- shader_string
;
1355 return assemble_spirv(GL_VERTEX_SHADER
);
1357 case vertex_shader_specializations
:
1360 case tess_ctrl_shader
:
1361 if (spirv_replaces_glsl
)
1363 shader_string_size
= line
- shader_string
;
1364 return compile_glsl(GL_TESS_CONTROL_SHADER
);
1366 case tess_ctrl_shader_spirv
:
1367 if (!spirv_replaces_glsl
)
1369 shader_string_size
= line
- shader_string
;
1370 return assemble_spirv(GL_TESS_CONTROL_SHADER
);
1372 case tess_ctrl_shader_specializations
:
1375 case tess_eval_shader
:
1376 if (spirv_replaces_glsl
)
1378 shader_string_size
= line
- shader_string
;
1379 return compile_glsl(GL_TESS_EVALUATION_SHADER
);
1381 case tess_eval_shader_spirv
:
1382 if (!spirv_replaces_glsl
)
1384 shader_string_size
= line
- shader_string
;
1385 return assemble_spirv(GL_TESS_EVALUATION_SHADER
);
1387 case tess_eval_shader_specializations
:
1390 case geometry_shader
:
1391 if (spirv_replaces_glsl
)
1393 shader_string_size
= line
- shader_string
;
1394 return compile_glsl(GL_GEOMETRY_SHADER
);
1396 case geometry_shader_spirv
:
1397 if (!spirv_replaces_glsl
)
1399 shader_string_size
= line
- shader_string
;
1400 return assemble_spirv(GL_GEOMETRY_SHADER
);
1402 case geometry_shader_specializations
:
1405 case geometry_layout
:
1408 case fragment_shader
:
1409 if (spirv_replaces_glsl
)
1411 shader_string_size
= line
- shader_string
;
1412 return compile_glsl(GL_FRAGMENT_SHADER
);
1414 case fragment_program
:
1415 return compile_and_bind_program(GL_FRAGMENT_PROGRAM_ARB
,
1417 line
- shader_string
);
1420 case fragment_shader_spirv
:
1421 if (!spirv_replaces_glsl
)
1423 shader_string_size
= line
- shader_string
;
1424 return assemble_spirv(GL_FRAGMENT_SHADER
);
1426 case fragment_shader_specializations
:
1429 case compute_shader
:
1430 if (spirv_replaces_glsl
)
1432 shader_string_size
= line
- shader_string
;
1433 return compile_glsl(GL_COMPUTE_SHADER
);
1435 case compute_shader_spirv
:
1436 if (!spirv_replaces_glsl
)
1438 shader_string_size
= line
- shader_string
;
1439 return assemble_spirv(GL_COMPUTE_SHADER
);
1441 case compute_shader_specializations
:
1445 vertex_data_end
= line
;
1448 case shader_include
: {
1449 const char *path_end
= strchrnul(shader_string
, '\n');
1451 if (shader_string
== path_end
) {
1452 fprintf(stderr
, "No shader include path provided\n");
1456 if (!piglit_is_extension_supported("GL_ARB_shading_language_include"))
1459 int path_name_len
= path_end
- shader_string
;
1460 glNamedStringARB(GL_SHADER_INCLUDE_ARB
, path_name_len
, shader_string
,
1461 line
- shader_string
- path_name_len
, shader_string
+ path_name_len
);
1463 shader_include_names
[num_shader_includes
] = strndup(shader_string
, path_name_len
);
1464 num_shader_includes
++;
1465 assert(num_shader_includes
<= 256);
1467 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
1468 fprintf(stderr
, "glNamedStringARB error\n");
1475 case shader_include_paths
: {
1476 num_shader_include_paths
= 0;
1477 const char *cursor
= shader_string
;
1479 const char *line_start
= cursor
;
1480 cursor
= strchr(cursor
, '\n');
1482 if (cursor
== line_start
) {
1488 num_shader_include_paths
++;
1489 } while (cursor
&& cursor
< line
);
1491 shader_include_path
= calloc(num_shader_include_paths
, sizeof(char *));
1493 cursor
= shader_string
;
1494 for (unsigned i
= 0; i
< num_shader_include_paths
; i
++) {
1495 char *line_end
= strchr(cursor
, '\n');
1496 unsigned path_len
= line_end
- cursor
- 1;
1497 char *path
= malloc(path_len
+ 1);
1498 path
[path_len
] = '\0';
1500 memcpy(path
, cursor
, path_len
);
1501 shader_include_path
[i
] = path
;
1502 cursor
= line_end
+ 1;
1512 assert(!"Not yet supported.");
1518 static enum piglit_result
1519 process_shader(GLenum target
, unsigned num_shaders
, GLuint
*shaders
)
1521 if (num_shaders
== 0)
1525 prog
= glCreateProgram();
1526 glProgramParameteri(prog
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
1529 for (unsigned i
= 0; i
< num_shaders
; i
++) {
1530 glAttachShader(prog
, shaders
[i
]);
1533 #ifdef PIGLIT_USE_OPENGL
1534 if (geometry_layout_input_type
!= GL_TRIANGLES
) {
1535 glProgramParameteriARB(prog
, GL_GEOMETRY_INPUT_TYPE_ARB
,
1536 geometry_layout_input_type
);
1538 if (geometry_layout_output_type
!= GL_TRIANGLE_STRIP
) {
1539 glProgramParameteriARB(prog
, GL_GEOMETRY_OUTPUT_TYPE_ARB
,
1540 geometry_layout_output_type
);
1542 if (geometry_layout_vertices_out
!= 0) {
1543 glProgramParameteriARB(prog
, GL_GEOMETRY_VERTICES_OUT_ARB
,
1544 geometry_layout_vertices_out
);
1548 /* If the shaders reference piglit_vertex or piglit_tex, bind
1549 * them to some fixed attribute locations so they can be used
1550 * with piglit_draw_rect_tex() in GLES.
1552 glBindAttribLocation(prog
, PIGLIT_ATTRIB_POS
, "piglit_vertex");
1553 glBindAttribLocation(prog
, PIGLIT_ATTRIB_TEX
, "piglit_texcoord");
1556 return link_sso(target
);
1562 static enum piglit_result
1563 link_and_use_shaders(void)
1565 enum piglit_result result
;
1570 if ((num_vertex_shaders
== 0)
1571 && (num_fragment_shaders
== 0)
1572 && (num_tess_ctrl_shaders
== 0)
1573 && (num_tess_eval_shaders
== 0)
1574 && (num_geometry_shaders
== 0)
1575 && (num_compute_shaders
== 0))
1579 prog
= glCreateProgram();
1581 result
= process_shader(GL_VERTEX_SHADER
, num_vertex_shaders
, vertex_shaders
);
1582 if (result
!= PIGLIT_PASS
)
1584 result
= process_shader(GL_TESS_CONTROL_SHADER
, num_tess_ctrl_shaders
, tess_ctrl_shaders
);
1585 if (result
!= PIGLIT_PASS
)
1587 result
= process_shader(GL_TESS_EVALUATION_SHADER
, num_tess_eval_shaders
, tess_eval_shaders
);
1588 if (result
!= PIGLIT_PASS
)
1590 result
= process_shader(GL_GEOMETRY_SHADER
, num_geometry_shaders
, geometry_shaders
);
1591 if (result
!= PIGLIT_PASS
)
1593 result
= process_shader(GL_FRAGMENT_SHADER
, num_fragment_shaders
, fragment_shaders
);
1594 if (result
!= PIGLIT_PASS
)
1596 result
= process_shader(GL_COMPUTE_SHADER
, num_compute_shaders
, compute_shaders
);
1597 if (result
!= PIGLIT_PASS
)
1601 if (separable_program
)
1602 glProgramParameteri(prog
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
1604 glLinkProgram(prog
);
1608 if (!program_binary_save_restore(false))
1610 glGetProgramiv(prog
, GL_LINK_STATUS
, &ok
);
1616 glGetProgramiv(prog
, GL_INFO_LOG_LENGTH
, &size
);
1617 prog_err_info
= malloc(MAX2(size
, 1));
1618 prog_err_info
[0] = 0;
1620 glGetProgramInfoLog(prog
, size
, NULL
, prog_err_info
);
1622 result
= PIGLIT_PASS
;
1635 glGetProgramiv(prog
, GL_INFO_LOG_LENGTH
, &size
);
1636 prog_err_info
= malloc(MAX2(size
, 1));
1637 prog_err_info
[0] = 0;
1639 glGetProgramInfoLog(prog
, size
, NULL
, prog_err_info
);
1643 for (i
= 0; i
< num_vertex_shaders
; i
++) {
1644 glDeleteShader(vertex_shaders
[i
]);
1646 num_vertex_shaders
= 0;
1648 for (i
= 0; i
< num_tess_ctrl_shaders
; i
++) {
1649 glDeleteShader(tess_ctrl_shaders
[i
]);
1651 num_tess_ctrl_shaders
= 0;
1653 for (i
= 0; i
< num_tess_eval_shaders
; i
++) {
1654 glDeleteShader(tess_eval_shaders
[i
]);
1656 num_tess_eval_shaders
= 0;
1658 for (i
= 0; i
< num_geometry_shaders
; i
++) {
1659 glDeleteShader(geometry_shaders
[i
]);
1661 num_geometry_shaders
= 0;
1663 for (i
= 0; i
< num_fragment_shaders
; i
++) {
1664 glDeleteShader(fragment_shaders
[i
]);
1666 num_fragment_shaders
= 0;
1668 for (i
= 0; i
< num_compute_shaders
; i
++) {
1669 glDeleteShader(compute_shaders
[i
]);
1671 num_compute_shaders
= 0;
1676 static enum piglit_result
1677 process_specialization(enum states state
, const char *line
)
1679 const char *end
= strchrnul(line
, '\n');
1681 enum { TYPE_FLOAT
, TYPE_UINT
} type
;
1683 while (line
< end
&& isspace(*line
))
1686 if (line
>= end
|| *line
== '#')
1689 if (parse_str(line
, "uint", &next
))
1691 else if (parse_str(line
, "float", &next
))
1696 struct specialization_list
*list
;
1699 case vertex_shader_specializations
:
1700 list
= specializations
+ 0;
1702 case tess_ctrl_shader_specializations
:
1703 list
= specializations
+ 1;
1705 case tess_eval_shader_specializations
:
1706 list
= specializations
+ 2;
1708 case geometry_shader_specializations
:
1709 list
= specializations
+ 3;
1711 case fragment_shader_specializations
:
1712 list
= specializations
+ 4;
1714 case compute_shader_specializations
:
1715 list
= specializations
+ 5;
1718 assert(!"Should not get here.");
1721 if (list
->n_entries
>= list
->buffer_size
) {
1722 if (list
->buffer_size
== 0)
1723 list
->buffer_size
= 1;
1725 list
->buffer_size
*= 2;
1726 list
->indices
= realloc(list
->indices
,
1727 (sizeof list
->indices
[0]) *
1729 list
->values
= realloc(list
->values
,
1730 (sizeof list
->values
[0]) *
1734 if (parse_uints(next
, list
->indices
+ list
->n_entries
, 1, &next
) != 1)
1739 if (parse_uints(next
,
1740 &list
->values
[list
->n_entries
].u
,
1746 if (parse_floats(next
,
1747 &list
->values
[list
->n_entries
].f
,
1759 fprintf(stderr
, "Invalid specialization line\n");
1763 static enum piglit_result
1764 process_test_script(const char *script_name
)
1768 char *text
= piglit_load_text_file(script_name
, &text_size
);
1769 enum states state
= none
;
1770 const char *line
= text
;
1771 enum piglit_result result
;
1774 printf("could not read file \"%s\"\n", script_name
);
1780 while (line
[0] != '\0') {
1781 if (line
[0] == '[') {
1782 result
= leave_state(state
, line
, script_name
);
1783 if (result
!= PIGLIT_PASS
)
1786 if (parse_str(line
, "[require]", NULL
)) {
1787 state
= requirements
;
1788 } else if (parse_str(line
, "[vertex shader]", NULL
)) {
1789 state
= vertex_shader
;
1790 shader_string
= NULL
;
1791 } else if (parse_str(line
, "[vertex program]", NULL
)) {
1792 state
= vertex_program
;
1793 shader_string
= NULL
;
1794 } else if (parse_str(line
, "[vertex shader passthrough]", NULL
)) {
1795 state
= vertex_shader_passthrough
;
1797 (char *) passthrough_vertex_shader_source
;
1798 shader_string_size
= strlen(shader_string
);
1799 } else if (parse_str(line
, "[vertex shader spirv]", NULL
)) {
1800 state
= vertex_shader_spirv
;
1801 shader_string
= NULL
;
1802 } else if (parse_str(line
, "[vertex shader specializations]", NULL
)) {
1803 state
= vertex_shader_specializations
;
1804 } else if (parse_str(line
, "[tessellation control shader]", NULL
)) {
1805 state
= tess_ctrl_shader
;
1806 shader_string
= NULL
;
1807 } else if (parse_str(line
, "[tessellation control shader spirv]", NULL
)) {
1808 state
= tess_ctrl_shader_spirv
;
1809 shader_string
= NULL
;
1810 } else if (parse_str(line
, "[tessellation control shader specializations]", NULL
)) {
1811 state
= tess_ctrl_shader_specializations
;
1812 } else if (parse_str(line
, "[tessellation evaluation shader]", NULL
)) {
1813 state
= tess_eval_shader
;
1814 shader_string
= NULL
;
1815 } else if (parse_str(line
, "[tessellation evaluation shader spirv]", NULL
)) {
1816 state
= tess_eval_shader_spirv
;
1817 shader_string
= NULL
;
1818 } else if (parse_str(line
, "[tessellation evaluation shader specializations]", NULL
)) {
1819 state
= tess_eval_shader_specializations
;
1820 } else if (parse_str(line
, "[geometry shader]", NULL
)) {
1821 state
= geometry_shader
;
1822 shader_string
= NULL
;
1823 } else if (parse_str(line
, "[geometry shader specializations]", NULL
)) {
1824 state
= geometry_shader_specializations
;
1825 } else if (parse_str(line
, "[geometry shader spirv]", NULL
)) {
1826 state
= geometry_shader_spirv
;
1827 shader_string
= NULL
;
1828 } else if (parse_str(line
, "[geometry shader specializations]", NULL
)) {
1829 state
= geometry_shader_specializations
;
1830 } else if (parse_str(line
, "[geometry layout]", NULL
)) {
1831 state
= geometry_layout
;
1832 shader_string
= NULL
;
1833 } else if (parse_str(line
, "[fragment shader]", NULL
)) {
1834 state
= fragment_shader
;
1835 shader_string
= NULL
;
1836 } else if (parse_str(line
, "[fragment program]", NULL
)) {
1837 state
= fragment_program
;
1838 shader_string
= NULL
;
1839 } else if (parse_str(line
, "[fragment shader specializations]", NULL
)) {
1840 state
= fragment_shader_specializations
;
1841 } else if (parse_str(line
, "[fragment shader spirv]", NULL
)) {
1842 state
= fragment_shader_spirv
;
1843 shader_string
= NULL
;
1844 } else if (parse_str(line
, "[fragment shader specializations]", NULL
)) {
1845 state
= fragment_shader_specializations
;
1846 } else if (parse_str(line
, "[compute shader]", NULL
)) {
1847 state
= compute_shader
;
1848 shader_string
= NULL
;
1849 } else if (parse_str(line
, "[compute shader spirv]", NULL
)) {
1850 state
= compute_shader_spirv
;
1851 shader_string
= NULL
;
1852 } else if (parse_str(line
, "[compute shader specializations]", NULL
)) {
1853 state
= compute_shader_specializations
;
1854 } else if (parse_str(line
, "[vertex data]", NULL
)) {
1855 state
= vertex_data
;
1856 vertex_data_start
= NULL
;
1857 } else if (parse_str(line
, "[shader include]", NULL
)) {
1858 state
= shader_include
;
1859 shader_string
= NULL
;
1860 } else if (parse_str(line
, "[shader include paths]", NULL
)) {
1861 state
= shader_include_paths
;
1862 shader_string
= NULL
;
1863 } else if (parse_str(line
, "[test]", NULL
)) {
1864 test_start
= strchrnul(line
, '\n');
1865 test_start_line_num
= line_num
+ 1;
1866 if (test_start
[0] != '\0')
1871 "Unknown section in test script. "
1872 "Perhaps missing closing ']'?\n");
1878 case vertex_shader_passthrough
:
1882 result
= process_requirement(line
);
1883 if (result
!= PIGLIT_PASS
)
1887 case geometry_layout
:
1888 process_geometry_layout(line
);
1892 case vertex_program
:
1893 case tess_ctrl_shader
:
1894 case tess_eval_shader
:
1895 case geometry_shader
:
1896 case fragment_shader
:
1897 case fragment_program
:
1898 case compute_shader
:
1899 case vertex_shader_spirv
:
1900 case tess_ctrl_shader_spirv
:
1901 case tess_eval_shader_spirv
:
1902 case geometry_shader_spirv
:
1903 case fragment_shader_spirv
:
1904 case compute_shader_spirv
:
1905 case shader_include
:
1906 case shader_include_paths
:
1907 if (shader_string
== NULL
)
1908 shader_string
= (char *) line
;
1911 case vertex_shader_specializations
:
1912 case tess_ctrl_shader_specializations
:
1913 case tess_eval_shader_specializations
:
1914 case geometry_shader_specializations
:
1915 case fragment_shader_specializations
:
1916 case compute_shader_specializations
: {
1917 enum piglit_result result
=
1918 process_specialization(state
, line
);
1919 if (result
!= PIGLIT_PASS
)
1925 if (vertex_data_start
== NULL
)
1926 vertex_data_start
= line
;
1934 line
= strchrnul(line
, '\n');
1935 if (line
[0] != '\0')
1941 return leave_state(state
, line
, script_name
);
1944 struct requirement_parse_results
{
1948 bool found_depthbuffer
;
1949 struct component_version gl_version
;
1950 struct component_version glsl_version
;
1955 parse_required_config(struct requirement_parse_results
*results
,
1956 const char *script_name
)
1959 char *text
= piglit_load_text_file(script_name
, &text_size
);
1960 const char *line
= text
;
1961 bool in_requirement_section
= false;
1963 results
->found_gl
= false;
1964 results
->found_glsl
= false;
1965 results
->found_size
= false;
1966 results
->found_depthbuffer
= false;
1969 printf("could not read file \"%s\"\n", script_name
);
1970 piglit_report_result(PIGLIT_FAIL
);
1973 while (line
[0] != '\0') {
1974 if (line
[0] == '[') {
1975 if (in_requirement_section
)
1978 in_requirement_section
= false;
1981 if (!in_requirement_section
) {
1982 if (parse_str(line
, "[require]", NULL
)) {
1983 in_requirement_section
= true;
1986 if (parse_str(line
, "GL_", NULL
)
1987 || parse_str(line
, "!GL_", NULL
)) {
1989 } else if (parse_str(line
, "GLSL", &line
)) {
1990 enum comparison cmp
;
1991 struct component_version version
;
1993 parse_version_comparison(line
, &cmp
,
1994 &version
, VERSION_GLSL
);
1995 if (cmp
== greater_equal
) {
1996 results
->found_glsl
= true;
1997 version_copy(&results
->glsl_version
, &version
);
1999 } else if (parse_str(line
, "GL", &line
)) {
2000 enum comparison cmp
;
2001 struct component_version version
;
2003 parse_version_comparison(line
, &cmp
,
2004 &version
, VERSION_GL
);
2005 if (cmp
== greater_equal
2008 results
->found_gl
= true;
2009 version_copy(&results
->gl_version
, &version
);
2011 } else if (parse_str(line
, "SIZE", &line
)) {
2012 results
->found_size
= true;
2013 parse_uints(line
, results
->size
, 2, NULL
);
2014 } else if (parse_str(line
, "depthbuffer", NULL
)) {
2015 results
->found_depthbuffer
= true;
2019 line
= strchrnul(line
, '\n');
2020 if (line
[0] != '\0')
2026 if (!in_requirement_section
) {
2027 printf("[require] section missing\n");
2028 piglit_report_result(PIGLIT_FAIL
);
2031 if (results
->found_glsl
&& results
->glsl_version
.es
&& !results
->found_gl
) {
2032 printf("%s", "The test specifies a requirement for GLSL ES, "
2033 "but specifies no GL requirement\n.");
2034 piglit_report_result(PIGLIT_FAIL
);
2040 choose_required_gl_version(struct requirement_parse_results
*parse_results
,
2041 struct component_version
*gl_version
)
2043 if (parse_results
->found_gl
) {
2044 version_copy(gl_version
, &parse_results
->gl_version
);
2046 assert(!parse_results
->found_glsl
|| !parse_results
->glsl_version
.es
);
2047 version_init(gl_version
, VERSION_GL
, false, false, false, 10);
2053 /* Possibly promote the GL version. */
2054 if (parse_results
->found_glsl
2055 && gl_version
->num
< required_gl_version_from_glsl_version(
2056 parse_results
->glsl_version
.num
)) {
2057 gl_version
->num
= required_gl_version_from_glsl_version(
2058 parse_results
->glsl_version
.num
);
2063 * Just determine the GLSL version required by the shader script.
2065 * This function is a bit of a hack that is, unfortunately necessary. A test
2066 * script can require a specific GLSL version or a specific GL version. To
2067 * satisfy this requirement, the piglit framework code needs to know about the
2068 * requirement before creating the context. However, the requirements section
2069 * can contain other requirements, such as minimum number of uniforms.
2071 * The requirements section can't be fully processed until after the context
2072 * is created, but the context can't be created until after the requirements
2073 * section is processed. Do a quick scan over the requirements section to find
2074 * the GL and GLSL version requirements. Use these to guide context creation.
2077 get_required_config(const char *script_name
, bool spirv
,
2078 struct piglit_gl_test_config
*config
)
2080 struct requirement_parse_results parse_results
;
2081 struct component_version required_gl_version
;
2083 parse_required_config(&parse_results
, script_name
);
2084 choose_required_gl_version(&parse_results
, &required_gl_version
);
2087 required_gl_version
.es
= false;
2088 required_gl_version
.core
= true;
2089 required_gl_version
.num
= MAX2(required_gl_version
.num
, 33);
2092 if (parse_results
.found_size
) {
2093 config
->window_width
= parse_results
.size
[0];
2094 config
->window_height
= parse_results
.size
[1];
2097 if (required_gl_version
.es
) {
2098 config
->supports_gl_es_version
= required_gl_version
.num
;
2099 } else if (required_gl_version
.num
>= 31) {
2100 if (!required_gl_version
.compat
)
2101 config
->supports_gl_core_version
= required_gl_version
.num
;
2102 if (!required_gl_version
.core
)
2103 config
->supports_gl_compat_version
= required_gl_version
.num
;
2105 config
->supports_gl_compat_version
= 10;
2108 if (parse_results
.found_depthbuffer
) {
2109 config
->window_visual
|= PIGLIT_GL_VISUAL_DEPTH
;
2114 * Check that the GL implementation supports unsigned uniforms
2115 * (e.g. through glUniform1ui). If not, terminate the test with a
2119 check_unsigned_support(void)
2121 if (gl_version
.num
< 30 && !piglit_is_extension_supported("GL_EXT_gpu_shader4"))
2122 piglit_report_result(PIGLIT_SKIP
);
2126 * Check that the GL implementation supports double uniforms
2127 * (e.g. through glUniform1d). If not, terminate the test with a
2131 check_double_support(void)
2133 if (gl_version
.num
< 40 && !piglit_is_extension_supported("GL_ARB_gpu_shader_fp64"))
2134 piglit_report_result(PIGLIT_SKIP
);
2138 * Check that the GL implementation supports double uniforms
2139 * (e.g. through glUniform1d). If not, terminate the test with a
2143 check_int64_support(void)
2145 if (!piglit_is_extension_supported("GL_ARB_gpu_shader_int64"))
2146 piglit_report_result(PIGLIT_SKIP
);
2150 * Check that the GL implementation supports shader subroutines
2151 * If not, terminate the test with a SKIP.
2154 check_shader_subroutine_support(void)
2156 if (gl_version
.num
< 40 && !piglit_is_extension_supported("GL_ARB_shader_subroutine"))
2157 piglit_report_result(PIGLIT_SKIP
);
2161 * Check that the GL implementation supports texture handles.
2162 * If not, terminate the test with a SKIP.
2165 check_texture_handle_support(void)
2167 if (!piglit_is_extension_supported("GL_ARB_bindless_texture"))
2168 piglit_report_result(PIGLIT_SKIP
);
2172 get_indexes_and_offset_from_ubo(char *name
, struct block_info block_data
,
2173 GLuint
*uniform_index_out
,
2174 GLint
*block_index_out
,
2178 * Handles uploads of UBO uniforms by mapping the buffer and storing
2179 * the data. If the uniform is not in a uniform block, returns false.
2182 set_ubo_uniform(char *name
, const char *type
,
2184 struct block_info block_data
)
2186 /* Note: on SPIR-V we can't access to uniform_index as we
2187 * could lack the name. We force that with force_no_names on
2190 GLuint uniform_index
;
2198 uint64_t uint64s
[16];
2201 if (!get_indexes_and_offset_from_ubo(name
, block_data
, &uniform_index
,
2202 &block_index
, &offset
)) {
2206 glBindBuffer(GL_UNIFORM_BUFFER
,
2207 uniform_block_bos
[block_index
]);
2208 data
= glMapBuffer(GL_UNIFORM_BUFFER
, GL_WRITE_ONLY
);
2211 if (parse_str(type
, "float", NULL
)) {
2212 parse_floats(line
, f
, 1, NULL
);
2213 memcpy(data
, f
, sizeof(float));
2214 } else if (parse_str(type
, "int64_t", NULL
)) {
2215 parse_int64s(line
, int64s
, 1, NULL
);
2216 memcpy(data
, int64s
, sizeof(int64_t));
2217 } else if (parse_str(type
, "uint64_t", NULL
)) {
2218 parse_uint64s(line
, uint64s
, 1, NULL
);
2219 memcpy(data
, uint64s
, sizeof(uint64_t));
2220 } else if (parse_str(type
, "int", NULL
)) {
2221 parse_ints(line
, ints
, 1, NULL
);
2222 memcpy(data
, ints
, sizeof(int));
2223 } else if (parse_str(type
, "uint", NULL
)) {
2224 parse_uints(line
, uints
, 1, NULL
);
2225 memcpy(data
, uints
, sizeof(int));
2226 } else if (parse_str(type
, "double", NULL
)) {
2227 parse_doubles(line
, d
, 1, NULL
);
2228 memcpy(data
, d
, sizeof(double));
2229 } else if (parse_str(type
, "vec", NULL
)) {
2230 int elements
= type
[3] - '0';
2231 parse_floats(line
, f
, elements
, NULL
);
2232 memcpy(data
, f
, elements
* sizeof(float));
2233 } else if (parse_str(type
, "ivec", NULL
)) {
2234 int elements
= type
[4] - '0';
2235 parse_ints(line
, ints
, elements
, NULL
);
2236 memcpy(data
, ints
, elements
* sizeof(int));
2237 } else if (parse_str(type
, "uvec", NULL
)) {
2238 int elements
= type
[4] - '0';
2239 parse_uints(line
, uints
, elements
, NULL
);
2240 memcpy(data
, uints
, elements
* sizeof(unsigned));
2241 } else if (parse_str(type
, "i64vec", NULL
)) {
2242 int elements
= type
[6] - '0';
2243 parse_int64s(line
, int64s
, elements
, NULL
);
2244 memcpy(data
, int64s
, elements
* sizeof(int64_t));
2245 } else if (parse_str(type
, "u64vec", NULL
)) {
2246 int elements
= type
[6] - '0';
2247 parse_uint64s(line
, uint64s
, elements
, NULL
);
2248 memcpy(data
, uint64s
, elements
* sizeof(uint64_t));
2249 } else if (parse_str(type
, "dvec", NULL
)) {
2250 int elements
= type
[4] - '0';
2251 parse_doubles(line
, d
, elements
, NULL
);
2252 memcpy(data
, d
, elements
* sizeof(double));
2253 } else if (parse_str(type
, "mat", NULL
)) {
2254 GLint matrix_stride
, row_major
;
2255 int cols
= type
[3] - '0';
2256 int rows
= type
[4] == 'x' ? type
[5] - '0' : cols
;
2258 float *matrixdata
= (float *)data
;
2260 assert(cols
>= 2 && cols
<= 4);
2261 assert(rows
>= 2 && rows
<= 4);
2263 parse_floats(line
, f
, rows
* cols
, NULL
);
2265 if (!force_no_names
) {
2266 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2267 GL_UNIFORM_MATRIX_STRIDE
,
2269 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2270 GL_UNIFORM_IS_ROW_MAJOR
,
2273 matrix_stride
= block_data
.matrix_stride
;
2274 row_major
= block_data
.row_major
;
2277 matrix_stride
/= sizeof(float);
2279 /* Expect the data in the .shader_test file to be listed in
2280 * column-major order no matter what the layout of the data in
2283 for (c
= 0; c
< cols
; c
++) {
2284 for (r
= 0; r
< rows
; r
++) {
2286 matrixdata
[matrix_stride
* r
+ c
] =
2289 matrixdata
[matrix_stride
* c
+ r
] =
2294 } else if (parse_str(type
, "dmat", NULL
)) {
2295 GLint matrix_stride
, row_major
;
2296 int cols
= type
[4] - '0';
2297 int rows
= type
[5] == 'x' ? type
[6] - '0' : cols
;
2299 double *matrixdata
= (double *)data
;
2301 assert(cols
>= 2 && cols
<= 4);
2302 assert(rows
>= 2 && rows
<= 4);
2304 parse_doubles(line
, d
, rows
* cols
, NULL
);
2306 if (!force_no_names
) {
2307 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2308 GL_UNIFORM_MATRIX_STRIDE
,
2310 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2311 GL_UNIFORM_IS_ROW_MAJOR
,
2314 matrix_stride
= block_data
.matrix_stride
;
2315 row_major
= block_data
.row_major
;
2318 matrix_stride
/= sizeof(double);
2320 /* Expect the data in the .shader_test file to be listed in
2321 * column-major order no matter what the layout of the data in
2324 for (c
= 0; c
< cols
; c
++) {
2325 for (r
= 0; r
< rows
; r
++) {
2327 matrixdata
[matrix_stride
* r
+ c
] =
2330 matrixdata
[matrix_stride
* c
+ r
] =
2335 } else if (parse_str(type
, "handle", NULL
)) {
2336 check_unsigned_support();
2337 check_texture_handle_support();
2338 parse_uints(line
, uints
, 1, NULL
);
2339 GLuint64 handle
= get_resident_handle(uints
[0])->handle
;
2340 memcpy(data
, &handle
, sizeof(uint64_t));
2342 printf("unknown uniform type \"%s\" for \"%s\"\n", type
, name
);
2343 piglit_report_result(PIGLIT_FAIL
);
2346 glUnmapBuffer(GL_UNIFORM_BUFFER
);
2352 * Get the uniform_index, block_index and offset of a given
2353 * uniform. By default it gets those values using the uniform name. If
2354 * force_no_names mode is active, it uses the current values stored at
2355 * @block_data. On the latter, uniform index is not filled up.
2358 get_indexes_and_offset_from_ubo(char *name
, struct block_info block_data
,
2359 GLuint
*uniform_index_out
,
2360 GLint
*block_index_out
,
2363 GLuint uniform_index
= 0;
2366 int name_len
= strlen(name
);
2367 GLint array_index
= 0;
2369 if (!num_uniform_blocks
)
2372 if (!force_no_names
) {
2373 /* if the uniform is an array, strip the index, as GL
2374 prevents non-zero indexes from matching a name */
2375 if (name
[name_len
- 1] == ']') {
2378 for (i
= name_len
- 1; (i
> 0) && isdigit(name
[i
-1]); --i
)
2381 array_index
= strtol(&name
[i
], NULL
, 0);
2385 if (name
[i
] != '[') {
2386 printf("cannot parse uniform \"%s\"\n", name
);
2387 piglit_report_result(PIGLIT_FAIL
);
2394 glGetUniformIndices(prog
, 1, (const char **)&name
, &uniform_index
);
2395 if (uniform_index
== GL_INVALID_INDEX
) {
2396 printf("cannot get index of uniform \"%s\"\n", name
);
2397 piglit_report_result(PIGLIT_FAIL
);
2400 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2401 GL_UNIFORM_BLOCK_INDEX
, &block_index
);
2403 if (block_index
== -1)
2406 /* if the uniform block is an array, then GetActiveUniformsiv with
2407 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2408 * element in the array.
2410 block_index
+= block_data
.array_index
;
2412 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2413 GL_UNIFORM_OFFSET
, &offset
);
2415 if (name
[name_len
- 1] == ']') {
2418 glGetActiveUniformsiv(prog
, 1, &uniform_index
,
2419 GL_UNIFORM_ARRAY_STRIDE
, &stride
);
2420 offset
+= stride
* array_index
;
2423 if (block_data
.binding
< 0) {
2424 printf("if you force to use a explicit ubo binding, you "
2425 "need to provide it when filling the data with "
2426 "\"ubo binding\"\n");
2427 piglit_report_result(PIGLIT_FAIL
);
2430 /* The mapping could be improved using a hash
2431 * table. For now, this is enough.
2433 block_index
= uniform_block_indexes
[block_data
.binding
];
2435 /* if the uniform block is an array, then GetActiveUniformsiv with
2436 * UNIFORM_BLOCK_INDEX will have given us the index of the first
2437 * element in the array.
2439 block_index
+= block_data
.array_index
;
2441 if (block_data
.offset
< 0) {
2442 printf("if you force to use a explicit ubo binding, you "
2443 "need to provide offset when filling the data with "
2444 "\"ubo offset\"\n");
2445 piglit_report_result(PIGLIT_FAIL
);
2447 offset
= block_data
.offset
;
2450 *offset_out
= offset
;
2451 *block_index_out
= block_index
;
2452 *uniform_index_out
= uniform_index
;
2458 set_uniform(const char *line
, struct block_info block_data
)
2460 char name
[512], type
[512];
2466 uint64_t uint64s
[16];
2469 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2470 parse_word_copy(line
, name
, sizeof(name
), &line
),
2471 "Invalid set uniform command at: %s\n", line
);
2473 if (isdigit(name
[0])) {
2474 loc
= strtol(name
, NULL
, 0);
2478 if (set_ubo_uniform(name
, type
, line
, block_data
))
2481 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2482 loc
= glGetUniformLocation(prog
, name
);
2484 if (ignore_missing_uniforms
)
2486 printf("cannot get location of uniform \"%s\"\n",
2488 piglit_report_result(PIGLIT_FAIL
);
2492 if (parse_str(type
, "float", NULL
)) {
2493 parse_floats(line
, f
, 1, NULL
);
2494 glUniform1fv(loc
, 1, f
);
2496 } else if (parse_str(type
, "int64_t", NULL
)) {
2497 check_int64_support();
2498 parse_int64s(line
, int64s
, 1, NULL
);
2499 glUniform1i64vARB(loc
, 1, int64s
);
2501 } else if (parse_str(type
, "uint64_t", NULL
)) {
2502 check_int64_support();
2503 parse_uint64s(line
, uint64s
, 1, NULL
);
2504 glUniform1ui64vARB(loc
, 1, uint64s
);
2506 } else if (parse_str(type
, "int", NULL
)) {
2507 parse_ints(line
, ints
, 1, NULL
);
2508 glUniform1iv(loc
, 1, ints
);
2510 } else if (parse_str(type
, "uint", NULL
)) {
2511 check_unsigned_support();
2512 parse_uints(line
, uints
, 1, NULL
);
2513 glUniform1uiv(loc
, 1, uints
);
2515 } else if (parse_str(type
, "double", NULL
)) {
2516 check_double_support();
2517 parse_doubles(line
, d
, 1, NULL
);
2518 glUniform1dv(loc
, 1, d
);
2520 } else if (parse_str(type
, "vec", NULL
)) {
2523 parse_floats(line
, f
, 2, NULL
);
2524 glUniform2fv(loc
, 1, f
);
2527 parse_floats(line
, f
, 3, NULL
);
2528 glUniform3fv(loc
, 1, f
);
2531 parse_floats(line
, f
, 4, NULL
);
2532 glUniform4fv(loc
, 1, f
);
2535 } else if (parse_str(type
, "ivec", NULL
)) {
2538 parse_ints(line
, ints
, 2, NULL
);
2539 glUniform2iv(loc
, 1, ints
);
2542 parse_ints(line
, ints
, 3, NULL
);
2543 glUniform3iv(loc
, 1, ints
);
2546 parse_ints(line
, ints
, 4, NULL
);
2547 glUniform4iv(loc
, 1, ints
);
2550 } else if (parse_str(type
, "uvec", NULL
)) {
2551 check_unsigned_support();
2554 parse_uints(line
, uints
, 2, NULL
);
2555 glUniform2uiv(loc
, 1, uints
);
2558 parse_uints(line
, uints
, 3, NULL
);
2559 glUniform3uiv(loc
, 1, uints
);
2562 parse_uints(line
, uints
, 4, NULL
);
2563 glUniform4uiv(loc
, 1, uints
);
2566 } else if (parse_str(type
, "dvec", NULL
)) {
2567 check_double_support();
2570 parse_doubles(line
, d
, 2, NULL
);
2571 glUniform2dv(loc
, 1, d
);
2574 parse_doubles(line
, d
, 3, NULL
);
2575 glUniform3dv(loc
, 1, d
);
2578 parse_doubles(line
, d
, 4, NULL
);
2579 glUniform4dv(loc
, 1, d
);
2582 } else if (parse_str(type
, "i64vec", NULL
)) {
2583 check_int64_support();
2586 parse_int64s(line
, int64s
, 2, NULL
);
2587 glUniform2i64vARB(loc
, 1, int64s
);
2590 parse_int64s(line
, int64s
, 3, NULL
);
2591 glUniform3i64vARB(loc
, 1, int64s
);
2594 parse_int64s(line
, int64s
, 4, NULL
);
2595 glUniform4i64vARB(loc
, 1, int64s
);
2598 } else if (parse_str(type
, "u64vec", NULL
)) {
2599 check_int64_support();
2602 parse_uint64s(line
, uint64s
, 2, NULL
);
2603 glUniform2ui64vARB(loc
, 1, uint64s
);
2606 parse_uint64s(line
, uint64s
, 3, NULL
);
2607 glUniform3ui64vARB(loc
, 1, uint64s
);
2610 parse_uint64s(line
, uint64s
, 4, NULL
);
2611 glUniform4ui64vARB(loc
, 1, uint64s
);
2614 } else if (parse_str(type
, "mat", NULL
) && type
[3] != '\0') {
2615 char cols
= type
[3];
2616 char rows
= type
[4] == 'x' ? type
[5] : cols
;
2621 parse_floats(line
, f
, 4, NULL
);
2622 glUniformMatrix2fv(loc
, 1, GL_FALSE
, f
);
2625 parse_floats(line
, f
, 6, NULL
);
2626 glUniformMatrix2x3fv(loc
, 1, GL_FALSE
, f
);
2629 parse_floats(line
, f
, 8, NULL
);
2630 glUniformMatrix2x4fv(loc
, 1, GL_FALSE
, f
);
2636 parse_floats(line
, f
, 6, NULL
);
2637 glUniformMatrix3x2fv(loc
, 1, GL_FALSE
, f
);
2640 parse_floats(line
, f
, 9, NULL
);
2641 glUniformMatrix3fv(loc
, 1, GL_FALSE
, f
);
2644 parse_floats(line
, f
, 12, NULL
);
2645 glUniformMatrix3x4fv(loc
, 1, GL_FALSE
, f
);
2651 parse_floats(line
, f
, 8, NULL
);
2652 glUniformMatrix4x2fv(loc
, 1, GL_FALSE
, f
);
2655 parse_floats(line
, f
, 12, NULL
);
2656 glUniformMatrix4x3fv(loc
, 1, GL_FALSE
, f
);
2659 parse_floats(line
, f
, 16, NULL
);
2660 glUniformMatrix4fv(loc
, 1, GL_FALSE
, f
);
2664 } else if (parse_str(type
, "dmat", NULL
) && type
[4] != '\0') {
2665 char cols
= type
[4];
2666 char rows
= type
[5] == 'x' ? type
[6] : cols
;
2671 parse_doubles(line
, d
, 4, NULL
);
2672 glUniformMatrix2dv(loc
, 1, GL_FALSE
, d
);
2675 parse_doubles(line
, d
, 6, NULL
);
2676 glUniformMatrix2x3dv(loc
, 1, GL_FALSE
, d
);
2679 parse_doubles(line
, d
, 8, NULL
);
2680 glUniformMatrix2x4dv(loc
, 1, GL_FALSE
, d
);
2686 parse_doubles(line
, d
, 6, NULL
);
2687 glUniformMatrix3x2dv(loc
, 1, GL_FALSE
, d
);
2690 parse_doubles(line
, d
, 9, NULL
);
2691 glUniformMatrix3dv(loc
, 1, GL_FALSE
, d
);
2694 parse_doubles(line
, d
, 12, NULL
);
2695 glUniformMatrix3x4dv(loc
, 1, GL_FALSE
, d
);
2701 parse_doubles(line
, d
, 8, NULL
);
2702 glUniformMatrix4x2dv(loc
, 1, GL_FALSE
, d
);
2705 parse_doubles(line
, d
, 12, NULL
);
2706 glUniformMatrix4x3dv(loc
, 1, GL_FALSE
, d
);
2709 parse_doubles(line
, d
, 16, NULL
);
2710 glUniformMatrix4dv(loc
, 1, GL_FALSE
, d
);
2714 } else if (parse_str(type
, "handle", NULL
)) {
2715 check_unsigned_support();
2716 check_texture_handle_support();
2717 parse_uints(line
, uints
, 1, NULL
);
2718 glUniformHandleui64ARB(loc
, get_resident_handle(uints
[0])->handle
);
2722 printf("unknown uniform type \"%s\"\n", type
);
2723 piglit_report_result(PIGLIT_FAIL
);
2729 set_vertex_attrib(const char *line
)
2731 char name
[512], type
[512];
2735 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2736 parse_word_copy(line
, name
, sizeof(name
), &line
),
2737 "Invalid set vertex attrib command at: %s\n", line
);
2739 if (isdigit(name
[0])) {
2740 loc
= strtol(name
, NULL
, 0);
2744 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2745 loc
= glGetAttribLocation(prog
, name
);
2747 if (ignore_missing_uniforms
)
2749 printf("cannot get location of vertex attrib \"%s\"\n",
2751 piglit_report_result(PIGLIT_FAIL
);
2755 if (parse_str(type
, "handle", NULL
)) {
2756 check_unsigned_support();
2757 check_texture_handle_support();
2758 parse_uints(line
, uints
, 1, NULL
);
2759 glVertexAttribL1ui64ARB(loc
, get_resident_handle(uints
[0])->handle
);
2763 printf("unknown vertex attrib type \"%s\"\n", type
);
2764 printf("use [vertex data] instead if possible\n");
2765 piglit_report_result(PIGLIT_FAIL
);
2770 static GLenum
lookup_shader_type(GLuint idx
)
2774 return GL_VERTEX_SHADER
;
2776 return GL_FRAGMENT_SHADER
;
2778 return GL_GEOMETRY_SHADER
;
2780 return GL_TESS_CONTROL_SHADER
;
2782 return GL_TESS_EVALUATION_SHADER
;
2784 return GL_COMPUTE_SHADER
;
2790 static GLenum
get_shader_from_string(const char *name
, int *idx
)
2792 if (parse_str(name
, "GL_VERTEX_SHADER", NULL
)) {
2794 return GL_VERTEX_SHADER
;
2796 if (parse_str(name
, "GL_FRAGMENT_SHADER", NULL
)) {
2798 return GL_FRAGMENT_SHADER
;
2800 if (parse_str(name
, "GL_GEOMETRY_SHADER", NULL
)) {
2802 return GL_GEOMETRY_SHADER
;
2804 if (parse_str(name
, "GL_TESS_CONTROL_SHADER", NULL
)) {
2806 return GL_TESS_CONTROL_SHADER
;
2808 if (parse_str(name
, "GL_TESS_EVALUATION_SHADER", NULL
)) {
2810 return GL_TESS_EVALUATION_SHADER
;
2812 if (parse_str(name
, "GL_COMPUTE_SHADER", NULL
)) {
2814 return GL_COMPUTE_SHADER
;
2820 free_subroutine_uniforms(void)
2823 for (sidx
= 0; sidx
< 4; sidx
++) {
2824 free(subuniform_locations
[sidx
]);
2825 subuniform_locations
[sidx
] = NULL
;
2830 program_subroutine_uniforms(void)
2835 for (sidx
= 0; sidx
< 4; sidx
++) {
2837 if (num_subuniform_locations
[sidx
] == 0)
2840 stype
= lookup_shader_type(sidx
);
2844 glUniformSubroutinesuiv(stype
, num_subuniform_locations
[sidx
], subuniform_locations
[sidx
]);
2849 set_subroutine_uniform(const char *line
)
2860 REQUIRE(parse_word_copy(line
, type
, sizeof(type
), &line
) &&
2861 parse_word_copy(line
, name
, sizeof(name
), &line
) &&
2862 parse_word_copy(line
, subname
, sizeof(subname
), &line
),
2863 "Invalid set subroutine uniform command at: %s\n", line
);
2865 ptype
= get_shader_from_string(type
, &sidx
);
2867 printf("illegal type in subroutine uniform\n");
2868 piglit_report_result(PIGLIT_FAIL
);
2871 glGetIntegerv(GL_CURRENT_PROGRAM
, (GLint
*) &prog
);
2873 if (num_subuniform_locations
[sidx
] == 0) {
2874 glGetProgramStageiv(prog
, ptype
, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS
,
2875 &num_subuniform_locations
[sidx
]);
2877 if (num_subuniform_locations
[sidx
] == 0) {
2878 printf("illegal subroutine uniform specified\n");
2879 piglit_report_result(PIGLIT_FAIL
);
2882 subuniform_locations
[sidx
] = calloc(num_subuniform_locations
[sidx
], sizeof(GLuint
));
2883 if (!subuniform_locations
[sidx
])
2884 piglit_report_result(PIGLIT_FAIL
);
2887 loc
= glGetSubroutineUniformLocation(prog
, ptype
, name
);
2889 if (ignore_missing_uniforms
)
2891 printf("cannot get location of subroutine uniform \"%s\"\n",
2893 piglit_report_result(PIGLIT_FAIL
);
2896 idx
= glGetSubroutineIndex(prog
, ptype
, subname
);
2897 if (idx
== GL_INVALID_INDEX
) {
2898 printf("cannot get index of subroutine uniform \"%s\"\n",
2900 piglit_report_result(PIGLIT_FAIL
);
2903 subuniform_locations
[sidx
][loc
] = idx
;
2908 * Query values from current program using glGetProgram.
2910 * Format of the command:
2911 * verify program_query GL_PNAME_ENUM integer
2915 * verify program_query GL_PNAME_ENUM <enum>
2917 * Note: GL_COMPUTE_WORK_GROUP_SIZE is not supported, as is the only
2918 * query that requires a params with more than one component, and we
2919 * want to keep things simple.
2923 verify_program_query(const char *line
)
2925 static const struct string_to_enum all_pnames
[] = {
2926 ENUM_STRING(GL_DELETE_STATUS
),
2927 ENUM_STRING(GL_LINK_STATUS
),
2928 ENUM_STRING(GL_VALIDATE_STATUS
),
2929 ENUM_STRING(GL_INFO_LOG_LENGTH
),
2930 ENUM_STRING(GL_ATTACHED_SHADERS
),
2931 ENUM_STRING(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS
),
2932 ENUM_STRING(GL_ACTIVE_ATTRIBUTES
),
2933 ENUM_STRING(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
),
2934 ENUM_STRING(GL_ACTIVE_UNIFORMS
),
2935 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCKS
),
2936 ENUM_STRING(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
),
2937 ENUM_STRING(GL_ACTIVE_UNIFORM_MAX_LENGTH
),
2938 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE
),
2939 ENUM_STRING(GL_PROGRAM_BINARY_LENGTH
),
2940 ENUM_STRING(GL_TRANSFORM_FEEDBACK_BUFFER_MODE
),
2941 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYINGS
),
2942 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
),
2943 ENUM_STRING(GL_GEOMETRY_VERTICES_OUT
),
2944 ENUM_STRING(GL_GEOMETRY_INPUT_TYPE
),
2945 ENUM_STRING(GL_GEOMETRY_OUTPUT_TYPE
),
2949 static const struct string_to_enum all_possible_param_enums
[] = {
2950 ENUM_STRING(GL_TRUE
),
2951 ENUM_STRING(GL_FALSE
),
2952 ENUM_STRING(GL_SEPARATE_ATTRIBS
),
2953 ENUM_STRING(GL_INTERLEAVED_ATTRIBS
),
2954 ENUM_STRING(GL_POINTS
),
2955 ENUM_STRING(GL_LINES
),
2956 ENUM_STRING(GL_LINES_ADJACENCY
),
2957 ENUM_STRING(GL_TRIANGLES
),
2958 ENUM_STRING(GL_TRIANGLES_ADJACENCY
),
2959 ENUM_STRING(GL_LINE_STRIP
),
2960 ENUM_STRING(GL_TRIANGLE_STRIP
),
2961 ENUM_STRING(GL_COMPUTE_WORK_GROUP_SIZE
),
2969 REQUIRE(parse_enum_tab(all_pnames
, line
,
2971 "Bad glGetProgram pname at: %s\n", line
);
2973 REQUIRE(parse_enum_tab(all_possible_param_enums
, line
, (unsigned *)&expected
, &line
) ||
2974 parse_int(line
, &expected
, &line
),
2975 "Bad expected value at: %s\n", line
);
2977 if (pname
== GL_COMPUTE_WORK_GROUP_SIZE
) {
2978 /* TODO: eventually it would be good to add support for
2979 * this parameter. What it makes different to the rest is
2980 * that it requires a param with more than one component
2982 fprintf(stderr
, "glGetProgram queries with GL_COMPUTE_WORK_GROUP_SIZE "
2983 "not supported yet\n");
2984 piglit_report_result(PIGLIT_FAIL
);
2987 glGetProgramiv(prog
, pname
, &value
);
2989 if (expected
!= value
) {
2990 fprintf(stderr
, "glGetProgram(%s): expected %d, got %d\n",
2991 piglit_get_gl_enum_name(pname
), expected
, value
);
2992 piglit_report_result(PIGLIT_FAIL
);
2997 * Query a uniform using glGetActiveUniformsiv
2999 * Format of the command:
3001 * active uniform uniform_name GL_PNAME_ENUM integer
3005 * active uniform uniform_name GL_PNAME_ENUM GL_TYPE_ENUM
3008 active_uniform(const char *line
)
3010 static const struct string_to_enum all_pnames
[] = {
3011 ENUM_STRING(GL_UNIFORM_TYPE
),
3012 ENUM_STRING(GL_UNIFORM_SIZE
),
3013 ENUM_STRING(GL_UNIFORM_NAME_LENGTH
),
3014 ENUM_STRING(GL_UNIFORM_BLOCK_INDEX
),
3015 ENUM_STRING(GL_UNIFORM_OFFSET
),
3016 ENUM_STRING(GL_UNIFORM_ARRAY_STRIDE
),
3017 ENUM_STRING(GL_UNIFORM_MATRIX_STRIDE
),
3018 ENUM_STRING(GL_UNIFORM_IS_ROW_MAJOR
),
3019 ENUM_STRING(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX
),
3023 const char *rest
= line
;
3029 int num_active_uniforms
;
3031 REQUIRE(parse_word_copy(rest
, name
, sizeof(name
), &rest
),
3032 "Bad uniform name at: %s\n", line
);
3034 REQUIRE(parse_enum_tab(all_pnames
, rest
, &pname
, &rest
),
3035 "Bad glGetUniformsiv pname at: %s\n", line
);
3037 REQUIRE(parse_enum_tab(all_types
, rest
, (unsigned *)&expected
, &rest
) ||
3038 parse_int(rest
, &expected
, &rest
),
3039 "Bad expected value at: %s\n", line
);
3041 glGetProgramiv(prog
, GL_ACTIVE_UNIFORMS
, &num_active_uniforms
);
3042 for (i
= 0; i
< num_active_uniforms
; i
++) {
3049 glGetActiveUniform(prog
, i
, sizeof(name_buf
), &name_len
,
3050 &size
, &type
, name_buf
);
3052 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3053 fprintf(stderr
, "glGetActiveUniform error\n");
3054 piglit_report_result(PIGLIT_FAIL
);
3057 if (strcmp(name
, name_buf
) != 0)
3060 /* If the requested pname is one of the values that
3061 * glGetActiveUniform happens to return, check the value
3062 * returned by that function too.
3065 case GL_UNIFORM_TYPE
:
3069 case GL_UNIFORM_SIZE
:
3073 case GL_UNIFORM_NAME_LENGTH
:
3078 /* This ensures the check below will pass when the
3079 * requested enum is not one of the values already
3080 * returned by glGetActiveUniform.
3086 if (got
!= expected
) {
3088 "glGetActiveUniform(%s, %s): "
3089 "expected %d (0x%04x), got %d (0x%04x)\n",
3090 name
, piglit_get_gl_enum_name(pname
),
3091 expected
, expected
, got
, got
);
3095 /* Set 'got' to some value in case glGetActiveUniformsiv
3096 * doesn't write to it. That should only be able to occur
3097 * when the function raises a GL error, but "should" is kind
3101 glGetActiveUniformsiv(prog
, 1, (GLuint
*) &i
, pname
, &got
);
3103 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3104 fprintf(stderr
, "glGetActiveUniformsiv error\n");
3105 piglit_report_result(PIGLIT_FAIL
);
3108 if (got
!= expected
) {
3110 "glGetActiveUniformsiv(%s, %s): "
3111 "expected %d, got %d\n",
3112 name
, piglit_get_gl_enum_name(pname
),
3118 piglit_report_result(PIGLIT_FAIL
);
3123 fprintf(stderr
, "No active uniform named \"%s\"\n", name
);
3124 piglit_report_result(PIGLIT_FAIL
);
3130 * Confirms if @resource_index is a given resource, within @interface_type.
3132 * In order to identify it, it uses by default @resource_name. If
3133 * force_no_names mode is activated it uses the binding contained at
3134 * @block_data. Note that for the latter, only ubos or ssbos are
3135 * supported as @interface_type.
3137 * @resource_name_buf, @prop and @value_expected are only used for
3138 * some extra checks.
3140 * Return true if @resource_index is the resource within
3141 * @interface_type we search for. false otherwise.
3144 confirm_program_resource(GLenum interface_type
, GLuint resource_index
,
3145 const char *resource_name
, char *resource_name_buf
,
3146 struct block_info block_data
, unsigned prop
,
3149 if (!force_no_names
) {
3150 GLsizei resource_name_len
;
3152 glGetProgramResourceName(prog
, interface_type
, resource_index
,
3153 512, &resource_name_len
,
3156 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3157 fprintf(stderr
, "glGetProgramResourceName error\n");
3158 piglit_report_result(PIGLIT_FAIL
);
3161 if (strcmp(resource_name
, resource_name_buf
) != 0)
3164 /* glGetProgramResourceName does not consider the NULL
3165 * terminator when returning the name length, however,
3166 * glGetProgramResourceiv does. We take that into account
3167 * when doing the comparison.
3169 if (prop
== GL_NAME_LENGTH
&&
3170 resource_name_len
!= (value_expected
- 1)) {
3172 "glGetProgramResourceName(%s, %s, %s): "
3173 "expected length: %d (0x%04x), "
3174 "got length: %d (0x%04x)\n",
3175 piglit_get_gl_enum_name(interface_type
),
3176 resource_name
, piglit_get_gl_enum_name(prop
),
3177 value_expected
- 1, value_expected
- 1,
3178 resource_name_len
, resource_name_len
);
3179 piglit_report_result(PIGLIT_FAIL
);
3182 unsigned binding_prop
= GL_BUFFER_BINDING
;
3183 int current_binding
= 0;
3186 if (interface_type
!= GL_SHADER_STORAGE_BLOCK
&&
3187 interface_type
!= GL_UNIFORM_BLOCK
) {
3189 "active_program_interface queries under force_no_names "
3190 "mode are only supported for GL_SHADER_STORAGE_BLOCK "
3191 "or GL_UNIFORM_BLOCK interfaces\n");
3192 piglit_report_result(PIGLIT_FAIL
);
3195 glGetProgramResourceiv(prog
, interface_type
,
3196 resource_index
, 1, &binding_prop
, 1,
3197 &length
, ¤t_binding
);
3198 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3199 fprintf(stderr
, "glGetProgramResourceiv error\n");
3200 piglit_report_result(PIGLIT_FAIL
);
3203 if (block_data
.binding
!= current_binding
)
3211 * Query an active resource using ARB_program_interface_query functions
3213 * Format of the command:
3215 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM integer
3219 * verify program_interface_query GL_INTERFACE_TYPE_ENUM name GL_PNAME_ENUM GL_TYPE_ENUM
3222 active_program_interface(const char *line
, struct block_info block_data
)
3224 static const struct string_to_enum all_props
[] = {
3225 ENUM_STRING(GL_TYPE
),
3226 ENUM_STRING(GL_ARRAY_SIZE
),
3227 ENUM_STRING(GL_NAME_LENGTH
),
3228 ENUM_STRING(GL_BLOCK_INDEX
),
3229 ENUM_STRING(GL_OFFSET
),
3230 ENUM_STRING(GL_ARRAY_STRIDE
),
3231 ENUM_STRING(GL_MATRIX_STRIDE
),
3232 ENUM_STRING(GL_IS_ROW_MAJOR
),
3233 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER_INDEX
),
3234 ENUM_STRING(GL_BUFFER_BINDING
),
3235 ENUM_STRING(GL_BUFFER_DATA_SIZE
),
3236 ENUM_STRING(GL_NUM_ACTIVE_VARIABLES
),
3237 ENUM_STRING(GL_REFERENCED_BY_VERTEX_SHADER
),
3238 ENUM_STRING(GL_REFERENCED_BY_TESS_CONTROL_SHADER
),
3239 ENUM_STRING(GL_REFERENCED_BY_TESS_EVALUATION_SHADER
),
3240 ENUM_STRING(GL_REFERENCED_BY_GEOMETRY_SHADER
),
3241 ENUM_STRING(GL_REFERENCED_BY_FRAGMENT_SHADER
),
3242 ENUM_STRING(GL_REFERENCED_BY_COMPUTE_SHADER
),
3243 ENUM_STRING(GL_TOP_LEVEL_ARRAY_SIZE
),
3244 ENUM_STRING(GL_TOP_LEVEL_ARRAY_STRIDE
),
3245 ENUM_STRING(GL_LOCATION
),
3246 ENUM_STRING(GL_LOCATION_INDEX
),
3247 ENUM_STRING(GL_LOCATION_COMPONENT
),
3248 ENUM_STRING(GL_IS_PER_PATCH
),
3249 ENUM_STRING(GL_NUM_COMPATIBLE_SUBROUTINES
),
3250 ENUM_STRING(GL_COMPATIBLE_SUBROUTINES
),
3254 static const struct string_to_enum all_program_interface
[] = {
3255 ENUM_STRING(GL_UNIFORM
),
3256 ENUM_STRING(GL_UNIFORM_BLOCK
),
3257 ENUM_STRING(GL_PROGRAM_INPUT
),
3258 ENUM_STRING(GL_PROGRAM_OUTPUT
),
3259 ENUM_STRING(GL_BUFFER_VARIABLE
),
3260 ENUM_STRING(GL_SHADER_STORAGE_BLOCK
),
3261 ENUM_STRING(GL_ATOMIC_COUNTER_BUFFER
),
3262 ENUM_STRING(GL_VERTEX_SUBROUTINE
),
3263 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE
),
3264 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE
),
3265 ENUM_STRING(GL_GEOMETRY_SUBROUTINE
),
3266 ENUM_STRING(GL_FRAGMENT_SUBROUTINE
),
3267 ENUM_STRING(GL_COMPUTE_SUBROUTINE
),
3268 ENUM_STRING(GL_VERTEX_SUBROUTINE_UNIFORM
),
3269 ENUM_STRING(GL_TESS_CONTROL_SUBROUTINE_UNIFORM
),
3270 ENUM_STRING(GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
),
3271 ENUM_STRING(GL_GEOMETRY_SUBROUTINE_UNIFORM
),
3272 ENUM_STRING(GL_FRAGMENT_SUBROUTINE_UNIFORM
),
3273 ENUM_STRING(GL_COMPUTE_SUBROUTINE_UNIFORM
),
3274 ENUM_STRING(GL_TRANSFORM_FEEDBACK_VARYING
),
3280 unsigned prop
, interface_type
;
3283 int num_active_buffers
;
3285 if (!piglit_is_extension_supported("GL_ARB_program_interface_query") &&
3286 piglit_get_gl_version() < 43) {
3288 "GL_ARB_program_interface_query not supported or "
3289 "OpenGL version < 4.3\n");
3293 REQUIRE(parse_enum_tab(all_program_interface
, line
,
3294 &interface_type
, &line
),
3295 "Bad program interface at: %s\n", line
);
3296 REQUIRE(parse_word_copy(line
, name
, sizeof(name
), &line
),
3297 "Bad program resource name at: %s\n", line
);
3298 REQUIRE(parse_enum_tab(all_props
, line
, &prop
, &line
),
3299 "Bad glGetProgramResourceiv pname at: %s\n", line
);
3300 REQUIRE(parse_enum_tab(all_types
, line
, (unsigned *)&expected
, &line
) ||
3301 parse_int(line
, &expected
, &line
),
3302 "Bad expected value at: %s\n", line
);
3304 glGetProgramInterfaceiv(prog
, interface_type
,
3305 GL_ACTIVE_RESOURCES
, &num_active_buffers
);
3306 for (i
= 0; i
< num_active_buffers
; i
++) {
3311 if (!confirm_program_resource(interface_type
, i
, name
, name_buf
,
3312 block_data
, prop
, expected
))
3315 /* Set 'got' to some value in case glGetActiveUniformsiv
3316 * doesn't write to it. That should only be able to occur
3317 * when the function raises a GL error, but "should" is kind
3321 glGetProgramResourceiv(prog
, interface_type
,
3325 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
3326 fprintf(stderr
, "glGetProgramResourceiv error\n");
3327 piglit_report_result(PIGLIT_FAIL
);
3330 if (got
!= expected
) {
3332 "glGetProgramResourceiv(%s, %s): "
3333 "expected %d, got %d\n",
3334 name
, piglit_get_gl_enum_name(prop
),
3340 piglit_report_result(PIGLIT_FAIL
);
3345 if (!force_no_names
)
3346 fprintf(stderr
, "No active resource named \"%s\"\n", name
);
3348 fprintf(stderr
, "No active resource with binding %i\n", block_data
.binding
);
3350 piglit_report_result(PIGLIT_FAIL
);
3356 query_index(GLenum query
)
3359 case GL_PRIMITIVES_GENERATED
:
3361 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
3368 * Checks if the GL_QUERY_RESULT of a given query object has the
3371 * Note that right now it only supports the following two queries:
3372 * * GL_PRIMITIVES_GENERATED
3373 * * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
3375 * As right now we are only creating those query objects with xfb
3378 * Format of the command:
3380 * verify query_object GL_PRIMITIVES_GENERATED integer
3384 * verify query_object GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN integer
3386 static enum piglit_result
3387 verify_query_object_result(const char *line
)
3389 static const struct string_to_enum all_targets
[] = {
3390 ENUM_STRING(GL_PRIMITIVES_GENERATED
),
3391 ENUM_STRING(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
),
3400 REQUIRE(parse_enum_tab(all_targets
, line
,
3402 "Bad query object target at: %s\n", line
);
3404 REQUIRE(parse_uint(line
, &expected
, &line
),
3405 "Bad expected value at: %s\n", line
);
3407 /* Previous require already checks if the target is one of the
3410 index
= query_index(target
);
3412 if (queries
[index
]) {
3413 glGetQueryObjectuiv(queries
[index
], GL_QUERY_RESULT
, &value
);
3415 fprintf(stderr
, "query object for target %s is not initialized. "
3416 "Did you forget to call \"xfb draw arrays\"?\n",
3417 piglit_get_gl_enum_name(target
));
3421 if (expected
!= value
) {
3422 fprintf(stderr
, "glGetQueryObjectuiv(GL_QUERY_RESULT) for a %s "
3423 "query object: expected %d, got %d\n",
3424 piglit_get_gl_enum_name(target
), expected
, value
);
3431 set_parameter(const char *line
)
3437 count
= sscanf(line
, "%s %d (%f , %f , %f , %f)",
3438 type
, &index
, &f
[0], &f
[1], &f
[2], &f
[3]);
3440 fprintf(stderr
, "Couldn't parse parameter command:\n%s\n", line
);
3441 piglit_report_result(PIGLIT_FAIL
);
3444 if (parse_str(type
, "env_vp", NULL
)) {
3445 glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB
, index
, f
);
3446 } else if (parse_str(type
, "local_vp", NULL
)) {
3447 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB
, index
, f
);
3448 } else if (parse_str(type
, "env_fp", NULL
)) {
3449 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB
, index
, f
);
3450 } else if (parse_str(type
, "local_fp", NULL
)) {
3451 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB
, index
, f
);
3453 fprintf(stderr
, "Unknown parameter type `%s'\n", type
);
3454 piglit_report_result(PIGLIT_FAIL
);
3459 set_patch_parameter(const char *line
)
3461 #ifdef PIGLIT_USE_OPENGL
3464 const char *const line0
= line
;
3466 if (gl_version
.num
< 40)
3467 piglit_require_extension("GL_ARB_tessellation_shader");
3469 if (parse_str(line
, "vertices ", &line
)) {
3470 count
= sscanf(line
, "%d", &i
);
3472 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3473 piglit_report_result(PIGLIT_FAIL
);
3475 glPatchParameteri(GL_PATCH_VERTICES
, i
);
3476 } else if (parse_str(line
, "default level outer ", &line
)) {
3477 count
= sscanf(line
, "%f %f %f %f", &f
[0], &f
[1], &f
[2], &f
[3]);
3479 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3480 piglit_report_result(PIGLIT_FAIL
);
3482 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL
, f
);
3483 } else if (parse_str(line
, "default level inner ", &line
)) {
3484 count
= sscanf(line
, "%f %f", &f
[0], &f
[1]);
3486 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line0
);
3487 piglit_report_result(PIGLIT_FAIL
);
3489 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL
, f
);
3491 fprintf(stderr
, "Couldn't parse patch parameter command:\n%s\n", line
);
3492 piglit_report_result(PIGLIT_FAIL
);
3495 printf("patch parameters are only available in desktop GL\n");
3496 piglit_report_result(PIGLIT_SKIP
);
3501 set_provoking_vertex(const char *line
)
3503 if (parse_str(line
, "first", NULL
)) {
3504 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT
);
3505 } else if (parse_str(line
, "last", NULL
)) {
3506 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT
);
3508 fprintf(stderr
, "Unknown provoking vertex parameter `%s'\n", line
);
3509 piglit_report_result(PIGLIT_FAIL
);
3513 static const struct string_to_enum enable_table
[] = {
3514 { "GL_CLIP_PLANE0", GL_CLIP_PLANE0
},
3515 { "GL_CLIP_PLANE1", GL_CLIP_PLANE1
},
3516 { "GL_CLIP_PLANE2", GL_CLIP_PLANE2
},
3517 { "GL_CLIP_PLANE3", GL_CLIP_PLANE3
},
3518 { "GL_CLIP_PLANE4", GL_CLIP_PLANE4
},
3519 { "GL_CLIP_PLANE5", GL_CLIP_PLANE5
},
3520 { "GL_CLIP_PLANE6", GL_CLIP_PLANE0
+6 },
3521 { "GL_CLIP_PLANE7", GL_CLIP_PLANE0
+7 },
3522 { "GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE
},
3523 { "GL_PROGRAM_POINT_SIZE", GL_PROGRAM_POINT_SIZE
},
3524 { "GL_DEPTH_TEST", GL_DEPTH_TEST
},
3525 { "GL_DEPTH_CLAMP", GL_DEPTH_CLAMP
},
3530 do_enable_disable(const char *line
, bool enable_flag
)
3533 REQUIRE(parse_enum_tab(enable_table
, line
, &value
, NULL
),
3534 "Bad enable/disable enum at: %s\n", line
);
3542 static const struct string_to_enum hint_target_table
[] = {
3543 ENUM_STRING(GL_LINE_SMOOTH_HINT
),
3544 ENUM_STRING(GL_POLYGON_SMOOTH_HINT
),
3545 ENUM_STRING(GL_TEXTURE_COMPRESSION_HINT
),
3546 ENUM_STRING(GL_FRAGMENT_SHADER_DERIVATIVE_HINT
),
3550 static const struct string_to_enum hint_param_table
[] = {
3551 ENUM_STRING(GL_FASTEST
),
3552 ENUM_STRING(GL_NICEST
),
3553 ENUM_STRING(GL_DONT_CARE
),
3557 static void do_hint(const char *line
)
3559 unsigned target
, param
;
3560 REQUIRE(parse_enum_tab(hint_target_table
, line
, &target
, &line
),
3561 "Bad hint target at: %s\n", line
);
3562 REQUIRE(parse_enum_tab(hint_param_table
, line
, ¶m
, &line
),
3563 "Bad hint param at: %s\n", line
);
3565 glHint(target
, param
);
3569 draw_instanced_rect(int primcount
, float x
, float y
, float w
, float h
)
3573 piglit_require_extension("GL_ARB_draw_instanced");
3579 verts
[1][0] = x
+ w
;
3584 verts
[2][1] = y
+ h
;
3587 verts
[3][0] = x
+ w
;
3588 verts
[3][1] = y
+ h
;
3592 glVertexPointer(4, GL_FLOAT
, 0, verts
);
3593 glEnableClientState(GL_VERTEX_ARRAY
);
3595 glDrawArraysInstanced(GL_TRIANGLE_STRIP
, 0, 4, primcount
);
3597 glDisableClientState(GL_VERTEX_ARRAY
);
3602 decode_drawing_mode(const char *mode_str
)
3606 for (i
= GL_POINTS
; i
<= GL_PATCHES
; ++i
) {
3607 const char *name
= piglit_get_prim_name(i
);
3608 if (0 == strcmp(mode_str
, name
))
3612 printf("unknown drawing mode \"%s\"\n", mode_str
);
3613 piglit_report_result(PIGLIT_FAIL
);
3615 /* Should not be reached, but return 0 to avoid compiler warning */
3620 handle_texparameter(const char *line
)
3622 static const struct string_to_enum compare_funcs
[] = {
3623 { "greater", GL_GREATER
},
3624 { "gequal", GL_GEQUAL
},
3625 { "less", GL_LESS
},
3626 { "lequal", GL_LEQUAL
},
3627 { "equal", GL_EQUAL
},
3628 { "notequal", GL_NOTEQUAL
},
3629 { "never", GL_NEVER
},
3630 { "always", GL_ALWAYS
},
3633 static const struct string_to_enum depth_modes
[] = {
3634 { "intensity", GL_INTENSITY
},
3635 { "luminance", GL_LUMINANCE
},
3636 { "alpha", GL_ALPHA
},
3637 { "red", GL_RED
}, /* Requires GL 3.0 or GL_ARB_texture_rg */
3640 static const struct string_to_enum min_filter_modes
[] = {
3641 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST
},
3642 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST
},
3643 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR
},
3644 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR
},
3645 { "nearest", GL_NEAREST
},
3646 { "linear", GL_LINEAR
},
3649 static const struct string_to_enum mag_filter_modes
[] = {
3650 { "nearest", GL_NEAREST
},
3651 { "linear", GL_LINEAR
},
3654 static const struct string_to_enum wrap_modes
[] = {
3655 { "repeat", GL_REPEAT
},
3656 { "clamp_to_edge", GL_CLAMP_TO_EDGE
},
3657 { "clamp_to_border", GL_CLAMP_TO_BORDER
},
3660 static const struct string_to_enum swizzle_modes
[] = {
3662 { "green", GL_GREEN
},
3663 { "blue", GL_BLUE
},
3664 { "alpha", GL_ALPHA
},
3667 unsigned target
= 0;
3668 GLenum parameter
= GL_NONE
;
3669 const char *parameter_name
= NULL
;
3670 const struct string_to_enum
*strings
= NULL
;
3673 REQUIRE(parse_tex_target(line
, &target
, &line
),
3674 "Bad texture target at: %s\n", line
);
3676 if (parse_str(line
, "compare_func ", &line
)) {
3677 parameter
= GL_TEXTURE_COMPARE_FUNC
;
3678 parameter_name
= "compare_func";
3679 strings
= compare_funcs
;
3680 } else if (parse_str(line
, "depth_mode ", &line
)) {
3681 parameter
= GL_DEPTH_TEXTURE_MODE
;
3682 parameter_name
= "depth_mode";
3683 strings
= depth_modes
;
3684 } else if (parse_str(line
, "min ", &line
)) {
3685 parameter
= GL_TEXTURE_MIN_FILTER
;
3686 parameter_name
= "min";
3687 strings
= min_filter_modes
;
3688 } else if (parse_str(line
, "mag ", &line
)) {
3689 parameter
= GL_TEXTURE_MAG_FILTER
;
3690 parameter_name
= "mag";
3691 strings
= mag_filter_modes
;
3692 } else if (parse_str(line
, "wrap_s ", &line
)) {
3693 parameter
= GL_TEXTURE_WRAP_S
;
3694 parameter_name
= "wrap_s";
3695 strings
= wrap_modes
;
3696 } else if (parse_str(line
, "wrap_t ", &line
)) {
3697 parameter
= GL_TEXTURE_WRAP_T
;
3698 parameter_name
= "wrap_t";
3699 strings
= wrap_modes
;
3700 } else if (parse_str(line
, "wrap_r ", &line
)) {
3701 parameter
= GL_TEXTURE_WRAP_R
;
3702 parameter_name
= "wrap_r";
3703 strings
= wrap_modes
;
3704 } else if (parse_str(line
, "lod_bias ", &line
)) {
3705 #ifdef PIGLIT_USE_OPENGL
3706 glTexParameterf(target
, GL_TEXTURE_LOD_BIAS
,
3707 strtod(line
, NULL
));
3710 printf("lod_bias feature is only available in desktop GL\n");
3711 piglit_report_result(PIGLIT_SKIP
);
3713 } else if (parse_str(line
, "max_level ", &line
)) {
3714 glTexParameteri(target
, GL_TEXTURE_MAX_LEVEL
,
3715 strtol(line
, NULL
, 10));
3717 } else if (parse_str(line
, "base_level ", &line
)) {
3718 glTexParameteri(target
, GL_TEXTURE_BASE_LEVEL
,
3719 strtol(line
, NULL
, 10));
3721 } else if (parse_str(line
, "border_color ", &line
)) {
3724 count
= sscanf(line
, "%f %f %f %f", &bc
[0], &bc
[1], &bc
[2], &bc
[3]);
3726 fprintf(stderr
, "Could not parse border_color texture parameter.\n");
3727 piglit_report_result(PIGLIT_FAIL
);
3729 glTexParameterfv(target
, GL_TEXTURE_BORDER_COLOR
, bc
);
3731 } else if (parse_str(line
, "swizzle_r ", &line
)) {
3732 parameter
= GL_TEXTURE_SWIZZLE_R
;
3733 parameter_name
= "swizzle_r";
3734 strings
= swizzle_modes
;
3736 fprintf(stderr
, "unknown texture parameter in `%s'\n", line
);
3737 piglit_report_result(PIGLIT_FAIL
);
3740 REQUIRE(parse_enum_tab(strings
, line
, &value
, &line
),
3741 "Bad %s at: %s\n", parameter_name
, line
);
3743 glTexParameteri(target
, parameter
, value
);
3746 static const struct string_to_enum viewport_swizzle_table
[] = {
3747 { "POSITIVE_X", GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV
},
3748 { "NEGATIVE_X", GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV
},
3749 { "POSITIVE_Y", GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV
},
3750 { "NEGATIVE_Y", GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV
},
3751 { "POSITIVE_Z", GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV
},
3752 { "NEGATIVE_Z", GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV
},
3753 { "POSITIVE_W", GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV
},
3754 { "NEGATIVE_W", GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV
},
3759 handle_viewport_swizzle(const char *line
)
3764 viewport
= strtol(line
, (char **)&line
, 0);
3765 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &x
, &line
),
3766 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3767 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &y
, &line
),
3768 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3769 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &z
, &line
),
3770 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3771 REQUIRE(parse_enum_tab(viewport_swizzle_table
, line
, &w
, &line
),
3772 "Bad ViewportSwizzle swizzle at: %s\n", line
);
3774 glViewportSwizzleNV(viewport
, x
, y
, z
, w
);
3782 if (!piglit_is_extension_supported("GL_ARB_uniform_buffer_object") &&
3783 piglit_get_gl_version() < 31) {
3788 /* probably running an ARB_vertex/fragment_program test */
3792 glGetProgramiv(prog
, GL_ACTIVE_UNIFORM_BLOCKS
, &num_uniform_blocks
);
3793 if (num_uniform_blocks
== 0)
3796 uniform_block_bos
= calloc(num_uniform_blocks
, sizeof(GLuint
));
3797 glGenBuffers(num_uniform_blocks
, uniform_block_bos
);
3800 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
, &max_ubos
);
3801 uniform_block_indexes
= calloc(max_ubos
, sizeof(int));
3803 for (i
= 0; i
< num_uniform_blocks
; i
++) {
3807 glGetActiveUniformBlockiv(prog
, i
, GL_UNIFORM_BLOCK_DATA_SIZE
,
3810 glBindBuffer(GL_UNIFORM_BUFFER
, uniform_block_bos
[i
]);
3811 glBufferData(GL_UNIFORM_BUFFER
, size
, NULL
, GL_STATIC_DRAW
);
3813 if (!force_no_names
) {
3814 glUniformBlockBinding(prog
, i
, i
);
3815 uniform_block_indexes
[i
] = i
;
3818 glGetActiveUniformBlockiv(prog
, i
, GL_UNIFORM_BLOCK_BINDING
,
3820 uniform_block_indexes
[binding
] = i
;
3823 glBindBufferBase(GL_UNIFORM_BUFFER
, binding
, uniform_block_bos
[i
]);
3830 if (draw_fbo
!= 0 &&
3831 draw_fbo
!= piglit_winsys_fbo
)
3832 glDeleteFramebuffers(1, &draw_fbo
);
3834 if (read_fbo
!= 0 &&
3835 read_fbo
!= piglit_winsys_fbo
&&
3836 read_fbo
!= draw_fbo
)
3837 glDeleteFramebuffers(1, &read_fbo
);
3846 if (num_uniform_blocks
== 0) {
3850 glDeleteBuffers(num_uniform_blocks
, uniform_block_bos
);
3851 free(uniform_block_bos
);
3852 uniform_block_bos
= NULL
;
3853 free(uniform_block_indexes
);
3854 uniform_block_indexes
= NULL
;
3855 num_uniform_blocks
= 0;
3859 teardown_atomics(void)
3861 for (unsigned i
= 0; i
< ARRAY_SIZE(atomics_bos
); ++i
) {
3863 glDeleteBuffers(1, &atomics_bos
[i
]);
3868 teardown_shader_include_paths(void)
3870 for (unsigned i
= 0; i
< num_shader_include_paths
; i
++)
3871 free(shader_include_path
[i
]);
3873 for (unsigned i
= 0; i
< num_shader_includes
; i
++) {
3874 glDeleteNamedStringARB(-1, shader_include_names
[i
]);
3875 free(shader_include_names
[i
]);
3878 num_shader_includes
= 0;
3879 num_shader_include_paths
= 0;
3880 free(shader_include_path
);
3881 shader_include_path
= NULL
;
3887 glDeleteBuffers(MAX_XFB_BUFFERS
, xfb
);
3889 glDeleteQueries(1, &queries
[query_index(GL_PRIMITIVES_GENERATED
)]);
3890 glDeleteQueries(1, &queries
[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
)]);
3891 queries
[query_index(GL_PRIMITIVES_GENERATED
)] = 0;
3892 queries
[query_index(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
)] = 0;
3895 static enum piglit_result
3896 program_must_be_in_use(void)
3899 fprintf(stderr
, "Failed to link:\n%s\n", prog_err_info
);
3901 } else if (!prog_in_use
) {
3902 fprintf(stderr
, "Failed to use program: %s\n", prog_err_info
);
3909 bind_vao_if_supported()
3911 if (vao
== 0 && piglit_is_core_profile
) {
3912 glGenVertexArrays(1, &vao
);
3913 glBindVertexArray(vao
);
3917 static enum piglit_result
3918 draw_arrays_common(int first
, size_t count
)
3920 enum piglit_result result
= program_must_be_in_use();
3922 printf("draw arrays 'first' must be >= 0\n");
3923 piglit_report_result(PIGLIT_FAIL
);
3924 } else if (vbo_present
&&
3925 (size_t) first
>= num_vbo_rows
) {
3926 printf("draw arrays 'first' must be < %lu\n",
3927 (unsigned long) num_vbo_rows
);
3928 piglit_report_result(PIGLIT_FAIL
);
3931 printf("draw arrays 'count' must be > 0\n");
3932 piglit_report_result(PIGLIT_FAIL
);
3933 } else if (vbo_present
&&
3934 count
> num_vbo_rows
- (size_t) first
) {
3935 printf("draw arrays cannot draw beyond %lu\n",
3936 (unsigned long) num_vbo_rows
);
3937 piglit_report_result(PIGLIT_FAIL
);
3939 bind_vao_if_supported();
3944 probe_atomic_counter(unsigned buffer_num
, GLint counter_num
, const char *op
,
3945 uint32_t value
, bool uses_layout_qualifiers
)
3949 enum comparison cmp
;
3952 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
3953 "Invalid comparison operation at: %s\n", op
);
3955 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER
, atomics_bos
[buffer_num
]);
3956 p
= glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER
,
3957 uses_layout_qualifiers
? counter_num
: counter_num
* sizeof(uint32_t),
3958 sizeof(uint32_t), GL_MAP_READ_BIT
);
3961 printf("Couldn't map atomic counter to verify expected value.\n");
3966 result
= compare_uint(value
, observed
, cmp
);
3969 if (uses_layout_qualifiers
)
3970 printf("Atomic counter (binding = %d, offset = %d) test failed: "
3971 "Reference %s Observed\n",
3972 buffer_num
, counter_num
, comparison_string(cmp
));
3974 printf("Atomic counter %d test failed: Reference %s Observed\n",
3975 counter_num
, comparison_string(cmp
));
3976 printf(" Reference: %u\n", value
);
3977 printf(" Observed: %u\n", observed
);
3978 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER
);
3982 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER
);
3987 probe_ssbo_uint(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, uint32_t value
)
3991 enum comparison cmp
;
3994 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
3995 "Invalid comparison operation at: %s\n", op
);
3997 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
3998 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
3999 sizeof(uint32_t), GL_MAP_READ_BIT
);
4002 printf("Couldn't map ssbo to verify expected value.\n");
4007 result
= compare_uint(value
, observed
, cmp
);
4010 printf("SSBO %d test failed: Reference %s Observed\n",
4011 ssbo_offset
, comparison_string(cmp
));
4012 printf(" Reference: %u\n", value
);
4013 printf(" Observed: %u\n", observed
);
4014 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4018 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4023 probe_ssbo_int(GLint ssbo_index
, GLint ssbo_offset
, const char *op
, int32_t value
)
4027 enum comparison cmp
;
4030 REQUIRE(parse_comparison_op(op
, &cmp
, NULL
),
4031 "Invalid comparison operation at: %s\n", op
);
4033 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
[ssbo_index
]);
4034 p
= glMapBufferRange(GL_SHADER_STORAGE_BUFFER
, ssbo_offset
,
4035 sizeof(uint32_t), GL_MAP_READ_BIT
);
4038 printf("Couldn't map ssbo to verify expected value.\n");
4043 result
= compare_int(value
, observed
, cmp
);
4046 printf("SSBO %d test failed: Reference %s Observed\n",
4047 ssbo_offset
, comparison_string(cmp
));
4048 printf(" Reference: %d\n", value
);
4049 printf(" Observed: %d\n", observed
);
4050 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4054 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER
);
4058 GLenum
piglit_xfb_primitive_mode(GLenum draw_arrays_mode
)
4060 switch (draw_arrays_mode
) {
4066 case GL_LINES_ADJACENCY
:
4067 case GL_LINE_STRIP_ADJACENCY
:
4070 case GL_TRIANGLE_STRIP
:
4071 case GL_TRIANGLE_FAN
:
4072 case GL_TRIANGLES_ADJACENCY
:
4073 case GL_TRIANGLE_STRIP_ADJACENCY
:
4074 return GL_TRIANGLES
;
4077 printf("glDrawArrays mode %s not supported for a transform feedback operation\n",
4078 piglit_get_gl_enum_name(draw_arrays_mode
));
4079 piglit_report_result(PIGLIT_FAIL
);
4083 begin_query(GLenum query_type
)
4085 unsigned idx
= query_index(query_type
);
4086 if (queries
[idx
] == 0)
4087 glGenQueries(1, &queries
[idx
]);
4088 glBeginQuery(query_type
, queries
[idx
]);
4092 piglit_xfb_draw_arrays(GLenum mode
, int first
, size_t count
)
4094 GLenum primitive_mode
= piglit_xfb_primitive_mode(mode
);
4096 begin_query(GL_PRIMITIVES_GENERATED
);
4097 begin_query(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
4099 glEnable(GL_RASTERIZER_DISCARD
);
4101 /* We don't need to call glBindBufferBase here, it is done on
4102 * the "xfb buffer object" command
4105 glBeginTransformFeedback(primitive_mode
);
4106 glDrawArrays(mode
, first
, count
);
4107 glEndTransformFeedback();
4109 glDisable(GL_RASTERIZER_DISCARD
);
4113 glEndQuery(GL_PRIMITIVES_GENERATED
);
4114 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
4118 probe_xfb_float(GLuint buf
, unsigned n
, float expected
)
4122 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, buf
);
4123 p
= glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, n
* sizeof(float),
4124 sizeof(float), GL_MAP_READ_BIT
);
4126 printf("Couldn't map xfb buffer %u\n", buf
);
4129 result
= fabsf(expected
- *p
) < piglit_tolerance
[0];
4131 printf("xfb buffer %i[%i]: %f, Expected: %f\n",
4132 buf
, n
, *p
, expected
);
4135 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
4140 probe_xfb_double(GLuint buf
, unsigned n
, double expected
)
4145 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, buf
);
4146 p
= glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, n
* sizeof(double),
4147 sizeof(double), GL_MAP_READ_BIT
);
4149 printf("Couldn't map xfb buffer %u\n", buf
);
4152 result
= fabs(expected
- *p
) < piglit_tolerance
[0];
4154 printf("xfb buffer %i[%i]: %lf, Expected: %lf\n",
4155 buf
, n
, *p
, expected
);
4158 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
4163 piglit_display(void)
4165 const char *line
, *next_line
, *rest
;
4167 enum piglit_result full_result
= PIGLIT_PASS
;
4168 GLbitfield clear_bits
= 0;
4169 bool link_error_expected
= false;
4171 struct block_info block_data
= {0, -1, -1, -1, -1};
4173 if (test_start
== NULL
)
4176 next_line
= test_start
;
4177 line_num
= test_start_line_num
;
4178 while (next_line
[0] != '\0') {
4181 int x
, y
, z
, w
, h
, l
, tex
, level
;
4182 unsigned ux
, uy
, uz
;
4183 char s
[300]; // 300 for safety
4184 enum piglit_result result
= PIGLIT_PASS
;
4186 parse_whitespace(next_line
, &line
);
4188 next_line
= strchrnul(next_line
, '\n');
4190 /* Duplicate the line to make it null terminated */
4191 line
= strndup(line
, next_line
- line
);
4193 /* If strchrnul found a newline, then skip it */
4194 if (next_line
[0] != '\0')
4197 if (line
[0] == '\0') {
4198 } else if (sscanf(line
, "active shader program %s", s
) == 1) {
4199 switch (get_shader_from_string(s
, &x
)) {
4200 case GL_VERTEX_SHADER
:
4201 glActiveShaderProgram(pipeline
, sso_vertex_prog
);
4203 case GL_TESS_CONTROL_SHADER
:
4204 glActiveShaderProgram(pipeline
, sso_tess_control_prog
);
4206 case GL_TESS_EVALUATION_SHADER
:
4207 glActiveShaderProgram(pipeline
, sso_tess_eval_prog
);
4209 case GL_GEOMETRY_SHADER
:
4210 glActiveShaderProgram(pipeline
, sso_geometry_prog
);
4212 case GL_FRAGMENT_SHADER
:
4213 glActiveShaderProgram(pipeline
, sso_fragment_prog
);
4215 case GL_COMPUTE_SHADER
:
4216 glActiveShaderProgram(pipeline
, sso_compute_prog
);
4219 } else if (sscanf(line
, "atomic counter buffer %u %u", &x
, &y
) == 2) {
4220 GLuint
*atomics_buf
= calloc(y
, sizeof(GLuint
));
4221 glGenBuffers(1, &atomics_bos
[x
]);
4222 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, x
, atomics_bos
[x
]);
4223 glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
4224 sizeof(GLuint
) * y
, atomics_buf
,
4227 } else if (sscanf(line
, "atomic counters %d", &x
) == 1) {
4228 GLuint
*atomics_buf
= calloc(x
, sizeof(GLuint
));
4229 glGenBuffers(1, &atomics_bos
[0]);
4230 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, atomics_bos
[0]);
4231 glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
4233 atomics_buf
, GL_STATIC_DRAW
);
4235 } else if (sscanf(line
, "atomic counter %u %u %u", &x
, &y
, &z
) == 3) {
4236 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, x
, atomics_bos
[x
]);
4237 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER
,
4238 sizeof(GLuint
) * y
, sizeof(GLuint
),
4240 } else if (parse_str(line
, "clear color ", &rest
)) {
4241 parse_floats(rest
, c
, 4, NULL
);
4242 glClearColor(c
[0], c
[1], c
[2], c
[3]);
4243 clear_bits
|= GL_COLOR_BUFFER_BIT
;
4244 } else if (parse_str(line
, "clear depth ", &rest
)) {
4245 parse_floats(rest
, c
, 1, NULL
);
4247 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
4248 } else if (parse_str(line
, "clear", NULL
)) {
4249 glClear(clear_bits
);
4250 } else if (sscanf(line
,
4251 "clip plane %d %lf %lf %lf %lf",
4252 &x
, &d
[0], &d
[1], &d
[2], &d
[3]) == 5) {
4253 if (x
< 0 || x
>= gl_max_clip_planes
) {
4254 printf("clip plane id %d out of range\n", x
);
4255 piglit_report_result(PIGLIT_FAIL
);
4257 glClipPlane(GL_CLIP_PLANE0
+ x
, d
);
4258 #ifdef PIGLIT_USE_OPENGL
4259 } else if (parse_str(line
, "color ", &rest
)) {
4260 parse_floats(rest
, c
, 4, NULL
);
4261 assert(!piglit_is_core_profile
);
4264 } else if (sscanf(line
,
4267 result
= program_must_be_in_use();
4268 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4269 glDispatchCompute(x
, y
, z
);
4270 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4271 } else if (sscanf(line
,
4272 "compute group size %d %d %d %d %d %d",
4273 &x
, &y
, &z
, &w
, &h
, &l
) == 6) {
4274 result
= program_must_be_in_use();
4275 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4276 glDispatchComputeGroupSizeARB(x
, y
, z
, w
, h
, l
);
4277 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
4278 } else if (parse_str(line
, "draw rect tex ", &rest
)) {
4279 result
= program_must_be_in_use();
4280 program_subroutine_uniforms();
4281 parse_floats(rest
, c
, 8, NULL
);
4282 piglit_draw_rect_tex(c
[0], c
[1], c
[2], c
[3],
4283 c
[4], c
[5], c
[6], c
[7]);
4284 } else if (parse_str(line
, "draw rect ortho patch ", &rest
)) {
4285 result
= program_must_be_in_use();
4286 program_subroutine_uniforms();
4287 parse_floats(rest
, c
, 4, NULL
);
4289 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4290 -1.0 + 2.0 * (c
[1] / piglit_height
),
4291 2.0 * (c
[2] / piglit_width
),
4292 2.0 * (c
[3] / piglit_height
), true, 1);
4293 } else if (parse_str(line
, "draw rect ortho ", &rest
)) {
4294 result
= program_must_be_in_use();
4295 program_subroutine_uniforms();
4296 parse_floats(rest
, c
, 4, NULL
);
4298 piglit_draw_rect(-1.0 + 2.0 * (c
[0] / piglit_width
),
4299 -1.0 + 2.0 * (c
[1] / piglit_height
),
4300 2.0 * (c
[2] / piglit_width
),
4301 2.0 * (c
[3] / piglit_height
));
4302 } else if (parse_str(line
, "draw rect patch ", &rest
)) {
4303 result
= program_must_be_in_use();
4304 parse_floats(rest
, c
, 4, NULL
);
4305 piglit_draw_rect_custom(c
[0], c
[1], c
[2], c
[3], true, 1);
4306 } else if (parse_str(line
, "draw rect ", &rest
)) {
4307 result
= program_must_be_in_use();
4308 program_subroutine_uniforms();
4309 parse_floats(rest
, c
, 4, NULL
);
4310 piglit_draw_rect(c
[0], c
[1], c
[2], c
[3]);
4311 } else if (parse_str(line
, "draw instanced rect ortho patch ", &rest
)) {
4314 result
= program_must_be_in_use();
4315 sscanf(rest
, "%d %f %f %f %f",
4317 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4318 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4319 -1.0 + 2.0 * (c
[1] / piglit_height
),
4320 2.0 * (c
[2] / piglit_width
),
4321 2.0 * (c
[3] / piglit_height
), true,
4323 } else if (parse_str(line
, "draw instanced rect ortho ", &rest
)) {
4326 result
= program_must_be_in_use();
4327 sscanf(rest
, "%d %f %f %f %f",
4329 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4330 piglit_draw_rect_custom(-1.0 + 2.0 * (c
[0] / piglit_width
),
4331 -1.0 + 2.0 * (c
[1] / piglit_height
),
4332 2.0 * (c
[2] / piglit_width
),
4333 2.0 * (c
[3] / piglit_height
), false,
4335 } else if (parse_str(line
, "draw instanced rect ", &rest
)) {
4338 result
= program_must_be_in_use();
4339 sscanf(rest
, "%d %f %f %f %f",
4341 c
+ 0, c
+ 1, c
+ 2, c
+ 3);
4342 draw_instanced_rect(primcount
, c
[0], c
[1], c
[2], c
[3]);
4343 } else if (sscanf(line
, "draw arrays instanced %31s %d %d %d", s
, &x
, &y
, &z
) == 4) {
4344 GLenum mode
= decode_drawing_mode(s
);
4346 size_t count
= (size_t) y
;
4347 size_t primcount
= (size_t) z
;
4348 draw_arrays_common(first
, count
);
4349 glDrawArraysInstanced(mode
, first
, count
, primcount
);
4350 } else if (sscanf(line
, "draw arrays %31s %d %d", s
, &x
, &y
) == 3) {
4351 GLenum mode
= decode_drawing_mode(s
);
4353 size_t count
= (size_t) y
;
4354 result
= draw_arrays_common(first
, count
);
4355 glDrawArrays(mode
, first
, count
);
4356 } else if (parse_str(line
, "disable ", &rest
)) {
4357 do_enable_disable(rest
, false);
4358 } else if (parse_str(line
, "enable ", &rest
)) {
4359 do_enable_disable(rest
, true);
4360 } else if (sscanf(line
, "depthfunc %31s", s
) == 1) {
4361 glDepthFunc(piglit_get_gl_enum_from_name(s
));
4362 } else if (parse_str(line
, "fb ", &rest
)) {
4363 const GLenum target
=
4364 parse_str(rest
, "draw ", &rest
) ? GL_DRAW_FRAMEBUFFER
:
4365 parse_str(rest
, "read ", &rest
) ? GL_READ_FRAMEBUFFER
:
4369 if (parse_str(rest
, "tex 2d ", &rest
)) {
4370 GLenum attachments
[32];
4371 unsigned num_attachments
= 0;
4373 glGenFramebuffers(1, &fbo
);
4374 glBindFramebuffer(target
, fbo
);
4376 while (parse_int(rest
, &tex
, &rest
)) {
4377 attachments
[num_attachments
] =
4378 GL_COLOR_ATTACHMENT0
+ num_attachments
;
4379 glFramebufferTexture2D(
4380 target
, attachments
[num_attachments
],
4382 get_texture_binding(tex
)->obj
, 0);
4384 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4386 "glFramebufferTexture2D error\n");
4387 piglit_report_result(PIGLIT_FAIL
);
4393 if (target
!= GL_READ_FRAMEBUFFER
)
4394 glDrawBuffers(num_attachments
, attachments
);
4396 w
= get_texture_binding(tex
)->width
;
4397 h
= get_texture_binding(tex
)->height
;
4399 } else if (parse_str(rest
, "tex slice ", &rest
)) {
4402 REQUIRE(parse_tex_target(rest
, &tex_target
, &rest
) &&
4403 parse_int(rest
, &tex
, &rest
) &&
4404 parse_int(rest
, &l
, &rest
) &&
4405 parse_int(rest
, &z
, &rest
),
4406 "Framebuffer binding command not "
4407 "understood at: %s\n", rest
);
4409 const GLuint tex_obj
= get_texture_binding(tex
)->obj
;
4411 glGenFramebuffers(1, &fbo
);
4412 glBindFramebuffer(target
, fbo
);
4414 if (tex_target
== GL_TEXTURE_1D
) {
4416 "Invalid layer index provided "
4417 "in command: %s\n", line
);
4418 glFramebufferTexture1D(
4419 target
, GL_COLOR_ATTACHMENT0
,
4420 tex_target
, tex_obj
, l
);
4422 } else if (tex_target
== GL_TEXTURE_2D
||
4423 tex_target
== GL_TEXTURE_RECTANGLE
||
4424 tex_target
== GL_TEXTURE_2D_MULTISAMPLE
) {
4426 "Invalid layer index provided "
4427 "in command: %s\n", line
);
4428 glFramebufferTexture2D(
4429 target
, GL_COLOR_ATTACHMENT0
,
4430 tex_target
, tex_obj
, l
);
4432 } else if (tex_target
== GL_TEXTURE_CUBE_MAP
) {
4433 static const GLenum cubemap_targets
[] = {
4434 GL_TEXTURE_CUBE_MAP_POSITIVE_X
,
4435 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
,
4436 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
,
4437 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
,
4438 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
,
4439 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4441 REQUIRE(z
< ARRAY_SIZE(cubemap_targets
),
4442 "Invalid layer index provided "
4443 "in command: %s\n", line
);
4444 tex_target
= cubemap_targets
[z
];
4446 glFramebufferTexture2D(
4447 target
, GL_COLOR_ATTACHMENT0
,
4448 tex_target
, tex_obj
, l
);
4451 glFramebufferTextureLayer(
4452 target
, GL_COLOR_ATTACHMENT0
,
4456 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4457 fprintf(stderr
, "Error binding texture "
4458 "attachment for command: %s\n",
4460 piglit_report_result(PIGLIT_FAIL
);
4463 w
= MAX2(1, get_texture_binding(tex
)->width
>> l
);
4464 h
= MAX2(1, get_texture_binding(tex
)->height
>> l
);
4466 } else if (sscanf(rest
, "tex layered %d", &tex
) == 1) {
4467 glGenFramebuffers(1, &fbo
);
4468 glBindFramebuffer(target
, fbo
);
4470 glFramebufferTexture(
4471 target
, GL_COLOR_ATTACHMENT0
,
4472 get_texture_binding(tex
)->obj
, 0);
4473 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4475 "glFramebufferTexture error\n");
4476 piglit_report_result(PIGLIT_FAIL
);
4479 w
= get_texture_binding(tex
)->width
;
4480 h
= get_texture_binding(tex
)->height
;
4482 } else if (parse_str(rest
, "ms ", &rest
)) {
4487 REQUIRE(parse_enum_gl(rest
, &format
, &rest
) &&
4488 parse_int(rest
, &w
, &rest
) &&
4489 parse_int(rest
, &h
, &rest
) &&
4490 parse_int(rest
, &samples
, &rest
),
4491 "Framebuffer binding command not "
4492 "understood at: %s\n", rest
);
4494 glGenFramebuffers(1, &fbo
);
4495 glBindFramebuffer(target
, fbo
);
4497 glGenRenderbuffers(1, &rb
);
4498 glBindRenderbuffer(GL_RENDERBUFFER
, rb
);
4500 glRenderbufferStorageMultisample(GL_RENDERBUFFER
, samples
,
4503 glFramebufferRenderbuffer(target
,
4504 GL_COLOR_ATTACHMENT0
,
4505 GL_RENDERBUFFER
, rb
);
4507 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4508 fprintf(stderr
, "glFramebufferRenderbuffer error\n");
4509 piglit_report_result(PIGLIT_FAIL
);
4512 } else if (parse_str(rest
, "winsys", &rest
)) {
4513 fbo
= piglit_winsys_fbo
;
4514 glBindFramebuffer(target
, fbo
);
4515 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4516 fprintf(stderr
, "glBindFramebuffer error\n");
4517 piglit_report_result(PIGLIT_FAIL
);
4524 fprintf(stderr
, "Unknown fb bind subcommand "
4526 piglit_report_result(PIGLIT_FAIL
);
4529 const GLenum status
= glCheckFramebufferStatus(target
);
4530 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
4531 fprintf(stderr
, "incomplete fbo (status 0x%x)\n",
4533 piglit_report_result(PIGLIT_FAIL
);
4536 if (target
!= GL_READ_FRAMEBUFFER
) {
4540 /* Delete the previous draw FB in case
4541 * it's no longer reachable.
4543 if (draw_fbo
!= 0 &&
4544 draw_fbo
!= piglit_winsys_fbo
&&
4545 draw_fbo
!= (target
== GL_DRAW_FRAMEBUFFER
?
4547 glDeleteFramebuffers(1, &draw_fbo
);
4552 if (target
!= GL_DRAW_FRAMEBUFFER
) {
4556 /* Delete the previous read FB in case
4557 * it's no longer reachable.
4559 if (read_fbo
!= 0 &&
4560 read_fbo
!= piglit_winsys_fbo
&&
4561 read_fbo
!= (target
== GL_READ_FRAMEBUFFER
?
4563 glDeleteFramebuffers(1, &read_fbo
);
4568 } else if (parse_str(line
, "blit ", &rest
)) {
4569 static const struct string_to_enum buffers
[] = {
4570 { "color", GL_COLOR_BUFFER_BIT
},
4571 { "depth", GL_DEPTH_BUFFER_BIT
},
4572 { "stencil", GL_STENCIL_BUFFER_BIT
},
4575 static const struct string_to_enum filters
[] = {
4576 { "linear", GL_LINEAR
},
4577 { "nearest", GL_NEAREST
},
4580 unsigned buffer
, filter
;
4582 REQUIRE(parse_enum_tab(buffers
, rest
, &buffer
, &rest
) &&
4583 parse_enum_tab(filters
, rest
, &filter
, &rest
),
4584 "FB blit command not understood at: %s\n",
4587 glBlitFramebuffer(0, 0, read_width
, read_height
,
4588 0, 0, render_width
, render_height
,
4591 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4592 fprintf(stderr
, "glBlitFramebuffer error\n");
4593 piglit_report_result(PIGLIT_FAIL
);
4596 } else if (parse_str(line
, "frustum", &rest
)) {
4597 parse_floats(rest
, c
, 6, NULL
);
4598 piglit_frustum_projection(false, c
[0], c
[1], c
[2],
4600 } else if (parse_str(line
, "hint", &rest
)) {
4602 } else if (sscanf(line
,
4603 "image texture %d %31s",
4605 const GLenum img_fmt
= piglit_get_gl_enum_from_name(s
);
4606 glBindImageTexture(tex
, get_texture_binding(tex
)->obj
, 0,
4607 GL_FALSE
, 0, GL_READ_WRITE
, img_fmt
);
4608 } else if (sscanf(line
, "memory barrier %s", s
) == 1) {
4609 glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s
));
4610 } else if (parse_str(line
, "blend barrier", NULL
)) {
4612 } else if (parse_str(line
, "fbfetch barrier", NULL
)) {
4613 glFramebufferFetchBarrierEXT();
4614 } else if (sscanf(line
, "ortho %f %f %f %f",
4615 c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 4) {
4616 piglit_gen_ortho_projection(c
[0], c
[1], c
[2], c
[3],
4618 } else if (parse_str(line
, "ortho", NULL
)) {
4619 piglit_ortho_projection(render_width
, render_height
,
4621 } else if (sscanf(line
, "viewport indexed %u %f %f %f %f",
4622 &x
, c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 5) {
4623 glViewportIndexedfv(x
, c
);
4624 } else if (parse_str(line
, "probe rgba ", &rest
)) {
4625 parse_floats(rest
, c
, 6, NULL
);
4626 if (!piglit_probe_pixel_rgba((int) c
[0], (int) c
[1],
4628 result
= PIGLIT_FAIL
;
4630 } else if (parse_str(line
, "probe depth ", &rest
)) {
4631 parse_floats(rest
, c
, 3, NULL
);
4632 if (!piglit_probe_pixel_depth((int) c
[0], (int) c
[1],
4634 result
= PIGLIT_FAIL
;
4636 } else if (sscanf(line
,
4637 "probe atomic counter buffer %u %u %s %u",
4638 &ux
, &uy
, s
, &uz
) == 4) {
4639 if (!probe_atomic_counter(ux
, uy
, s
, uz
, true)) {
4640 result
= PIGLIT_FAIL
;
4642 } else if (sscanf(line
,
4643 "probe atomic counter %u %s %u",
4644 &ux
, s
, &uy
) == 3) {
4645 if (!probe_atomic_counter(0, ux
, s
, uy
, false)) {
4646 result
= PIGLIT_FAIL
;
4648 } else if (sscanf(line
, "probe ssbo uint %d %d %s 0x%x",
4649 &x
, &y
, s
, &z
) == 4) {
4650 if (!probe_ssbo_uint(x
, y
, s
, z
))
4651 result
= PIGLIT_FAIL
;
4652 } else if (sscanf(line
, "probe ssbo uint %d %d %s %d",
4653 &x
, &y
, s
, &z
) == 4) {
4654 if (!probe_ssbo_uint(x
, y
, s
, z
))
4655 result
= PIGLIT_FAIL
;
4656 } else if (sscanf(line
, "probe ssbo int %d %d %s %d",
4657 &x
, &y
, s
, &z
) == 4) {
4658 if (!probe_ssbo_int(x
, y
, s
, z
))
4659 result
= PIGLIT_FAIL
;
4660 } else if (sscanf(line
,
4661 "relative probe rgba ( %f , %f ) "
4662 "( %f , %f , %f , %f )",
4664 c
+ 2, c
+ 3, c
+ 4, c
+ 5) == 6) {
4665 x
= c
[0] * read_width
;
4666 y
= c
[1] * read_height
;
4667 if (x
>= read_width
)
4669 if (y
>= read_height
)
4670 y
= read_height
- 1;
4672 if (!piglit_probe_pixel_rgba(x
, y
, &c
[2])) {
4673 result
= PIGLIT_FAIL
;
4675 } else if (parse_str(line
, "probe rgb ", &rest
)) {
4676 parse_floats(rest
, c
, 5, NULL
);
4677 if (!piglit_probe_pixel_rgb((int) c
[0], (int) c
[1],
4679 result
= PIGLIT_FAIL
;
4681 } else if (sscanf(line
,
4682 "relative probe rgb ( %f , %f ) "
4685 c
+ 2, c
+ 3, c
+ 4) == 5) {
4686 x
= c
[0] * read_width
;
4687 y
= c
[1] * read_height
;
4688 if (x
>= read_width
)
4690 if (y
>= read_height
)
4691 y
= read_height
- 1;
4693 if (!piglit_probe_pixel_rgb(x
, y
, &c
[2])) {
4694 result
= PIGLIT_FAIL
;
4696 } else if (sscanf(line
, "probe rect rgba "
4697 "( %d , %d , %d , %d ) "
4698 "( %f , %f , %f , %f )",
4700 c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 8) {
4701 if (!piglit_probe_rect_rgba(x
, y
, w
, h
, c
)) {
4702 result
= PIGLIT_FAIL
;
4704 } else if (sscanf(line
, "relative probe rect rgb "
4705 "( %f , %f , %f , %f ) "
4707 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4708 c
+ 4, c
+ 5, c
+ 6) == 7) {
4709 x
= c
[0] * read_width
;
4710 y
= c
[1] * read_height
;
4711 w
= c
[2] * read_width
;
4712 h
= c
[3] * read_height
;
4714 if (!piglit_probe_rect_rgb(x
, y
, w
, h
, &c
[4])) {
4715 result
= PIGLIT_FAIL
;
4717 } else if (sscanf(line
, "relative probe rect rgba "
4718 "( %f , %f , %f , %f ) "
4719 "( %f , %f , %f , %f )",
4720 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4721 c
+ 4, c
+ 5, c
+ 6, c
+ 7) == 8) {
4722 x
= c
[0] * read_width
;
4723 y
= c
[1] * read_height
;
4724 w
= c
[2] * read_width
;
4725 h
= c
[3] * read_height
;
4727 if (!piglit_probe_rect_rgba(x
, y
, w
, h
, &c
[4])) {
4728 result
= PIGLIT_FAIL
;
4730 } else if (sscanf(line
, "relative probe rect rgba int "
4731 "( %f , %f , %f , %f ) "
4732 "( %d , %d , %d , %d )",
4733 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4734 &x
, &y
, &z
, &w
) == 8) {
4735 const int expected
[] = { x
, y
, z
, w
};
4736 if (!piglit_probe_rect_rgba_int(c
[0] * read_width
,
4741 result
= PIGLIT_FAIL
;
4743 } else if (parse_str(line
, "polygon mode ", &rest
)) {
4746 REQUIRE(parse_enum_gl(rest
, &face
, &rest
) &&
4747 parse_enum_gl(rest
, &mode
, &rest
),
4748 "Polygon mode command not understood at %s\n",
4751 glPolygonMode(face
, mode
);
4753 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4754 fprintf(stderr
, "glPolygonMode error\n");
4755 piglit_report_result(PIGLIT_FAIL
);
4757 } else if (parse_str(line
, "probe all rgba ", &rest
)) {
4758 parse_floats(rest
, c
, 4, NULL
);
4759 if (result
!= PIGLIT_FAIL
&&
4760 !piglit_probe_rect_rgba(0, 0, read_width
,
4762 result
= PIGLIT_FAIL
;
4763 } else if (parse_str(line
, "probe warn all rgba ", &rest
)) {
4764 parse_floats(rest
, c
, 4, NULL
);
4765 if (result
== PIGLIT_PASS
&&
4766 !piglit_probe_rect_rgba(0, 0, read_width
,
4768 result
= PIGLIT_WARN
;
4769 } else if (parse_str(line
, "probe all rgb", &rest
)) {
4770 parse_floats(rest
, c
, 3, NULL
);
4771 if (result
!= PIGLIT_FAIL
&&
4772 !piglit_probe_rect_rgb(0, 0, read_width
,
4774 result
= PIGLIT_FAIL
;
4775 } else if (parse_str(line
, "tolerance", &rest
)) {
4776 parse_floats(rest
, piglit_tolerance
, 4, NULL
);
4777 } else if (parse_str(line
, "shade model smooth", NULL
)) {
4778 glShadeModel(GL_SMOOTH
);
4779 } else if (parse_str(line
, "shade model flat", NULL
)) {
4780 glShadeModel(GL_FLAT
);
4781 } else if (sscanf(line
, "ssbo %d %d", &x
, &y
) == 2) {
4782 GLuint
*ssbo_init
= calloc(y
, 1);
4783 glGenBuffers(1, &ssbo
[x
]);
4784 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, x
, ssbo
[x
]);
4785 glBufferData(GL_SHADER_STORAGE_BUFFER
, y
,
4786 ssbo_init
, GL_DYNAMIC_DRAW
);
4789 else if (sscanf(line
, "xfb buffer object %u %u", &ux
, &uy
) == 2) {
4790 GLuint
*xfb_init
= calloc(uy
, 1);
4791 if (ux
< 0 || ux
>= MAX_XFB_BUFFERS
) {
4792 printf("xfb buffer id %d out of range\n", ux
);
4793 piglit_report_result(PIGLIT_FAIL
);
4795 glGenBuffers(1, &xfb
[ux
]);
4796 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, ux
, xfb
[ux
]);
4797 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, uy
,
4798 xfb_init
, GL_STREAM_READ
);
4800 } else if (sscanf(line
, "xfb draw arrays %31s %d %d", s
, &x
, &y
) == 3) {
4801 GLenum mode
= decode_drawing_mode(s
);
4803 size_t count
= (size_t) y
;
4804 result
= draw_arrays_common(first
, count
);
4805 piglit_xfb_draw_arrays(mode
, first
, count
);
4806 } else if (sscanf(line
, "probe xfb buffer float %u %u %f",
4807 &ux
, &uy
, &c
[0]) == 3) {
4808 if (!probe_xfb_float(xfb
[ux
], uy
, c
[0]))
4809 result
= PIGLIT_FAIL
;
4810 } else if (sscanf(line
, "probe xfb buffer double %u %u %lf",
4811 &ux
, &uy
, &d
[0]) == 3) {
4812 if (!probe_xfb_double(xfb
[ux
], uy
, d
[0]))
4813 result
= PIGLIT_FAIL
;
4814 } else if (sscanf(line
, "ssbo %d subdata float %d %f", &x
, &y
, &c
[0]) == 3) {
4815 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
4816 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, y
, 4, &c
[0]);
4817 } else if (sscanf(line
, "ssbo %d subdata int %d %s", &x
, &y
, s
) == 3) {
4818 parse_ints(s
, &z
, 1, NULL
);
4819 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
[x
]);
4820 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, y
, 4, &z
);
4821 } else if (sscanf(line
, "texture rgbw %d ( %d", &tex
, &w
) == 2) {
4822 GLenum int_fmt
= GL_RGBA
;
4825 "texture rgbw %d ( %d , %d ) %31s",
4827 if (num_scanned
< 3) {
4829 "invalid texture rgbw command!\n");
4830 piglit_report_result(PIGLIT_FAIL
);
4833 if (num_scanned
>= 4) {
4834 int_fmt
= piglit_get_gl_enum_from_name(s
);
4837 glActiveTexture(GL_TEXTURE0
+ tex
);
4838 int handle
= piglit_rgbw_texture(
4839 int_fmt
, w
, h
, GL_FALSE
, GL_FALSE
,
4840 (piglit_is_gles() ? GL_UNSIGNED_BYTE
:
4841 GL_UNSIGNED_NORMALIZED
));
4842 set_texture_binding(tex
, handle
, w
, h
, 1);
4844 if (!piglit_is_core_profile
&&
4845 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4846 glEnable(GL_TEXTURE_2D
);
4848 } else if (sscanf(line
, "resident texture %d", &tex
) == 1) {
4851 glBindTexture(GL_TEXTURE_2D
, 0);
4853 handle
= glGetTextureHandleARB(get_texture_binding(tex
)->obj
);
4854 glMakeTextureHandleResidentARB(handle
);
4856 set_resident_handle(tex
, handle
, true);
4858 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4860 "glMakeTextureHandleResidentARB error\n");
4861 piglit_report_result(PIGLIT_FAIL
);
4863 } else if (sscanf(line
, "resident image texture %d %31s",
4865 const GLenum img_fmt
= piglit_get_gl_enum_from_name(s
);
4868 glBindTexture(GL_TEXTURE_2D
, 0);
4870 handle
= glGetImageHandleARB(get_texture_binding(tex
)->obj
,
4871 0, GL_FALSE
, 0, img_fmt
);
4872 glMakeImageHandleResidentARB(handle
, GL_READ_WRITE
);
4874 set_resident_handle(tex
, handle
, false);
4876 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4878 "glMakeImageHandleResidentARB error\n");
4879 piglit_report_result(PIGLIT_FAIL
);
4881 } else if (parse_str(line
, "texture integer ", &rest
)) {
4885 sscanf(rest
, "%d ( %d , %d ) ( %d, %d ) %31s",
4886 &tex
, &w
, &h
, &b
, &a
, s
);
4887 if (num_scanned
< 6) {
4889 "invalid texture integer command!\n");
4890 piglit_report_result(PIGLIT_FAIL
);
4893 int_fmt
= piglit_get_gl_enum_from_name(s
);
4895 glActiveTexture(GL_TEXTURE0
+ tex
);
4896 const GLuint handle
=
4897 piglit_integer_texture(int_fmt
, w
, h
, b
, a
);
4898 set_texture_binding(tex
, handle
, w
, h
, 1);
4900 } else if (sscanf(line
, "texture miptree %d", &tex
) == 1) {
4901 glActiveTexture(GL_TEXTURE0
+ tex
);
4902 const GLuint handle
= piglit_miptree_texture();
4903 set_texture_binding(tex
, handle
, 8, 8, 1);
4905 if (!piglit_is_core_profile
&&
4906 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4907 glEnable(GL_TEXTURE_2D
);
4908 } else if (sscanf(line
,
4909 "texture checkerboard %d %d ( %d , %d ) "
4910 "( %f , %f , %f , %f ) "
4911 "( %f , %f , %f , %f )",
4912 &tex
, &level
, &w
, &h
,
4913 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4914 c
+ 4, c
+ 5, c
+ 6, c
+ 7) == 12) {
4915 glActiveTexture(GL_TEXTURE0
+ tex
);
4916 const GLuint handle
= piglit_checkerboard_texture(
4917 0, level
, w
, h
, w
/ 2, h
/ 2, c
+ 0, c
+ 4);
4918 set_texture_binding(tex
, handle
, w
, h
, 1);
4920 if (!piglit_is_core_profile
&&
4921 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4922 glEnable(GL_TEXTURE_2D
);
4923 } else if (sscanf(line
,
4924 "texture quads %d %d ( %d , %d ) ( %d , %d ) "
4925 "( %f , %f , %f , %f ) "
4926 "( %f , %f , %f , %f ) "
4927 "( %f , %f , %f , %f ) "
4928 "( %f , %f , %f , %f )",
4929 &tex
, &level
, &w
, &h
, &x
, &y
,
4930 c
+ 0, c
+ 1, c
+ 2, c
+ 3,
4931 c
+ 4, c
+ 5, c
+ 6, c
+ 7,
4932 c
+ 8, c
+ 9, c
+ 10, c
+ 11,
4933 c
+ 12, c
+ 13, c
+ 14, c
+ 15) == 22) {
4934 glActiveTexture(GL_TEXTURE0
+ tex
);
4935 const GLuint handle
= piglit_quads_texture(
4936 0, level
, w
, h
, x
, y
, c
+ 0, c
+ 4, c
+ 8, c
+ 12);
4937 set_texture_binding(tex
, handle
, w
, h
, 1);
4939 if (!piglit_is_core_profile
&&
4940 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
4941 glEnable(GL_TEXTURE_2D
);
4942 } else if (sscanf(line
,
4943 "texture junk 2DArray %d ( %d , %d , %d )",
4944 &tex
, &w
, &h
, &l
) == 4) {
4946 glActiveTexture(GL_TEXTURE0
+ tex
);
4947 glGenTextures(1, &texobj
);
4948 glBindTexture(GL_TEXTURE_2D_ARRAY
, texobj
);
4949 glTexImage3D(GL_TEXTURE_2D_ARRAY
, 0, GL_RGBA
,
4950 w
, h
, l
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, 0);
4951 set_texture_binding(tex
, texobj
, w
, h
, l
);
4953 } else if (parse_str(line
, "texture storage ", &rest
)) {
4954 GLenum target
, format
;
4958 REQUIRE(parse_int(rest
, &tex
, &rest
) &&
4959 parse_tex_target(rest
, &target
, &rest
) &&
4960 parse_enum_gl(rest
, &format
, &rest
) &&
4961 parse_str(rest
, "(", &rest
) &&
4962 parse_int(rest
, &l
, &rest
) &&
4963 parse_int(rest
, &w
, &rest
),
4964 "Texture storage command not understood "
4967 glActiveTexture(GL_TEXTURE0
+ tex
);
4968 glGenTextures(1, &tex_obj
);
4969 glBindTexture(target
, tex_obj
);
4971 if (!parse_int(rest
, &h
, &rest
))
4972 glTexStorage1D(target
, l
, format
, w
);
4973 else if (!parse_int(rest
, &d
, &rest
))
4974 glTexStorage2D(target
, l
, format
, w
, h
);
4976 glTexStorage3D(target
, l
, format
, w
, h
, d
);
4978 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
4979 fprintf(stderr
, "glTexStorage error\n");
4980 piglit_report_result(PIGLIT_FAIL
);
4983 if (target
== GL_TEXTURE_1D_ARRAY
)
4984 set_texture_binding(tex
, tex_obj
, w
, 1, h
);
4986 set_texture_binding(tex
, tex_obj
, w
, h
, d
);
4988 #ifdef PIGLIT_USE_OPENGL
4989 } else if (sscanf(line
,
4990 "texture rgbw 1D %d",
4992 glActiveTexture(GL_TEXTURE0
+ tex
);
4993 const GLuint handle
= piglit_rgbw_texture_1d();
4994 set_texture_binding(tex
, handle
, 4, 1, 1);
4997 } else if (sscanf(line
,
4998 "texture rgbw 3D %d",
5000 glActiveTexture(GL_TEXTURE0
+ tex
);
5001 const GLuint handle
= piglit_rgbw_texture_3d();
5002 set_texture_binding(tex
, handle
, 2, 2, 2);
5004 } else if (sscanf(line
,
5005 "texture rgbw 2DArray %d ( %d , %d , %d )",
5006 &tex
, &w
, &h
, &l
) == 4) {
5007 glActiveTexture(GL_TEXTURE0
+ tex
);
5008 const GLuint handle
= piglit_array_texture(
5009 GL_TEXTURE_2D_ARRAY
, GL_RGBA
, w
, h
, l
, GL_FALSE
);
5010 set_texture_binding(tex
, handle
, w
, h
, l
);
5012 } else if (sscanf(line
,
5013 "texture rgbw 1DArray %d ( %d , %d )",
5014 &tex
, &w
, &l
) == 3) {
5015 glActiveTexture(GL_TEXTURE0
+ tex
);
5017 const GLuint handle
= piglit_array_texture(
5018 GL_TEXTURE_1D_ARRAY
, GL_RGBA
, w
, h
, l
, GL_FALSE
);
5019 set_texture_binding(tex
, handle
, w
, 1, l
);
5021 } else if (sscanf(line
,
5022 "texture shadow2D %d ( %d , %d )",
5023 &tex
, &w
, &h
) == 3) {
5024 glActiveTexture(GL_TEXTURE0
+ tex
);
5025 const GLuint handle
= piglit_depth_texture(
5026 GL_TEXTURE_2D
, GL_DEPTH_COMPONENT
,
5028 glTexParameteri(GL_TEXTURE_2D
,
5029 GL_TEXTURE_COMPARE_MODE
,
5030 GL_COMPARE_R_TO_TEXTURE
);
5031 glTexParameteri(GL_TEXTURE_2D
,
5032 GL_TEXTURE_COMPARE_FUNC
,
5034 set_texture_binding(tex
, handle
, w
, h
, 1);
5036 if (!piglit_is_core_profile
&&
5037 !(piglit_is_gles() && piglit_get_gl_version() >= 20))
5038 glEnable(GL_TEXTURE_2D
);
5039 } else if (sscanf(line
,
5040 "texture shadowRect %d ( %d , %d )",
5041 &tex
, &w
, &h
) == 3) {
5042 glActiveTexture(GL_TEXTURE0
+ tex
);
5043 const GLuint handle
= piglit_depth_texture(
5044 GL_TEXTURE_RECTANGLE
, GL_DEPTH_COMPONENT
,
5046 glTexParameteri(GL_TEXTURE_RECTANGLE
,
5047 GL_TEXTURE_COMPARE_MODE
,
5048 GL_COMPARE_R_TO_TEXTURE
);
5049 glTexParameteri(GL_TEXTURE_RECTANGLE
,
5050 GL_TEXTURE_COMPARE_FUNC
,
5052 set_texture_binding(tex
, handle
, w
, h
, 1);
5053 } else if (sscanf(line
,
5054 "texture shadow1D %d ( %d )",
5056 glActiveTexture(GL_TEXTURE0
+ tex
);
5057 const GLuint handle
= piglit_depth_texture(
5058 GL_TEXTURE_1D
, GL_DEPTH_COMPONENT
,
5060 glTexParameteri(GL_TEXTURE_1D
,
5061 GL_TEXTURE_COMPARE_MODE
,
5062 GL_COMPARE_R_TO_TEXTURE
);
5063 glTexParameteri(GL_TEXTURE_1D
,
5064 GL_TEXTURE_COMPARE_FUNC
,
5066 set_texture_binding(tex
, handle
, w
, 1, 1);
5067 } else if (sscanf(line
,
5068 "texture shadow1DArray %d ( %d , %d )",
5069 &tex
, &w
, &l
) == 3) {
5070 glActiveTexture(GL_TEXTURE0
+ tex
);
5071 const GLuint handle
= piglit_depth_texture(
5072 GL_TEXTURE_1D_ARRAY
, GL_DEPTH_COMPONENT
,
5074 glTexParameteri(GL_TEXTURE_1D_ARRAY
,
5075 GL_TEXTURE_COMPARE_MODE
,
5076 GL_COMPARE_R_TO_TEXTURE
);
5077 glTexParameteri(GL_TEXTURE_1D_ARRAY
,
5078 GL_TEXTURE_COMPARE_FUNC
,
5080 set_texture_binding(tex
, handle
, w
, 1, l
);
5081 } else if (sscanf(line
,
5082 "texture shadow2DArray %d ( %d , %d , %d )",
5083 &tex
, &w
, &h
, &l
) == 4) {
5084 glActiveTexture(GL_TEXTURE0
+ tex
);
5085 const GLuint handle
= piglit_depth_texture(
5086 GL_TEXTURE_2D_ARRAY
, GL_DEPTH_COMPONENT
,
5088 glTexParameteri(GL_TEXTURE_2D_ARRAY
,
5089 GL_TEXTURE_COMPARE_MODE
,
5090 GL_COMPARE_R_TO_TEXTURE
);
5091 glTexParameteri(GL_TEXTURE_2D_ARRAY
,
5092 GL_TEXTURE_COMPARE_FUNC
,
5094 set_texture_binding(tex
, handle
, w
, h
, l
);
5095 } else if (sscanf(line
, "texcoord %d ( %f , %f , %f , %f )",
5096 &x
, c
+ 0, c
+ 1, c
+ 2, c
+ 3) == 5) {
5097 glMultiTexCoord4fv(GL_TEXTURE0
+ x
, c
);
5098 } else if (parse_str(line
, "texparameter ", &rest
)) {
5099 handle_texparameter(rest
);
5100 } else if (parse_str(line
, "uniform ", &rest
)) {
5101 result
= program_must_be_in_use();
5102 set_uniform(rest
, block_data
);
5103 } else if (parse_str(line
, "subuniform ", &rest
)) {
5104 result
= program_must_be_in_use();
5105 check_shader_subroutine_support();
5106 set_subroutine_uniform(rest
);
5107 } else if (parse_str(line
, "parameter ", &rest
)) {
5108 set_parameter(rest
);
5109 } else if (parse_str(line
, "patch parameter ", &rest
)) {
5110 set_patch_parameter(rest
);
5111 } else if (parse_str(line
, "program binary save restore", &rest
)) {
5112 program_binary_save_restore(true);
5113 } else if (parse_str(line
, "provoking vertex ", &rest
)) {
5114 set_provoking_vertex(rest
);
5115 } else if (parse_str(line
, "link error", &rest
)) {
5116 link_error_expected
= true;
5118 printf("shader link error expected, but it was successful!\n");
5119 piglit_report_result(PIGLIT_FAIL
);
5121 fprintf(stderr
, "Failed to link:\n%s\n", prog_err_info
);
5123 } else if (parse_str(line
, "link success", &rest
)) {
5124 result
= program_must_be_in_use();
5125 } else if (parse_str(line
, "ubo array index ", &rest
)) {
5126 /* we allow "ubo array index" in order to not
5127 * change existing tests using ubo array index
5129 parse_ints(rest
, &block_data
.array_index
, 1, NULL
);
5130 } else if (parse_str(line
, "block array index ", &rest
)) {
5131 parse_ints(rest
, &block_data
.array_index
, 1, NULL
);
5132 } else if (parse_str(line
, "block binding ", &rest
)) {
5133 parse_ints(rest
, &block_data
.binding
, 1, NULL
);
5134 } else if (parse_str(line
, "block offset ", &rest
)) {
5135 parse_ints(rest
, &block_data
.offset
, 1, NULL
);
5136 } else if (parse_str(line
, "block matrix stride", &rest
)) {
5137 parse_ints(rest
, &block_data
.matrix_stride
, 1, NULL
);
5138 } else if (parse_str(line
, "block row major", &rest
)) {
5139 parse_ints(rest
, &block_data
.row_major
, 1, NULL
);
5140 } else if (parse_str(line
, "active uniform ", &rest
)) {
5141 active_uniform(rest
);
5142 } else if (parse_str(line
, "verify program_query", &rest
)) {
5143 verify_program_query(rest
);
5144 } else if (parse_str(line
, "verify program_interface_query ", &rest
)) {
5145 active_program_interface(rest
, block_data
);
5146 } else if (parse_str(line
, "verify query_object", &rest
)) {
5147 result
= verify_query_object_result(rest
);
5148 } else if (parse_str(line
, "vertex attrib ", &rest
)) {
5149 set_vertex_attrib(rest
);
5150 } else if (parse_str(line
, "newlist ", &rest
)) {
5153 REQUIRE(parse_enum_gl(rest
, &mode
, &rest
),
5154 "NewList mode command not understood at %s\n",
5157 list
= glGenLists(1);
5158 glNewList(list
, mode
);
5159 } else if (parse_str(line
, "endlist", NULL
)) {
5161 } else if (parse_str(line
, "calllist", NULL
)) {
5163 } else if (parse_str(line
, "deletelist", NULL
)) {
5164 glDeleteLists(list
, 1);
5165 } else if (parse_str(line
, "viewport swizzle ", &rest
)) {
5166 handle_viewport_swizzle(rest
);
5167 } else if ((line
[0] != '\n') && (line
[0] != '\0')
5168 && (line
[0] != '#')) {
5169 printf("unknown command \"%s\"\n", line
);
5170 piglit_report_result(PIGLIT_FAIL
);
5175 if (result
!= PIGLIT_PASS
) {
5176 printf("Test failure on line %u\n", line_num
);
5177 full_result
= result
;
5183 if (!link_ok
&& !link_error_expected
) {
5184 full_result
= program_must_be_in_use();
5187 piglit_present_results();
5189 if (piglit_automatic
) {
5192 /* Free our resources, useful for valgrinding. */
5193 free_subroutine_uniforms();
5195 for (i
= 0; i
< ARRAY_SIZE(resident_handles
); i
++)
5196 clear_resident_handle(i
);
5198 for (i
= 0; i
< ARRAY_SIZE(texture_bindings
); i
++)
5199 clear_texture_binding(i
);
5202 glDeleteProgram(prog
);
5206 glDeleteProgramsARB(1, &prog
);
5210 glDeleteProgramPipelines(1, &pipeline
);
5216 static enum piglit_result
5217 init_test(const char *file
)
5219 enum piglit_result result
;
5221 result
= process_test_script(file
);
5222 if (result
!= PIGLIT_PASS
)
5225 result
= link_and_use_shaders();
5226 if (result
!= PIGLIT_PASS
)
5230 glBindProgramPipeline(pipeline
);
5232 if (link_ok
&& vertex_data_start
!= NULL
) {
5233 result
= program_must_be_in_use();
5234 if (result
!= PIGLIT_PASS
)
5237 bind_vao_if_supported();
5239 num_vbo_rows
= setup_vbo_from_text(prog
, vertex_data_start
,
5248 recreate_gl_context(char *exec_arg
, int param_argc
, char **param_argv
)
5250 int argc
= param_argc
+ 4;
5251 char **argv
= malloc(sizeof(char*) * argc
);
5254 fprintf(stderr
, "%s: malloc failed.\n", __func__
);
5255 piglit_report_result(PIGLIT_FAIL
);
5259 memcpy(&argv
[1], param_argv
, param_argc
* sizeof(char*));
5260 argv
[argc
-3] = "-auto";
5261 argv
[argc
-2] = "-fbo";
5262 argv
[argc
-1] = "-report-subtests";
5265 gl_fw
->destroy(gl_fw
);
5268 exit(main(argc
, argv
));
5272 validate_current_gl_context(const char *filename
)
5274 struct piglit_gl_test_config config
= { 0 };
5276 if (!piglit_gl_test_config_override_size(&config
)) {
5277 config
.window_width
= DEFAULT_WINDOW_WIDTH
;
5278 config
.window_height
= DEFAULT_WINDOW_HEIGHT
;
5281 get_required_config(filename
, spirv_replaces_glsl
, &config
);
5283 if (!current_config
.supports_gl_compat_version
!=
5284 !config
.supports_gl_compat_version
)
5287 if (!current_config
.supports_gl_core_version
!=
5288 !config
.supports_gl_core_version
)
5291 if (!current_config
.supports_gl_es_version
!=
5292 !config
.supports_gl_es_version
)
5295 if (current_config
.window_width
!= config
.window_width
||
5296 current_config
.window_height
!= config
.window_height
)
5299 if (!(current_config
.window_visual
& PIGLIT_GL_VISUAL_DEPTH
) &&
5300 config
.window_visual
& PIGLIT_GL_VISUAL_DEPTH
)
5307 piglit_init(int argc
, char **argv
)
5311 bool core
= piglit_is_core_profile
;
5313 enum piglit_result result
;
5314 float default_piglit_tolerance
[4];
5316 use_get_program_binary
=
5317 piglit_strip_arg(&argc
, argv
, "-get-program-binary") ||
5318 piglit_env_var_as_boolean("SHADER_RUNNER_GET_PROGRAM_BINARY",
5321 report_subtests
= piglit_strip_arg(&argc
, argv
, "-report-subtests");
5322 force_glsl
= piglit_strip_arg(&argc
, argv
, "-glsl");
5323 ignore_missing_uniforms
= piglit_strip_arg(&argc
, argv
, "-ignore-missing-uniforms");
5325 force_no_names
= piglit_strip_arg(&argc
, argv
, "-force-no-names");
5327 if (force_glsl
&& spirv_replaces_glsl
) {
5328 printf("Options -glsl and -spirv can't be used at the same time\n");
5329 piglit_report_result(PIGLIT_FAIL
);
5332 if (spirv_replaces_glsl
)
5333 force_no_names
= true;
5336 printf("usage: shader_runner <test.shader_test> [-glsl] [-force-no-names]\n");
5340 memcpy(default_piglit_tolerance
, piglit_tolerance
,
5341 sizeof(piglit_tolerance
));
5343 piglit_require_GLSL();
5345 version_init(&gl_version
, VERSION_GL
,
5348 piglit_get_gl_version());
5349 piglit_get_glsl_version(&es
, &major
, &minor
);
5350 version_init(&glsl_version
, VERSION_GLSL
, core
, !core
, es
,
5351 (major
* 100) + minor
);
5353 #ifdef PIGLIT_USE_OPENGL
5354 if (piglit_get_gl_version() >= 32)
5355 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
5356 &gl_max_vertex_output_components
);
5357 if (piglit_get_gl_version() >= 20 ||
5358 piglit_is_extension_supported("GL_ARB_fragment_shader"))
5359 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
5360 &gl_max_fragment_uniform_components
);
5361 if (piglit_get_gl_version() >= 20 ||
5362 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5363 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
5364 &gl_max_vertex_uniform_components
);
5365 if (piglit_get_gl_version() >= 20 ||
5366 piglit_is_extension_supported("GL_ARB_vertex_shader") ||
5367 piglit_is_extension_supported("GL_ARB_geometry_shader4") ||
5368 piglit_is_extension_supported("GL_EXT_geometry_shader4"))
5369 glGetIntegerv(GL_MAX_VARYING_COMPONENTS
,
5370 &gl_max_varying_components
);
5372 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
5373 &gl_max_fragment_uniform_components
);
5374 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
5375 &gl_max_vertex_uniform_components
);
5376 glGetIntegerv(GL_MAX_VARYING_VECTORS
,
5377 &gl_max_varying_components
);
5378 gl_max_fragment_uniform_components
*= 4;
5379 gl_max_vertex_uniform_components
*= 4;
5380 gl_max_varying_components
*= 4;
5382 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max_clip_planes
);
5384 if (gl_version
.num
>= 20 ||
5385 piglit_is_extension_supported("GL_ARB_vertex_shader"))
5386 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS
,
5387 &gl_max_vertex_attribs
);
5389 gl_max_vertex_attribs
= 16;
5391 read_width
= render_width
= piglit_width
;
5392 read_height
= render_height
= piglit_height
;
5394 #ifdef PIGLIT_USE_OPENGL
5395 if (piglit_is_extension_supported("GL_ARB_get_program_binary"))
5396 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
5397 &gl_num_program_binary_formats
);
5399 if (piglit_is_extension_supported("GL_OES_get_program_binary"))
5400 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES
,
5401 &gl_num_program_binary_formats
);
5404 if (use_get_program_binary
) {
5405 if (gl_num_program_binary_formats
== 0) {
5406 printf("Trying to use get_program_binary, but "
5407 "GL_NUM_PROGRAM_BINARY == 0\n");
5408 piglit_report_result(PIGLIT_SKIP
);
5412 /* Automatic mode can run multiple tests per session. */
5413 if (report_subtests
) {
5414 char testname
[4096], *ext
;
5417 for (i
= 1; i
< argc
; i
++) {
5418 const char *hit
, *filename
= argv
[i
];
5420 memcpy(piglit_tolerance
, default_piglit_tolerance
,
5421 sizeof(piglit_tolerance
));
5423 /* Re-initialize the GL context if a different GL config is required. */
5424 if (!validate_current_gl_context(filename
))
5425 recreate_gl_context(argv
[0], argc
- i
, argv
+ i
);
5427 /* Clear global variables to defaults. */
5429 assert(num_vertex_shaders
== 0);
5430 assert(num_tess_ctrl_shaders
== 0);
5431 assert(num_tess_eval_shaders
== 0);
5432 assert(num_geometry_shaders
== 0);
5433 assert(num_fragment_shaders
== 0);
5434 assert(num_compute_shaders
== 0);
5435 assert(num_uniform_blocks
== 0);
5436 assert(uniform_block_bos
== NULL
);
5437 assert(uniform_block_indexes
== NULL
);
5438 geometry_layout_input_type
= GL_TRIANGLES
;
5439 geometry_layout_output_type
= GL_TRIANGLE_STRIP
;
5440 geometry_layout_vertices_out
= 0;
5441 memset(atomics_bos
, 0, sizeof(atomics_bos
));
5442 memset(ssbo
, 0, sizeof(ssbo
));
5443 for (j
= 0; j
< ARRAY_SIZE(subuniform_locations
); j
++)
5444 assert(subuniform_locations
[j
] == NULL
);
5445 memset(num_subuniform_locations
, 0, sizeof(num_subuniform_locations
));
5446 shader_string
= NULL
;
5447 shader_string_size
= 0;
5448 vertex_data_start
= NULL
;
5449 vertex_data_end
= NULL
;
5451 sso_vertex_prog
= 0;
5452 sso_tess_control_prog
= 0;
5453 sso_tess_eval_prog
= 0;
5454 sso_geometry_prog
= 0;
5455 sso_fragment_prog
= 0;
5456 sso_compute_prog
= 0;
5458 vbo_present
= false;
5460 prog_in_use
= false;
5462 separable_program
= false;
5463 prog_err_info
= NULL
;
5466 /* Clear GL states to defaults. */
5467 glClearColor(0, 0, 0, 0);
5468 # if PIGLIT_USE_OPENGL
5473 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
5474 glActiveTexture(GL_TEXTURE0
);
5476 glDisable(GL_DEPTH_TEST
);
5477 glBindBuffer(GL_ARRAY_BUFFER
, 0);
5479 for (int k
= 0; k
< gl_max_clip_planes
; k
++) {
5480 static const GLdouble zero
[4];
5482 if (!piglit_is_core_profile
&& !es
)
5483 glClipPlane(GL_CLIP_PLANE0
+ k
, zero
);
5484 glDisable(GL_CLIP_PLANE0
+ k
);
5487 if (!(es
) && (gl_version
.num
>= 20 ||
5488 piglit_is_extension_supported("GL_ARB_vertex_program")))
5489 glDisable(GL_PROGRAM_POINT_SIZE
);
5491 for (int i
= 0; i
< 16; i
++)
5492 glDisableVertexAttribArray(i
);
5494 if (!piglit_is_core_profile
&& !es
) {
5495 glMatrixMode(GL_PROJECTION
);
5497 glMatrixMode(GL_MODELVIEW
);
5499 glShadeModel(GL_SMOOTH
);
5500 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE
);
5503 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
5504 glDisable(GL_VERTEX_PROGRAM_ARB
);
5505 glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, 0);
5507 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
5508 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
5509 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, 0);
5511 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
5513 glGenProgramPipelines(1, &pipeline
);
5514 glBindProgramPipeline(0);
5517 if (piglit_is_extension_supported("GL_EXT_provoking_vertex"))
5518 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT
);
5520 # if PIGLIT_USE_OPENGL
5521 if (gl_version
.num
>= 40 ||
5522 piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
5523 static float ones
[] = {1, 1, 1, 1};
5524 glPatchParameteri(GL_PATCH_VERTICES
, 3);
5525 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL
, ones
);
5526 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL
, ones
);
5529 /* Ideally one would use the following code:
5531 * if (gl_version.num >= 32) {
5532 * glPatchParameteri(GL_PATCH_VERTICES, 3);
5535 * however, that doesn't work with mesa because those
5536 * symbols apparently need to be exported, but that
5537 * breaks non-gles builds.
5539 * It seems rather unlikely that an implementation
5540 * would have GLES 3.2 support but not
5541 * OES_tessellation_shader.
5543 if (piglit_is_extension_supported("GL_OES_tessellation_shader")) {
5544 glPatchParameteriOES(GL_PATCH_VERTICES_OES
, 3);
5548 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
5550 /* Strip the file path. */
5551 hit
= strrchr(filename
, PIGLIT_PATH_SEP
);
5553 strcpy(testname
, hit
+1);
5555 strcpy(testname
, filename
);
5557 /* Strip the file extension. */
5558 ext
= strstr(testname
, ".shader_test");
5559 if (ext
&& !ext
[12])
5562 /* Print the name before we start the test, that way if
5563 * the test fails we can still resume and know which
5565 printf("PIGLIT TEST: %i - %s\n", test_num
, testname
);
5566 fprintf(stderr
, "PIGLIT TEST: %i - %s\n", test_num
, testname
);
5570 result
= init_test(filename
);
5572 if (result
== PIGLIT_PASS
) {
5573 result
= piglit_display();
5575 /* Use subtest when running with more than one test,
5576 * but use regular test result when running with just
5577 * one. This allows the standard process-at-a-time
5578 * mode to keep working.
5580 if (report_subtests
) {
5581 piglit_report_subtest_result(
5582 result
, "%s", testname
);
5584 piglit_report_result(result
);
5587 /* destroy GL objects? */
5591 teardown_shader_include_paths();
5597 result
= init_test(argv
[1]);
5598 if (result
!= PIGLIT_PASS
)
5599 piglit_report_result(result
);