2 * Copyright © 2015 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 DEALINGS
25 * \file resource-query.c
27 * Tests querying resources.
29 * From the GL_ARB_program_interface_query spec:
32 * void GetProgramInterfaceiv(uint program, enum programInterface,
33 * enum pname, int *params);
35 * queries a property of the interface <programInterface> in program
36 * <program>, returning its value in <params>. The property to return is
37 * specified by <pname>.
39 * If <pname> is ACTIVE_RESOURCES, the value returned is the number of
40 * resources in the active resource list for <programInterface>. If the
41 * list of active resources for <programInterface> is empty, zero is
44 * If <pname> is MAX_NAME_LENGTH, the value returned is the length of the
45 * longest active name string for an active resource in <programInterface>.
46 * This length includes an extra character for the null terminator. If
47 * the list of active resources for <programInterface> is empty, zero is
48 * returned. The error INVALID_OPERATION is generated if
49 * <programInterface> is ATOMIC_COUNTER_BUFFER, since active atomic counter
50 * buffer resources are not assigned name strings.
52 * If <pname> is MAX_NUM_ACTIVE_VARIABLES, the value returned is the number
53 * of active variables belonging to the interface block or atomic counter
54 * buffer resource in <programInterface> with the most active variables.
55 * If the list of active resources for <programInterface> is empty, zero is
56 * returned. The error INVALID_OPERATION is generated if
57 * <programInterface> is not UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER, or
58 * SHADER_STORAGE_BLOCK.
60 * If <pname> is MAX_NUM_COMPATIBLE_SUBROUTINES, the value returned is the
61 * number of compatible subroutines belonging to the active subroutine
62 * uniform in <programInterface> with the most compatible subroutines. If
63 * the list of active resources for <programInterface> is empty, zero is
64 * returned. The error INVALID_OPERATION is generated unless
65 * <programInterface> is VERTEX_SUBROUTINE_UNIFORM,
66 * TESS_CONTROL_SUBROUTINE_UNIFORM, TESS_EVALUATION_SUBROUTINE_UNIFORM,
67 * GEOMETRY_SUBROUTINE_UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM, or
68 * COMPUTE_SUBROUTINE_UNIFORM.
72 * uint GetProgramResourceIndex(uint program, enum programInterface,
75 * returns the unsigned integer index assigned to a resource named <name>
76 * in the interface type <programInterface> of program object <program>.
77 * The error INVALID_ENUM is generated if <programInterface> is
78 * ATOMIC_COUNTER_BUFFER, since active atomic counter buffer resources are
79 * not assigned name strings.
81 * If <name> exactly matches the name string of one of the active resources
82 * for <programInterface>, the index of the matched resource is returned.
83 * Additionally, if <name> would exactly match the name string of an active
84 * resource if "[0]" were appended to <name>, the index of the matched
85 * resource is returned. Otherwise, <name> is considered not to be the
86 * name of an active resource, and INVALID_INDEX is returned. Note that if
87 * an interface enumerates a single active resource list entry for an array
88 * variable (e.g., "a[0]"), a <name> identifying any array element other
89 * than the first (e.g., "a[1]") is not considered to match.
91 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
92 * should be returned when querying the index assigned to the special names
93 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
94 * "gl_SkipComponents3", and "gl_SkipComponents4".
98 * void GetProgramResourceName(uint program, enum programInterface,
99 * uint index, sizei bufSize, sizei *length,
102 * returns the name string assigned to the single active resource with an
103 * index of <index> in the interface <programInterface> of program object
104 * <program>. The error INVALID_VALUE is generated if <index> is greater
105 * than or equal to the number of entries in the active resource list for
106 * <programInterface>. The error INVALID_ENUM is generated if
107 * <programInterface> is ATOMIC_COUNTER_BUFFER, since active atomic counter
108 * buffer resources are not assigned name strings.
110 * The name string assigned to the active resource identified by <index> is
111 * returned as a null-terminated string in <name>. The actual number of
112 * characters written into <name>, excluding the null terminator, is
113 * returned in <length>. If <length> is NULL, no length is returned. The
114 * maximum number of characters that may be written into <name>, including
115 * the null terminator, is specified by <bufSize>. If the length of the
116 * name string (including the null terminator) is greater than <bufSize>,
117 * the first <bufSize>-1 characters of the name string will be written to
118 * <name>, followed by a null terminator. If <bufSize> is zero, no error
119 * will be generated but no characters will be written to <name>. The
120 * length of the longest name string for <programInterface>, including a
121 * null terminator, can be queried by calling GetProgramInterfaceiv with a
122 * <pname> of MAX_NAME_LENGTH.
125 #include "piglit-util-gl.h"
128 PIGLIT_GL_TEST_CONFIG_BEGIN
130 config
.supports_gl_core_version
= 32;
131 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
133 PIGLIT_GL_TEST_CONFIG_END
135 /* Naming conventions, from the GL_ARB_program_interface_query extension:
137 * "When building a list of active variable or interface blocks, resources
138 * with aggregate types (such as arrays or structures) may produce multiple
139 * entries in the active resource list for the corresponding interface.
140 * Additionally, each active variable, interface block, or subroutine in the
141 * list is assigned an associated name string that can be used by
142 * applications to refer to the resources. For interfaces involving
143 * variables, interface blocks, or subroutines, the entries of active
144 * resource lists are generated as follows:
146 * * For an active variable declared as a single instance of a basic type,
147 * a single entry will be generated, using the variable name from the
150 * * For an active variable declared as an array of basic types, a single
151 * entry will be generated, with its name string formed by concatenating
152 * the name of the array and the string "[0]".
154 * * For an active variable declared as a structure, a separate entry will
155 * be generated for each active structure member. The name of each entry
156 * is formed by concatenating the name of the structure, the "."
157 * character, and the name of the structure member. If a structure
158 * member to enumerate is itself a structure or array, these enumeration
159 * rules are applied recursively.
161 * * For an active variable declared as an array of an aggregate data type
162 * (structures or arrays), a separate entry will be generated for each
163 * active array element, unless noted immediately below. The name of
164 * each entry is formed by concatenating the name of the array, the "["
165 * character, an integer identifying the element number, and the "]"
166 * character. These enumeration rules are applied recursively, treating
167 * each enumerated array element as a separate active variable.
169 * * For an active shader storage block member declared as an array, an
170 * entry will be generated only for the first array element, regardless
171 * of its type. For arrays of aggregate types, the enumeration rules are
172 * applied recursively for the single enumerated array element.
174 * * For an active interface block not declared as an array of block
175 * instances, a single entry will be generated, using the block name from
178 * * For an active interface block declared as an array of instances,
179 * separate entries will be generated for each active instance. The name
180 * of the instance is formed by concatenating the block name, the "["
181 * character, an integer identifying the instance number, and the "]"
184 * * For an active subroutine, a single entry will be generated, using the
185 * subroutine name from the shader source.
187 * When an integer array element or block instance number is part of the name
188 * string, it will be specified in decimal form without a "+" or "-" sign or
189 * any extra leading zeroes. Additionally, the name string will not include
190 * white space anywhere in the string.
192 static const char *st_r_uniform
[] = {"vs_test", "gs_test", "fs_color",
194 "fs_array_uniform_block.fs_color",
195 "fs_array_uniform_block.fs_array[0]",
196 "sa[0].a[0]", "sa[1].a[0]",
198 static const char *st_r_tess_uniform
[] = {"tcs_test", "tes_test", NULL
};
199 static const char *st_r_cs_uniform
[] = {"cs_test", "tex", NULL
};
200 static const char *st_r_uniform_block
[] = {"vs_uniform_block",
203 "fs_array_uniform_block[0]",
204 "fs_array_uniform_block[1]",
205 "fs_array_uniform_block[2]",
206 "fs_array_uniform_block[3]",
208 static const char *st_r_tess_uniform_block
[] = {"tcs_uniform_block",
209 "tes_uniform_block", NULL
};
210 static const char *st_r_cs_uniform_block
[] = {"cs_uniform_block", NULL
};
211 static const char *st_r_in_vs
[] = {"vs_input0", "vs_input1", NULL
};
212 static const char *st_r_in_gs
[] = {"vs_output1[0]", "gl_PerVertex.gl_Position", NULL
};
213 static const char *st_r_in_fs
[] = {"fs_input1", NULL
};
214 static const char *st_r_in_tes
[] = {"tes_input1[0]", "gl_PerVertex.gl_Position", NULL
};
215 static const char *st_r_in_tcs
[] = {"vs_output1[0]",
217 "gl_PerVertex.gl_Position",
219 static const char *st_r_out_vs
[] = {"vs_output1", "gl_Position", NULL
};
220 static const char *st_r_out_gs
[] = {"fs_input1", "gl_Position", NULL
};
221 static const char *st_r_out_fs
[] = {"fs_output0", "fs_output1", NULL
};
222 static const char *st_r_out_tes
[] = {"vs_output1", "gl_Position", NULL
};
223 static const char *st_r_out_tcs
[] = {"tes_input1[0]", "tcs_patch",
224 "gl_PerVertex.gl_Position",
226 static const char *st_r_buffer
[] = {"vs_buf_var", "gs_buf_var", "fs_buf_var",
228 static const char *st_r_stor_block
[] = {"vs_buffer_block", "gs_buffer_block",
229 "fs_buffer_block", NULL
};
230 static const char *st_r_tf_varying
[] = {"gl_Position", "fs_input1", NULL
};
231 static const char *st_r_vs_sub
[] = {"vss", "vss2", NULL
};
232 static const char *st_r_gs_sub
[] = {"gss", NULL
};
233 static const char *st_r_fs_sub
[] = {"fss", NULL
};
234 static const char *st_r_cs_sub
[] = {"css", NULL
};
235 static const char *st_r_tcs_sub
[] = {"tcss", NULL
};
236 static const char *st_r_tes_sub
[] = {"tess", NULL
};
237 static const char *st_r_vs_sub_uni
[] = {"VERTEX", NULL
};
238 static const char *st_r_gs_sub_uni
[] = {"GEOMETRY", NULL
};
239 static const char *st_r_fs_sub_uni
[] = {"FRAGMENT", NULL
};
240 static const char *st_r_cs_sub_uni
[] = {"COMPUTE", NULL
};
241 static const char *st_r_tcs_sub_uni
[] = {"TESS_CONTROL", NULL
};
242 static const char *st_r_tes_sub_uni
[] = {"TESS_EVALUATION", NULL
};
244 /* From the GL_ARB_program_interface_query extension:
246 * "The GL provides a number of commands to query properties of the interfaces
247 * of a program object. Each such command accepts a <programInterface>
248 * token, identifying a specific interface. The supported values for
249 * <programInterface> are as follows:
250 * * UNIFORM corresponds to the set of active uniform variables (section
251 * 2.14.7) used by <program>.
253 * * UNIFORM_BLOCK corresponds to the set of active uniform blocks (section
254 * 2.14.7) used by <program>.
256 * * ATOMIC_COUNTER_BUFFER corresponds to the set of active atomic counter
257 * buffer binding points (section 2.14.7) used by <program>.
259 * * PROGRAM_INPUT corresponds to the set of active input variables used by
260 * the first shader stage of <program>. If <program> includes multiple
261 * shader stages, input variables from any shader stage other than the
262 * first will not be enumerated.
264 * * PROGRAM_OUTPUT corresponds to the set of active output variables
265 * (section 2.14.11) used by the last shader stage of <program>. If
266 * <program> includes multiple shader stages, output variables from any
267 * shader stage other than the last will not be enumerated.
269 * * VERTEX_SUBROUTINE, TESS_CONTROL_SUBROUTINE,
270 * TESS_EVALUATION_SUBROUTINE, GEOMETRY_SUBROUTINE, FRAGMENT_SUBROUTINE,
271 * and COMPUTE_SUBROUTINE correspond to the set of active subroutines for
272 * the vertex, tessellation control, tessellation evaluation, geometry,
273 * fragment, and compute shader stages of <program>, respectively
276 * * VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_SUBROUTINE_UNIFORM,
277 * TESS_EVALUATION_SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_UNIFORM,
278 * FRAGMENT_SUBROUTINE_UNIFORM, and COMPUTE_SUBROUTINE_UNIFORM correspond
279 * to the set of active subroutine uniform variables used by the vertex,
280 * tessellation control, tessellation evaluation, geometry, fragment, and
281 * compute shader stages of <program>, respectively (section 2.14.8).
283 * * TRANSFORM_FEEDBACK_VARYING corresponds to the set of output variables
284 * in the last non-fragment stage of <program> that would be captured
285 * when transform feedback is active (section 2.20.2).
287 * * BUFFER_VARIABLE corresponds to the set of active buffer variables (see
288 * the ARB_shader_storage_buffer_object extension) used by <program>.
290 * * SHADER_STORAGE_BLOCK corresponds to the set of active shader storage
291 * blocks (see the ARB_shader_storage_buffer_object extension) used by
294 * Additionally, from the GL_ARB_program_interface_query extension:
296 * "For the ATOMIC_COUNTER_BUFFER interface, the list of active buffer binding
297 * points is built by identifying each unique binding point associated with
298 * one or more active atomic counter uniform variables. Active atomic
299 * counter buffers do not have an associated name string.
301 * For the UNIFORM, PROGRAM_INPUT, PROGRAM_OUTPUT, and
302 * TRANSFORM_FEEDBACK_VARYING interfaces, the active resource list will
303 * include all active variables for the interface, including any active
304 * built-in variables.
306 * For PROGRAM_INPUT and PROGRAM_OUTPUT interfaces for shaders that receive
307 * or produce patch primitives, the active resource list will include both
308 * per-vertex and per-patch inputs and outputs.
310 * For the TRANSFORM_FEEDBACK_VARYING interface, the active resource list
311 * will entries for the special varying names gl_NextBuffer,
312 * gl_SkipComponents1, gl_SkipComponents2, gl_SkipComponents3, and
313 * gl_SkipComponents4 (section 2.14.11). These variables are used to control
314 * how varying values are written to transform feedback buffers. When
315 * enumerating the properties of such resources, these variables are
316 * considered to have a TYPE of NONE and an ARRAY_SIZE of 0 (gl_NextBuffer),
317 * 1, 2, 3, and 4, respectively."
321 GLenum programInterface
;
323 const char *programInterface_str
;
324 const char *active_resources_str
;
325 const char *max_length_name_str
;
326 const char *max_num_active_str
;
327 const char *max_num_compat_sub_str
;
329 /* set to -1 to disable the test */
330 int active_resources
;
333 int max_num_compat_sub
;
338 const char *tcs_text
;
339 const char *tes_text
;
342 const char **resources
;
345 #define ST(active_r, max_len, max_num_active, max_num_compat_sub, vs, tcs, \
346 tes, gs, fs, cs, name, suffix, resources) { \
347 (name), #name suffix, #name suffix " active resources", \
348 #name suffix " max length name", \
349 #name suffix " max num active", \
350 #name suffix " max num compat sub", \
351 (active_r), (max_len), (max_num_active), (max_num_compat_sub), \
352 (vs), (gs), (fs), (tcs), (tes), (cs), (resources) \
355 static const struct subtest_t subtests
[] = {
356 ST( 8, 35, -1, -1, vs_std
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_UNIFORM
, "(vs,gs,fs)", st_r_uniform
),
357 ST( 2, 9, -1, -1, NULL
, tcs_sub
, tes_in
, NULL
, NULL
, NULL
, GL_UNIFORM
, "(tes,tcs)", st_r_tess_uniform
),
358 ST( 2, 8, -1, -1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_UNIFORM
, "(cs)", st_r_cs_uniform
),
359 ST( 7, 26, 2, -1, vs_std
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_UNIFORM_BLOCK
, "(vs,gs,fs)", st_r_uniform_block
),
360 ST( 2, 18, -1, -1, NULL
, tcs_sub
, tes_in
, NULL
, NULL
, NULL
, GL_UNIFORM_BLOCK
, "(tcs,tes)", st_r_tess_uniform_block
),
361 ST( 1, 17, -1, -1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_UNIFORM_BLOCK
, "(cs)", st_r_cs_uniform_block
),
362 ST( 2, 10, -1, -1, vs_std
, NULL
, NULL
, NULL
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(vs)", st_r_in_vs
),
363 ST( 2, 25, -1, -1, NULL
, NULL
, NULL
, gs_std
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(gs)", st_r_in_gs
),
364 ST( 1, 10, -1, -1, NULL
, NULL
, NULL
, NULL
, fs_in
, NULL
, GL_PROGRAM_INPUT
, "(fs)", st_r_in_fs
),
365 ST( 2, 10, -1, -1, vs_std
, NULL
, NULL
, NULL
, fs_std
, NULL
, GL_PROGRAM_INPUT
, "(vs,fs)", st_r_in_vs
),
366 ST( 2, 10, -1, -1, vs_std
, NULL
, NULL
, gs_std
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(vs,gs)", st_r_in_vs
),
367 ST( 2, 25, -1, -1, NULL
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_PROGRAM_INPUT
, "(gs,fs)", st_r_in_gs
),
368 ST( 2, 10, -1, -1, vs_std
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_PROGRAM_INPUT
, "(vs,gs,fs)", st_r_in_vs
),
369 ST( 2, 25, -1, -1, NULL
, NULL
, tes_in
, NULL
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(tes)", st_r_in_tes
),
370 ST( 3, 25, -1, -1, NULL
, tcs_sub
, NULL
, NULL
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(tcs)", st_r_in_tcs
),
371 ST( 3, 25, -1, -1, NULL
, tcs_sub
, tes_in
, NULL
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(tcs,tes)", st_r_in_tcs
),
372 ST( 2, 10, -1, -1, vs_std
, tcs_sub
, tes_in
, NULL
, NULL
, NULL
, GL_PROGRAM_INPUT
, "(vs,tcs,tes)", st_r_in_vs
),
373 ST( 0, 0, -1, -1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_PROGRAM_INPUT
, "(cs)", NULL
),
374 ST( 2, 12, -1, -1, vs_std
, NULL
, NULL
, NULL
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(vs)", st_r_out_vs
),
375 ST( 2, 12, -1, -1, NULL
, NULL
, NULL
, gs_std
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(gs)", st_r_out_gs
),
376 ST( 2, 11, -1, -1, NULL
, NULL
, NULL
, NULL
, fs_std
, NULL
, GL_PROGRAM_OUTPUT
, "(fs)", st_r_out_fs
),
377 ST( 2, 11, -1, -1, vs_std
, NULL
, NULL
, NULL
, fs_std
, NULL
, GL_PROGRAM_OUTPUT
, "(vs,fs)", st_r_out_fs
),
378 ST( 2, 12, -1, -1, vs_std
, NULL
, NULL
, gs_std
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(vs,gs)", st_r_out_gs
),
379 ST( 2, 11, -1, -1, NULL
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_PROGRAM_OUTPUT
, "(gs,fs)", st_r_out_fs
),
380 ST( 2, 11, -1, -1, vs_std
, NULL
, NULL
, gs_std
, fs_in
, NULL
, GL_PROGRAM_OUTPUT
, "(vs,gs,fs)", st_r_out_fs
),
381 ST( 2, 12, -1, -1, NULL
, NULL
, tes_in
, NULL
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(tes)", st_r_out_tes
),
382 ST( 3, 25, -1, -1, NULL
, tcs_sub
, NULL
, NULL
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(tcs)", st_r_out_tcs
),
383 ST( 2, 12, -1, -1, NULL
, tcs_sub
, tes_in
, NULL
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(tcs,tes)", st_r_out_tes
),
384 ST( 2, 12, -1, -1, NULL
, tcs_sub
, tes_in
, gs_std
, NULL
, NULL
, GL_PROGRAM_OUTPUT
, "(tcs,tes,gs)", st_r_out_gs
),
385 ST( 0, 0, -1, -1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_PROGRAM_OUTPUT
, "(cs)", st_r_cs_sub
),
386 ST( 3, 11, -1, -1, vs_stor
, NULL
, NULL
, gs_stor
, fs_stor
, NULL
, GL_BUFFER_VARIABLE
, "", st_r_buffer
),
387 ST( 3, 16, 1, -1, vs_stor
, NULL
, NULL
, gs_stor
, fs_stor
, NULL
, GL_SHADER_STORAGE_BLOCK
, "", st_r_stor_block
),
388 ST( 3, -1, 1, -1, vs_atom
, NULL
, NULL
, gs_atom
, fs_atom
, NULL
, GL_ATOMIC_COUNTER_BUFFER
, "", NULL
),
389 ST( 2, 12, -1, -1, vs_std
, NULL
, NULL
, gs_std
, NULL
, NULL
, GL_TRANSFORM_FEEDBACK_VARYING
, "", st_r_tf_varying
),
390 ST( 2, 5, -1, -1, vs_sub
, NULL
, NULL
, NULL
, NULL
, NULL
, GL_VERTEX_SUBROUTINE
, "", st_r_vs_sub
),
391 ST( 1, 4, -1, -1, vs_sub
, NULL
, NULL
, gs_sub
, NULL
, NULL
, GL_GEOMETRY_SUBROUTINE
, "", st_r_gs_sub
),
392 ST( 1, 4, -1, -1, vs_sub
, NULL
, NULL
, gs_sub
, fs_sub
, NULL
, GL_FRAGMENT_SUBROUTINE
, "", st_r_fs_sub
),
393 ST( 1, 4, -1, -1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_COMPUTE_SUBROUTINE
, "", st_r_cs_sub
),
394 ST( 1, 5, -1, -1, vs_sub
, tcs_sub
, NULL
, NULL
, NULL
, NULL
, GL_TESS_CONTROL_SUBROUTINE
, "", st_r_tcs_sub
),
395 ST( 1, 5, -1, -1, vs_sub
, NULL
, tes_sub
, NULL
, NULL
, NULL
, GL_TESS_EVALUATION_SUBROUTINE
, "", st_r_tes_sub
),
396 ST( 1, 7, -1, 2, vs_sub
, NULL
, NULL
, NULL
, NULL
, NULL
, GL_VERTEX_SUBROUTINE_UNIFORM
, "", st_r_vs_sub_uni
),
397 ST( 1, 9, -1, 1, vs_sub
, NULL
, NULL
, gs_sub
, NULL
, NULL
, GL_GEOMETRY_SUBROUTINE_UNIFORM
, "", st_r_gs_sub_uni
),
398 ST( 1, 9, -1, 1, vs_sub
, NULL
, NULL
, gs_sub
, fs_sub
, NULL
, GL_FRAGMENT_SUBROUTINE_UNIFORM
, "", st_r_fs_sub_uni
),
399 ST( 1, 13, -1, 1, vs_sub
, tcs_sub
, NULL
, NULL
, NULL
, NULL
, GL_TESS_CONTROL_SUBROUTINE_UNIFORM
, "", st_r_tcs_sub_uni
),
400 ST( 1, 16, -1, 1, vs_sub
, NULL
, tes_sub
, NULL
, NULL
, NULL
, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
, "", st_r_tes_sub_uni
),
401 ST( 1, 8, -1, 1, NULL
, NULL
, NULL
, NULL
, NULL
, cs_sub
, GL_COMPUTE_SUBROUTINE_UNIFORM
, "", st_r_cs_sub_uni
),
405 check_pname(GLuint prog
, GLenum programInterface
, GLenum pname
, bool *pass
,
406 const char *subtest
, int expected_value
)
410 if (expected_value
< 0) {
414 glGetProgramInterfaceiv(prog
, programInterface
, pname
, &value
);
415 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
416 printf(" Latest error generated while running '%s'\n",
420 if (value
!= expected_value
) {
421 fprintf(stderr
, "'%s' expected %i but got %i\n", subtest
,
422 expected_value
, value
);
428 is_resource_in_list(const char **list
, const char *resource
, int index
,
432 while (list
&& list
[i
]) {
433 if (strcmp(list
[i
], resource
) == 0) {
434 return !check_order
|| index
== i
;
443 consistency_check(GLuint prog
, GLenum programInterface
, const char *name
,
446 bool subroutine
= false;
447 const GLchar
*names
[] = { name
};
448 GLuint old_idx
= 0xdeadcafe;
451 /* Validate result against old API. */
452 switch (programInterface
) {
454 glGetUniformIndices(prog
, 1, names
, &old_idx
);
455 piglit_check_gl_error(GL_NO_ERROR
);
458 case GL_UNIFORM_BLOCK
:
459 old_idx
= glGetUniformBlockIndex(prog
, name
);
460 piglit_check_gl_error(GL_NO_ERROR
);
463 case GL_VERTEX_SUBROUTINE
:
464 shader
= GL_VERTEX_SHADER
;
468 case GL_TESS_CONTROL_SUBROUTINE
:
469 shader
= GL_TESS_CONTROL_SHADER
;
473 case GL_TESS_EVALUATION_SUBROUTINE
:
474 shader
= GL_TESS_EVALUATION_SHADER
;
478 case GL_GEOMETRY_SUBROUTINE
:
479 shader
= GL_GEOMETRY_SHADER
;
483 case GL_FRAGMENT_SUBROUTINE
:
484 shader
= GL_FRAGMENT_SHADER
;
488 case GL_COMPUTE_SUBROUTINE
:
489 shader
= GL_COMPUTE_SHADER
;
494 /* There are no old APIs for this program interface */
499 old_idx
= glGetSubroutineIndex(prog
, shader
, name
);
500 piglit_check_gl_error(GL_NO_ERROR
);
503 if (index
!= old_idx
) {
504 printf("Index inconsistent with the old API: %i vs %i\n", index
,
513 validate_resources(const struct subtest_t st
, GLuint prog
, bool *pass
)
515 GLsizei max_size
= 0, size
, i
;
518 /* Do not run the test for GL_ATOMIC_COUNTER_BUFFER.
519 * From the GL_ARB_program_interface_query extension:
521 * "The error INVALID_OPERATION is generated if <programInterface>
522 * is ATOMIC_COUNTER_BUFFER, since active atomic counter buffer
523 * resources are not assigned name strings."
525 if (st
.programInterface
== GL_ATOMIC_COUNTER_BUFFER
)
528 name
= (char *) malloc(st
.max_length_name
);
529 for (i
= 0; i
< st
.active_resources
; i
++) {
532 glGetProgramResourceName(prog
, st
.programInterface
,
533 i
, st
.max_length_name
,
535 piglit_check_gl_error(GL_NO_ERROR
);
537 /* keep track of the maximum size */
538 if (size
> max_size
) {
542 /* Check the names. Transform feedback requires the order to be
543 * the same as the one given in glTransformFeedbackVaryings.
544 * From the GL_ARB_program_interface_query extension:
546 * "The order of the active resource list is
547 * implementation-dependent for all interfaces except for
548 * TRANSFORM_FEEDBACK_VARYING. For TRANSFORM_FEEDBACK_VARYING,
549 * the active resource list will use the variable order
550 * specified in the the most recent call to
551 * TransformFeedbackVaryings before the last call to
554 if (st
.resources
&& !is_resource_in_list(st
.resources
, name
, i
,
555 st
.programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
)) {
556 fprintf(stderr
, "Resource '%s' not found in '%s' "
557 "resource list or found at the wrong "
559 st
.programInterface_str
);
563 /* Check the position of the arguments and see if it matches
564 * with the current position we are in.
566 index
= glGetProgramResourceIndex(prog
, st
.programInterface
,
569 fprintf(stderr
, "%s: Resource '%s' is not at the "
570 "position reported by "
571 "glGetProgramResourceIndex (%i instead "
573 st
.programInterface_str
, name
, index
, i
);
577 /* check the equivalence with the old API */
578 if (!consistency_check(prog
, st
.programInterface
, name
,
585 /* glGetProgramResourceName does not count the NULL terminator as part
586 * of the size contrarily to glGetProgramInterfaceiv.
587 * From the GL_ARB_program_interface_query extension:
589 * "void GetProgramInterfaceiv(uint program, enum programInterface,
590 * enum pname, int *params);
592 * If <pname> is MAX_NAME_LENGTH, the value returned is the length of
593 * the longest active name string for an active resource in
594 * <programInterface>. This length includes an extra character for the
597 * "void GetProgramResourceName(uint program, enum programInterface,
598 * uint index, sizei bufSize,
599 * sizei *length, char *name);
601 * The actual number of characters written into <name>, excluding the
602 * null terminator, is returned in <length>."
604 if (max_size
!= MAX2(0, st
.max_length_name
- 1)) {
605 fprintf(stderr
, "'%s actual max length' expected %i but got "
606 "%i\n", st
.programInterface_str
,
607 st
.max_length_name
- 1, max_size
);
613 check_extensions(const struct subtest_t st
)
615 if (st
.programInterface
== GL_ATOMIC_COUNTER_BUFFER
&&
616 !piglit_is_extension_supported("GL_ARB_shader_atomic_counters")) {
620 if ((st
.programInterface
== GL_BUFFER_VARIABLE
||
621 st
.programInterface
== GL_SHADER_STORAGE_BLOCK
) &&
622 !piglit_is_extension_supported("GL_ARB_shader_storage_buffer_object")) {
626 if ((st
.programInterface
== GL_VERTEX_SUBROUTINE
||
627 st
.programInterface
== GL_GEOMETRY_SUBROUTINE
||
628 st
.programInterface
== GL_FRAGMENT_SUBROUTINE
||
629 st
.programInterface
== GL_COMPUTE_SUBROUTINE
||
630 st
.programInterface
== GL_VERTEX_SUBROUTINE_UNIFORM
||
631 st
.programInterface
== GL_GEOMETRY_SUBROUTINE_UNIFORM
||
632 st
.programInterface
== GL_FRAGMENT_SUBROUTINE_UNIFORM
||
633 st
.programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
||
634 st
.programInterface
== GL_TESS_CONTROL_SUBROUTINE
||
635 st
.programInterface
== GL_TESS_EVALUATION_SUBROUTINE
||
636 st
.programInterface
== GL_TESS_CONTROL_SUBROUTINE_UNIFORM
||
637 st
.programInterface
== GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
||
638 st
.programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
) &&
639 !piglit_is_extension_supported("GL_ARB_shader_subroutine")) {
643 if ((st
.programInterface
== GL_TESS_CONTROL_SUBROUTINE
||
644 st
.programInterface
== GL_TESS_EVALUATION_SUBROUTINE
||
645 st
.programInterface
== GL_TESS_CONTROL_SUBROUTINE_UNIFORM
||
646 st
.programInterface
== GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
||
647 st
.tcs_text
|| st
.tes_text
) &&
648 (!piglit_is_extension_supported("GL_ARB_shader_subroutine") ||
649 !piglit_is_extension_supported("GL_ARB_tessellation_shader"))) {
653 if ((st
.programInterface
== GL_COMPUTE_SUBROUTINE
||
654 st
.programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
||
656 (!piglit_is_extension_supported("GL_ARB_compute_shader") ||
657 !piglit_is_extension_supported("GL_ARB_shader_image_load_store"))) {
665 run_subtest(const struct subtest_t st
, bool *pass
)
667 enum piglit_result result
;
668 bool local_pass
= true;
671 if (!check_extensions(st
)) {
672 result
= PIGLIT_SKIP
;
676 prog
= piglit_build_simple_program_unlinked_multiple_shaders(
677 GL_VERTEX_SHADER
, st
.vs_text
,
678 GL_GEOMETRY_SHADER
, st
.gs_text
,
679 GL_FRAGMENT_SHADER
, st
.fs_text
,
680 GL_TESS_CONTROL_SHADER
, st
.tcs_text
,
681 GL_TESS_EVALUATION_SHADER
, st
.tes_text
,
682 GL_COMPUTE_SHADER
, st
.cs_text
,
685 if (st
.programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
) {
686 glTransformFeedbackVaryings(prog
, 2, st_r_tf_varying
,
687 GL_INTERLEAVED_ATTRIBS
);
688 piglit_check_gl_error(GL_NO_ERROR
);
691 /* force the compiler not to optimise away inputs/outputs */
692 glProgramParameteri(prog
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
693 piglit_check_gl_error(GL_NO_ERROR
);
696 if (!piglit_link_check_status(prog
)) {
697 glDeleteProgram(prog
);
698 result
= PIGLIT_FAIL
;
703 check_pname(prog
, st
.programInterface
, GL_ACTIVE_RESOURCES
,
704 &local_pass
, st
.active_resources_str
, st
.active_resources
);
707 glGetProgramInterfaceiv(prog
, st
.programInterface
, GL_ACTIVE_RESOURCES
, &active
);
708 printf("Active resources:\n");
709 for (int i
= 0; i
< active
; i
++) {
712 glGetProgramResourceName(prog
, st
.programInterface
, i
, ARRAY_SIZE(name
), &len
, name
);
713 printf(" %s\n", name
);
717 check_pname(prog
, st
.programInterface
, GL_MAX_NAME_LENGTH
,
718 &local_pass
, st
.max_length_name_str
, st
.max_length_name
);
720 /* do not test fetching the names if the previous tests failed */
722 validate_resources(st
, prog
, &local_pass
);
725 check_pname(prog
, st
.programInterface
, GL_MAX_NUM_ACTIVE_VARIABLES
,
726 &local_pass
, st
.max_num_active_str
, st
.max_num_active
);
728 check_pname(prog
, st
.programInterface
,
729 GL_MAX_NUM_COMPATIBLE_SUBROUTINES
, &local_pass
,
730 st
.max_num_compat_sub_str
, st
.max_num_compat_sub
);
732 glDeleteProgram(prog
);
734 *pass
= *pass
&& local_pass
;
735 result
= local_pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
738 piglit_report_subtest_result(result
, "%s", st
.programInterface_str
);
742 piglit_init(int argc
, char **argv
)
744 piglit_require_extension("GL_ARB_program_interface_query");
745 piglit_require_extension("GL_ARB_separate_shader_objects");
754 /* run all the getprograminterfaceiv tests */
755 for (i
= 0; i
< sizeof(subtests
) / sizeof(struct subtest_t
); i
++) {
756 run_subtest(subtests
[i
], &pass
);
759 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;