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