main: Add SHADER_STORAGE_BLOCK and BUFFER_VARIABLE support for ARB_program_interface_...
[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(var_name);
999 return array_stride;
1000 }
1001
1002 /**
1003 * Function implements following location queries:
1004 * glGetUniformLocation
1005 */
1006 GLint
1007 _mesa_program_resource_location(struct gl_shader_program *shProg,
1008 GLenum programInterface, const char *name)
1009 {
1010 unsigned array_index = 0;
1011 struct gl_program_resource *res =
1012 _mesa_program_resource_find_name(shProg, programInterface, name,
1013 &array_index);
1014
1015 /* Resource not found. */
1016 if (!res)
1017 return -1;
1018
1019 return program_resource_location(shProg, res, name, array_index);
1020 }
1021
1022 /**
1023 * Function implements following index queries:
1024 * glGetFragDataIndex
1025 */
1026 GLint
1027 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
1028 GLenum programInterface, const char *name)
1029 {
1030 struct gl_program_resource *res =
1031 _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
1032
1033 /* Non-existent variable or resource is not referenced by fragment stage. */
1034 if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
1035 return -1;
1036
1037 return RESOURCE_VAR(res)->data.index;
1038 }
1039
1040 static uint8_t
1041 stage_from_enum(GLenum ref)
1042 {
1043 switch (ref) {
1044 case GL_REFERENCED_BY_VERTEX_SHADER:
1045 return MESA_SHADER_VERTEX;
1046 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1047 return MESA_SHADER_TESS_CTRL;
1048 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1049 return MESA_SHADER_TESS_EVAL;
1050 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1051 return MESA_SHADER_GEOMETRY;
1052 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1053 return MESA_SHADER_FRAGMENT;
1054 case GL_REFERENCED_BY_COMPUTE_SHADER:
1055 return MESA_SHADER_COMPUTE;
1056 default:
1057 assert(!"shader stage not supported");
1058 return MESA_SHADER_STAGES;
1059 }
1060 }
1061
1062 /**
1063 * Check if resource is referenced by given 'referenced by' stage enum.
1064 * ATC and UBO resources hold stage references of their own.
1065 */
1066 static bool
1067 is_resource_referenced(struct gl_shader_program *shProg,
1068 struct gl_program_resource *res,
1069 GLuint index, uint8_t stage)
1070 {
1071 /* First, check if we even have such a stage active. */
1072 if (!shProg->_LinkedShaders[stage])
1073 return false;
1074
1075 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
1076 return RESOURCE_ATC(res)->StageReferences[stage];
1077
1078 if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK)
1079 return shProg->UniformBlockStageIndex[stage][index] != -1;
1080
1081 return res->StageReferences & (1 << stage);
1082 }
1083
1084 static unsigned
1085 get_buffer_property(struct gl_shader_program *shProg,
1086 struct gl_program_resource *res, const GLenum prop,
1087 GLint *val, const char *caller)
1088 {
1089 GET_CURRENT_CONTEXT(ctx);
1090 if (res->Type != GL_UNIFORM_BLOCK &&
1091 res->Type != GL_ATOMIC_COUNTER_BUFFER &&
1092 res->Type != GL_SHADER_STORAGE_BLOCK)
1093 goto invalid_operation;
1094
1095 if (res->Type == GL_UNIFORM_BLOCK) {
1096 switch (prop) {
1097 case GL_BUFFER_BINDING:
1098 *val = RESOURCE_UBO(res)->Binding;
1099 return 1;
1100 case GL_BUFFER_DATA_SIZE:
1101 *val = RESOURCE_UBO(res)->UniformBufferSize;
1102 return 1;
1103 case GL_NUM_ACTIVE_VARIABLES:
1104 *val = 0;
1105 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1106 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1107 struct gl_program_resource *uni =
1108 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1109 NULL);
1110 if (!uni)
1111 continue;
1112 (*val)++;
1113 }
1114 return 1;
1115 case GL_ACTIVE_VARIABLES:
1116 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1117 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1118 struct gl_program_resource *uni =
1119 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1120 NULL);
1121 if (!uni)
1122 continue;
1123 *val++ =
1124 _mesa_program_resource_index(shProg, uni);
1125 }
1126 return RESOURCE_UBO(res)->NumUniforms;
1127 }
1128 } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
1129 switch (prop) {
1130 case GL_BUFFER_BINDING:
1131 *val = RESOURCE_UBO(res)->Binding;
1132 return 1;
1133 case GL_BUFFER_DATA_SIZE:
1134 *val = RESOURCE_UBO(res)->UniformBufferSize;
1135 return 1;
1136 case GL_NUM_ACTIVE_VARIABLES:
1137 *val = 0;
1138 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1139 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1140 struct gl_program_resource *uni =
1141 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1142 iname, NULL);
1143 if (!uni)
1144 continue;
1145 (*val)++;
1146 }
1147 return 1;
1148 case GL_ACTIVE_VARIABLES:
1149 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1150 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1151 struct gl_program_resource *uni =
1152 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1153 iname, NULL);
1154 if (!uni)
1155 continue;
1156 *val++ =
1157 _mesa_program_resource_index(shProg, uni);
1158 }
1159 return RESOURCE_UBO(res)->NumUniforms;
1160 }
1161 } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1162 switch (prop) {
1163 case GL_BUFFER_BINDING:
1164 *val = RESOURCE_ATC(res)->Binding;
1165 return 1;
1166 case GL_BUFFER_DATA_SIZE:
1167 *val = RESOURCE_ATC(res)->MinimumSize;
1168 return 1;
1169 case GL_NUM_ACTIVE_VARIABLES:
1170 *val = RESOURCE_ATC(res)->NumUniforms;
1171 return 1;
1172 case GL_ACTIVE_VARIABLES:
1173 for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
1174 *val++ = RESOURCE_ATC(res)->Uniforms[i];
1175 return RESOURCE_ATC(res)->NumUniforms;
1176 }
1177 }
1178 assert(!"support for property type not implemented");
1179
1180 invalid_operation:
1181 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1182 _mesa_enum_to_string(res->Type),
1183 _mesa_enum_to_string(prop));
1184
1185 return 0;
1186 }
1187
1188 unsigned
1189 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1190 struct gl_program_resource *res, GLuint index,
1191 const GLenum prop, GLint *val, const char *caller)
1192 {
1193 GET_CURRENT_CONTEXT(ctx);
1194
1195 #define VALIDATE_TYPE(type)\
1196 if (res->Type != type)\
1197 goto invalid_operation;
1198
1199 #define VALIDATE_TYPE_2(type1, type2)\
1200 if (res->Type != type1 && res->Type != type2)\
1201 goto invalid_operation;
1202
1203 switch(prop) {
1204 case GL_NAME_LENGTH:
1205 switch (res->Type) {
1206 case GL_ATOMIC_COUNTER_BUFFER:
1207 goto invalid_operation;
1208 case GL_TRANSFORM_FEEDBACK_VARYING:
1209 *val = strlen(_mesa_program_resource_name(res)) + 1;
1210 break;
1211 default:
1212 /* Base name +3 if array '[0]' + terminator. */
1213 *val = strlen(_mesa_program_resource_name(res)) +
1214 (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1;
1215 }
1216 return 1;
1217 case GL_TYPE:
1218 switch (res->Type) {
1219 case GL_UNIFORM:
1220 case GL_BUFFER_VARIABLE:
1221 *val = RESOURCE_UNI(res)->type->gl_type;
1222 return 1;
1223 case GL_PROGRAM_INPUT:
1224 case GL_PROGRAM_OUTPUT:
1225 *val = RESOURCE_VAR(res)->type->gl_type;
1226 return 1;
1227 case GL_TRANSFORM_FEEDBACK_VARYING:
1228 *val = RESOURCE_XFB(res)->Type;
1229 return 1;
1230 default:
1231 goto invalid_operation;
1232 }
1233 case GL_ARRAY_SIZE:
1234 switch (res->Type) {
1235 case GL_UNIFORM:
1236 case GL_BUFFER_VARIABLE:
1237 *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1238 return 1;
1239 case GL_PROGRAM_INPUT:
1240 case GL_PROGRAM_OUTPUT:
1241 *val = MAX2(RESOURCE_VAR(res)->type->length, 1);
1242 return 1;
1243 case GL_TRANSFORM_FEEDBACK_VARYING:
1244 *val = MAX2(RESOURCE_XFB(res)->Size, 1);
1245 return 1;
1246 default:
1247 goto invalid_operation;
1248 }
1249 case GL_OFFSET:
1250 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1251 *val = RESOURCE_UNI(res)->offset;
1252 return 1;
1253 case GL_BLOCK_INDEX:
1254 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1255 *val = RESOURCE_UNI(res)->block_index;
1256 return 1;
1257 case GL_ARRAY_STRIDE:
1258 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1259 *val = RESOURCE_UNI(res)->array_stride;
1260 return 1;
1261 case GL_MATRIX_STRIDE:
1262 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1263 *val = RESOURCE_UNI(res)->matrix_stride;
1264 return 1;
1265 case GL_IS_ROW_MAJOR:
1266 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1267 *val = RESOURCE_UNI(res)->row_major;
1268 return 1;
1269 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1270 VALIDATE_TYPE(GL_UNIFORM);
1271 *val = RESOURCE_UNI(res)->atomic_buffer_index;
1272 return 1;
1273 case GL_BUFFER_BINDING:
1274 case GL_BUFFER_DATA_SIZE:
1275 case GL_NUM_ACTIVE_VARIABLES:
1276 case GL_ACTIVE_VARIABLES:
1277 return get_buffer_property(shProg, res, prop, val, caller);
1278 case GL_REFERENCED_BY_COMPUTE_SHADER:
1279 if (!_mesa_has_compute_shaders(ctx))
1280 goto invalid_enum;
1281 /* fallthrough */
1282 case GL_REFERENCED_BY_VERTEX_SHADER:
1283 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1284 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1285 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1286 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1287 switch (res->Type) {
1288 case GL_UNIFORM:
1289 case GL_PROGRAM_INPUT:
1290 case GL_PROGRAM_OUTPUT:
1291 case GL_UNIFORM_BLOCK:
1292 case GL_BUFFER_VARIABLE:
1293 case GL_SHADER_STORAGE_BLOCK:
1294 case GL_ATOMIC_COUNTER_BUFFER:
1295 *val = is_resource_referenced(shProg, res, index,
1296 stage_from_enum(prop));
1297 return 1;
1298 default:
1299 goto invalid_operation;
1300 }
1301 case GL_LOCATION:
1302 switch (res->Type) {
1303 case GL_UNIFORM:
1304 case GL_PROGRAM_INPUT:
1305 case GL_PROGRAM_OUTPUT:
1306 *val = program_resource_location(shProg, res,
1307 _mesa_program_resource_name(res),
1308 0);
1309 return 1;
1310 default:
1311 goto invalid_operation;
1312 }
1313 case GL_LOCATION_INDEX:
1314 if (res->Type != GL_PROGRAM_OUTPUT)
1315 goto invalid_operation;
1316 *val = RESOURCE_VAR(res)->data.index;
1317 return 1;
1318
1319 case GL_NUM_COMPATIBLE_SUBROUTINES:
1320 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1321 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1322 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1323 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1324 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1325 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1326 goto invalid_operation;
1327 *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1328 return 1;
1329 case GL_COMPATIBLE_SUBROUTINES: {
1330 const struct gl_uniform_storage *uni;
1331 struct gl_shader *sh;
1332 unsigned count, i;
1333 int j;
1334
1335 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1336 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1337 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1338 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1339 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1340 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1341 goto invalid_operation;
1342 uni = RESOURCE_UNI(res);
1343
1344 sh = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)];
1345 count = 0;
1346 for (i = 0; i < sh->NumSubroutineFunctions; i++) {
1347 struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i];
1348 for (j = 0; j < fn->num_compat_types; j++) {
1349 if (fn->types[j] == uni->type) {
1350 val[count++] = i;
1351 break;
1352 }
1353 }
1354 }
1355 return count;
1356 }
1357
1358 case GL_TOP_LEVEL_ARRAY_SIZE:
1359 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1360 *val = program_resource_top_level_array_size(shProg, res,
1361 _mesa_program_resource_name(res));
1362 return 1;
1363
1364 case GL_TOP_LEVEL_ARRAY_STRIDE:
1365 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1366 *val = program_resource_top_level_array_stride(shProg, res,
1367 _mesa_program_resource_name(res));
1368 return 1;
1369
1370 /* GL_ARB_tessellation_shader */
1371 case GL_IS_PER_PATCH:
1372 switch (res->Type) {
1373 case GL_PROGRAM_INPUT:
1374 case GL_PROGRAM_OUTPUT:
1375 *val = RESOURCE_VAR(res)->data.patch;
1376 return 1;
1377 default:
1378 goto invalid_operation;
1379 }
1380 default:
1381 goto invalid_enum;
1382 }
1383
1384 #undef VALIDATE_TYPE
1385 #undef VALIDATE_TYPE_2
1386
1387 invalid_enum:
1388 _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1389 _mesa_enum_to_string(res->Type),
1390 _mesa_enum_to_string(prop));
1391 return 0;
1392
1393 invalid_operation:
1394 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1395 _mesa_enum_to_string(res->Type),
1396 _mesa_enum_to_string(prop));
1397 return 0;
1398 }
1399
1400 extern void
1401 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1402 GLenum programInterface, GLuint index, GLsizei propCount,
1403 const GLenum *props, GLsizei bufSize,
1404 GLsizei *length, GLint *params)
1405 {
1406 GET_CURRENT_CONTEXT(ctx);
1407 GLint *val = (GLint *) params;
1408 const GLenum *prop = props;
1409 GLsizei amount = 0;
1410
1411 struct gl_program_resource *res =
1412 _mesa_program_resource_find_index(shProg, programInterface, index);
1413
1414 /* No such resource found or bufSize negative. */
1415 if (!res || bufSize < 0) {
1416 _mesa_error(ctx, GL_INVALID_VALUE,
1417 "glGetProgramResourceiv(%s index %d bufSize %d)",
1418 _mesa_enum_to_string(programInterface), index, bufSize);
1419 return;
1420 }
1421
1422 /* Write propCount values until error occurs or bufSize reached. */
1423 for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1424 int props_written =
1425 _mesa_program_resource_prop(shProg, res, index, *prop, val,
1426 "glGetProgramResourceiv");
1427
1428 /* Error happened. */
1429 if (props_written == 0)
1430 return;
1431
1432 amount += props_written;
1433 }
1434
1435 /* If <length> is not NULL, the actual number of integer values
1436 * written to <params> will be written to <length>.
1437 */
1438 if (length)
1439 *length = amount;
1440 }