ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_program_interface_query / getprogramresourceiv.c
blobe55cf96ac0aaca268ee5f561585f7d6766b9e8ea
1 /*
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
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /**
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:
31 * "The command
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,
61 * BUFFER_VARIABLE
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,
91 * PROGRAM_OUTPUT
93 * REFERENCED_BY_TESS_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
94 * CONTROL_SHADER BUFFER, SHADER_STORAGE_BLOCK,
95 * BUFFER_VARIABLE, PROGRAM_INPUT,
96 * PROGRAM_OUTPUT
98 * REFERENCED_BY_TESS_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
99 * EVALUATION_SHADER BUFFER, SHADER_STORAGE_BLOCK,
100 * BUFFER_VARIABLE, PROGRAM_INPUT,
101 * PROGRAM_OUTPUT
103 * REFERENCED_BY_GEOMETRY_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
104 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
105 * BUFFER_VARIABLE, PROGRAM_INPUT,
106 * PROGRAM_OUTPUT
108 * REFERENCED_BY_FRAGMENT_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
109 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
110 * BUFFER_VARIABLE, PROGRAM_INPUT,
111 * PROGRAM_OUTPUT
113 * REFERENCED_BY_COMPUTE_ UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_
114 * SHADER BUFFER, SHADER_STORAGE_BLOCK,
115 * BUFFER_VARIABLE, PROGRAM_INPUT,
116 * PROGRAM_OUTPUT
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
150 * null character.
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
183 * type.
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"
276 #include "common.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 */
294 struct subtest_t {
295 GLuint *prog;
296 GLenum programInterface;
297 const char *name;
298 void *inputs;
300 /* set to -1 to disable the test */
301 struct check_t{
302 GLenum prop;
303 size_t count;
304 int values[10];
305 } props[25];
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 } },
330 { 0, 0, { 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 } },
345 { 0, 0, { 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 */
364 { 0, 0, { 0 } }}
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 } },
378 { 0, 0, { 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 } },
393 { 0, 0, { 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 */
412 { 0, 0, { 0 } }}
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 } },
427 { 0, 0, { 0 } }}
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 */
446 { 0, 0, { 0 } }}
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 } },
460 { 0, 0, { 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 */
479 { 0, 0, { 0 } }}
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 } },
498 { 0, 0, { 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 } },
512 { 0, 0, { 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 } },
526 { 0, 0, { 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 } },
540 { 0, 0, { 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 } },
554 { 0, 0, { 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 } },
568 { 0, 0, { 0 } }}
570 { &prog_std, GL_TRANSFORM_FEEDBACK_VARYING, "fs_input1", NULL, {
571 { GL_NAME_LENGTH, 1, { 10 } },
572 { GL_ARRAY_SIZE, 1, { 1 } },
573 { 0, 0, { 0 } }}
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 } },
579 { 0, 0, { 0 } }}
581 { &prog_sub_tess, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, "TESS_CONTROL",
582 tess_sub_uniforms, {
583 { GL_NAME_LENGTH, 1, { 13 } },
584 { GL_NUM_COMPATIBLE_SUBROUTINES, 1, { 1 } },
585 { GL_COMPATIBLE_SUBROUTINES, 1, { 0 } },
586 { 0, 0, { 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 } },
592 { 0, 0, { 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 } },
605 { 0, 0, { 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
613 static bool
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")) {
619 return false;
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")) {
625 return false;
628 if ((prop == GL_NUM_COMPATIBLE_SUBROUTINES ||
629 prop == GL_COMPATIBLE_SUBROUTINES) &&
630 !piglit_is_extension_supported("GL_ARB_shader_subroutine")) {
631 return false;
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")) {
638 return false;
641 if ((prop == GL_REFERENCED_BY_COMPUTE_SHADER ||
642 prop == GL_COMPUTE_SUBROUTINE_UNIFORM) &&
643 !piglit_is_extension_supported("GL_ARB_compute_shader")) {
644 return false;
647 return true;
650 static bool
651 is_resource_in_list(const char **list, const char *resource, int index,
652 bool check_order)
654 int i = 0;
655 while (list && list[i]) {
656 if (strcmp(list[i], resource) == 0) {
657 return !check_order || index == i;
659 i++;
662 return false;
665 static void
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);
678 *pass = false;
682 static void
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;
689 char buf[21];
690 GLenum pif;
691 GLuint loc;
693 /* skip the test if it is not supported */
694 if(!check_extensions_prop(c.prop)) {
695 return;
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,
705 &length, values);
706 if (!piglit_check_gl_error(GL_NO_ERROR)) {
707 printf(" Latest error generated while running '%s'\n",
708 subsubtest);
709 *pass = false;
710 return;
713 /* check the return value */
714 switch (c.prop) {
715 case GL_OFFSET:
716 case GL_ARRAY_STRIDE:
717 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
718 basic_check(subsubtest, values[0], c.values[0], pass);
719 break;
721 case GL_BLOCK_INDEX:
722 /* check that the index of the parent matches the name
723 * of the parent
725 switch (programInterface) {
726 case GL_UNIFORM:
727 pif = GL_UNIFORM_BLOCK;
728 break;
729 case GL_BUFFER_VARIABLE:
730 pif = GL_SHADER_STORAGE_BLOCK;
731 break;
732 default:
733 assert(!"unexpected programInterface value");
734 pif = GL_NONE;
737 parent_idx = glGetProgramResourceIndex(prog, pif,
738 (char*)inputs);
739 piglit_check_gl_error(GL_NO_ERROR);
740 if (parent_idx != values[0]) {
741 glGetProgramResourceName(prog, programInterface,
742 values[0], sizeof(buf), NULL,
743 buf);
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,
748 values[0]);
749 *pass = false;
751 break;
753 case GL_BUFFER_BINDING:
754 if (values[0] < 0) {
755 fprintf(stderr, "'%s' invalid buffer binding point\n",
756 subsubtest);
757 *pass = false;
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]);
766 *pass = false;
768 break;
771 /* check against another API call */
772 if (programInterface != GL_UNIFORM_BLOCK) {
773 break;
776 glGetActiveUniformBlockiv(prog, index, GL_UNIFORM_BLOCK_BINDING,
777 &tmp);
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);
783 *pass = false;
786 break;
788 case GL_ACTIVE_VARIABLES:
789 case GL_COMPATIBLE_SUBROUTINES:
790 switch (programInterface) {
791 case GL_UNIFORM_BLOCK:
792 pif = GL_UNIFORM;
793 break;
794 case GL_SHADER_STORAGE_BLOCK:
795 pif = GL_BUFFER_VARIABLE;
796 break;
797 case GL_VERTEX_SUBROUTINE_UNIFORM:
798 pif = GL_VERTEX_SUBROUTINE;
799 break;
800 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
801 pif = GL_TESS_CONTROL_SUBROUTINE;
802 break;
803 case GL_COMPUTE_SUBROUTINE_UNIFORM:
804 pif = GL_COMPUTE_SUBROUTINE;
805 break;
806 case GL_ATOMIC_COUNTER_BUFFER:
807 /* do nothing */
808 break;
809 default:
810 assert(!"unexpected programInterface value");
811 pif = GL_NONE;
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);
818 length = 1;
819 *pass = false;
820 break;
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]);
829 *pass = false;
831 break;
834 for (i = 0; i < length; i++) {
835 buf[0] = '\0';
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]);
843 *pass = false;
846 break;
848 case GL_BUFFER_DATA_SIZE:
849 /* Nothing we can check here... */
850 break;
852 case GL_LOCATION:
853 loc = glGetProgramResourceLocation(prog, programInterface,
854 name);
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);
861 *pass = false;
862 break;
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],
868 values[0]);
869 *pass = false;
870 break;
873 /* continue by testing the (in)validity of the index */
874 basic_check(subsubtest, values[0], c.values[0], pass);
875 break;
877 case GL_LOCATION_INDEX:
878 loc = glGetProgramResourceLocationIndex(prog, programInterface,
879 name);
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);
886 *pass = false;
887 break;
890 /* continue by testing the (in)validity of the index */
891 basic_check(subsubtest, values[0], c.values[0], pass);
892 break;
894 default:
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);
899 length = 1;
900 *pass = false;
901 break;
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],
909 values[i], i);
910 *pass = false;
914 break;
918 static bool
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")) {
926 return false;
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")) {
944 return false;
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")) {
953 return false;
956 if ((programInterface == GL_COMPUTE_SUBROUTINE ||
957 programInterface == GL_COMPUTE_SUBROUTINE_UNIFORM ||
958 prog == prog_cs) &&
959 !piglit_is_extension_supported("GL_ARB_compute_shader") &&
960 !piglit_is_extension_supported("GL_ARB_shader_image_load_store")) {
961 return false;
964 return true;
967 static void
968 run_subtest(const struct subtest_t st, bool *pass)
970 enum piglit_result result;
971 bool local_pass = true;
972 int index, i = 0;
974 if (*st.prog == -1 || !check_extensions(*st.prog, st.programInterface)) {
975 result = PIGLIT_SKIP;
976 goto report_result;
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);
983 if (index < 0) {
984 printf(" Could not find resource '%s' in program"
985 " %u\n", st.name, *st.prog);
986 result = PIGLIT_FAIL;
987 goto report_result;
989 } else {
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.
995 index = 0;
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);
1001 i++;
1004 *pass = *pass && local_pass;
1005 result = local_pass ? PIGLIT_PASS : PIGLIT_FAIL;
1007 report_result:
1008 piglit_report_subtest_result(result, "%s on %s", st.name,
1009 piglit_get_gl_enum_name(st.programInterface));
1012 void
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,
1068 GL_TRUE);
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")) {
1079 return;
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")) {
1089 prog_sub_tess =
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,
1095 GL_TRUE);
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,
1112 static void
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};
1118 int values[10];
1119 GLuint shader;
1120 bool prg_tst;
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,
1141 values);
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,
1145 "Invalid index");
1147 /* test propcount == 0 */
1148 glGetProgramResourceiv(prog_std, GL_UNIFORM, 0, 0, props, 10, NULL,
1149 values);
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,
1157 values);
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,
1161 "<propcount> < 0");
1163 /* one invalid property */
1164 glGetProgramResourceiv(prog_std, GL_UNIFORM, 0, 3, props_invalid, 10,
1165 NULL, values);
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,
1169 "prop == GL_TRUE");
1171 /* property not acceptable for one program interface */
1172 glGetProgramResourceiv(prog_std, GL_PROGRAM_INPUT, 0, 3, props_error,
1173 10, NULL, values);
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");
1180 static void
1181 glDeleteProgramSafe(GLuint prog)
1183 if (prog != -1)
1184 glDeleteProgram(prog);
1187 enum piglit_result
1188 piglit_display(void)
1190 bool pass = true;
1191 int i;
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;