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 getprogramresourceiv.c
27 * Tests the values returned by GetProgramResourceiv on multiple pipelines.
28 * Also checks some error cases.
30 * From the GL_ARB_program_interface_query spec:
33 * void GetProgramResourceiv(uint program, enum programInterface,
34 * uint index, sizei propCount,
35 * const enum *props, sizei bufSize,
36 * sizei *length, int *params);
38 * returns values for multiple properties of a single active resource with an
39 * index of <index> in the interface <programInterface> of program object
40 * <program>. For each resource, values for <propCount> properties specified
41 * by the array <props> are returned. The error INVALID_VALUE is generated
42 * if <propCount> is zero. The error INVALID_ENUM is generated if any value
43 * in <props> is not one of the properties described immediately below. The
44 * error INVALID_OPERATION is generated if any value in <props> is not
45 * allowed for <programInterface>. The set of allowed <programInterface>
46 * values for each property can be found in Table X.1.
48 * The values associated with the properties of the active resource are
49 * written to consecutive entries in <params>, in increasing order according
50 * to position in <props>. If no error is generated, only the first
51 * <bufSize> integer values will be written to <params>; any extra values
52 * will not be returned. If <length> is not NULL, the actual number of
53 * integer values written to <params> will be written to <length>.
55 * Property Supported Interfaces
56 * --------------------------- ----------------------------------------
57 * NAME_LENGTH all but ATOMIC_COUNTER_BUFFER
59 * TYPE UNIFORM, PROGRAM_INPUT, PROGRAM_OUTPUT,
60 * TRANSFORM_FEEDBACK_VARYING,
63 * ARRAY_SIZE UNIFORM, BUFFER_VARIABLE, PROGRAM_INPUT,
64 * PROGRAM_OUTPUT, VERTEX_SUBROUTINE_
65 * UNIFORM, TESS_CONTROL_SUBROUTINE_UNIFORM,
66 * TESS_EVALUATION_SUBROUTINE_UNIFORM,
67 * GEOMETRY_SUBROUTINE_UNIFORM, FRAGMENT_
68 * SUBROUTINE_UNIFORM, COMPUTE_SUBROUTINE_
69 * UNIFORM, TRANSFORM_FEEDBACK_VARYING
71 * OFFSET UNIFORM, BUFFER_VARIABLE
72 * BLOCK_INDEX UNIFORM, BUFFER_VARIABLE
73 * ARRAY_STRIDE UNIFORM, BUFFER_VARIABLE
74 * MATRIX_STRIDE UNIFORM, BUFFER_VARIABLE
75 * IS_ROW_MAJOR UNIFORM, BUFFER_VARIABLE
77 * ATOMIC_COUNTER_BUFFER_INDEX UNIFORM
79 * BUFFER_BINDING UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER,
80 * SHADER_STORAGE_BLOCK
81 * BUFFER_DATA_SIZE UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER
82 * SHADER_STORAGE_BLOCK
83 * NUM_ACTIVE_VARIABLES UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER
84 * SHADER_STORAGE_BLOCK
85 * ACTIVE_VARIABLES UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER
86 * SHADER_STORAGE_BLOCK
88 * REFERENCED_BY_VERTEX_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
89 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
90 * BUFFER_VARIABLE, PROGRAM_INPUT,
93 * REFERENCED_BY_TESS_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
94 * CONTROL_SHADER BUFFER, SHADER_STORAGE_BLOCK,
95 * BUFFER_VARIABLE, PROGRAM_INPUT,
98 * REFERENCED_BY_TESS_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
99 * EVALUATION_SHADER BUFFER, SHADER_STORAGE_BLOCK,
100 * BUFFER_VARIABLE, PROGRAM_INPUT,
103 * REFERENCED_BY_GEOMETRY_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
104 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
105 * BUFFER_VARIABLE, PROGRAM_INPUT,
108 * REFERENCED_BY_FRAGMENT_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
109 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
110 * BUFFER_VARIABLE, PROGRAM_INPUT,
113 * REFERENCED_BY_COMPUTE_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
114 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
115 * BUFFER_VARIABLE, PROGRAM_INPUT,
118 * NUM_COMPATIBLE_SUBROUTINES VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_
119 * SUBROUTINE_UNIFORM, TESS_EVALUATION_
120 * SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_
121 * UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM,
122 * COMPUTE_SUBROUTINE_UNIFORM
124 * COMPATIBLE_SUBROUTINES VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_
125 * SUBROUTINE_UNIFORM, TESS_EVALUATION_
126 * SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_
127 * UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM,
128 * COMPUTE_SUBROUTINE_UNIFORM
130 * TOP_LEVEL_ARRAY_SIZE BUFFER_VARIABLE
132 * TOP_LEVEL_ARRAY_STRIDE BUFFER_VARIABLE
134 * LOCATION UNIFORM, PROGRAM_INPUT, PROGRAM_OUTPUT,
135 * VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_
136 * SUBROUTINE_UNIFORM, TESS_EVALUATION_
137 * SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_
138 * UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM,
139 * COMPUTE_SUBROUTINE_UNIFORM
141 * LOCATION_INDEX PROGRAM_OUTPUT
143 * IS_PER_PATCH PROGRAM_INPUT, PROGRAM_OUTPUT
145 * Table X.1, GetProgramResourceiv properties and supported interfaces
147 * For the property NAME_LENGTH, a single integer identifying the length of
148 * the name string associated with an active variable, interface block, or
149 * subroutine is written to <params>. The name length includes a terminating
152 * For the property TYPE, a single integer identifying the type of an active
153 * variable is written to <params>. The integer returned is one of the
154 * values found in table 2.16.
156 * For the property ARRAY_SIZE, a single integer identifying the number of
157 * active array elements of an active variable is written to <params>. The
158 * array size returned is in units of the type associated with the property
159 * TYPE. For active variables not corresponding to an array of basic types,
160 * the value one is written to <params>. If the variable is a shader
161 * storage block member in an array with no declared size, the value zero
162 * is written to <params>.
164 * For the property BLOCK_INDEX, a single integer identifying the index of
165 * the active interface block containing an active variable is written to
166 * <params>. If the variable is not the member of an interface block, the
167 * value -1 is written to <params>.
169 * For the property OFFSET, a single integer identifying the offset of an
170 * active variable is written to <params>. For active variables backed by a
171 * buffer object, the value written is the offset, in basic machine units,
172 * relative to the base of buffer range holding the values of the variable.
173 * For active variables not backed by a buffer object, an offset of -1 is
174 * written to <params>.
176 * For the property ARRAY_STRIDE, a single integer identifying the stride
177 * between array elements in an active variable is written to <params>. For
178 * active variables declared as an array of basic types, the value written is
179 * the difference, in basic machine units, between the offsets of consecutive
180 * elements in an array. For active variables not declared as an array of
181 * basic types, zero is written to <params>. For active variables not backed
182 * by a buffer object, -1 is written to <params>, regardless of the variable
185 * For the property MATRIX_STRIDE, a single integer identifying the stride
186 * between columns of a column-major matrix or rows of a row-major matrix is
187 * written to <params>. For active variables declared a single matrix or
188 * array of matrices, the value written is the difference, in basic machine
189 * units, between the offsets of consecutive columns or rows in each matrix.
190 * For active variables not declared as a matrix or array of matrices, zero
191 * is written to <params>. For active variables not backed by a buffer
192 * object, -1 is written to <params>, regardless of the variable type.
194 * For the property IS_ROW_MAJOR, a single integer identifying whether an
195 * active variable is a row-major matrix is written to <params>. For active
196 * variables backed by a buffer object, declared as a single matrix or array
197 * of matrices, and stored in row-major order, one is written to <params>.
198 * For all other active variables, zero is written to <params>.
200 * For the property ATOMIC_COUNTER_BUFFER_INDEX, a single integer identifying
201 * the index of the active atomic counter buffer containing an active
202 * variable is written to <params>. If the variable is not an atomic counter
203 * uniform, the value -1 is written to <params>.
205 * For the property of BUFFER_BINDING, to index of the buffer binding point
206 * associated with the active uniform block, shader storage block, or atomic
207 * counter buffer is written to <params>.
209 * For the property of BUFFER_DATA_SIZE, then the implementation-dependent
210 * minimum total buffer object size, in basic machine units, required to hold
211 * all active variables associated with an active uniform block, shader
212 * storage block, or atomic counter buffer is written to <params>. If the
213 * final member of an active shader storage block is array with no declared
214 * size, the minimum buffer size is computed assuming the array was declared
215 * as an array with one element.
217 * For the property of NUM_ACTIVE_VARIABLES, the number of active variables
218 * associated with an active uniform block, shader storage block, or atomic
219 * counter buffer is written to <params>.
221 * For the property of ACTIVE_VARIABLES, an array of active variable indices
222 * associated with an active uniform block, shader storage block, or atomic
223 * counter buffer is written to <params>. The number of values written to
224 * <params> for an active resource is given by the value of the property
225 * NUM_ACTIVE_VARIABLES for the resource.
227 * For the properties REFERENCED_BY_VERTEX_SHADER,
228 * REFERENCED_BY_TESS_CONTROL_SHADER, REFERENCED_BY_TESS_EVALUATION_SHADER,
229 * REFERENCED_BY_GEOMETRY_SHADER, REFERENCED_BY_FRAGMENT_SHADER, and
230 * REFERENCED_BY_COMPUTE_SHADER, a single integer is written to <params>,
231 * identifying whether the active resource is referenced by the vertex,
232 * tessellation control, tessellation evaluation, geometry, or fragment
233 * shaders, respectively, in the program object. The value one is written to
234 * <params> if an active variable is referenced by the corresponding shader,
235 * or if an active uniform block, shader storage block, or atomic counter
236 * buffer contains at least one variable referenced by the corresponding
237 * shader. Otherwise, the value zero is written to <params>.
239 * For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying the
240 * number of active array elements of the top-level shader storage block
241 * member containing to the active variable is written to <params>. If the
242 * top-level block member is not declared as an array, the value one is
243 * written to <params>. If the top-level block member is an array with no
244 * declared size, the value zero is written to <params>.
246 * For the property TOP_LEVEL_ARRAY_STRIDE, a single integer identifying the
247 * stride between array elements of the top-level shader storage block member
248 * containing the active variable is written to <params>. For top-level
249 * block members declared as arrays, the value written is the difference, in
250 * basic machine units, between the offsets of the active variable for
251 * consecutive elements in the top-level array. For top-level block members
252 * not declared as an array, zero is written to <params>.
254 * For the property LOCATION, a single integer identifying the assigned
255 * location for an active uniform, input, output, or subroutine uniform
256 * variable is written to <params>. For input, output, or uniform variables
257 * with locations specified by a layout qualifier, the specified location is
258 * used. For vertex shader input or fragment shader output variables without
259 * a layout qualifier, the location assigned when a program is linked is
260 * written to <params>. For all other input and output variables, the value
261 * -1 is written to <params>. For uniforms in uniform blocks, the value -1
262 * is written to <params>.
264 * For the property LOCATION_INDEX, a single integer identifying the fragment
265 * color index of an active fragment shader output variable is written to
266 * <params>. If the active variable is an output for a non-fragment shader,
267 * the value -1 will be written to <params>.
269 * For the property IS_PER_PATCH, a single integer identifying whether the
270 * input or output is a per-patch attribute. If the active variable is a
271 * per-patch attribute (declared with the "patch" qualifier), the value one
272 * is written to <params>; otherwise, the value zero is written to <params>."
275 #include "piglit-util-gl.h"
278 PIGLIT_GL_TEST_CONFIG_BEGIN
280 config
.supports_gl_core_version
= 32;
281 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
283 PIGLIT_GL_TEST_CONFIG_END
285 GLuint prog_std
= -1; /* (vs,gs,fs)_std */
286 GLuint prog_stor
= -1; /* (vs,gs,fs)_stor */
287 GLuint prog_buff_blks
= -1; /* (vs,fs)_buff_blks */
288 GLuint prog_sub
= -1; /* (vs,gs,fs)_sub */
289 GLuint prog_sub_tess
= -1; /* tcs_sub */
290 GLuint prog_cs
= -1; /* cs_sub */
291 GLuint prog_loc
= -1; /* (vs,fs)_loc */
292 GLuint prog_atom
= -1; /* fs_atom */
296 GLenum programInterface
;
300 /* set to -1 to disable the test */
308 const char *vs_std_vs_uniform_blk
[] = {"vs_test", NULL
};
309 const char *fs_std_fs_uniform_blk
[] = {"fs_color", "fs_array[0]", NULL
};
310 const char *vs_stor_vs_buf_blk
[] = {"vs_buf_var", NULL
};
311 const char *fs_stor_gs_buf_blk
[] = {"gs_buf_var", NULL
};
312 const char *fs_stor_fs_buf_blk
[] = {"fs_buf_var", NULL
};
313 const char *vs_sub_uniforms
[] = {"vss", "vss2", NULL
};
314 const char *tess_sub_uniforms
[] = {"tcss", NULL
};
315 const char *cs_sub_uniforms
[] = {"css", NULL
};
317 static const struct subtest_t subtests
[] = {
318 { &prog_std
, GL_PROGRAM_INPUT
, "vs_input0", NULL
, {
319 { GL_NAME_LENGTH
, 1, { 10 } },
320 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
321 { GL_ARRAY_SIZE
, 1, { 1 } },
322 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 1 } },
323 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
324 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
325 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
326 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
327 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
328 { GL_LOCATION
, 1, { 0 } }, /* valid index == anything but -1 */
329 { GL_IS_PER_PATCH
, 1, { 0 } },
332 { &prog_std
, GL_PROGRAM_OUTPUT
, "fs_output0", NULL
, {
333 { GL_NAME_LENGTH
, 1, { 11 } },
334 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
335 { GL_ARRAY_SIZE
, 1, { 1 } },
336 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
337 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
338 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
339 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
340 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
341 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
342 { GL_LOCATION
, 1, { 0 } }, /* valid index == anything but -1 */
343 { GL_LOCATION_INDEX
, 1, { 0 } }, /* valid index == anything but -1 */
344 { GL_IS_PER_PATCH
, 1, { 0 } },
347 { &prog_std
, GL_UNIFORM
, "vs_test", "vs_uniform_block", {
348 { GL_NAME_LENGTH
, 1, { 8 } },
349 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
350 { GL_ARRAY_SIZE
, 1, { 1 } },
351 { GL_OFFSET
, 1, { 0 } }, /* valid index == anything but -1 */
352 { GL_BLOCK_INDEX
, 1, { 1 } }, /* compared to vs_uniform_block's idx */
353 { GL_ARRAY_STRIDE
, 1, { 0 } }, /* valid index == anything but -1 */
354 { GL_MATRIX_STRIDE
, 1, { 0 } },
355 { GL_IS_ROW_MAJOR
, 1, { 0 } },
356 { GL_ATOMIC_COUNTER_BUFFER_INDEX
, 1, { -1 } },
357 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 1 } },
358 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
359 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
360 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
361 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
362 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
363 { GL_LOCATION
, 1, { -1 } }, /* invalid index */
366 { &prog_loc
, GL_PROGRAM_INPUT
, "input0", NULL
, {
367 { GL_NAME_LENGTH
, 1, { 7 } },
368 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
369 { GL_ARRAY_SIZE
, 1, { 1 } },
370 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 1 } },
371 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
372 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
373 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
374 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
375 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
376 { GL_LOCATION
, 1, { 3 } }, /* value checked because it uses prog_loc */
377 { GL_IS_PER_PATCH
, 1, { 0 } },
380 { &prog_loc
, GL_PROGRAM_OUTPUT
, "output0", NULL
, {
381 { GL_NAME_LENGTH
, 1, { 8 } },
382 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
383 { GL_ARRAY_SIZE
, 1, { 1 } },
384 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
385 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
386 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
387 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
388 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
389 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
390 { GL_LOCATION
, 1, { 1 } }, /* value checked because it uses prog_loc */
391 { GL_LOCATION_INDEX
, 1, { 0 } }, /* valid index == anything but -1 */
392 { GL_IS_PER_PATCH
, 1, { 0 } },
395 { &prog_loc
, GL_UNIFORM
, "color", NULL
, {
396 { GL_NAME_LENGTH
, 1, { 6 } },
397 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
398 { GL_ARRAY_SIZE
, 1, { 1 } },
399 { GL_OFFSET
, 1, { -1 } }, /* invalid index */
400 { GL_BLOCK_INDEX
, 1, { -1 } }, /* invalid index */
401 { GL_ARRAY_STRIDE
, 1, { -1 } }, /* invalid index */
402 { GL_MATRIX_STRIDE
, 1, { -1 } },
403 { GL_IS_ROW_MAJOR
, 1, { 0 } },
404 { GL_ATOMIC_COUNTER_BUFFER_INDEX
, 1, { -1 } }, /* invalid index */
405 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
406 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
407 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
408 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
409 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
410 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
411 { GL_LOCATION
, 1, { 9 } }, /* valid index == anything but -1 */
414 { &prog_sub_tess
, GL_PROGRAM_OUTPUT
, "tcs_patch", NULL
, {
415 { GL_NAME_LENGTH
, 1, { 10 } },
416 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
417 { GL_ARRAY_SIZE
, 1, { 1 } },
418 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
419 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 1 } },
420 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
421 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
422 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
423 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
424 { GL_LOCATION
, 1, { -1 } }, /* invalid index */
425 { GL_LOCATION_INDEX
, 1, { -1 } }, /* invalid index */
426 { GL_IS_PER_PATCH
, 1, { 1 } },
429 { &prog_std
, GL_UNIFORM
, "fs_array", "fs_uniform_block", {
430 { GL_NAME_LENGTH
, 1, { 12 } },
431 { GL_TYPE
, 1, { GL_FLOAT
} },
432 { GL_ARRAY_SIZE
, 1, { 4 } },
433 { GL_OFFSET
, 1, { 0 } }, /* valid index == anything but -1 */
434 { GL_BLOCK_INDEX
, 1, { 1 } }, /* compared to fs_uniform_block's idx */
435 { GL_ARRAY_STRIDE
, 1, { 0 } }, /* valid index == anything but -1 */
436 { GL_MATRIX_STRIDE
, 1, { 0 } },
437 { GL_IS_ROW_MAJOR
, 1, { 0 } },
438 { GL_ATOMIC_COUNTER_BUFFER_INDEX
, 1, { -1 } }, /* invalid index */
439 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
440 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
441 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
442 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
443 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
444 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
445 { GL_LOCATION
, 1, { -1 } }, /* invalid index */
448 { &prog_std
, GL_UNIFORM_BLOCK
, "fs_uniform_block", fs_std_fs_uniform_blk
, {
449 { GL_NAME_LENGTH
, 1, { 17 } },
450 { GL_BUFFER_BINDING
, 1, { 0 } },
451 { GL_BUFFER_DATA_SIZE
, 1, { 32 } }, /* only checks for GL errors */
452 { GL_NUM_ACTIVE_VARIABLES
, 1, { 2 } },
453 { GL_ACTIVE_VARIABLES
, 2, { 0, 0 } },
454 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
455 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
456 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
457 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
458 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
459 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
462 { &prog_std
, GL_UNIFORM
, "fs_array_uniform_block.fs_array", "fs_array_uniform_block[0]", {
463 { GL_NAME_LENGTH
, 1, { 35 } },
464 { GL_TYPE
, 1, { GL_FLOAT
} },
465 { GL_ARRAY_SIZE
, 1, { 4 } },
466 { GL_OFFSET
, 1, { 0 } }, /* valid index == anything but -1 */
467 { GL_BLOCK_INDEX
, 1, { 2 } }, /* compared to fs_array_uniform_block[0]'s idx */
468 { GL_ARRAY_STRIDE
, 1, { 0 } }, /* valid index == anything but -1 */
469 { GL_MATRIX_STRIDE
, 1, { 0 } },
470 { GL_IS_ROW_MAJOR
, 1, { 0 } },
471 { GL_ATOMIC_COUNTER_BUFFER_INDEX
, 1, { -1 } }, /* valid index == anything but -1 */
472 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
473 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
474 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
475 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
476 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
477 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
478 { GL_LOCATION
, 1, { -1 } }, /* valid index == anything but -1 */
481 { &prog_stor
, GL_BUFFER_VARIABLE
, "gs_buf_var", "gs_buffer_block", {
482 { GL_NAME_LENGTH
, 1, { 11 } },
483 { GL_TYPE
, 1, { GL_FLOAT_VEC4
} },
484 { GL_ARRAY_SIZE
, 1, { 1 } },
485 { GL_OFFSET
, 1, { 0 } }, /* valid index == anything but -1 */
486 { GL_BLOCK_INDEX
, 1, { 1 } }, /* compared to gs_buffer_block's idx */
487 { GL_ARRAY_STRIDE
, 1, { 0 } }, /* valid index == anything but -1 */
488 { GL_MATRIX_STRIDE
, 1, { 0 } },
489 { GL_IS_ROW_MAJOR
, 1, { 0 } },
490 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
491 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
492 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
493 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 1 } },
494 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
495 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
496 { GL_TOP_LEVEL_ARRAY_SIZE
, 1, { 1 } },
497 { GL_TOP_LEVEL_ARRAY_STRIDE
, 1, { 0 } },
500 { &prog_stor
, GL_SHADER_STORAGE_BLOCK
, "gs_buffer_block", fs_stor_gs_buf_blk
, {
501 { GL_NAME_LENGTH
, 1, { 16 } },
502 { GL_BUFFER_BINDING
, 1, { 0 } },
503 { GL_BUFFER_DATA_SIZE
, 1, { 16 } }, /* only checks for GL errors */
504 { GL_NUM_ACTIVE_VARIABLES
, 1, { 1 } },
505 { GL_ACTIVE_VARIABLES
, 1, { 1 } },
506 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
507 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
508 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
509 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 1 } },
510 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
511 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
514 { &prog_buff_blks
, GL_UNIFORM_BLOCK
, "vs_uni_block", vs_std_vs_uniform_blk
, {
515 { GL_NAME_LENGTH
, 1, { 13 } },
516 { GL_BUFFER_BINDING
, 1, { 0 } },
517 { GL_BUFFER_DATA_SIZE
, 1, { 16 } }, /* only checks for GL errors */
518 { GL_NUM_ACTIVE_VARIABLES
, 1, { 1 } },
519 { GL_ACTIVE_VARIABLES
, 1, { 0 } },
520 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 1 } },
521 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
522 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
523 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
524 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
525 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
528 { &prog_buff_blks
, GL_UNIFORM_BLOCK
, "fs_uni_block", fs_std_fs_uniform_blk
, {
529 { GL_NAME_LENGTH
, 1, { 13 } },
530 { GL_BUFFER_BINDING
, 1, { 0 } },
531 { GL_BUFFER_DATA_SIZE
, 1, { 32 } }, /* only checks for GL errors */
532 { GL_NUM_ACTIVE_VARIABLES
, 1, { 2 } },
533 { GL_ACTIVE_VARIABLES
, 2, { 0, 0 } },
534 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
535 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
536 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
537 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
538 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
539 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
542 { &prog_buff_blks
, GL_SHADER_STORAGE_BLOCK
, "vs_buffer_block", vs_stor_vs_buf_blk
, {
543 { GL_NAME_LENGTH
, 1, { 16 } },
544 { GL_BUFFER_BINDING
, 1, { 0 } },
545 { GL_BUFFER_DATA_SIZE
, 1, { 16 } }, /* only checks for GL errors */
546 { GL_NUM_ACTIVE_VARIABLES
, 1, { 1 } },
547 { GL_ACTIVE_VARIABLES
, 1, { 1 } },
548 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 1 } },
549 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
550 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
551 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
552 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 0 } },
553 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
556 { &prog_buff_blks
, GL_SHADER_STORAGE_BLOCK
, "fs_buffer_block", fs_stor_fs_buf_blk
, {
557 { GL_NAME_LENGTH
, 1, { 16 } },
558 { GL_BUFFER_BINDING
, 1, { 0 } },
559 { GL_BUFFER_DATA_SIZE
, 1, { 16 } }, /* only checks for GL errors */
560 { GL_NUM_ACTIVE_VARIABLES
, 1, { 1 } },
561 { GL_ACTIVE_VARIABLES
, 1, { 1 } },
562 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
563 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
564 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
565 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
566 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
567 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
570 { &prog_std
, GL_TRANSFORM_FEEDBACK_VARYING
, "fs_input1", NULL
, {
571 { GL_NAME_LENGTH
, 1, { 10 } },
572 { GL_ARRAY_SIZE
, 1, { 1 } },
575 { &prog_sub
, GL_VERTEX_SUBROUTINE_UNIFORM
, "VERTEX", vs_sub_uniforms
, {
576 { GL_NAME_LENGTH
, 1, { 7 } },
577 { GL_NUM_COMPATIBLE_SUBROUTINES
, 1, { 2 } },
578 { GL_COMPATIBLE_SUBROUTINES
, 2, { 0, 1 } },
581 { &prog_sub_tess
, GL_TESS_CONTROL_SUBROUTINE_UNIFORM
, "TESS_CONTROL",
583 { GL_NAME_LENGTH
, 1, { 13 } },
584 { GL_NUM_COMPATIBLE_SUBROUTINES
, 1, { 1 } },
585 { GL_COMPATIBLE_SUBROUTINES
, 1, { 0 } },
588 { &prog_cs
, GL_COMPUTE_SUBROUTINE_UNIFORM
, "COMPUTE", cs_sub_uniforms
, {
589 { GL_NAME_LENGTH
, 1, { 8 } },
590 { GL_NUM_COMPATIBLE_SUBROUTINES
, 1, { 1 } },
591 { GL_COMPATIBLE_SUBROUTINES
, 1, { 0 } },
594 { &prog_atom
, GL_ATOMIC_COUNTER_BUFFER
, "fs_counter", NULL
, {
595 { GL_BUFFER_BINDING
, 1, { 2 } },
596 { GL_BUFFER_DATA_SIZE
, 1, { 4 } }, /* only checks for GL errors */
597 { GL_NUM_ACTIVE_VARIABLES
, 1, { 1 } },
598 { GL_ACTIVE_VARIABLES
, 1, { 0 } },
599 { GL_REFERENCED_BY_VERTEX_SHADER
, 1, { 0 } },
600 { GL_REFERENCED_BY_TESS_CONTROL_SHADER
, 1, { 0 } },
601 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER
, 1, { 0 } },
602 { GL_REFERENCED_BY_GEOMETRY_SHADER
, 1, { 0 } },
603 { GL_REFERENCED_BY_FRAGMENT_SHADER
, 1, { 1 } },
604 { GL_REFERENCED_BY_COMPUTE_SHADER
, 1, { 0 } },
609 /* WARNING: ATOMIC_COUNTER_BUFFER is left untested because it is impossible to
610 * fetch the index of variables which means we cannot reliably test anything
614 check_extensions_prop(GLenum prop
)
616 /* First check the availability of the extensions */
617 if (prop
== GL_ATOMIC_COUNTER_BUFFER_INDEX
&&
618 !piglit_is_extension_supported("GL_ARB_shader_atomic_counters")) {
622 if ((prop
== GL_TOP_LEVEL_ARRAY_SIZE
||
623 prop
== GL_TOP_LEVEL_ARRAY_STRIDE
) &&
624 !piglit_is_extension_supported("GL_ARB_shader_storage_buffer_object")) {
628 if ((prop
== GL_NUM_COMPATIBLE_SUBROUTINES
||
629 prop
== GL_COMPATIBLE_SUBROUTINES
) &&
630 !piglit_is_extension_supported("GL_ARB_shader_subroutine")) {
634 if ((prop
== GL_REFERENCED_BY_TESS_CONTROL_SHADER
||
635 prop
== GL_REFERENCED_BY_TESS_EVALUATION_SHADER
||
636 prop
== GL_IS_PER_PATCH
) &&
637 !piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
641 if ((prop
== GL_REFERENCED_BY_COMPUTE_SHADER
||
642 prop
== GL_COMPUTE_SUBROUTINE_UNIFORM
) &&
643 !piglit_is_extension_supported("GL_ARB_compute_shader")) {
651 is_resource_in_list(const char **list
, const char *resource
, int index
,
655 while (list
&& list
[i
]) {
656 if (strcmp(list
[i
], resource
) == 0) {
657 return !check_order
|| index
== i
;
666 basic_check(const char *subsubtest
, int value
, int expected_value
, bool *pass
)
668 /* no real check can be done other than checking that
669 * the index or offset is not invalid when it was
670 * supposed to be valid (or the other way round).
672 if ((value
>= 0 && expected_value
== -1) ||
673 (value
== -1 && expected_value
>= 0)) {
674 const char *validity
= expected_value
== -1 ?
675 "an invalid" : "a valid";
676 fprintf(stderr
, "'%s' expected %s offset or index but "
677 "got %i\n", subsubtest
, validity
, value
);
683 check_prop(GLuint prog
, GLenum programInterface
, int index
, const char *name
,
684 void *inputs
, struct check_t c
, bool *pass
)
686 int values
[10], parent_idx
, i
;
687 char subsubtest
[150];
688 GLsizei length
, tmp
= -1;
693 /* skip the test if it is not supported */
694 if(!check_extensions_prop(c
.prop
)) {
698 /* generate the name of the subsubtest for error-reporting purposes */
699 snprintf(subsubtest
, sizeof(subsubtest
), "%s: %s on %s",
700 name
, piglit_get_gl_enum_name(c
.prop
),
701 piglit_get_gl_enum_name(programInterface
));
703 /* retrieve the property */
704 glGetProgramResourceiv(prog
, programInterface
, index
, 1, &c
.prop
, 10,
706 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
707 printf(" Latest error generated while running '%s'\n",
713 /* check the return value */
716 case GL_ARRAY_STRIDE
:
717 case GL_ATOMIC_COUNTER_BUFFER_INDEX
:
718 basic_check(subsubtest
, values
[0], c
.values
[0], pass
);
722 /* check that the index of the parent matches the name
725 switch (programInterface
) {
727 pif
= GL_UNIFORM_BLOCK
;
729 case GL_BUFFER_VARIABLE
:
730 pif
= GL_SHADER_STORAGE_BLOCK
;
733 assert(!"unexpected programInterface value");
737 parent_idx
= glGetProgramResourceIndex(prog
, pif
,
739 piglit_check_gl_error(GL_NO_ERROR
);
740 if (parent_idx
!= values
[0]) {
741 glGetProgramResourceName(prog
, programInterface
,
742 values
[0], sizeof(buf
), NULL
,
745 fprintf(stderr
, "'%s' expected parent name to be %s"
746 "(idx = %i) but got parent name %s(idx = %i)\n",
747 subsubtest
, (char*)inputs
, parent_idx
, buf
,
753 case GL_BUFFER_BINDING
:
755 fprintf(stderr
, "'%s' invalid buffer binding point\n",
760 /* Binding index is necessary for ATOMIC_COUNTER_BUFFER */
761 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
) {
762 if (values
[0] != c
.values
[0]) {
763 fprintf(stderr
, "'%s' expected binding point %i"
764 " but got %i\n", subsubtest
,
765 c
.values
[0], values
[0]);
771 /* check against another API call */
772 if (programInterface
!= GL_UNIFORM_BLOCK
) {
776 glGetActiveUniformBlockiv(prog
, index
, GL_UNIFORM_BLOCK_BINDING
,
778 piglit_check_gl_error(GL_NO_ERROR
);
779 if (tmp
!= values
[0]) {
780 fprintf(stderr
, "'%s' inconsistent buffer binding point"
781 "(%i) with glGetActiveUniformBlockiv"
782 "(%i)\n", subsubtest
, values
[0], tmp
);
788 case GL_ACTIVE_VARIABLES
:
789 case GL_COMPATIBLE_SUBROUTINES
:
790 switch (programInterface
) {
791 case GL_UNIFORM_BLOCK
:
794 case GL_SHADER_STORAGE_BLOCK
:
795 pif
= GL_BUFFER_VARIABLE
;
797 case GL_VERTEX_SUBROUTINE_UNIFORM
:
798 pif
= GL_VERTEX_SUBROUTINE
;
800 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
801 pif
= GL_TESS_CONTROL_SUBROUTINE
;
803 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
804 pif
= GL_COMPUTE_SUBROUTINE
;
806 case GL_ATOMIC_COUNTER_BUFFER
:
810 assert(!"unexpected programInterface value");
814 /* check that the return count is as expected */
815 if (c
.count
!= length
) {
816 fprintf(stderr
, "'%s' expected %zu entries but got %i"
817 "\n", subsubtest
, c
.count
, length
);
823 /* harcode the index test for GL_ATOMIC_COUNTER_BUFFER */
824 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
) {
826 if (values
[0] != 0) {
827 fprintf(stderr
, "'%s' expected index 0 but got "
828 "%i", subsubtest
, values
[0]);
834 for (i
= 0; i
< length
; i
++) {
836 glGetProgramResourceName(prog
, pif
, values
[i
],
837 sizeof(buf
), NULL
, buf
);
838 piglit_check_gl_error(GL_NO_ERROR
);
839 if (!is_resource_in_list(inputs
, buf
, i
, false)) {
840 fprintf(stderr
, "'%s' could not find active "
841 "resource '%s' (idx = %i) in the active"
842 " list\n", subsubtest
, buf
, values
[i
]);
848 case GL_BUFFER_DATA_SIZE
:
849 /* Nothing we can check here... */
853 loc
= glGetProgramResourceLocation(prog
, programInterface
,
855 piglit_check_gl_error(GL_NO_ERROR
);
856 if (loc
!= values
[0]) {
857 fprintf(stderr
, "'%s' inconsistent value between "
858 "glGetProgramResourceiv(%i) and "
859 "glGetProgramResourceLocation(%i).\n",
860 subsubtest
, values
[0], loc
);
865 if (prog
== prog_loc
&& values
[0] != c
.values
[0]) {
866 fprintf(stderr
, "'%s' expected location %i but got "
867 "%i\n", subsubtest
, c
.values
[0],
873 /* continue by testing the (in)validity of the index */
874 basic_check(subsubtest
, values
[0], c
.values
[0], pass
);
877 case GL_LOCATION_INDEX
:
878 loc
= glGetProgramResourceLocationIndex(prog
, programInterface
,
880 piglit_check_gl_error(GL_NO_ERROR
);
881 if (loc
!= values
[0]) {
882 fprintf(stderr
, "'%s' inconsistent value between "
883 "glGetProgramResourceiv(%i) and "
884 "glGetProgramResourceLocationIndex(%i)."
885 "\n", subsubtest
, values
[0], loc
);
890 /* continue by testing the (in)validity of the index */
891 basic_check(subsubtest
, values
[0], c
.values
[0], pass
);
895 /* check that the return count is as expected */
896 if (c
.count
!= length
) {
897 fprintf(stderr
, "'%s' expected %zu entries but got %i"
898 "\n", subsubtest
, c
.count
, length
);
904 /* go through all the values returned */
905 for (i
= 0; i
< length
; i
++) {
906 if (values
[i
] != c
.values
[i
]) {
907 fprintf(stderr
, "'%s' expected %i but got %i at"
908 " index %i\n", subsubtest
, c
.values
[i
],
919 check_extensions(GLuint prog
, GLenum programInterface
)
921 /* First check the availability of the extensions */
922 if ((programInterface
== GL_BUFFER_VARIABLE
||
923 programInterface
== GL_SHADER_STORAGE_BLOCK
||
924 prog
== prog_stor
|| prog
== prog_buff_blks
) &&
925 !piglit_is_extension_supported("GL_ARB_shader_storage_buffer_object")) {
929 if ((programInterface
== GL_VERTEX_SUBROUTINE
||
930 programInterface
== GL_GEOMETRY_SUBROUTINE
||
931 programInterface
== GL_FRAGMENT_SUBROUTINE
||
932 programInterface
== GL_COMPUTE_SUBROUTINE
||
933 programInterface
== GL_VERTEX_SUBROUTINE_UNIFORM
||
934 programInterface
== GL_GEOMETRY_SUBROUTINE_UNIFORM
||
935 programInterface
== GL_FRAGMENT_SUBROUTINE_UNIFORM
||
936 programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
||
937 programInterface
== GL_TESS_CONTROL_SUBROUTINE
||
938 programInterface
== GL_TESS_EVALUATION_SUBROUTINE
||
939 programInterface
== GL_TESS_CONTROL_SUBROUTINE_UNIFORM
||
940 programInterface
== GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
||
941 programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
||
942 prog
== prog_sub
|| prog
== prog_sub_tess
) &&
943 !piglit_is_extension_supported("GL_ARB_shader_subroutine")) {
947 if ((programInterface
== GL_TESS_CONTROL_SUBROUTINE
||
948 programInterface
== GL_TESS_EVALUATION_SUBROUTINE
||
949 programInterface
== GL_TESS_CONTROL_SUBROUTINE_UNIFORM
||
950 programInterface
== GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
||
951 prog
== prog_sub_tess
) &&
952 !piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
956 if ((programInterface
== GL_COMPUTE_SUBROUTINE
||
957 programInterface
== GL_COMPUTE_SUBROUTINE_UNIFORM
||
959 !piglit_is_extension_supported("GL_ARB_compute_shader") &&
960 !piglit_is_extension_supported("GL_ARB_shader_image_load_store")) {
968 run_subtest(const struct subtest_t st
, bool *pass
)
970 enum piglit_result result
;
971 bool local_pass
= true;
974 if (*st
.prog
== -1 || !check_extensions(*st
.prog
, st
.programInterface
)) {
975 result
= PIGLIT_SKIP
;
979 if (st
.programInterface
!= GL_ATOMIC_COUNTER_BUFFER
) {
980 index
= glGetProgramResourceIndex(*st
.prog
,
981 st
.programInterface
, st
.name
);
982 piglit_check_gl_error(GL_NO_ERROR
);
984 printf(" Could not find resource '%s' in program"
985 " %u\n", st
.name
, *st
.prog
);
986 result
= PIGLIT_FAIL
;
990 /* As we cannot query the index of an atomic variable, let's
991 * hardcode it to 0 and make sure the program only has ONE
992 * atomic variable. In our case, we only use the fs_atom stage
993 * which defines only one variable.
998 while (st
.props
[i
].prop
!= 0) {
999 check_prop(*st
.prog
, st
.programInterface
, index
, st
.name
,
1000 st
.inputs
, st
.props
[i
], &local_pass
);
1004 *pass
= *pass
&& local_pass
;
1005 result
= local_pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
1008 piglit_report_subtest_result(result
, "%s on %s", st
.name
,
1009 piglit_get_gl_enum_name(st
.programInterface
));
1013 piglit_init(int argc
, char **argv
)
1015 static const char *st_r_tf_varying
[] = {"fs_input1", NULL
};
1017 piglit_require_extension("GL_ARB_program_interface_query");
1018 piglit_require_extension("GL_ARB_separate_shader_objects");
1020 /* Allocate the different programs */
1021 prog_std
= piglit_build_simple_program_unlinked_multiple_shaders(
1022 GL_VERTEX_SHADER
, vs_std
,
1023 GL_GEOMETRY_SHADER
, gs_std
,
1024 GL_FRAGMENT_SHADER
, fs_in
,
1026 glTransformFeedbackVaryings(prog_std
, 1, st_r_tf_varying
,
1027 GL_INTERLEAVED_ATTRIBS
);
1028 piglit_check_gl_error(GL_NO_ERROR
);
1030 /* force the compiler not to optimise away inputs/outputs */
1031 glProgramParameteri(prog_std
, GL_PROGRAM_SEPARABLE
, GL_TRUE
);
1032 piglit_check_gl_error(GL_NO_ERROR
);
1034 glLinkProgram(prog_std
);
1035 if (!piglit_link_check_status(prog_std
)) {
1036 glDeleteProgram(prog_std
);
1037 piglit_report_result(PIGLIT_FAIL
);
1040 if (piglit_is_extension_supported("GL_ARB_shader_storage_buffer_object")) {
1041 prog_stor
= piglit_build_simple_program_multiple_shaders(
1042 GL_VERTEX_SHADER
, vs_stor
,
1043 GL_GEOMETRY_SHADER
, gs_stor
,
1044 GL_FRAGMENT_SHADER
, fs_stor
,
1047 prog_buff_blks
= piglit_build_simple_program_multiple_shaders(
1048 GL_VERTEX_SHADER
, vs_buff_blks
,
1049 GL_FRAGMENT_SHADER
, fs_buff_blks
,
1053 if (piglit_is_extension_supported("GL_ARB_explicit_attrib_location") &&
1054 piglit_is_extension_supported("GL_ARB_explicit_uniform_location")) {
1055 prog_loc
= piglit_build_simple_program_multiple_shaders(
1056 GL_VERTEX_SHADER
, vs_loc
,
1057 GL_FRAGMENT_SHADER
, fs_loc
,
1061 if (piglit_is_extension_supported("GL_ARB_shader_atomic_counters")) {
1062 prog_atom
= piglit_build_simple_program_unlinked_multiple_shaders(
1063 GL_FRAGMENT_SHADER
, fs_atom
,
1066 /* force the compiler not to optimise away inputs/outputs */
1067 glProgramParameteri(prog_atom
, GL_PROGRAM_SEPARABLE
,
1069 piglit_check_gl_error(GL_NO_ERROR
);
1071 glLinkProgram(prog_atom
);
1072 if (!piglit_link_check_status(prog_atom
)) {
1073 glDeleteProgram(prog_atom
);
1074 piglit_report_result(PIGLIT_FAIL
);
1078 if (!piglit_is_extension_supported("GL_ARB_shader_subroutine")) {
1082 prog_sub
= piglit_build_simple_program_multiple_shaders(
1083 GL_VERTEX_SHADER
, vs_sub
,
1084 GL_GEOMETRY_SHADER
, gs_sub
,
1085 GL_FRAGMENT_SHADER
, fs_sub
,
1088 if (piglit_is_extension_supported("GL_ARB_tessellation_shader")) {
1090 piglit_build_simple_program_unlinked_multiple_shaders(
1091 GL_TESS_CONTROL_SHADER
, tcs_sub
,
1093 /* force the compiler not to optimise away inputs/outputs */
1094 glProgramParameteri(prog_sub_tess
, GL_PROGRAM_SEPARABLE
,
1096 piglit_check_gl_error(GL_NO_ERROR
);
1098 glLinkProgram(prog_sub_tess
);
1099 if (!piglit_link_check_status(prog_sub_tess
)) {
1100 glDeleteProgram(prog_sub_tess
);
1101 piglit_report_result(PIGLIT_FAIL
);
1105 if (piglit_is_extension_supported("GL_ARB_compute_shader")) {
1106 prog_cs
= piglit_build_simple_program_multiple_shaders(
1107 GL_COMPUTE_SHADER
, cs_sub
,
1113 test_error_cases(bool *pass
)
1115 GLenum props
[] = {GL_NAME_LENGTH
};
1116 GLenum props_invalid
[] = {GL_NAME_LENGTH
, GL_TRUE
, GL_TYPE
};
1117 GLenum props_error
[] = {GL_NAME_LENGTH
, GL_OFFSET
, GL_TYPE
};
1122 /* test using an unexisting program ID */
1123 glGetProgramResourceiv(1337, GL_UNIFORM
, 0, 1, props
, 10, NULL
, values
);
1124 prg_tst
= piglit_check_gl_error(GL_INVALID_VALUE
);
1125 *pass
= *pass
&& prg_tst
;
1126 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1127 "Invalid program (undefined ID)");
1129 /* test using a shader ID */
1130 shader
= piglit_compile_shader_text(GL_VERTEX_SHADER
, vs_empty
);
1131 glGetProgramResourceIndex(shader
, GL_UNIFORM
, "resource");
1132 prg_tst
= piglit_check_gl_error(GL_INVALID_OPERATION
);
1133 *pass
= *pass
&& prg_tst
;
1134 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1135 "Invalid program (call on shader)");
1137 /* invalid index. This is unspecified but let's check it is consistent
1138 * with GetProgramResourceName.
1140 glGetProgramResourceiv(prog_std
, GL_UNIFORM
, 1337, 0, props
, 10, NULL
,
1142 prg_tst
= piglit_check_gl_error(GL_INVALID_VALUE
);
1143 *pass
= *pass
&& prg_tst
;
1144 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1147 /* test propcount == 0 */
1148 glGetProgramResourceiv(prog_std
, GL_UNIFORM
, 0, 0, props
, 10, NULL
,
1150 prg_tst
= piglit_check_gl_error(GL_INVALID_VALUE
);
1151 *pass
= *pass
&& prg_tst
;
1152 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1153 "<propcount> == 0");
1155 /* test propcount < 0 */
1156 glGetProgramResourceiv(prog_std
, GL_UNIFORM
, 0, -1, props
, 10, NULL
,
1158 prg_tst
= piglit_check_gl_error(GL_INVALID_VALUE
);
1159 *pass
= *pass
&& prg_tst
;
1160 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1163 /* one invalid property */
1164 glGetProgramResourceiv(prog_std
, GL_UNIFORM
, 0, 3, props_invalid
, 10,
1166 prg_tst
= piglit_check_gl_error(GL_INVALID_ENUM
);
1167 *pass
= *pass
&& prg_tst
;
1168 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1171 /* property not acceptable for one program interface */
1172 glGetProgramResourceiv(prog_std
, GL_PROGRAM_INPUT
, 0, 3, props_error
,
1174 prg_tst
= piglit_check_gl_error(GL_INVALID_OPERATION
);
1175 *pass
= *pass
&& prg_tst
;
1176 piglit_report_subtest_result(prg_tst
? PIGLIT_PASS
: PIGLIT_FAIL
,
1177 "GL_OFFSET on GL_PROGRAM_INPUT");
1181 glDeleteProgramSafe(GLuint prog
)
1184 glDeleteProgram(prog
);
1188 piglit_display(void)
1193 if (!piglit_khr_no_error
)
1194 test_error_cases(&pass
);
1196 /* run all the getprogramresourceiv tests */
1197 for (i
= 0; i
< sizeof(subtests
) / sizeof(struct subtest_t
); i
++) {
1198 run_subtest(subtests
[i
], &pass
);
1201 glDeleteProgramSafe(prog_atom
);
1202 glDeleteProgramSafe(prog_loc
);
1203 glDeleteProgramSafe(prog_cs
);
1204 glDeleteProgramSafe(prog_sub_tess
);
1205 glDeleteProgramSafe(prog_sub
);
1206 glDeleteProgramSafe(prog_stor
);
1207 glDeleteProgramSafe(prog_buff_blks
);
1208 glDeleteProgramSafe(prog_std
);
1210 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;