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