mesa: fix ARRAY_SIZE query for GetProgramResourceiv
[mesa.git] / src / mesa / main / shader_query.cpp
1 /*
2 * Copyright © 2011 Intel Corporation
3 *
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:
10 *
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.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file shader_query.cpp
26 * C-to-C++ bridge functions to query GLSL shader data
27 *
28 * \author Ian Romanick <ian.d.romanick@intel.com>
29 */
30
31 #include "main/context.h"
32 #include "main/core.h"
33 #include "glsl_symbol_table.h"
34 #include "ir.h"
35 #include "shaderobj.h"
36 #include "program/hash_table.h"
37 #include "../glsl/program.h"
38 #include "uniforms.h"
39 #include "main/enums.h"
40 #include "util/strndup.h"
41
42 extern "C" {
43 #include "shaderapi.h"
44 }
45
46 static GLint
47 program_resource_location(struct gl_shader_program *shProg,
48 struct gl_program_resource *res, const char *name,
49 unsigned array_index);
50
51 /**
52 * Declare convenience functions to return resource data in a given type.
53 * Warning! this is not type safe so be *very* careful when using these.
54 */
55 #define DECL_RESOURCE_FUNC(name, type) \
56 const type * RESOURCE_ ## name (gl_program_resource *res) { \
57 assert(res->Data); \
58 return (type *) res->Data; \
59 }
60
61 DECL_RESOURCE_FUNC(VAR, ir_variable);
62 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
63 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
64 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
65 DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
66 DECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
67
68 void GLAPIENTRY
69 _mesa_BindAttribLocation(GLhandleARB program, GLuint index,
70 const GLcharARB *name)
71 {
72 GET_CURRENT_CONTEXT(ctx);
73
74 struct gl_shader_program *const shProg =
75 _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
76 if (!shProg)
77 return;
78
79 if (!name)
80 return;
81
82 if (strncmp(name, "gl_", 3) == 0) {
83 _mesa_error(ctx, GL_INVALID_OPERATION,
84 "glBindAttribLocation(illegal name)");
85 return;
86 }
87
88 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
89 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
90 return;
91 }
92
93 /* Replace the current value if it's already in the list. Add
94 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
95 * between built-in attributes and user-defined attributes.
96 */
97 shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
98
99 /*
100 * Note that this attribute binding won't go into effect until
101 * glLinkProgram is called again.
102 */
103 }
104
105 static bool
106 is_active_attrib(const ir_variable *var)
107 {
108 if (!var)
109 return false;
110
111 switch (var->data.mode) {
112 case ir_var_shader_in:
113 return var->data.location != -1;
114
115 case ir_var_system_value:
116 /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
117 * "For GetActiveAttrib, all active vertex shader input variables
118 * are enumerated, including the special built-in inputs gl_VertexID
119 * and gl_InstanceID."
120 */
121 return var->data.location == SYSTEM_VALUE_VERTEX_ID ||
122 var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE ||
123 var->data.location == SYSTEM_VALUE_INSTANCE_ID;
124
125 default:
126 return false;
127 }
128 }
129
130 void GLAPIENTRY
131 _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
132 GLsizei maxLength, GLsizei * length, GLint * size,
133 GLenum * type, GLcharARB * name)
134 {
135 GET_CURRENT_CONTEXT(ctx);
136 struct gl_shader_program *shProg;
137
138 if (maxLength < 0) {
139 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
140 return;
141 }
142
143 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
144 if (!shProg)
145 return;
146
147 if (!shProg->LinkStatus) {
148 _mesa_error(ctx, GL_INVALID_VALUE,
149 "glGetActiveAttrib(program not linked)");
150 return;
151 }
152
153 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
154 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
155 return;
156 }
157
158 struct gl_program_resource *res =
159 _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
160 desired_index);
161
162 /* User asked for index that does not exist. */
163 if (!res) {
164 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
165 return;
166 }
167
168 const ir_variable *const var = RESOURCE_VAR(res);
169
170 if (!is_active_attrib(var))
171 return;
172
173 const char *var_name = var->name;
174
175 /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
176 * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
177 * active attributes.
178 */
179 if (var->data.mode == ir_var_system_value &&
180 var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
181 var_name = "gl_VertexID";
182 }
183
184 _mesa_copy_string(name, maxLength, length, var_name);
185
186 if (size)
187 _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
188 size, "glGetActiveAttrib");
189
190 if (type)
191 _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
192 (GLint *) type, "glGetActiveAttrib");
193 }
194
195 GLint GLAPIENTRY
196 _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name)
197 {
198 GET_CURRENT_CONTEXT(ctx);
199 struct gl_shader_program *const shProg =
200 _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
201
202 if (!shProg) {
203 return -1;
204 }
205
206 if (!shProg->LinkStatus) {
207 _mesa_error(ctx, GL_INVALID_OPERATION,
208 "glGetAttribLocation(program not linked)");
209 return -1;
210 }
211
212 if (!name)
213 return -1;
214
215 /* Not having a vertex shader is not an error.
216 */
217 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
218 return -1;
219
220 unsigned array_index = 0;
221 struct gl_program_resource *res =
222 _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
223 &array_index);
224
225 if (!res)
226 return -1;
227
228 GLint loc = program_resource_location(shProg, res, name, array_index);
229
230 /* The extra check against against 0 is made because of builtin-attribute
231 * locations that have offset applied. Function program_resource_location
232 * can return built-in attribute locations < 0 and glGetAttribLocation
233 * cannot be used on "conventional" attributes.
234 *
235 * From page 95 of the OpenGL 3.0 spec:
236 *
237 * "If name is not an active attribute, if name is a conventional
238 * attribute, or if an error occurs, -1 will be returned."
239 */
240 return (loc >= 0) ? loc : -1;
241 }
242
243 unsigned
244 _mesa_count_active_attribs(struct gl_shader_program *shProg)
245 {
246 if (!shProg->LinkStatus
247 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
248 return 0;
249 }
250
251 struct gl_program_resource *res = shProg->ProgramResourceList;
252 unsigned count = 0;
253 for (unsigned j = 0; j < shProg->NumProgramResourceList; j++, res++) {
254 if (res->Type == GL_PROGRAM_INPUT &&
255 res->StageReferences & (1 << MESA_SHADER_VERTEX) &&
256 is_active_attrib(RESOURCE_VAR(res)))
257 count++;
258 }
259 return count;
260 }
261
262
263 size_t
264 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
265 {
266 if (!shProg->LinkStatus
267 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
268 return 0;
269 }
270
271 struct gl_program_resource *res = shProg->ProgramResourceList;
272 size_t longest = 0;
273 for (unsigned j = 0; j < shProg->NumProgramResourceList; j++, res++) {
274 if (res->Type == GL_PROGRAM_INPUT &&
275 res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
276
277 const size_t length = strlen(RESOURCE_VAR(res)->name);
278 if (length >= longest)
279 longest = length + 1;
280 }
281 }
282
283 return longest;
284 }
285
286 void GLAPIENTRY
287 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
288 const GLchar *name)
289 {
290 _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
291 }
292
293 void GLAPIENTRY
294 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
295 GLuint index, const GLchar *name)
296 {
297 GET_CURRENT_CONTEXT(ctx);
298
299 struct gl_shader_program *const shProg =
300 _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
301 if (!shProg)
302 return;
303
304 if (!name)
305 return;
306
307 if (strncmp(name, "gl_", 3) == 0) {
308 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
309 return;
310 }
311
312 if (index > 1) {
313 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
314 return;
315 }
316
317 if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
318 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
319 return;
320 }
321
322 if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
323 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
324 return;
325 }
326
327 /* Replace the current value if it's already in the list. Add
328 * FRAG_RESULT_DATA0 because that's how the linker differentiates
329 * between built-in attributes and user-defined attributes.
330 */
331 shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
332 shProg->FragDataIndexBindings->put(index, name);
333 /*
334 * Note that this binding won't go into effect until
335 * glLinkProgram is called again.
336 */
337
338 }
339
340 GLint GLAPIENTRY
341 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
342 {
343 GET_CURRENT_CONTEXT(ctx);
344 struct gl_shader_program *const shProg =
345 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
346
347 if (!shProg) {
348 return -1;
349 }
350
351 if (!shProg->LinkStatus) {
352 _mesa_error(ctx, GL_INVALID_OPERATION,
353 "glGetFragDataIndex(program not linked)");
354 return -1;
355 }
356
357 if (!name)
358 return -1;
359
360 if (strncmp(name, "gl_", 3) == 0) {
361 _mesa_error(ctx, GL_INVALID_OPERATION,
362 "glGetFragDataIndex(illegal name)");
363 return -1;
364 }
365
366 /* Not having a fragment shader is not an error.
367 */
368 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
369 return -1;
370
371 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
372 name);
373 }
374
375 GLint GLAPIENTRY
376 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
377 {
378 GET_CURRENT_CONTEXT(ctx);
379 struct gl_shader_program *const shProg =
380 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
381
382 if (!shProg) {
383 return -1;
384 }
385
386 if (!shProg->LinkStatus) {
387 _mesa_error(ctx, GL_INVALID_OPERATION,
388 "glGetFragDataLocation(program not linked)");
389 return -1;
390 }
391
392 if (!name)
393 return -1;
394
395 if (strncmp(name, "gl_", 3) == 0) {
396 _mesa_error(ctx, GL_INVALID_OPERATION,
397 "glGetFragDataLocation(illegal name)");
398 return -1;
399 }
400
401 /* Not having a fragment shader is not an error.
402 */
403 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
404 return -1;
405
406 unsigned array_index = 0;
407 struct gl_program_resource *res =
408 _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
409 &array_index);
410
411 if (!res)
412 return -1;
413
414 GLint loc = program_resource_location(shProg, res, name, array_index);
415
416 /* The extra check against against 0 is made because of builtin-attribute
417 * locations that have offset applied. Function program_resource_location
418 * can return built-in attribute locations < 0 and glGetFragDataLocation
419 * cannot be used on "conventional" attributes.
420 *
421 * From page 95 of the OpenGL 3.0 spec:
422 *
423 * "If name is not an active attribute, if name is a conventional
424 * attribute, or if an error occurs, -1 will be returned."
425 */
426 return (loc >= 0) ? loc : -1;
427 }
428
429 const char*
430 _mesa_program_resource_name(struct gl_program_resource *res)
431 {
432 const ir_variable *var;
433 switch (res->Type) {
434 case GL_UNIFORM_BLOCK:
435 case GL_SHADER_STORAGE_BLOCK:
436 return RESOURCE_UBO(res)->Name;
437 case GL_TRANSFORM_FEEDBACK_VARYING:
438 return RESOURCE_XFB(res)->Name;
439 case GL_PROGRAM_INPUT:
440 var = RESOURCE_VAR(res);
441 /* Special case gl_VertexIDMESA -> gl_VertexID. */
442 if (var->data.mode == ir_var_system_value &&
443 var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
444 return "gl_VertexID";
445 }
446 /* fallthrough */
447 case GL_PROGRAM_OUTPUT:
448 return RESOURCE_VAR(res)->name;
449 case GL_UNIFORM:
450 case GL_BUFFER_VARIABLE:
451 return RESOURCE_UNI(res)->name;
452 case GL_VERTEX_SUBROUTINE_UNIFORM:
453 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
454 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
455 case GL_COMPUTE_SUBROUTINE_UNIFORM:
456 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
457 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
458 return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
459 case GL_VERTEX_SUBROUTINE:
460 case GL_GEOMETRY_SUBROUTINE:
461 case GL_FRAGMENT_SUBROUTINE:
462 case GL_COMPUTE_SUBROUTINE:
463 case GL_TESS_CONTROL_SUBROUTINE:
464 case GL_TESS_EVALUATION_SUBROUTINE:
465 return RESOURCE_SUB(res)->name;
466 default:
467 assert(!"support for resource type not implemented");
468 }
469 return NULL;
470 }
471
472
473 unsigned
474 _mesa_program_resource_array_size(struct gl_program_resource *res)
475 {
476 switch (res->Type) {
477 case GL_TRANSFORM_FEEDBACK_VARYING:
478 return RESOURCE_XFB(res)->Size > 1 ?
479 RESOURCE_XFB(res)->Size : 0;
480 case GL_PROGRAM_INPUT:
481 case GL_PROGRAM_OUTPUT:
482 return RESOURCE_VAR(res)->type->length;
483 case GL_UNIFORM:
484 case GL_VERTEX_SUBROUTINE_UNIFORM:
485 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
486 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
487 case GL_COMPUTE_SUBROUTINE_UNIFORM:
488 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
489 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
490 case GL_BUFFER_VARIABLE:
491 return RESOURCE_UNI(res)->array_elements;
492 case GL_VERTEX_SUBROUTINE:
493 case GL_GEOMETRY_SUBROUTINE:
494 case GL_FRAGMENT_SUBROUTINE:
495 case GL_COMPUTE_SUBROUTINE:
496 case GL_TESS_CONTROL_SUBROUTINE:
497 case GL_TESS_EVALUATION_SUBROUTINE:
498 case GL_ATOMIC_COUNTER_BUFFER:
499 case GL_UNIFORM_BLOCK:
500 case GL_SHADER_STORAGE_BLOCK:
501 return 0;
502 default:
503 assert(!"support for resource type not implemented");
504 }
505 return 0;
506 }
507
508 /**
509 * Checks if array subscript is valid and if so sets array_index.
510 */
511 static bool
512 valid_array_index(const GLchar *name, unsigned *array_index)
513 {
514 long idx = 0;
515 const GLchar *out_base_name_end;
516
517 idx = parse_program_resource_name(name, &out_base_name_end);
518 if (idx < 0)
519 return false;
520
521 if (array_index)
522 *array_index = idx;
523
524 return true;
525 }
526
527 /* Find a program resource with specific name in given interface.
528 */
529 struct gl_program_resource *
530 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
531 GLenum programInterface, const char *name,
532 unsigned *array_index)
533 {
534 struct gl_program_resource *res = shProg->ProgramResourceList;
535 for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
536 if (res->Type != programInterface)
537 continue;
538
539 /* Resource basename. */
540 const char *rname = _mesa_program_resource_name(res);
541 unsigned baselen = strlen(rname);
542
543 if (strncmp(rname, name, baselen) == 0) {
544 switch (programInterface) {
545 case GL_UNIFORM_BLOCK:
546 case GL_SHADER_STORAGE_BLOCK:
547 /* Basename match, check if array or struct. */
548 if (name[baselen] == '\0' ||
549 name[baselen] == '[' ||
550 name[baselen] == '.') {
551 return res;
552 }
553 break;
554 case GL_TRANSFORM_FEEDBACK_VARYING:
555 case GL_BUFFER_VARIABLE:
556 case GL_UNIFORM:
557 case GL_VERTEX_SUBROUTINE_UNIFORM:
558 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
559 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
560 case GL_COMPUTE_SUBROUTINE_UNIFORM:
561 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
562 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
563 case GL_VERTEX_SUBROUTINE:
564 case GL_GEOMETRY_SUBROUTINE:
565 case GL_FRAGMENT_SUBROUTINE:
566 case GL_COMPUTE_SUBROUTINE:
567 case GL_TESS_CONTROL_SUBROUTINE:
568 case GL_TESS_EVALUATION_SUBROUTINE:
569 if (name[baselen] == '.') {
570 return res;
571 }
572 /* fall-through */
573 case GL_PROGRAM_INPUT:
574 case GL_PROGRAM_OUTPUT:
575 if (name[baselen] == '\0') {
576 return res;
577 } else if (name[baselen] == '[' &&
578 valid_array_index(name, array_index)) {
579 return res;
580 }
581 break;
582 default:
583 assert(!"not implemented for given interface");
584 }
585 }
586 }
587 return NULL;
588 }
589
590 static GLuint
591 calc_resource_index(struct gl_shader_program *shProg,
592 struct gl_program_resource *res)
593 {
594 unsigned i;
595 GLuint index = 0;
596 for (i = 0; i < shProg->NumProgramResourceList; i++) {
597 if (&shProg->ProgramResourceList[i] == res)
598 return index;
599 if (shProg->ProgramResourceList[i].Type == res->Type)
600 index++;
601 }
602 return GL_INVALID_INDEX;
603 }
604
605 /**
606 * Calculate index for the given resource.
607 */
608 GLuint
609 _mesa_program_resource_index(struct gl_shader_program *shProg,
610 struct gl_program_resource *res)
611 {
612 if (!res)
613 return GL_INVALID_INDEX;
614
615 switch (res->Type) {
616 case GL_UNIFORM_BLOCK:
617 case GL_SHADER_STORAGE_BLOCK:
618 return RESOURCE_UBO(res)- shProg->UniformBlocks;
619 case GL_ATOMIC_COUNTER_BUFFER:
620 return RESOURCE_ATC(res) - shProg->AtomicBuffers;
621 case GL_TRANSFORM_FEEDBACK_VARYING:
622 default:
623 return calc_resource_index(shProg, res);
624 }
625 }
626
627 /* Find a program resource with specific index in given interface.
628 */
629 struct gl_program_resource *
630 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
631 GLenum programInterface, GLuint index)
632 {
633 struct gl_program_resource *res = shProg->ProgramResourceList;
634 int idx = -1;
635
636 for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
637 if (res->Type != programInterface)
638 continue;
639
640 switch (res->Type) {
641 case GL_UNIFORM_BLOCK:
642 case GL_ATOMIC_COUNTER_BUFFER:
643 case GL_SHADER_STORAGE_BLOCK:
644 if (_mesa_program_resource_index(shProg, res) == index)
645 return res;
646 break;
647 case GL_TRANSFORM_FEEDBACK_VARYING:
648 case GL_PROGRAM_INPUT:
649 case GL_PROGRAM_OUTPUT:
650 case GL_UNIFORM:
651 case GL_VERTEX_SUBROUTINE_UNIFORM:
652 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
653 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
654 case GL_COMPUTE_SUBROUTINE_UNIFORM:
655 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
656 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
657 case GL_VERTEX_SUBROUTINE:
658 case GL_GEOMETRY_SUBROUTINE:
659 case GL_FRAGMENT_SUBROUTINE:
660 case GL_COMPUTE_SUBROUTINE:
661 case GL_TESS_CONTROL_SUBROUTINE:
662 case GL_TESS_EVALUATION_SUBROUTINE:
663 case GL_BUFFER_VARIABLE:
664 if (++idx == (int) index)
665 return res;
666 break;
667 default:
668 assert(!"not implemented for given interface");
669 }
670 }
671 return NULL;
672 }
673
674 /* Function returns if resource name is expected to have index
675 * appended into it.
676 *
677 *
678 * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
679 * spec says:
680 *
681 * "If the active uniform is an array, the uniform name returned in
682 * name will always be the name of the uniform array appended with
683 * "[0]"."
684 *
685 * The same text also appears in the OpenGL 4.2 spec. It does not,
686 * however, appear in any previous spec. Previous specifications are
687 * ambiguous in this regard. However, either name can later be passed
688 * to glGetUniformLocation (and related APIs), so there shouldn't be any
689 * harm in always appending "[0]" to uniform array names.
690 *
691 * Geometry shader stage has different naming convention where the 'normal'
692 * condition is an array, therefore for variables referenced in geometry
693 * stage we do not add '[0]'.
694 *
695 * Note, that TCS outputs and TES inputs should not have index appended
696 * either.
697 */
698 static bool
699 add_index_to_name(struct gl_program_resource *res)
700 {
701 bool add_index = !(((res->Type == GL_PROGRAM_INPUT) &&
702 res->StageReferences & (1 << MESA_SHADER_GEOMETRY)));
703
704 /* Transform feedback varyings have array index already appended
705 * in their names.
706 */
707 if (res->Type == GL_TRANSFORM_FEEDBACK_VARYING)
708 add_index = false;
709
710 return add_index;
711 }
712
713 /* Get name length of a program resource. This consists of
714 * base name + 3 for '[0]' if resource is an array.
715 */
716 extern unsigned
717 _mesa_program_resource_name_len(struct gl_program_resource *res)
718 {
719 unsigned length = strlen(_mesa_program_resource_name(res));
720 if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
721 length += 3;
722 return length;
723 }
724
725 /* Get full name of a program resource.
726 */
727 bool
728 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
729 GLenum programInterface, GLuint index,
730 GLsizei bufSize, GLsizei *length,
731 GLchar *name, const char *caller)
732 {
733 GET_CURRENT_CONTEXT(ctx);
734
735 /* Find resource with given interface and index. */
736 struct gl_program_resource *res =
737 _mesa_program_resource_find_index(shProg, programInterface, index);
738
739 /* The error INVALID_VALUE is generated if <index> is greater than
740 * or equal to the number of entries in the active resource list for
741 * <programInterface>.
742 */
743 if (!res) {
744 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
745 return false;
746 }
747
748 if (bufSize < 0) {
749 _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
750 return false;
751 }
752
753 GLsizei localLength;
754
755 if (length == NULL)
756 length = &localLength;
757
758 _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
759
760 if (_mesa_program_resource_array_size(res) && add_index_to_name(res)) {
761 int i;
762
763 /* The comparison is strange because *length does *NOT* include the
764 * terminating NUL, but maxLength does.
765 */
766 for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
767 name[*length + i] = "[0]"[i];
768
769 name[*length + i] = '\0';
770 *length += i;
771 }
772 return true;
773 }
774
775 static GLint
776 program_resource_location(struct gl_shader_program *shProg,
777 struct gl_program_resource *res, const char *name,
778 unsigned array_index)
779 {
780 /* Built-in locations should report GL_INVALID_INDEX. */
781 if (is_gl_identifier(name))
782 return GL_INVALID_INDEX;
783
784 /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
785 * offsets are used internally to differentiate between built-in attributes
786 * and user-defined attributes.
787 */
788 switch (res->Type) {
789 case GL_PROGRAM_INPUT:
790 /* If the input is an array, fail if the index is out of bounds. */
791 if (array_index > 0
792 && array_index >= RESOURCE_VAR(res)->type->length) {
793 return -1;
794 }
795 return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0;
796 case GL_PROGRAM_OUTPUT:
797 /* If the output is an array, fail if the index is out of bounds. */
798 if (array_index > 0
799 && array_index >= RESOURCE_VAR(res)->type->length) {
800 return -1;
801 }
802 return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
803 case GL_UNIFORM:
804 /* If the uniform is built-in, fail. */
805 if (RESOURCE_UNI(res)->builtin)
806 return -1;
807
808 /* From the GL_ARB_uniform_buffer_object spec:
809 *
810 * "The value -1 will be returned if <name> does not correspond to an
811 * active uniform variable name in <program>, if <name> is associated
812 * with a named uniform block, or if <name> starts with the reserved
813 * prefix "gl_"."
814 */
815 if (RESOURCE_UNI(res)->block_index != -1 ||
816 RESOURCE_UNI(res)->atomic_buffer_index != -1)
817 return -1;
818
819 /* fallthrough */
820 case GL_VERTEX_SUBROUTINE_UNIFORM:
821 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
822 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
823 case GL_COMPUTE_SUBROUTINE_UNIFORM:
824 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
825 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
826 /* If the uniform is an array, fail if the index is out of bounds. */
827 if (array_index > 0
828 && array_index >= RESOURCE_UNI(res)->array_elements) {
829 return -1;
830 }
831
832 /* location in remap table + array element offset */
833 return RESOURCE_UNI(res)->remap_location + array_index;
834 default:
835 return -1;
836 }
837 }
838
839 static char*
840 get_top_level_name(const char *name)
841 {
842 const char *first_dot = strchr(name, '.');
843 const char *first_square_bracket = strchr(name, '[');
844 int name_size = 0;
845 /* From ARB_program_interface_query spec:
846 *
847 * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying the
848 * number of active array elements of the top-level shader storage block
849 * member containing to the active variable is written to <params>. If the
850 * top-level block member is not declared as an array, the value one is
851 * written to <params>. If the top-level block member is an array with no
852 * declared size, the value zero is written to <params>.
853 */
854
855 /* The buffer variable is on top level.*/
856 if (!first_square_bracket && !first_dot)
857 name_size = strlen(name);
858 else if ((!first_square_bracket ||
859 (first_dot && first_dot < first_square_bracket)))
860 name_size = first_dot - name;
861 else
862 name_size = first_square_bracket - name;
863
864 return strndup(name, name_size);
865 }
866
867 static char*
868 get_var_name(const char *name)
869 {
870 const char *first_dot = strchr(name, '.');
871
872 if (!first_dot)
873 return strdup(name);
874
875 return strndup(first_dot+1, strlen(first_dot) - 1);
876 }
877
878 static GLint
879 program_resource_top_level_array_size(struct gl_shader_program *shProg,
880 struct gl_program_resource *res,
881 const char *name)
882 {
883 int block_index = RESOURCE_UNI(res)->block_index;
884 int array_size = -1;
885 char *var_name = get_top_level_name(name);
886 char *interface_name =
887 get_top_level_name(shProg->UniformBlocks[block_index].Name);
888
889 if (strcmp(var_name, interface_name) == 0) {
890 /* Deal with instanced array of SSBOs */
891 char *temp_name = get_var_name(name);
892 free(var_name);
893 var_name = get_top_level_name(temp_name);
894 free(temp_name);
895 }
896
897 for (unsigned i = 0; i < shProg->NumShaders; i++) {
898 if (shProg->Shaders[i] == NULL)
899 continue;
900
901 const gl_shader *stage = shProg->Shaders[i];
902 foreach_in_list(ir_instruction, node, stage->ir) {
903 ir_variable *var = node->as_variable();
904 if (!var || !var->get_interface_type() ||
905 var->data.mode != ir_var_shader_storage)
906 continue;
907
908 const glsl_type *interface = var->get_interface_type();
909
910 if (strcmp(interface_name, interface->name) != 0)
911 continue;
912
913 for (unsigned i = 0; i < interface->length; i++) {
914 const glsl_struct_field *field = &interface->fields.structure[i];
915 if (strcmp(field->name, var_name) != 0)
916 continue;
917 /* From GL_ARB_program_interface_query spec:
918 *
919 * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer
920 * identifying the number of active array elements of the top-level
921 * shader storage block member containing to the active variable is
922 * written to <params>. If the top-level block member is not
923 * declared as an array, the value one is written to <params>. If
924 * the top-level block member is an array with no declared size,
925 * the value zero is written to <params>.
926 */
927 if (field->type->is_unsized_array())
928 array_size = 0;
929 else if (field->type->is_array())
930 array_size = field->type->length;
931 else
932 array_size = 1;
933 goto found_top_level_array_size;
934 }
935 }
936 }
937 found_top_level_array_size:
938 free(interface_name);
939 free(var_name);
940 return array_size;
941 }
942
943 static GLint
944 program_resource_top_level_array_stride(struct gl_shader_program *shProg,
945 struct gl_program_resource *res,
946 const char *name)
947 {
948 int block_index = RESOURCE_UNI(res)->block_index;
949 int array_stride = -1;
950 char *var_name = get_top_level_name(name);
951 char *interface_name =
952 get_top_level_name(shProg->UniformBlocks[block_index].Name);
953
954 if (strcmp(var_name, interface_name) == 0) {
955 /* Deal with instanced array of SSBOs */
956 char *temp_name = get_var_name(name);
957 free(var_name);
958 var_name = get_top_level_name(temp_name);
959 free(temp_name);
960 }
961
962 for (unsigned i = 0; i < shProg->NumShaders; i++) {
963 if (shProg->Shaders[i] == NULL)
964 continue;
965
966 const gl_shader *stage = shProg->Shaders[i];
967 foreach_in_list(ir_instruction, node, stage->ir) {
968 ir_variable *var = node->as_variable();
969 if (!var || !var->get_interface_type() ||
970 var->data.mode != ir_var_shader_storage)
971 continue;
972
973 const glsl_type *interface = var->get_interface_type();
974
975 if (strcmp(interface_name, interface->name) != 0) {
976 continue;
977 }
978
979 for (unsigned i = 0; i < interface->length; i++) {
980 const glsl_struct_field *field = &interface->fields.structure[i];
981 if (strcmp(field->name, var_name) != 0)
982 continue;
983 /* From GL_ARB_program_interface_query:
984 *
985 * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer
986 * identifying the stride between array elements of the top-level
987 * shader storage block member containing the active variable is
988 * written to <params>. For top-level block members declared as
989 * arrays, the value written is the difference, in basic machine
990 * units, between the offsets of the active variable for
991 * consecutive elements in the top-level array. For top-level
992 * block members not declared as an array, zero is written to
993 * <params>."
994 */
995 if (field->type->is_array()) {
996 const enum glsl_matrix_layout matrix_layout =
997 glsl_matrix_layout(field->matrix_layout);
998 bool row_major = matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
999 const glsl_type *array_type = field->type->fields.array;
1000
1001 if (interface->interface_packing != GLSL_INTERFACE_PACKING_STD430) {
1002 if (array_type->is_record()) {
1003 array_stride = array_type->std140_size(row_major);
1004 array_stride = glsl_align(array_stride, 16);
1005 } else {
1006 unsigned element_base_align = 0;
1007 element_base_align = array_type->std140_base_alignment(row_major);
1008 array_stride = MAX2(element_base_align, 16);
1009 }
1010 } else {
1011 array_stride = array_type->std430_array_stride(row_major);
1012 }
1013 } else {
1014 array_stride = 0;
1015 }
1016 goto found_top_level_array_size;
1017 }
1018 }
1019 }
1020 found_top_level_array_size:
1021 free(interface_name);
1022 free(var_name);
1023 return array_stride;
1024 }
1025
1026 /**
1027 * Function implements following location queries:
1028 * glGetUniformLocation
1029 */
1030 GLint
1031 _mesa_program_resource_location(struct gl_shader_program *shProg,
1032 GLenum programInterface, const char *name)
1033 {
1034 unsigned array_index = 0;
1035 struct gl_program_resource *res =
1036 _mesa_program_resource_find_name(shProg, programInterface, name,
1037 &array_index);
1038
1039 /* Resource not found. */
1040 if (!res)
1041 return -1;
1042
1043 return program_resource_location(shProg, res, name, array_index);
1044 }
1045
1046 /**
1047 * Function implements following index queries:
1048 * glGetFragDataIndex
1049 */
1050 GLint
1051 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
1052 GLenum programInterface, const char *name)
1053 {
1054 struct gl_program_resource *res =
1055 _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
1056
1057 /* Non-existent variable or resource is not referenced by fragment stage. */
1058 if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
1059 return -1;
1060
1061 return RESOURCE_VAR(res)->data.index;
1062 }
1063
1064 static uint8_t
1065 stage_from_enum(GLenum ref)
1066 {
1067 switch (ref) {
1068 case GL_REFERENCED_BY_VERTEX_SHADER:
1069 return MESA_SHADER_VERTEX;
1070 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1071 return MESA_SHADER_TESS_CTRL;
1072 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1073 return MESA_SHADER_TESS_EVAL;
1074 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1075 return MESA_SHADER_GEOMETRY;
1076 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1077 return MESA_SHADER_FRAGMENT;
1078 case GL_REFERENCED_BY_COMPUTE_SHADER:
1079 return MESA_SHADER_COMPUTE;
1080 default:
1081 assert(!"shader stage not supported");
1082 return MESA_SHADER_STAGES;
1083 }
1084 }
1085
1086 /**
1087 * Check if resource is referenced by given 'referenced by' stage enum.
1088 * ATC and UBO resources hold stage references of their own.
1089 */
1090 static bool
1091 is_resource_referenced(struct gl_shader_program *shProg,
1092 struct gl_program_resource *res,
1093 GLuint index, uint8_t stage)
1094 {
1095 /* First, check if we even have such a stage active. */
1096 if (!shProg->_LinkedShaders[stage])
1097 return false;
1098
1099 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
1100 return RESOURCE_ATC(res)->StageReferences[stage];
1101
1102 if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK)
1103 return shProg->UniformBlockStageIndex[stage][index] != -1;
1104
1105 return res->StageReferences & (1 << stage);
1106 }
1107
1108 static unsigned
1109 get_buffer_property(struct gl_shader_program *shProg,
1110 struct gl_program_resource *res, const GLenum prop,
1111 GLint *val, const char *caller)
1112 {
1113 GET_CURRENT_CONTEXT(ctx);
1114 if (res->Type != GL_UNIFORM_BLOCK &&
1115 res->Type != GL_ATOMIC_COUNTER_BUFFER &&
1116 res->Type != GL_SHADER_STORAGE_BLOCK)
1117 goto invalid_operation;
1118
1119 if (res->Type == GL_UNIFORM_BLOCK) {
1120 switch (prop) {
1121 case GL_BUFFER_BINDING:
1122 *val = RESOURCE_UBO(res)->Binding;
1123 return 1;
1124 case GL_BUFFER_DATA_SIZE:
1125 *val = RESOURCE_UBO(res)->UniformBufferSize;
1126 return 1;
1127 case GL_NUM_ACTIVE_VARIABLES:
1128 *val = 0;
1129 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1130 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1131 struct gl_program_resource *uni =
1132 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1133 NULL);
1134 if (!uni)
1135 continue;
1136 (*val)++;
1137 }
1138 return 1;
1139 case GL_ACTIVE_VARIABLES:
1140 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1141 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1142 struct gl_program_resource *uni =
1143 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1144 NULL);
1145 if (!uni)
1146 continue;
1147 *val++ =
1148 _mesa_program_resource_index(shProg, uni);
1149 }
1150 return RESOURCE_UBO(res)->NumUniforms;
1151 }
1152 } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
1153 switch (prop) {
1154 case GL_BUFFER_BINDING:
1155 *val = RESOURCE_UBO(res)->Binding;
1156 return 1;
1157 case GL_BUFFER_DATA_SIZE:
1158 *val = RESOURCE_UBO(res)->UniformBufferSize;
1159 return 1;
1160 case GL_NUM_ACTIVE_VARIABLES:
1161 *val = 0;
1162 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1163 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1164 struct gl_program_resource *uni =
1165 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1166 iname, NULL);
1167 if (!uni)
1168 continue;
1169 (*val)++;
1170 }
1171 return 1;
1172 case GL_ACTIVE_VARIABLES:
1173 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1174 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1175 struct gl_program_resource *uni =
1176 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1177 iname, NULL);
1178 if (!uni)
1179 continue;
1180 *val++ =
1181 _mesa_program_resource_index(shProg, uni);
1182 }
1183 return RESOURCE_UBO(res)->NumUniforms;
1184 }
1185 } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1186 switch (prop) {
1187 case GL_BUFFER_BINDING:
1188 *val = RESOURCE_ATC(res)->Binding;
1189 return 1;
1190 case GL_BUFFER_DATA_SIZE:
1191 *val = RESOURCE_ATC(res)->MinimumSize;
1192 return 1;
1193 case GL_NUM_ACTIVE_VARIABLES:
1194 *val = RESOURCE_ATC(res)->NumUniforms;
1195 return 1;
1196 case GL_ACTIVE_VARIABLES:
1197 for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
1198 *val++ = RESOURCE_ATC(res)->Uniforms[i];
1199 return RESOURCE_ATC(res)->NumUniforms;
1200 }
1201 }
1202 assert(!"support for property type not implemented");
1203
1204 invalid_operation:
1205 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1206 _mesa_enum_to_string(res->Type),
1207 _mesa_enum_to_string(prop));
1208
1209 return 0;
1210 }
1211
1212 unsigned
1213 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1214 struct gl_program_resource *res, GLuint index,
1215 const GLenum prop, GLint *val, const char *caller)
1216 {
1217 GET_CURRENT_CONTEXT(ctx);
1218
1219 #define VALIDATE_TYPE(type)\
1220 if (res->Type != type)\
1221 goto invalid_operation;
1222
1223 #define VALIDATE_TYPE_2(type1, type2)\
1224 if (res->Type != type1 && res->Type != type2)\
1225 goto invalid_operation;
1226
1227 switch(prop) {
1228 case GL_NAME_LENGTH:
1229 switch (res->Type) {
1230 case GL_ATOMIC_COUNTER_BUFFER:
1231 goto invalid_operation;
1232 default:
1233 /* Resource name length + terminator. */
1234 *val = _mesa_program_resource_name_len(res) + 1;
1235 }
1236 return 1;
1237 case GL_TYPE:
1238 switch (res->Type) {
1239 case GL_UNIFORM:
1240 case GL_BUFFER_VARIABLE:
1241 *val = RESOURCE_UNI(res)->type->gl_type;
1242 return 1;
1243 case GL_PROGRAM_INPUT:
1244 case GL_PROGRAM_OUTPUT:
1245 *val = RESOURCE_VAR(res)->type->gl_type;
1246 return 1;
1247 case GL_TRANSFORM_FEEDBACK_VARYING:
1248 *val = RESOURCE_XFB(res)->Type;
1249 return 1;
1250 default:
1251 goto invalid_operation;
1252 }
1253 case GL_ARRAY_SIZE:
1254 switch (res->Type) {
1255 case GL_UNIFORM:
1256 case GL_BUFFER_VARIABLE:
1257 *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1258 return 1;
1259 case GL_PROGRAM_INPUT:
1260 case GL_PROGRAM_OUTPUT:
1261 *val = MAX2(_mesa_program_resource_array_size(res), 1);
1262 return 1;
1263 case GL_TRANSFORM_FEEDBACK_VARYING:
1264 *val = MAX2(RESOURCE_XFB(res)->Size, 1);
1265 return 1;
1266 default:
1267 goto invalid_operation;
1268 }
1269 case GL_OFFSET:
1270 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1271 *val = RESOURCE_UNI(res)->offset;
1272 return 1;
1273 case GL_BLOCK_INDEX:
1274 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1275 *val = RESOURCE_UNI(res)->block_index;
1276 return 1;
1277 case GL_ARRAY_STRIDE:
1278 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1279 *val = RESOURCE_UNI(res)->array_stride;
1280 return 1;
1281 case GL_MATRIX_STRIDE:
1282 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1283 *val = RESOURCE_UNI(res)->matrix_stride;
1284 return 1;
1285 case GL_IS_ROW_MAJOR:
1286 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1287 *val = RESOURCE_UNI(res)->row_major;
1288 return 1;
1289 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1290 VALIDATE_TYPE(GL_UNIFORM);
1291 *val = RESOURCE_UNI(res)->atomic_buffer_index;
1292 return 1;
1293 case GL_BUFFER_BINDING:
1294 case GL_BUFFER_DATA_SIZE:
1295 case GL_NUM_ACTIVE_VARIABLES:
1296 case GL_ACTIVE_VARIABLES:
1297 return get_buffer_property(shProg, res, prop, val, caller);
1298 case GL_REFERENCED_BY_COMPUTE_SHADER:
1299 if (!_mesa_has_compute_shaders(ctx))
1300 goto invalid_enum;
1301 /* fallthrough */
1302 case GL_REFERENCED_BY_VERTEX_SHADER:
1303 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1304 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1305 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1306 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1307 switch (res->Type) {
1308 case GL_UNIFORM:
1309 case GL_PROGRAM_INPUT:
1310 case GL_PROGRAM_OUTPUT:
1311 case GL_UNIFORM_BLOCK:
1312 case GL_BUFFER_VARIABLE:
1313 case GL_SHADER_STORAGE_BLOCK:
1314 case GL_ATOMIC_COUNTER_BUFFER:
1315 *val = is_resource_referenced(shProg, res, index,
1316 stage_from_enum(prop));
1317 return 1;
1318 default:
1319 goto invalid_operation;
1320 }
1321 case GL_LOCATION:
1322 switch (res->Type) {
1323 case GL_UNIFORM:
1324 case GL_PROGRAM_INPUT:
1325 case GL_PROGRAM_OUTPUT:
1326 *val = program_resource_location(shProg, res,
1327 _mesa_program_resource_name(res),
1328 0);
1329 return 1;
1330 default:
1331 goto invalid_operation;
1332 }
1333 case GL_LOCATION_INDEX:
1334 if (res->Type != GL_PROGRAM_OUTPUT)
1335 goto invalid_operation;
1336 *val = RESOURCE_VAR(res)->data.index;
1337 return 1;
1338
1339 case GL_NUM_COMPATIBLE_SUBROUTINES:
1340 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1341 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1342 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1343 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1344 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1345 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1346 goto invalid_operation;
1347 *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1348 return 1;
1349 case GL_COMPATIBLE_SUBROUTINES: {
1350 const struct gl_uniform_storage *uni;
1351 struct gl_shader *sh;
1352 unsigned count, i;
1353 int j;
1354
1355 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1356 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1357 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1358 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1359 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1360 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1361 goto invalid_operation;
1362 uni = RESOURCE_UNI(res);
1363
1364 sh = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)];
1365 count = 0;
1366 for (i = 0; i < sh->NumSubroutineFunctions; i++) {
1367 struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i];
1368 for (j = 0; j < fn->num_compat_types; j++) {
1369 if (fn->types[j] == uni->type) {
1370 val[count++] = i;
1371 break;
1372 }
1373 }
1374 }
1375 return count;
1376 }
1377
1378 case GL_TOP_LEVEL_ARRAY_SIZE:
1379 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1380 *val = program_resource_top_level_array_size(shProg, res,
1381 _mesa_program_resource_name(res));
1382 return 1;
1383
1384 case GL_TOP_LEVEL_ARRAY_STRIDE:
1385 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1386 *val = program_resource_top_level_array_stride(shProg, res,
1387 _mesa_program_resource_name(res));
1388 return 1;
1389
1390 /* GL_ARB_tessellation_shader */
1391 case GL_IS_PER_PATCH:
1392 switch (res->Type) {
1393 case GL_PROGRAM_INPUT:
1394 case GL_PROGRAM_OUTPUT:
1395 *val = RESOURCE_VAR(res)->data.patch;
1396 return 1;
1397 default:
1398 goto invalid_operation;
1399 }
1400 default:
1401 goto invalid_enum;
1402 }
1403
1404 #undef VALIDATE_TYPE
1405 #undef VALIDATE_TYPE_2
1406
1407 invalid_enum:
1408 _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1409 _mesa_enum_to_string(res->Type),
1410 _mesa_enum_to_string(prop));
1411 return 0;
1412
1413 invalid_operation:
1414 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1415 _mesa_enum_to_string(res->Type),
1416 _mesa_enum_to_string(prop));
1417 return 0;
1418 }
1419
1420 extern void
1421 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1422 GLenum programInterface, GLuint index, GLsizei propCount,
1423 const GLenum *props, GLsizei bufSize,
1424 GLsizei *length, GLint *params)
1425 {
1426 GET_CURRENT_CONTEXT(ctx);
1427 GLint *val = (GLint *) params;
1428 const GLenum *prop = props;
1429 GLsizei amount = 0;
1430
1431 struct gl_program_resource *res =
1432 _mesa_program_resource_find_index(shProg, programInterface, index);
1433
1434 /* No such resource found or bufSize negative. */
1435 if (!res || bufSize < 0) {
1436 _mesa_error(ctx, GL_INVALID_VALUE,
1437 "glGetProgramResourceiv(%s index %d bufSize %d)",
1438 _mesa_enum_to_string(programInterface), index, bufSize);
1439 return;
1440 }
1441
1442 /* Write propCount values until error occurs or bufSize reached. */
1443 for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1444 int props_written =
1445 _mesa_program_resource_prop(shProg, res, index, *prop, val,
1446 "glGetProgramResourceiv");
1447
1448 /* Error happened. */
1449 if (props_written == 0)
1450 return;
1451
1452 amount += props_written;
1453 }
1454
1455 /* If <length> is not NULL, the actual number of integer values
1456 * written to <params> will be written to <length>.
1457 */
1458 if (length)
1459 *length = amount;
1460 }