mesa: add bind_attrib_location() helper
[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 "main/enums.h"
34 #include "main/shaderapi.h"
35 #include "main/shaderobj.h"
36 #include "main/uniforms.h"
37 #include "compiler/glsl/glsl_symbol_table.h"
38 #include "compiler/glsl/ir.h"
39 #include "compiler/glsl/program.h"
40 #include "util/string_to_uint_map.h"
41
42
43 static GLint
44 program_resource_location(struct gl_program_resource *res,
45 unsigned array_index);
46
47 /**
48 * Declare convenience functions to return resource data in a given type.
49 * Warning! this is not type safe so be *very* careful when using these.
50 */
51 #define DECL_RESOURCE_FUNC(name, type) \
52 const type * RESOURCE_ ## name (gl_program_resource *res) { \
53 assert(res->Data); \
54 return (type *) res->Data; \
55 }
56
57 DECL_RESOURCE_FUNC(VAR, gl_shader_variable);
58 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
59 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
60 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
61 DECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info);
62 DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer);
63 DECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
64
65 static void
66 bind_attrib_location(struct gl_context *ctx,
67 struct gl_shader_program *const shProg, GLuint index,
68 const GLchar *name, bool no_error)
69 {
70 if (!name)
71 return;
72
73 if (!no_error) {
74 if (strncmp(name, "gl_", 3) == 0) {
75 _mesa_error(ctx, GL_INVALID_OPERATION,
76 "glBindAttribLocation(illegal name)");
77 return;
78 }
79
80 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
81 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
82 index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
83 return;
84 }
85 }
86
87 /* Replace the current value if it's already in the list. Add
88 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
89 * between built-in attributes and user-defined attributes.
90 */
91 shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
92
93 /*
94 * Note that this attribute binding won't go into effect until
95 * glLinkProgram is called again.
96 */
97 }
98
99 void GLAPIENTRY
100 _mesa_BindAttribLocation(GLuint program, GLuint index,
101 const GLchar *name)
102 {
103 GET_CURRENT_CONTEXT(ctx);
104
105 struct gl_shader_program *const shProg =
106 _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
107 if (!shProg)
108 return;
109
110 bind_attrib_location(ctx, shProg, index, name, false);
111 }
112
113 void GLAPIENTRY
114 _mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
115 GLsizei maxLength, GLsizei * length, GLint * size,
116 GLenum * type, GLchar * name)
117 {
118 GET_CURRENT_CONTEXT(ctx);
119 struct gl_shader_program *shProg;
120
121 if (maxLength < 0) {
122 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
123 return;
124 }
125
126 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
127 if (!shProg)
128 return;
129
130 if (!shProg->data->LinkStatus) {
131 _mesa_error(ctx, GL_INVALID_VALUE,
132 "glGetActiveAttrib(program not linked)");
133 return;
134 }
135
136 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
137 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
138 return;
139 }
140
141 struct gl_program_resource *res =
142 _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
143 desired_index);
144
145 /* User asked for index that does not exist. */
146 if (!res) {
147 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
148 return;
149 }
150
151 const gl_shader_variable *const var = RESOURCE_VAR(res);
152
153 const char *var_name = var->name;
154
155 _mesa_copy_string(name, maxLength, length, var_name);
156
157 if (size)
158 _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
159 size, "glGetActiveAttrib");
160
161 if (type)
162 _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
163 (GLint *) type, "glGetActiveAttrib");
164 }
165
166 GLint GLAPIENTRY
167 _mesa_GetAttribLocation(GLuint program, const GLchar * name)
168 {
169 GET_CURRENT_CONTEXT(ctx);
170 struct gl_shader_program *const shProg =
171 _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
172
173 if (!shProg) {
174 return -1;
175 }
176
177 if (!shProg->data->LinkStatus) {
178 _mesa_error(ctx, GL_INVALID_OPERATION,
179 "glGetAttribLocation(program not linked)");
180 return -1;
181 }
182
183 if (!name)
184 return -1;
185
186 /* Not having a vertex shader is not an error.
187 */
188 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
189 return -1;
190
191 unsigned array_index = 0;
192 struct gl_program_resource *res =
193 _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
194 &array_index);
195
196 if (!res)
197 return -1;
198
199 return program_resource_location(res, array_index);
200 }
201
202 unsigned
203 _mesa_count_active_attribs(struct gl_shader_program *shProg)
204 {
205 if (!shProg->data->LinkStatus
206 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
207 return 0;
208 }
209
210 struct gl_program_resource *res = shProg->data->ProgramResourceList;
211 unsigned count = 0;
212 for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
213 j++, res++) {
214 if (res->Type == GL_PROGRAM_INPUT &&
215 res->StageReferences & (1 << MESA_SHADER_VERTEX))
216 count++;
217 }
218 return count;
219 }
220
221
222 size_t
223 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
224 {
225 if (!shProg->data->LinkStatus
226 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
227 return 0;
228 }
229
230 struct gl_program_resource *res = shProg->data->ProgramResourceList;
231 size_t longest = 0;
232 for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
233 j++, res++) {
234 if (res->Type == GL_PROGRAM_INPUT &&
235 res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
236
237 const size_t length = strlen(RESOURCE_VAR(res)->name);
238 if (length >= longest)
239 longest = length + 1;
240 }
241 }
242
243 return longest;
244 }
245
246 void GLAPIENTRY
247 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
248 const GLchar *name)
249 {
250 _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
251 }
252
253 void GLAPIENTRY
254 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
255 GLuint index, const GLchar *name)
256 {
257 GET_CURRENT_CONTEXT(ctx);
258
259 struct gl_shader_program *const shProg =
260 _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
261 if (!shProg)
262 return;
263
264 if (!name)
265 return;
266
267 if (strncmp(name, "gl_", 3) == 0) {
268 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
269 return;
270 }
271
272 if (index > 1) {
273 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
274 return;
275 }
276
277 if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
278 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
279 return;
280 }
281
282 if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
283 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
284 return;
285 }
286
287 /* Replace the current value if it's already in the list. Add
288 * FRAG_RESULT_DATA0 because that's how the linker differentiates
289 * between built-in attributes and user-defined attributes.
290 */
291 shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
292 shProg->FragDataIndexBindings->put(index, name);
293 /*
294 * Note that this binding won't go into effect until
295 * glLinkProgram is called again.
296 */
297
298 }
299
300 GLint GLAPIENTRY
301 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
302 {
303 GET_CURRENT_CONTEXT(ctx);
304 struct gl_shader_program *const shProg =
305 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
306
307 if (!shProg) {
308 return -1;
309 }
310
311 if (!shProg->data->LinkStatus) {
312 _mesa_error(ctx, GL_INVALID_OPERATION,
313 "glGetFragDataIndex(program not linked)");
314 return -1;
315 }
316
317 if (!name)
318 return -1;
319
320 if (strncmp(name, "gl_", 3) == 0) {
321 _mesa_error(ctx, GL_INVALID_OPERATION,
322 "glGetFragDataIndex(illegal name)");
323 return -1;
324 }
325
326 /* Not having a fragment shader is not an error.
327 */
328 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
329 return -1;
330
331 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
332 name);
333 }
334
335 GLint GLAPIENTRY
336 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
337 {
338 GET_CURRENT_CONTEXT(ctx);
339 struct gl_shader_program *const shProg =
340 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
341
342 if (!shProg) {
343 return -1;
344 }
345
346 if (!shProg->data->LinkStatus) {
347 _mesa_error(ctx, GL_INVALID_OPERATION,
348 "glGetFragDataLocation(program not linked)");
349 return -1;
350 }
351
352 if (!name)
353 return -1;
354
355 if (strncmp(name, "gl_", 3) == 0) {
356 _mesa_error(ctx, GL_INVALID_OPERATION,
357 "glGetFragDataLocation(illegal name)");
358 return -1;
359 }
360
361 /* Not having a fragment shader is not an error.
362 */
363 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
364 return -1;
365
366 unsigned array_index = 0;
367 struct gl_program_resource *res =
368 _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
369 &array_index);
370
371 if (!res)
372 return -1;
373
374 return program_resource_location(res, array_index);
375 }
376
377 const char*
378 _mesa_program_resource_name(struct gl_program_resource *res)
379 {
380 switch (res->Type) {
381 case GL_UNIFORM_BLOCK:
382 case GL_SHADER_STORAGE_BLOCK:
383 return RESOURCE_UBO(res)->Name;
384 case GL_TRANSFORM_FEEDBACK_VARYING:
385 return RESOURCE_XFV(res)->Name;
386 case GL_PROGRAM_INPUT:
387 case GL_PROGRAM_OUTPUT:
388 return RESOURCE_VAR(res)->name;
389 case GL_UNIFORM:
390 case GL_BUFFER_VARIABLE:
391 return RESOURCE_UNI(res)->name;
392 case GL_VERTEX_SUBROUTINE_UNIFORM:
393 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
394 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
395 case GL_COMPUTE_SUBROUTINE_UNIFORM:
396 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
397 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
398 return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
399 case GL_VERTEX_SUBROUTINE:
400 case GL_GEOMETRY_SUBROUTINE:
401 case GL_FRAGMENT_SUBROUTINE:
402 case GL_COMPUTE_SUBROUTINE:
403 case GL_TESS_CONTROL_SUBROUTINE:
404 case GL_TESS_EVALUATION_SUBROUTINE:
405 return RESOURCE_SUB(res)->name;
406 default:
407 assert(!"support for resource type not implemented");
408 }
409 return NULL;
410 }
411
412
413 unsigned
414 _mesa_program_resource_array_size(struct gl_program_resource *res)
415 {
416 switch (res->Type) {
417 case GL_TRANSFORM_FEEDBACK_VARYING:
418 return RESOURCE_XFV(res)->Size > 1 ?
419 RESOURCE_XFV(res)->Size : 0;
420 case GL_PROGRAM_INPUT:
421 case GL_PROGRAM_OUTPUT:
422 return RESOURCE_VAR(res)->type->length;
423 case GL_UNIFORM:
424 case GL_VERTEX_SUBROUTINE_UNIFORM:
425 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
426 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
427 case GL_COMPUTE_SUBROUTINE_UNIFORM:
428 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
429 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
430 return RESOURCE_UNI(res)->array_elements;
431 case GL_BUFFER_VARIABLE:
432 /* Unsized arrays */
433 if (RESOURCE_UNI(res)->array_stride > 0 &&
434 RESOURCE_UNI(res)->array_elements == 0)
435 return 1;
436 else
437 return RESOURCE_UNI(res)->array_elements;
438 case GL_VERTEX_SUBROUTINE:
439 case GL_GEOMETRY_SUBROUTINE:
440 case GL_FRAGMENT_SUBROUTINE:
441 case GL_COMPUTE_SUBROUTINE:
442 case GL_TESS_CONTROL_SUBROUTINE:
443 case GL_TESS_EVALUATION_SUBROUTINE:
444 case GL_ATOMIC_COUNTER_BUFFER:
445 case GL_UNIFORM_BLOCK:
446 case GL_SHADER_STORAGE_BLOCK:
447 return 0;
448 default:
449 assert(!"support for resource type not implemented");
450 }
451 return 0;
452 }
453
454 /**
455 * Checks if array subscript is valid and if so sets array_index.
456 */
457 static bool
458 valid_array_index(const GLchar *name, unsigned *array_index)
459 {
460 long idx = 0;
461 const GLchar *out_base_name_end;
462
463 idx = parse_program_resource_name(name, &out_base_name_end);
464 if (idx < 0)
465 return false;
466
467 if (array_index)
468 *array_index = idx;
469
470 return true;
471 }
472
473 /* Find a program resource with specific name in given interface.
474 */
475 struct gl_program_resource *
476 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
477 GLenum programInterface, const char *name,
478 unsigned *array_index)
479 {
480 struct gl_program_resource *res = shProg->data->ProgramResourceList;
481 for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
482 i++, res++) {
483 if (res->Type != programInterface)
484 continue;
485
486 /* Resource basename. */
487 const char *rname = _mesa_program_resource_name(res);
488 unsigned baselen = strlen(rname);
489 unsigned baselen_without_array_index = baselen;
490 const char *rname_last_square_bracket = strrchr(rname, '[');
491 bool found = false;
492 bool rname_has_array_index_zero = false;
493 /* From ARB_program_interface_query spec:
494 *
495 * "uint GetProgramResourceIndex(uint program, enum programInterface,
496 * const char *name);
497 * [...]
498 * If <name> exactly matches the name string of one of the active
499 * resources for <programInterface>, the index of the matched resource is
500 * returned. Additionally, if <name> would exactly match the name string
501 * of an active resource if "[0]" were appended to <name>, the index of
502 * the matched resource is returned. [...]"
503 *
504 * "A string provided to GetProgramResourceLocation or
505 * GetProgramResourceLocationIndex is considered to match an active variable
506 * if:
507 *
508 * * the string exactly matches the name of the active variable;
509 *
510 * * if the string identifies the base name of an active array, where the
511 * string would exactly match the name of the variable if the suffix
512 * "[0]" were appended to the string; [...]"
513 */
514 /* Remove array's index from interface block name comparison only if
515 * array's index is zero and the resulting string length is the same
516 * than the provided name's length.
517 */
518 if (rname_last_square_bracket) {
519 baselen_without_array_index -= strlen(rname_last_square_bracket);
520 rname_has_array_index_zero =
521 (strcmp(rname_last_square_bracket, "[0]") == 0) &&
522 (baselen_without_array_index == strlen(name));
523 }
524
525 if (strncmp(rname, name, baselen) == 0)
526 found = true;
527 else if (rname_has_array_index_zero &&
528 strncmp(rname, name, baselen_without_array_index) == 0)
529 found = true;
530
531 if (found) {
532 switch (programInterface) {
533 case GL_UNIFORM_BLOCK:
534 case GL_SHADER_STORAGE_BLOCK:
535 /* Basename match, check if array or struct. */
536 if (rname_has_array_index_zero ||
537 name[baselen] == '\0' ||
538 name[baselen] == '[' ||
539 name[baselen] == '.') {
540 return res;
541 }
542 break;
543 case GL_TRANSFORM_FEEDBACK_VARYING:
544 case GL_BUFFER_VARIABLE:
545 case GL_UNIFORM:
546 case GL_VERTEX_SUBROUTINE_UNIFORM:
547 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
548 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
549 case GL_COMPUTE_SUBROUTINE_UNIFORM:
550 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
551 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
552 case GL_VERTEX_SUBROUTINE:
553 case GL_GEOMETRY_SUBROUTINE:
554 case GL_FRAGMENT_SUBROUTINE:
555 case GL_COMPUTE_SUBROUTINE:
556 case GL_TESS_CONTROL_SUBROUTINE:
557 case GL_TESS_EVALUATION_SUBROUTINE:
558 if (name[baselen] == '.') {
559 return res;
560 }
561 /* fall-through */
562 case GL_PROGRAM_INPUT:
563 case GL_PROGRAM_OUTPUT:
564 if (name[baselen] == '\0') {
565 return res;
566 } else if (name[baselen] == '[' &&
567 valid_array_index(name, array_index)) {
568 return res;
569 }
570 break;
571 default:
572 assert(!"not implemented for given interface");
573 }
574 }
575 }
576 return NULL;
577 }
578
579 static GLuint
580 calc_resource_index(struct gl_shader_program *shProg,
581 struct gl_program_resource *res)
582 {
583 unsigned i;
584 GLuint index = 0;
585 for (i = 0; i < shProg->data->NumProgramResourceList; i++) {
586 if (&shProg->data->ProgramResourceList[i] == res)
587 return index;
588 if (shProg->data->ProgramResourceList[i].Type == res->Type)
589 index++;
590 }
591 return GL_INVALID_INDEX;
592 }
593
594 /**
595 * Calculate index for the given resource.
596 */
597 GLuint
598 _mesa_program_resource_index(struct gl_shader_program *shProg,
599 struct gl_program_resource *res)
600 {
601 if (!res)
602 return GL_INVALID_INDEX;
603
604 switch (res->Type) {
605 case GL_ATOMIC_COUNTER_BUFFER:
606 return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
607 case GL_VERTEX_SUBROUTINE:
608 case GL_GEOMETRY_SUBROUTINE:
609 case GL_FRAGMENT_SUBROUTINE:
610 case GL_COMPUTE_SUBROUTINE:
611 case GL_TESS_CONTROL_SUBROUTINE:
612 case GL_TESS_EVALUATION_SUBROUTINE:
613 return RESOURCE_SUB(res)->index;
614 case GL_UNIFORM_BLOCK:
615 case GL_SHADER_STORAGE_BLOCK:
616 case GL_TRANSFORM_FEEDBACK_BUFFER:
617 case GL_TRANSFORM_FEEDBACK_VARYING:
618 default:
619 return calc_resource_index(shProg, res);
620 }
621 }
622
623 /**
624 * Find a program resource that points to given data.
625 */
626 static struct gl_program_resource*
627 program_resource_find_data(struct gl_shader_program *shProg, void *data)
628 {
629 struct gl_program_resource *res = shProg->data->ProgramResourceList;
630 for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
631 i++, res++) {
632 if (res->Data == data)
633 return res;
634 }
635 return NULL;
636 }
637
638 /* Find a program resource with specific index in given interface.
639 */
640 struct gl_program_resource *
641 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
642 GLenum programInterface, GLuint index)
643 {
644 struct gl_program_resource *res = shProg->data->ProgramResourceList;
645 int idx = -1;
646
647 for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
648 i++, res++) {
649 if (res->Type != programInterface)
650 continue;
651
652 switch (res->Type) {
653 case GL_UNIFORM_BLOCK:
654 case GL_ATOMIC_COUNTER_BUFFER:
655 case GL_SHADER_STORAGE_BLOCK:
656 case GL_TRANSFORM_FEEDBACK_BUFFER:
657 if (_mesa_program_resource_index(shProg, res) == index)
658 return res;
659 break;
660 case GL_TRANSFORM_FEEDBACK_VARYING:
661 case GL_PROGRAM_INPUT:
662 case GL_PROGRAM_OUTPUT:
663 case GL_UNIFORM:
664 case GL_VERTEX_SUBROUTINE_UNIFORM:
665 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
666 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
667 case GL_COMPUTE_SUBROUTINE_UNIFORM:
668 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
669 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
670 case GL_VERTEX_SUBROUTINE:
671 case GL_GEOMETRY_SUBROUTINE:
672 case GL_FRAGMENT_SUBROUTINE:
673 case GL_COMPUTE_SUBROUTINE:
674 case GL_TESS_CONTROL_SUBROUTINE:
675 case GL_TESS_EVALUATION_SUBROUTINE:
676 case GL_BUFFER_VARIABLE:
677 if (++idx == (int) index)
678 return res;
679 break;
680 default:
681 assert(!"not implemented for given interface");
682 }
683 }
684 return NULL;
685 }
686
687 /* Function returns if resource name is expected to have index
688 * appended into it.
689 *
690 *
691 * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
692 * spec says:
693 *
694 * "If the active uniform is an array, the uniform name returned in
695 * name will always be the name of the uniform array appended with
696 * "[0]"."
697 *
698 * The same text also appears in the OpenGL 4.2 spec. It does not,
699 * however, appear in any previous spec. Previous specifications are
700 * ambiguous in this regard. However, either name can later be passed
701 * to glGetUniformLocation (and related APIs), so there shouldn't be any
702 * harm in always appending "[0]" to uniform array names.
703 */
704 static bool
705 add_index_to_name(struct gl_program_resource *res)
706 {
707 /* Transform feedback varyings have array index already appended
708 * in their names.
709 */
710 return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
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_program_resource *res, unsigned array_index)
777 {
778 switch (res->Type) {
779 case GL_PROGRAM_INPUT: {
780 const gl_shader_variable *var = RESOURCE_VAR(res);
781
782 if (var->location == -1)
783 return -1;
784
785 /* If the input is an array, fail if the index is out of bounds. */
786 if (array_index > 0
787 && array_index >= var->type->length) {
788 return -1;
789 }
790 return var->location +
791 (array_index * var->type->without_array()->matrix_columns);
792 }
793 case GL_PROGRAM_OUTPUT:
794 if (RESOURCE_VAR(res)->location == -1)
795 return -1;
796
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)->location + array_index;
803 case GL_UNIFORM:
804 /* If the uniform is built-in, fail. */
805 if (RESOURCE_UNI(res)->builtin)
806 return -1;
807
808 /* From page 79 of the OpenGL 4.2 spec:
809 *
810 * "A valid name cannot be a structure, an array of structures, or any
811 * portion of a single vector or a matrix."
812 */
813 if (RESOURCE_UNI(res)->type->without_array()->is_record())
814 return -1;
815
816 /* From the GL_ARB_uniform_buffer_object spec:
817 *
818 * "The value -1 will be returned if <name> does not correspond to an
819 * active uniform variable name in <program>, if <name> is associated
820 * with a named uniform block, or if <name> starts with the reserved
821 * prefix "gl_"."
822 */
823 if (RESOURCE_UNI(res)->block_index != -1 ||
824 RESOURCE_UNI(res)->atomic_buffer_index != -1)
825 return -1;
826
827 /* fallthrough */
828 case GL_VERTEX_SUBROUTINE_UNIFORM:
829 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
830 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
831 case GL_COMPUTE_SUBROUTINE_UNIFORM:
832 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
833 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
834 /* If the uniform is an array, fail if the index is out of bounds. */
835 if (array_index > 0
836 && array_index >= RESOURCE_UNI(res)->array_elements) {
837 return -1;
838 }
839
840 /* location in remap table + array element offset */
841 return RESOURCE_UNI(res)->remap_location + array_index;
842 default:
843 return -1;
844 }
845 }
846
847 /**
848 * Function implements following location queries:
849 * glGetUniformLocation
850 */
851 GLint
852 _mesa_program_resource_location(struct gl_shader_program *shProg,
853 GLenum programInterface, const char *name)
854 {
855 unsigned array_index = 0;
856 struct gl_program_resource *res =
857 _mesa_program_resource_find_name(shProg, programInterface, name,
858 &array_index);
859
860 /* Resource not found. */
861 if (!res)
862 return -1;
863
864 return program_resource_location(res, array_index);
865 }
866
867 /**
868 * Function implements following index queries:
869 * glGetFragDataIndex
870 */
871 GLint
872 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
873 GLenum programInterface, const char *name)
874 {
875 struct gl_program_resource *res =
876 _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
877
878 /* Non-existent variable or resource is not referenced by fragment stage. */
879 if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
880 return -1;
881
882 /* From OpenGL 4.5 spec, 7.3 Program Objects
883 * "The value -1 will be returned by either command...
884 * ... or if name identifies an active variable that does not have a
885 * valid location assigned.
886 */
887 if (RESOURCE_VAR(res)->location == -1)
888 return -1;
889 return RESOURCE_VAR(res)->index;
890 }
891
892 static uint8_t
893 stage_from_enum(GLenum ref)
894 {
895 switch (ref) {
896 case GL_REFERENCED_BY_VERTEX_SHADER:
897 return MESA_SHADER_VERTEX;
898 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
899 return MESA_SHADER_TESS_CTRL;
900 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
901 return MESA_SHADER_TESS_EVAL;
902 case GL_REFERENCED_BY_GEOMETRY_SHADER:
903 return MESA_SHADER_GEOMETRY;
904 case GL_REFERENCED_BY_FRAGMENT_SHADER:
905 return MESA_SHADER_FRAGMENT;
906 case GL_REFERENCED_BY_COMPUTE_SHADER:
907 return MESA_SHADER_COMPUTE;
908 default:
909 assert(!"shader stage not supported");
910 return MESA_SHADER_STAGES;
911 }
912 }
913
914 /**
915 * Check if resource is referenced by given 'referenced by' stage enum.
916 * ATC and UBO resources hold stage references of their own.
917 */
918 static bool
919 is_resource_referenced(struct gl_shader_program *shProg,
920 struct gl_program_resource *res,
921 GLuint index, uint8_t stage)
922 {
923 /* First, check if we even have such a stage active. */
924 if (!shProg->_LinkedShaders[stage])
925 return false;
926
927 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
928 return RESOURCE_ATC(res)->StageReferences[stage];
929
930 if (res->Type == GL_UNIFORM_BLOCK)
931 return shProg->data->UniformBlocks[index].stageref & (1 << stage);
932
933 if (res->Type == GL_SHADER_STORAGE_BLOCK)
934 return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
935
936 return res->StageReferences & (1 << stage);
937 }
938
939 static unsigned
940 get_buffer_property(struct gl_shader_program *shProg,
941 struct gl_program_resource *res, const GLenum prop,
942 GLint *val, const char *caller)
943 {
944 GET_CURRENT_CONTEXT(ctx);
945 if (res->Type != GL_UNIFORM_BLOCK &&
946 res->Type != GL_ATOMIC_COUNTER_BUFFER &&
947 res->Type != GL_SHADER_STORAGE_BLOCK &&
948 res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
949 goto invalid_operation;
950
951 if (res->Type == GL_UNIFORM_BLOCK) {
952 switch (prop) {
953 case GL_BUFFER_BINDING:
954 *val = RESOURCE_UBO(res)->Binding;
955 return 1;
956 case GL_BUFFER_DATA_SIZE:
957 *val = RESOURCE_UBO(res)->UniformBufferSize;
958 return 1;
959 case GL_NUM_ACTIVE_VARIABLES:
960 *val = 0;
961 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
962 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
963 struct gl_program_resource *uni =
964 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
965 NULL);
966 if (!uni)
967 continue;
968 (*val)++;
969 }
970 return 1;
971 case GL_ACTIVE_VARIABLES: {
972 unsigned num_values = 0;
973 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
974 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
975 struct gl_program_resource *uni =
976 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
977 NULL);
978 if (!uni)
979 continue;
980 *val++ =
981 _mesa_program_resource_index(shProg, uni);
982 num_values++;
983 }
984 return num_values;
985 }
986 }
987 } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
988 switch (prop) {
989 case GL_BUFFER_BINDING:
990 *val = RESOURCE_UBO(res)->Binding;
991 return 1;
992 case GL_BUFFER_DATA_SIZE:
993 *val = RESOURCE_UBO(res)->UniformBufferSize;
994 return 1;
995 case GL_NUM_ACTIVE_VARIABLES:
996 *val = 0;
997 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
998 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
999 struct gl_program_resource *uni =
1000 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1001 iname, NULL);
1002 if (!uni)
1003 continue;
1004 (*val)++;
1005 }
1006 return 1;
1007 case GL_ACTIVE_VARIABLES: {
1008 unsigned num_values = 0;
1009 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1010 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1011 struct gl_program_resource *uni =
1012 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1013 iname, NULL);
1014 if (!uni)
1015 continue;
1016 *val++ =
1017 _mesa_program_resource_index(shProg, uni);
1018 num_values++;
1019 }
1020 return num_values;
1021 }
1022 }
1023 } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1024 switch (prop) {
1025 case GL_BUFFER_BINDING:
1026 *val = RESOURCE_ATC(res)->Binding;
1027 return 1;
1028 case GL_BUFFER_DATA_SIZE:
1029 *val = RESOURCE_ATC(res)->MinimumSize;
1030 return 1;
1031 case GL_NUM_ACTIVE_VARIABLES:
1032 *val = RESOURCE_ATC(res)->NumUniforms;
1033 return 1;
1034 case GL_ACTIVE_VARIABLES:
1035 for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
1036 /* Active atomic buffer contains index to UniformStorage. Find
1037 * out gl_program_resource via data pointer and then calculate
1038 * index of that uniform.
1039 */
1040 unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
1041 struct gl_program_resource *uni =
1042 program_resource_find_data(shProg,
1043 &shProg->data->UniformStorage[idx]);
1044 assert(uni);
1045 *val++ = _mesa_program_resource_index(shProg, uni);
1046 }
1047 return RESOURCE_ATC(res)->NumUniforms;
1048 }
1049 } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
1050 switch (prop) {
1051 case GL_BUFFER_BINDING:
1052 *val = RESOURCE_XFB(res)->Binding;
1053 return 1;
1054 case GL_NUM_ACTIVE_VARIABLES:
1055 *val = RESOURCE_XFB(res)->NumVaryings;
1056 return 1;
1057 case GL_ACTIVE_VARIABLES:
1058 struct gl_transform_feedback_info *linked_xfb =
1059 shProg->last_vert_prog->sh.LinkedTransformFeedback;
1060 for (int i = 0; i < linked_xfb->NumVarying; i++) {
1061 unsigned index = linked_xfb->Varyings[i].BufferIndex;
1062 struct gl_program_resource *buf_res =
1063 _mesa_program_resource_find_index(shProg,
1064 GL_TRANSFORM_FEEDBACK_BUFFER,
1065 index);
1066 assert(buf_res);
1067 if (res == buf_res) {
1068 *val++ = i;
1069 }
1070 }
1071 return RESOURCE_XFB(res)->NumVaryings;
1072 }
1073 }
1074 assert(!"support for property type not implemented");
1075
1076 invalid_operation:
1077 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1078 _mesa_enum_to_string(res->Type),
1079 _mesa_enum_to_string(prop));
1080
1081 return 0;
1082 }
1083
1084 unsigned
1085 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1086 struct gl_program_resource *res, GLuint index,
1087 const GLenum prop, GLint *val, const char *caller)
1088 {
1089 GET_CURRENT_CONTEXT(ctx);
1090
1091 #define VALIDATE_TYPE(type)\
1092 if (res->Type != type)\
1093 goto invalid_operation;
1094
1095 #define VALIDATE_TYPE_2(type1, type2)\
1096 if (res->Type != type1 && res->Type != type2)\
1097 goto invalid_operation;
1098
1099 switch(prop) {
1100 case GL_NAME_LENGTH:
1101 switch (res->Type) {
1102 case GL_ATOMIC_COUNTER_BUFFER:
1103 case GL_TRANSFORM_FEEDBACK_BUFFER:
1104 goto invalid_operation;
1105 default:
1106 /* Resource name length + terminator. */
1107 *val = _mesa_program_resource_name_len(res) + 1;
1108 }
1109 return 1;
1110 case GL_TYPE:
1111 switch (res->Type) {
1112 case GL_UNIFORM:
1113 case GL_BUFFER_VARIABLE:
1114 *val = RESOURCE_UNI(res)->type->gl_type;
1115 return 1;
1116 case GL_PROGRAM_INPUT:
1117 case GL_PROGRAM_OUTPUT:
1118 *val = RESOURCE_VAR(res)->type->gl_type;
1119 return 1;
1120 case GL_TRANSFORM_FEEDBACK_VARYING:
1121 *val = RESOURCE_XFV(res)->Type;
1122 return 1;
1123 default:
1124 goto invalid_operation;
1125 }
1126 case GL_ARRAY_SIZE:
1127 switch (res->Type) {
1128 case GL_UNIFORM:
1129 case GL_BUFFER_VARIABLE:
1130 case GL_VERTEX_SUBROUTINE_UNIFORM:
1131 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1132 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1133 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1134 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1135 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1136
1137 /* Test if a buffer variable is an array or an unsized array.
1138 * Unsized arrays return zero as array size.
1139 */
1140 if (RESOURCE_UNI(res)->is_shader_storage &&
1141 RESOURCE_UNI(res)->array_stride > 0)
1142 *val = RESOURCE_UNI(res)->array_elements;
1143 else
1144 *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1145 return 1;
1146 case GL_PROGRAM_INPUT:
1147 case GL_PROGRAM_OUTPUT:
1148 *val = MAX2(_mesa_program_resource_array_size(res), 1);
1149 return 1;
1150 case GL_TRANSFORM_FEEDBACK_VARYING:
1151 *val = RESOURCE_XFV(res)->Size;
1152 return 1;
1153 default:
1154 goto invalid_operation;
1155 }
1156 case GL_OFFSET:
1157 switch (res->Type) {
1158 case GL_UNIFORM:
1159 case GL_BUFFER_VARIABLE:
1160 *val = RESOURCE_UNI(res)->offset;
1161 return 1;
1162 case GL_TRANSFORM_FEEDBACK_VARYING:
1163 *val = RESOURCE_XFV(res)->Offset;
1164 return 1;
1165 default:
1166 goto invalid_operation;
1167 }
1168 case GL_BLOCK_INDEX:
1169 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1170 *val = RESOURCE_UNI(res)->block_index;
1171 return 1;
1172 case GL_ARRAY_STRIDE:
1173 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1174 *val = RESOURCE_UNI(res)->array_stride;
1175 return 1;
1176 case GL_MATRIX_STRIDE:
1177 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1178 *val = RESOURCE_UNI(res)->matrix_stride;
1179 return 1;
1180 case GL_IS_ROW_MAJOR:
1181 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1182 *val = RESOURCE_UNI(res)->row_major;
1183 return 1;
1184 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1185 VALIDATE_TYPE(GL_UNIFORM);
1186 *val = RESOURCE_UNI(res)->atomic_buffer_index;
1187 return 1;
1188 case GL_BUFFER_BINDING:
1189 case GL_BUFFER_DATA_SIZE:
1190 case GL_NUM_ACTIVE_VARIABLES:
1191 case GL_ACTIVE_VARIABLES:
1192 return get_buffer_property(shProg, res, prop, val, caller);
1193 case GL_REFERENCED_BY_COMPUTE_SHADER:
1194 if (!_mesa_has_compute_shaders(ctx))
1195 goto invalid_enum;
1196 /* fallthrough */
1197 case GL_REFERENCED_BY_VERTEX_SHADER:
1198 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1199 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1200 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1201 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1202 switch (res->Type) {
1203 case GL_UNIFORM:
1204 case GL_PROGRAM_INPUT:
1205 case GL_PROGRAM_OUTPUT:
1206 case GL_UNIFORM_BLOCK:
1207 case GL_BUFFER_VARIABLE:
1208 case GL_SHADER_STORAGE_BLOCK:
1209 case GL_ATOMIC_COUNTER_BUFFER:
1210 *val = is_resource_referenced(shProg, res, index,
1211 stage_from_enum(prop));
1212 return 1;
1213 default:
1214 goto invalid_operation;
1215 }
1216 case GL_LOCATION:
1217 switch (res->Type) {
1218 case GL_UNIFORM:
1219 case GL_VERTEX_SUBROUTINE_UNIFORM:
1220 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1221 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1222 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1223 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1224 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1225 case GL_PROGRAM_INPUT:
1226 case GL_PROGRAM_OUTPUT:
1227 *val = program_resource_location(res, 0);
1228 return 1;
1229 default:
1230 goto invalid_operation;
1231 }
1232 case GL_LOCATION_COMPONENT:
1233 switch (res->Type) {
1234 case GL_PROGRAM_INPUT:
1235 case GL_PROGRAM_OUTPUT:
1236 *val = RESOURCE_VAR(res)->component;
1237 return 1;
1238 default:
1239 goto invalid_operation;
1240 }
1241 case GL_LOCATION_INDEX: {
1242 int tmp;
1243 if (res->Type != GL_PROGRAM_OUTPUT)
1244 goto invalid_operation;
1245 tmp = program_resource_location(res, 0);
1246 if (tmp == -1)
1247 *val = -1;
1248 else
1249 *val = _mesa_program_resource_location_index(shProg, res->Type,
1250 RESOURCE_VAR(res)->name);
1251 return 1;
1252 }
1253 case GL_NUM_COMPATIBLE_SUBROUTINES:
1254 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1255 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1256 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1257 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1258 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1259 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1260 goto invalid_operation;
1261 *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1262 return 1;
1263 case GL_COMPATIBLE_SUBROUTINES: {
1264 const struct gl_uniform_storage *uni;
1265 struct gl_program *p;
1266 unsigned count, i;
1267 int j;
1268
1269 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1270 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1271 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1272 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1273 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1274 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1275 goto invalid_operation;
1276 uni = RESOURCE_UNI(res);
1277
1278 p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
1279 count = 0;
1280 for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
1281 struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
1282 for (j = 0; j < fn->num_compat_types; j++) {
1283 if (fn->types[j] == uni->type) {
1284 val[count++] = i;
1285 break;
1286 }
1287 }
1288 }
1289 return count;
1290 }
1291
1292 case GL_TOP_LEVEL_ARRAY_SIZE:
1293 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1294 *val = RESOURCE_UNI(res)->top_level_array_size;
1295 return 1;
1296
1297 case GL_TOP_LEVEL_ARRAY_STRIDE:
1298 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1299 *val = RESOURCE_UNI(res)->top_level_array_stride;
1300 return 1;
1301
1302 /* GL_ARB_tessellation_shader */
1303 case GL_IS_PER_PATCH:
1304 switch (res->Type) {
1305 case GL_PROGRAM_INPUT:
1306 case GL_PROGRAM_OUTPUT:
1307 *val = RESOURCE_VAR(res)->patch;
1308 return 1;
1309 default:
1310 goto invalid_operation;
1311 }
1312
1313 case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
1314 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
1315 *val = RESOURCE_XFV(res)->BufferIndex;
1316 return 1;
1317 case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
1318 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
1319 *val = RESOURCE_XFB(res)->Stride * 4;
1320 return 1;
1321
1322 default:
1323 goto invalid_enum;
1324 }
1325
1326 #undef VALIDATE_TYPE
1327 #undef VALIDATE_TYPE_2
1328
1329 invalid_enum:
1330 _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1331 _mesa_enum_to_string(res->Type),
1332 _mesa_enum_to_string(prop));
1333 return 0;
1334
1335 invalid_operation:
1336 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1337 _mesa_enum_to_string(res->Type),
1338 _mesa_enum_to_string(prop));
1339 return 0;
1340 }
1341
1342 extern void
1343 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1344 GLenum programInterface, GLuint index, GLsizei propCount,
1345 const GLenum *props, GLsizei bufSize,
1346 GLsizei *length, GLint *params)
1347 {
1348 GET_CURRENT_CONTEXT(ctx);
1349 GLint *val = (GLint *) params;
1350 const GLenum *prop = props;
1351 GLsizei amount = 0;
1352
1353 struct gl_program_resource *res =
1354 _mesa_program_resource_find_index(shProg, programInterface, index);
1355
1356 /* No such resource found or bufSize negative. */
1357 if (!res || bufSize < 0) {
1358 _mesa_error(ctx, GL_INVALID_VALUE,
1359 "glGetProgramResourceiv(%s index %d bufSize %d)",
1360 _mesa_enum_to_string(programInterface), index, bufSize);
1361 return;
1362 }
1363
1364 /* Write propCount values until error occurs or bufSize reached. */
1365 for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1366 int props_written =
1367 _mesa_program_resource_prop(shProg, res, index, *prop, val,
1368 "glGetProgramResourceiv");
1369
1370 /* Error happened. */
1371 if (props_written == 0)
1372 return;
1373
1374 amount += props_written;
1375 }
1376
1377 /* If <length> is not NULL, the actual number of integer values
1378 * written to <params> will be written to <length>.
1379 */
1380 if (length)
1381 *length = amount;
1382 }
1383
1384 static bool
1385 validate_io(struct gl_program *producer, struct gl_program *consumer)
1386 {
1387 if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages)
1388 return true;
1389
1390 const bool producer_is_array_stage =
1391 producer->info.stage == MESA_SHADER_TESS_CTRL;
1392 const bool consumer_is_array_stage =
1393 consumer->info.stage == MESA_SHADER_GEOMETRY ||
1394 consumer->info.stage == MESA_SHADER_TESS_CTRL ||
1395 consumer->info.stage == MESA_SHADER_TESS_EVAL;
1396
1397 bool valid = true;
1398
1399 gl_shader_variable const **outputs =
1400 (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList,
1401 sizeof(gl_shader_variable *));
1402 if (outputs == NULL)
1403 return false;
1404
1405 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1406 * says:
1407 *
1408 * At an interface between program objects, the set of inputs and
1409 * outputs are considered to match exactly if and only if:
1410 *
1411 * - Every declared input variable has a matching output, as described
1412 * above.
1413 * - There are no user-defined output variables declared without a
1414 * matching input variable declaration.
1415 *
1416 * Every input has an output, and every output has an input. Scan the list
1417 * of producer resources once, and generate the list of outputs. As inputs
1418 * and outputs are matched, remove the matched outputs from the set. At
1419 * the end, the set must be empty. If the set is not empty, then there is
1420 * some output that did not have an input.
1421 */
1422 unsigned num_outputs = 0;
1423 for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) {
1424 struct gl_program_resource *res =
1425 &producer->sh.data->ProgramResourceList[i];
1426
1427 if (res->Type != GL_PROGRAM_OUTPUT)
1428 continue;
1429
1430 gl_shader_variable const *const var = RESOURCE_VAR(res);
1431
1432 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1433 * says:
1434 *
1435 * Built-in inputs or outputs do not affect interface matching.
1436 */
1437 if (is_gl_identifier(var->name))
1438 continue;
1439
1440 outputs[num_outputs++] = var;
1441 }
1442
1443 unsigned match_index = 0;
1444 for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) {
1445 struct gl_program_resource *res =
1446 &consumer->sh.data->ProgramResourceList[i];
1447
1448 if (res->Type != GL_PROGRAM_INPUT)
1449 continue;
1450
1451 gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
1452 gl_shader_variable const *producer_var = NULL;
1453
1454 if (is_gl_identifier(consumer_var->name))
1455 continue;
1456
1457 /* Inputs with explicit locations match other outputs with explicit
1458 * locations by location instead of by name.
1459 */
1460 if (consumer_var->explicit_location) {
1461 for (unsigned j = 0; j < num_outputs; j++) {
1462 const gl_shader_variable *const var = outputs[j];
1463
1464 if (var->explicit_location &&
1465 consumer_var->location == var->location) {
1466 producer_var = var;
1467 match_index = j;
1468 break;
1469 }
1470 }
1471 } else {
1472 for (unsigned j = 0; j < num_outputs; j++) {
1473 const gl_shader_variable *const var = outputs[j];
1474
1475 if (!var->explicit_location &&
1476 strcmp(consumer_var->name, var->name) == 0) {
1477 producer_var = var;
1478 match_index = j;
1479 break;
1480 }
1481 }
1482 }
1483
1484 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1485 * says:
1486 *
1487 * - An output variable is considered to match an input variable in
1488 * the subsequent shader if:
1489 *
1490 * - the two variables match in name, type, and qualification; or
1491 *
1492 * - the two variables are declared with the same location
1493 * qualifier and match in type and qualification.
1494 */
1495 if (producer_var == NULL) {
1496 valid = false;
1497 goto out;
1498 }
1499
1500 /* An output cannot match more than one input, so remove the output from
1501 * the set of possible outputs.
1502 */
1503 outputs[match_index] = NULL;
1504 num_outputs--;
1505 if (match_index < num_outputs)
1506 outputs[match_index] = outputs[num_outputs];
1507
1508 /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
1509 *
1510 * "Tessellation control shader per-vertex output variables and
1511 * blocks and tessellation control, tessellation evaluation, and
1512 * geometry shader per-vertex input variables and blocks are
1513 * required to be declared as arrays, with each element representing
1514 * input or output values for a single vertex of a multi-vertex
1515 * primitive. For the purposes of interface matching, such variables
1516 * and blocks are treated as though they were not declared as
1517 * arrays."
1518 *
1519 * So we unwrap those types before matching.
1520 */
1521 const glsl_type *consumer_type = consumer_var->type;
1522 const glsl_type *consumer_interface_type = consumer_var->interface_type;
1523 const glsl_type *producer_type = producer_var->type;
1524 const glsl_type *producer_interface_type = producer_var->interface_type;
1525
1526 if (consumer_is_array_stage) {
1527 if (consumer_interface_type) {
1528 /* the interface is the array; the underlying types should match */
1529 if (consumer_interface_type->is_array() && !consumer_var->patch)
1530 consumer_interface_type = consumer_interface_type->fields.array;
1531 } else {
1532 if (consumer_type->is_array() && !consumer_var->patch)
1533 consumer_type = consumer_type->fields.array;
1534 }
1535 }
1536
1537 if (producer_is_array_stage) {
1538 if (producer_interface_type) {
1539 /* the interface is the array; the underlying types should match */
1540 if (producer_interface_type->is_array() && !producer_var->patch)
1541 producer_interface_type = producer_interface_type->fields.array;
1542 } else {
1543 if (producer_type->is_array() && !producer_var->patch)
1544 producer_type = producer_type->fields.array;
1545 }
1546 }
1547
1548 if (producer_type != consumer_type) {
1549 valid = false;
1550 goto out;
1551 }
1552
1553 if (producer_interface_type != consumer_interface_type) {
1554 valid = false;
1555 goto out;
1556 }
1557
1558 /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
1559 *
1560 * Qualifier Class| Qualifier |in/out
1561 * ---------------+-------------+------
1562 * Storage | in |
1563 * | out | N/A
1564 * | uniform |
1565 * ---------------+-------------+------
1566 * Auxiliary | centroid | No
1567 * ---------------+-------------+------
1568 * | location | Yes
1569 * | Block layout| N/A
1570 * | binding | N/A
1571 * | offset | N/A
1572 * | format | N/A
1573 * ---------------+-------------+------
1574 * Interpolation | smooth |
1575 * | flat | Yes
1576 * ---------------+-------------+------
1577 * | lowp |
1578 * Precision | mediump | Yes
1579 * | highp |
1580 * ---------------+-------------+------
1581 * Variance | invariant | No
1582 * ---------------+-------------+------
1583 * Memory | all | N/A
1584 *
1585 * Note that location mismatches are detected by the loops above that
1586 * find the producer variable that goes with the consumer variable.
1587 */
1588 if (producer_var->interpolation != consumer_var->interpolation) {
1589 valid = false;
1590 goto out;
1591 }
1592
1593 if (producer_var->precision != consumer_var->precision) {
1594 valid = false;
1595 goto out;
1596 }
1597
1598 if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
1599 valid = false;
1600 goto out;
1601 }
1602 }
1603
1604 out:
1605 free(outputs);
1606 return valid && num_outputs == 0;
1607 }
1608
1609 /**
1610 * Validate inputs against outputs in a program pipeline.
1611 */
1612 extern "C" bool
1613 _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
1614 {
1615 struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram;
1616
1617 /* Find first active stage in pipeline. */
1618 unsigned idx, prev = 0;
1619 for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1620 if (prog[idx]) {
1621 prev = idx;
1622 break;
1623 }
1624 }
1625
1626 for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1627 if (prog[idx]) {
1628 /* Pipeline might include both non-compute and a compute program, do
1629 * not attempt to validate varyings between non-compute and compute
1630 * stage.
1631 */
1632 if (prog[idx]->info.stage == MESA_SHADER_COMPUTE)
1633 break;
1634
1635 if (!validate_io(prog[prev], prog[idx]))
1636 return false;
1637
1638 prev = idx;
1639 }
1640 }
1641 return true;
1642 }