2 * Copyright © 2011 Intel Corporation
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:
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
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.
25 * \file shader_query.cpp
26 * C-to-C++ bridge functions to query GLSL shader data
28 * \author Ian Romanick <ian.d.romanick@intel.com>
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 "compiler/glsl/string_to_uint_map.h"
44 program_resource_location(struct gl_program_resource
*res
,
45 unsigned array_index
);
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.
51 #define DECL_RESOURCE_FUNC(name, type) \
52 const type * RESOURCE_ ## name (gl_program_resource *res) { \
54 return (type *) res->Data; \
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
);
66 bind_attrib_location(struct gl_context
*ctx
,
67 struct gl_shader_program
*const shProg
, GLuint index
,
68 const GLchar
*name
, bool no_error
)
74 if (strncmp(name
, "gl_", 3) == 0) {
75 _mesa_error(ctx
, GL_INVALID_OPERATION
,
76 "glBindAttribLocation(illegal name)");
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
);
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.
91 shProg
->AttributeBindings
->put(index
+ VERT_ATTRIB_GENERIC0
, name
);
94 * Note that this attribute binding won't go into effect until
95 * glLinkProgram is called again.
100 _mesa_BindAttribLocation_no_error(GLuint program
, GLuint index
,
103 GET_CURRENT_CONTEXT(ctx
);
105 struct gl_shader_program
*const shProg
=
106 _mesa_lookup_shader_program(ctx
, program
);
107 bind_attrib_location(ctx
, shProg
, index
, name
, true);
111 _mesa_BindAttribLocation(GLuint program
, GLuint index
,
114 GET_CURRENT_CONTEXT(ctx
);
116 struct gl_shader_program
*const shProg
=
117 _mesa_lookup_shader_program_err(ctx
, program
, "glBindAttribLocation");
121 bind_attrib_location(ctx
, shProg
, index
, name
, false);
125 _mesa_GetActiveAttrib(GLuint program
, GLuint desired_index
,
126 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
127 GLenum
* type
, GLchar
* name
)
129 GET_CURRENT_CONTEXT(ctx
);
130 struct gl_shader_program
*shProg
;
133 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(maxLength < 0)");
137 shProg
= _mesa_lookup_shader_program_err(ctx
, program
, "glGetActiveAttrib");
141 if (!shProg
->data
->LinkStatus
) {
142 _mesa_error(ctx
, GL_INVALID_VALUE
,
143 "glGetActiveAttrib(program not linked)");
147 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
148 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(no vertex shader)");
152 struct gl_program_resource
*res
=
153 _mesa_program_resource_find_index(shProg
, GL_PROGRAM_INPUT
,
156 /* User asked for index that does not exist. */
158 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(index)");
162 const gl_shader_variable
*const var
= RESOURCE_VAR(res
);
164 const char *var_name
= var
->name
;
166 _mesa_copy_string(name
, maxLength
, length
, var_name
);
169 _mesa_program_resource_prop(shProg
, res
, desired_index
, GL_ARRAY_SIZE
,
170 size
, "glGetActiveAttrib");
173 _mesa_program_resource_prop(shProg
, res
, desired_index
, GL_TYPE
,
174 (GLint
*) type
, "glGetActiveAttrib");
178 _mesa_GetAttribLocation(GLuint program
, const GLchar
* name
)
180 GET_CURRENT_CONTEXT(ctx
);
181 struct gl_shader_program
*const shProg
=
182 _mesa_lookup_shader_program_err(ctx
, program
, "glGetAttribLocation");
188 if (!shProg
->data
->LinkStatus
) {
189 _mesa_error(ctx
, GL_INVALID_OPERATION
,
190 "glGetAttribLocation(program not linked)");
197 /* Not having a vertex shader is not an error.
199 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
)
202 unsigned array_index
= 0;
203 struct gl_program_resource
*res
=
204 _mesa_program_resource_find_name(shProg
, GL_PROGRAM_INPUT
, name
,
210 return program_resource_location(res
, array_index
);
214 _mesa_count_active_attribs(struct gl_shader_program
*shProg
)
216 if (!shProg
->data
->LinkStatus
217 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
221 struct gl_program_resource
*res
= shProg
->data
->ProgramResourceList
;
223 for (unsigned j
= 0; j
< shProg
->data
->NumProgramResourceList
;
225 if (res
->Type
== GL_PROGRAM_INPUT
&&
226 res
->StageReferences
& (1 << MESA_SHADER_VERTEX
))
234 _mesa_longest_attribute_name_length(struct gl_shader_program
*shProg
)
236 if (!shProg
->data
->LinkStatus
237 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
241 struct gl_program_resource
*res
= shProg
->data
->ProgramResourceList
;
243 for (unsigned j
= 0; j
< shProg
->data
->NumProgramResourceList
;
245 if (res
->Type
== GL_PROGRAM_INPUT
&&
246 res
->StageReferences
& (1 << MESA_SHADER_VERTEX
)) {
248 const size_t length
= strlen(RESOURCE_VAR(res
)->name
);
249 if (length
>= longest
)
250 longest
= length
+ 1;
258 bind_frag_data_location(struct gl_shader_program
*const shProg
,
259 const char *name
, unsigned colorNumber
,
262 /* Replace the current value if it's already in the list. Add
263 * FRAG_RESULT_DATA0 because that's how the linker differentiates
264 * between built-in attributes and user-defined attributes.
266 shProg
->FragDataBindings
->put(colorNumber
+ FRAG_RESULT_DATA0
, name
);
267 shProg
->FragDataIndexBindings
->put(index
, name
);
270 * Note that this binding won't go into effect until
271 * glLinkProgram is called again.
276 _mesa_BindFragDataLocation(GLuint program
, GLuint colorNumber
,
279 _mesa_BindFragDataLocationIndexed(program
, colorNumber
, 0, name
);
283 _mesa_BindFragDataLocation_no_error(GLuint program
, GLuint colorNumber
,
286 GET_CURRENT_CONTEXT(ctx
);
291 struct gl_shader_program
*const shProg
=
292 _mesa_lookup_shader_program(ctx
, program
);
294 bind_frag_data_location(shProg
, name
, colorNumber
, 0);
298 _mesa_BindFragDataLocationIndexed(GLuint program
, GLuint colorNumber
,
299 GLuint index
, const GLchar
*name
)
301 GET_CURRENT_CONTEXT(ctx
);
303 struct gl_shader_program
*const shProg
=
304 _mesa_lookup_shader_program_err(ctx
, program
, "glBindFragDataLocationIndexed");
311 if (strncmp(name
, "gl_", 3) == 0) {
312 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindFragDataLocationIndexed(illegal name)");
317 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(index)");
321 if (index
== 0 && colorNumber
>= ctx
->Const
.MaxDrawBuffers
) {
322 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
326 if (index
== 1 && colorNumber
>= ctx
->Const
.MaxDualSourceDrawBuffers
) {
327 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
331 bind_frag_data_location(shProg
, name
, colorNumber
, index
);
335 _mesa_BindFragDataLocationIndexed_no_error(GLuint program
, GLuint colorNumber
,
336 GLuint index
, const GLchar
*name
)
338 GET_CURRENT_CONTEXT(ctx
);
343 struct gl_shader_program
*const shProg
=
344 _mesa_lookup_shader_program(ctx
, program
);
346 bind_frag_data_location(shProg
, name
, colorNumber
, index
);
350 _mesa_GetFragDataIndex(GLuint program
, const GLchar
*name
)
352 GET_CURRENT_CONTEXT(ctx
);
353 struct gl_shader_program
*const shProg
=
354 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataIndex");
360 if (!shProg
->data
->LinkStatus
) {
361 _mesa_error(ctx
, GL_INVALID_OPERATION
,
362 "glGetFragDataIndex(program not linked)");
369 if (strncmp(name
, "gl_", 3) == 0) {
370 _mesa_error(ctx
, GL_INVALID_OPERATION
,
371 "glGetFragDataIndex(illegal name)");
375 /* Not having a fragment shader is not an error.
377 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
380 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,
385 _mesa_GetFragDataLocation(GLuint program
, const GLchar
*name
)
387 GET_CURRENT_CONTEXT(ctx
);
388 struct gl_shader_program
*const shProg
=
389 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataLocation");
395 if (!shProg
->data
->LinkStatus
) {
396 _mesa_error(ctx
, GL_INVALID_OPERATION
,
397 "glGetFragDataLocation(program not linked)");
404 if (strncmp(name
, "gl_", 3) == 0) {
405 _mesa_error(ctx
, GL_INVALID_OPERATION
,
406 "glGetFragDataLocation(illegal name)");
410 /* Not having a fragment shader is not an error.
412 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
415 unsigned array_index
= 0;
416 struct gl_program_resource
*res
=
417 _mesa_program_resource_find_name(shProg
, GL_PROGRAM_OUTPUT
, name
,
423 return program_resource_location(res
, array_index
);
427 _mesa_program_resource_name(struct gl_program_resource
*res
)
430 case GL_UNIFORM_BLOCK
:
431 case GL_SHADER_STORAGE_BLOCK
:
432 return RESOURCE_UBO(res
)->Name
;
433 case GL_TRANSFORM_FEEDBACK_VARYING
:
434 return RESOURCE_XFV(res
)->Name
;
435 case GL_PROGRAM_INPUT
:
436 case GL_PROGRAM_OUTPUT
:
437 return RESOURCE_VAR(res
)->name
;
439 case GL_BUFFER_VARIABLE
:
440 return RESOURCE_UNI(res
)->name
;
441 case GL_VERTEX_SUBROUTINE_UNIFORM
:
442 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
443 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
444 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
445 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
446 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
447 return RESOURCE_UNI(res
)->name
+ MESA_SUBROUTINE_PREFIX_LEN
;
448 case GL_VERTEX_SUBROUTINE
:
449 case GL_GEOMETRY_SUBROUTINE
:
450 case GL_FRAGMENT_SUBROUTINE
:
451 case GL_COMPUTE_SUBROUTINE
:
452 case GL_TESS_CONTROL_SUBROUTINE
:
453 case GL_TESS_EVALUATION_SUBROUTINE
:
454 return RESOURCE_SUB(res
)->name
;
456 assert(!"support for resource type not implemented");
463 _mesa_program_resource_array_size(struct gl_program_resource
*res
)
466 case GL_TRANSFORM_FEEDBACK_VARYING
:
467 return RESOURCE_XFV(res
)->Size
> 1 ?
468 RESOURCE_XFV(res
)->Size
: 0;
469 case GL_PROGRAM_INPUT
:
470 case GL_PROGRAM_OUTPUT
:
471 return RESOURCE_VAR(res
)->type
->length
;
473 case GL_VERTEX_SUBROUTINE_UNIFORM
:
474 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
475 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
476 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
477 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
478 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
479 return RESOURCE_UNI(res
)->array_elements
;
480 case GL_BUFFER_VARIABLE
:
482 if (RESOURCE_UNI(res
)->array_stride
> 0 &&
483 RESOURCE_UNI(res
)->array_elements
== 0)
486 return RESOURCE_UNI(res
)->array_elements
;
487 case GL_VERTEX_SUBROUTINE
:
488 case GL_GEOMETRY_SUBROUTINE
:
489 case GL_FRAGMENT_SUBROUTINE
:
490 case GL_COMPUTE_SUBROUTINE
:
491 case GL_TESS_CONTROL_SUBROUTINE
:
492 case GL_TESS_EVALUATION_SUBROUTINE
:
493 case GL_ATOMIC_COUNTER_BUFFER
:
494 case GL_UNIFORM_BLOCK
:
495 case GL_SHADER_STORAGE_BLOCK
:
498 assert(!"support for resource type not implemented");
504 * Checks if array subscript is valid and if so sets array_index.
507 valid_array_index(const GLchar
*name
, unsigned *array_index
)
510 const GLchar
*out_base_name_end
;
512 idx
= parse_program_resource_name(name
, &out_base_name_end
);
522 /* Find a program resource with specific name in given interface.
524 struct gl_program_resource
*
525 _mesa_program_resource_find_name(struct gl_shader_program
*shProg
,
526 GLenum programInterface
, const char *name
,
527 unsigned *array_index
)
529 struct gl_program_resource
*res
= shProg
->data
->ProgramResourceList
;
530 for (unsigned i
= 0; i
< shProg
->data
->NumProgramResourceList
;
532 if (res
->Type
!= programInterface
)
535 /* Resource basename. */
536 const char *rname
= _mesa_program_resource_name(res
);
537 unsigned baselen
= strlen(rname
);
538 unsigned baselen_without_array_index
= baselen
;
539 const char *rname_last_square_bracket
= strrchr(rname
, '[');
541 bool rname_has_array_index_zero
= false;
542 /* From ARB_program_interface_query spec:
544 * "uint GetProgramResourceIndex(uint program, enum programInterface,
547 * If <name> exactly matches the name string of one of the active
548 * resources for <programInterface>, the index of the matched resource is
549 * returned. Additionally, if <name> would exactly match the name string
550 * of an active resource if "[0]" were appended to <name>, the index of
551 * the matched resource is returned. [...]"
553 * "A string provided to GetProgramResourceLocation or
554 * GetProgramResourceLocationIndex is considered to match an active variable
557 * * the string exactly matches the name of the active variable;
559 * * if the string identifies the base name of an active array, where the
560 * string would exactly match the name of the variable if the suffix
561 * "[0]" were appended to the string; [...]"
563 /* Remove array's index from interface block name comparison only if
564 * array's index is zero and the resulting string length is the same
565 * than the provided name's length.
567 if (rname_last_square_bracket
) {
568 baselen_without_array_index
-= strlen(rname_last_square_bracket
);
569 rname_has_array_index_zero
=
570 (strcmp(rname_last_square_bracket
, "[0]") == 0) &&
571 (baselen_without_array_index
== strlen(name
));
574 if (strncmp(rname
, name
, baselen
) == 0)
576 else if (rname_has_array_index_zero
&&
577 strncmp(rname
, name
, baselen_without_array_index
) == 0)
581 switch (programInterface
) {
582 case GL_UNIFORM_BLOCK
:
583 case GL_SHADER_STORAGE_BLOCK
:
584 /* Basename match, check if array or struct. */
585 if (rname_has_array_index_zero
||
586 name
[baselen
] == '\0' ||
587 name
[baselen
] == '[' ||
588 name
[baselen
] == '.') {
592 case GL_TRANSFORM_FEEDBACK_VARYING
:
593 case GL_BUFFER_VARIABLE
:
595 case GL_VERTEX_SUBROUTINE_UNIFORM
:
596 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
597 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
598 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
599 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
600 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
601 case GL_VERTEX_SUBROUTINE
:
602 case GL_GEOMETRY_SUBROUTINE
:
603 case GL_FRAGMENT_SUBROUTINE
:
604 case GL_COMPUTE_SUBROUTINE
:
605 case GL_TESS_CONTROL_SUBROUTINE
:
606 case GL_TESS_EVALUATION_SUBROUTINE
:
607 if (name
[baselen
] == '.') {
611 case GL_PROGRAM_INPUT
:
612 case GL_PROGRAM_OUTPUT
:
613 if (name
[baselen
] == '\0') {
615 } else if (name
[baselen
] == '[' &&
616 valid_array_index(name
, array_index
)) {
621 assert(!"not implemented for given interface");
629 calc_resource_index(struct gl_shader_program
*shProg
,
630 struct gl_program_resource
*res
)
634 for (i
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
635 if (&shProg
->data
->ProgramResourceList
[i
] == res
)
637 if (shProg
->data
->ProgramResourceList
[i
].Type
== res
->Type
)
640 return GL_INVALID_INDEX
;
644 * Calculate index for the given resource.
647 _mesa_program_resource_index(struct gl_shader_program
*shProg
,
648 struct gl_program_resource
*res
)
651 return GL_INVALID_INDEX
;
654 case GL_ATOMIC_COUNTER_BUFFER
:
655 return RESOURCE_ATC(res
) - shProg
->data
->AtomicBuffers
;
656 case GL_VERTEX_SUBROUTINE
:
657 case GL_GEOMETRY_SUBROUTINE
:
658 case GL_FRAGMENT_SUBROUTINE
:
659 case GL_COMPUTE_SUBROUTINE
:
660 case GL_TESS_CONTROL_SUBROUTINE
:
661 case GL_TESS_EVALUATION_SUBROUTINE
:
662 return RESOURCE_SUB(res
)->index
;
663 case GL_UNIFORM_BLOCK
:
664 case GL_SHADER_STORAGE_BLOCK
:
665 case GL_TRANSFORM_FEEDBACK_BUFFER
:
666 case GL_TRANSFORM_FEEDBACK_VARYING
:
668 return calc_resource_index(shProg
, res
);
673 * Find a program resource that points to given data.
675 static struct gl_program_resource
*
676 program_resource_find_data(struct gl_shader_program
*shProg
, void *data
)
678 struct gl_program_resource
*res
= shProg
->data
->ProgramResourceList
;
679 for (unsigned i
= 0; i
< shProg
->data
->NumProgramResourceList
;
681 if (res
->Data
== data
)
687 /* Find a program resource with specific index in given interface.
689 struct gl_program_resource
*
690 _mesa_program_resource_find_index(struct gl_shader_program
*shProg
,
691 GLenum programInterface
, GLuint index
)
693 struct gl_program_resource
*res
= shProg
->data
->ProgramResourceList
;
696 for (unsigned i
= 0; i
< shProg
->data
->NumProgramResourceList
;
698 if (res
->Type
!= programInterface
)
702 case GL_UNIFORM_BLOCK
:
703 case GL_ATOMIC_COUNTER_BUFFER
:
704 case GL_SHADER_STORAGE_BLOCK
:
705 case GL_TRANSFORM_FEEDBACK_BUFFER
:
706 if (_mesa_program_resource_index(shProg
, res
) == index
)
709 case GL_TRANSFORM_FEEDBACK_VARYING
:
710 case GL_PROGRAM_INPUT
:
711 case GL_PROGRAM_OUTPUT
:
713 case GL_VERTEX_SUBROUTINE_UNIFORM
:
714 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
715 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
716 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
717 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
718 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
719 case GL_VERTEX_SUBROUTINE
:
720 case GL_GEOMETRY_SUBROUTINE
:
721 case GL_FRAGMENT_SUBROUTINE
:
722 case GL_COMPUTE_SUBROUTINE
:
723 case GL_TESS_CONTROL_SUBROUTINE
:
724 case GL_TESS_EVALUATION_SUBROUTINE
:
725 case GL_BUFFER_VARIABLE
:
726 if (++idx
== (int) index
)
730 assert(!"not implemented for given interface");
736 /* Function returns if resource name is expected to have index
740 * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
743 * "If the active uniform is an array, the uniform name returned in
744 * name will always be the name of the uniform array appended with
747 * The same text also appears in the OpenGL 4.2 spec. It does not,
748 * however, appear in any previous spec. Previous specifications are
749 * ambiguous in this regard. However, either name can later be passed
750 * to glGetUniformLocation (and related APIs), so there shouldn't be any
751 * harm in always appending "[0]" to uniform array names.
754 add_index_to_name(struct gl_program_resource
*res
)
756 /* Transform feedback varyings have array index already appended
759 return res
->Type
!= GL_TRANSFORM_FEEDBACK_VARYING
;
762 /* Get name length of a program resource. This consists of
763 * base name + 3 for '[0]' if resource is an array.
766 _mesa_program_resource_name_len(struct gl_program_resource
*res
)
768 unsigned length
= strlen(_mesa_program_resource_name(res
));
769 if (_mesa_program_resource_array_size(res
) && add_index_to_name(res
))
774 /* Get full name of a program resource.
777 _mesa_get_program_resource_name(struct gl_shader_program
*shProg
,
778 GLenum programInterface
, GLuint index
,
779 GLsizei bufSize
, GLsizei
*length
,
780 GLchar
*name
, const char *caller
)
782 GET_CURRENT_CONTEXT(ctx
);
784 /* Find resource with given interface and index. */
785 struct gl_program_resource
*res
=
786 _mesa_program_resource_find_index(shProg
, programInterface
, index
);
788 /* The error INVALID_VALUE is generated if <index> is greater than
789 * or equal to the number of entries in the active resource list for
790 * <programInterface>.
793 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index %u)", caller
, index
);
798 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(bufSize %d)", caller
, bufSize
);
805 length
= &localLength
;
807 _mesa_copy_string(name
, bufSize
, length
, _mesa_program_resource_name(res
));
809 if (_mesa_program_resource_array_size(res
) && add_index_to_name(res
)) {
812 /* The comparison is strange because *length does *NOT* include the
813 * terminating NUL, but maxLength does.
815 for (i
= 0; i
< 3 && (*length
+ i
+ 1) < bufSize
; i
++)
816 name
[*length
+ i
] = "[0]"[i
];
818 name
[*length
+ i
] = '\0';
825 program_resource_location(struct gl_program_resource
*res
, unsigned array_index
)
828 case GL_PROGRAM_INPUT
: {
829 const gl_shader_variable
*var
= RESOURCE_VAR(res
);
831 if (var
->location
== -1)
834 /* If the input is an array, fail if the index is out of bounds. */
836 && array_index
>= var
->type
->length
) {
839 return var
->location
+
840 (array_index
* var
->type
->without_array()->matrix_columns
);
842 case GL_PROGRAM_OUTPUT
:
843 if (RESOURCE_VAR(res
)->location
== -1)
846 /* If the output is an array, fail if the index is out of bounds. */
848 && array_index
>= RESOURCE_VAR(res
)->type
->length
) {
851 return RESOURCE_VAR(res
)->location
+ array_index
;
853 /* If the uniform is built-in, fail. */
854 if (RESOURCE_UNI(res
)->builtin
)
857 /* From page 79 of the OpenGL 4.2 spec:
859 * "A valid name cannot be a structure, an array of structures, or any
860 * portion of a single vector or a matrix."
862 if (RESOURCE_UNI(res
)->type
->without_array()->is_record())
865 /* From the GL_ARB_uniform_buffer_object spec:
867 * "The value -1 will be returned if <name> does not correspond to an
868 * active uniform variable name in <program>, if <name> is associated
869 * with a named uniform block, or if <name> starts with the reserved
872 if (RESOURCE_UNI(res
)->block_index
!= -1 ||
873 RESOURCE_UNI(res
)->atomic_buffer_index
!= -1)
877 case GL_VERTEX_SUBROUTINE_UNIFORM
:
878 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
879 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
880 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
881 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
882 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
883 /* If the uniform is an array, fail if the index is out of bounds. */
885 && array_index
>= RESOURCE_UNI(res
)->array_elements
) {
889 /* location in remap table + array element offset */
890 return RESOURCE_UNI(res
)->remap_location
+ array_index
;
897 * Function implements following location queries:
898 * glGetUniformLocation
901 _mesa_program_resource_location(struct gl_shader_program
*shProg
,
902 GLenum programInterface
, const char *name
)
904 unsigned array_index
= 0;
905 struct gl_program_resource
*res
=
906 _mesa_program_resource_find_name(shProg
, programInterface
, name
,
909 /* Resource not found. */
913 return program_resource_location(res
, array_index
);
917 * Function implements following index queries:
921 _mesa_program_resource_location_index(struct gl_shader_program
*shProg
,
922 GLenum programInterface
, const char *name
)
924 struct gl_program_resource
*res
=
925 _mesa_program_resource_find_name(shProg
, programInterface
, name
, NULL
);
927 /* Non-existent variable or resource is not referenced by fragment stage. */
928 if (!res
|| !(res
->StageReferences
& (1 << MESA_SHADER_FRAGMENT
)))
931 /* From OpenGL 4.5 spec, 7.3 Program Objects
932 * "The value -1 will be returned by either command...
933 * ... or if name identifies an active variable that does not have a
934 * valid location assigned.
936 if (RESOURCE_VAR(res
)->location
== -1)
938 return RESOURCE_VAR(res
)->index
;
942 stage_from_enum(GLenum ref
)
945 case GL_REFERENCED_BY_VERTEX_SHADER
:
946 return MESA_SHADER_VERTEX
;
947 case GL_REFERENCED_BY_TESS_CONTROL_SHADER
:
948 return MESA_SHADER_TESS_CTRL
;
949 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER
:
950 return MESA_SHADER_TESS_EVAL
;
951 case GL_REFERENCED_BY_GEOMETRY_SHADER
:
952 return MESA_SHADER_GEOMETRY
;
953 case GL_REFERENCED_BY_FRAGMENT_SHADER
:
954 return MESA_SHADER_FRAGMENT
;
955 case GL_REFERENCED_BY_COMPUTE_SHADER
:
956 return MESA_SHADER_COMPUTE
;
958 assert(!"shader stage not supported");
959 return MESA_SHADER_STAGES
;
964 * Check if resource is referenced by given 'referenced by' stage enum.
965 * ATC and UBO resources hold stage references of their own.
968 is_resource_referenced(struct gl_shader_program
*shProg
,
969 struct gl_program_resource
*res
,
970 GLuint index
, uint8_t stage
)
972 /* First, check if we even have such a stage active. */
973 if (!shProg
->_LinkedShaders
[stage
])
976 if (res
->Type
== GL_ATOMIC_COUNTER_BUFFER
)
977 return RESOURCE_ATC(res
)->StageReferences
[stage
];
979 if (res
->Type
== GL_UNIFORM_BLOCK
)
980 return shProg
->data
->UniformBlocks
[index
].stageref
& (1 << stage
);
982 if (res
->Type
== GL_SHADER_STORAGE_BLOCK
)
983 return shProg
->data
->ShaderStorageBlocks
[index
].stageref
& (1 << stage
);
985 return res
->StageReferences
& (1 << stage
);
989 get_buffer_property(struct gl_shader_program
*shProg
,
990 struct gl_program_resource
*res
, const GLenum prop
,
991 GLint
*val
, const char *caller
)
993 GET_CURRENT_CONTEXT(ctx
);
994 if (res
->Type
!= GL_UNIFORM_BLOCK
&&
995 res
->Type
!= GL_ATOMIC_COUNTER_BUFFER
&&
996 res
->Type
!= GL_SHADER_STORAGE_BLOCK
&&
997 res
->Type
!= GL_TRANSFORM_FEEDBACK_BUFFER
)
998 goto invalid_operation
;
1000 if (res
->Type
== GL_UNIFORM_BLOCK
) {
1002 case GL_BUFFER_BINDING
:
1003 *val
= RESOURCE_UBO(res
)->Binding
;
1005 case GL_BUFFER_DATA_SIZE
:
1006 *val
= RESOURCE_UBO(res
)->UniformBufferSize
;
1008 case GL_NUM_ACTIVE_VARIABLES
:
1010 for (unsigned i
= 0; i
< RESOURCE_UBO(res
)->NumUniforms
; i
++) {
1011 const char *iname
= RESOURCE_UBO(res
)->Uniforms
[i
].IndexName
;
1012 struct gl_program_resource
*uni
=
1013 _mesa_program_resource_find_name(shProg
, GL_UNIFORM
, iname
,
1020 case GL_ACTIVE_VARIABLES
: {
1021 unsigned num_values
= 0;
1022 for (unsigned i
= 0; i
< RESOURCE_UBO(res
)->NumUniforms
; i
++) {
1023 const char *iname
= RESOURCE_UBO(res
)->Uniforms
[i
].IndexName
;
1024 struct gl_program_resource
*uni
=
1025 _mesa_program_resource_find_name(shProg
, GL_UNIFORM
, iname
,
1030 _mesa_program_resource_index(shProg
, uni
);
1036 } else if (res
->Type
== GL_SHADER_STORAGE_BLOCK
) {
1038 case GL_BUFFER_BINDING
:
1039 *val
= RESOURCE_UBO(res
)->Binding
;
1041 case GL_BUFFER_DATA_SIZE
:
1042 *val
= RESOURCE_UBO(res
)->UniformBufferSize
;
1044 case GL_NUM_ACTIVE_VARIABLES
:
1046 for (unsigned i
= 0; i
< RESOURCE_UBO(res
)->NumUniforms
; i
++) {
1047 const char *iname
= RESOURCE_UBO(res
)->Uniforms
[i
].IndexName
;
1048 struct gl_program_resource
*uni
=
1049 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
1056 case GL_ACTIVE_VARIABLES
: {
1057 unsigned num_values
= 0;
1058 for (unsigned i
= 0; i
< RESOURCE_UBO(res
)->NumUniforms
; i
++) {
1059 const char *iname
= RESOURCE_UBO(res
)->Uniforms
[i
].IndexName
;
1060 struct gl_program_resource
*uni
=
1061 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
1066 _mesa_program_resource_index(shProg
, uni
);
1072 } else if (res
->Type
== GL_ATOMIC_COUNTER_BUFFER
) {
1074 case GL_BUFFER_BINDING
:
1075 *val
= RESOURCE_ATC(res
)->Binding
;
1077 case GL_BUFFER_DATA_SIZE
:
1078 *val
= RESOURCE_ATC(res
)->MinimumSize
;
1080 case GL_NUM_ACTIVE_VARIABLES
:
1081 *val
= RESOURCE_ATC(res
)->NumUniforms
;
1083 case GL_ACTIVE_VARIABLES
:
1084 for (unsigned i
= 0; i
< RESOURCE_ATC(res
)->NumUniforms
; i
++) {
1085 /* Active atomic buffer contains index to UniformStorage. Find
1086 * out gl_program_resource via data pointer and then calculate
1087 * index of that uniform.
1089 unsigned idx
= RESOURCE_ATC(res
)->Uniforms
[i
];
1090 struct gl_program_resource
*uni
=
1091 program_resource_find_data(shProg
,
1092 &shProg
->data
->UniformStorage
[idx
]);
1094 *val
++ = _mesa_program_resource_index(shProg
, uni
);
1096 return RESOURCE_ATC(res
)->NumUniforms
;
1098 } else if (res
->Type
== GL_TRANSFORM_FEEDBACK_BUFFER
) {
1100 case GL_BUFFER_BINDING
:
1101 *val
= RESOURCE_XFB(res
)->Binding
;
1103 case GL_NUM_ACTIVE_VARIABLES
:
1104 *val
= RESOURCE_XFB(res
)->NumVaryings
;
1106 case GL_ACTIVE_VARIABLES
:
1107 struct gl_transform_feedback_info
*linked_xfb
=
1108 shProg
->last_vert_prog
->sh
.LinkedTransformFeedback
;
1109 for (int i
= 0; i
< linked_xfb
->NumVarying
; i
++) {
1110 unsigned index
= linked_xfb
->Varyings
[i
].BufferIndex
;
1111 struct gl_program_resource
*buf_res
=
1112 _mesa_program_resource_find_index(shProg
,
1113 GL_TRANSFORM_FEEDBACK_BUFFER
,
1116 if (res
== buf_res
) {
1120 return RESOURCE_XFB(res
)->NumVaryings
;
1123 assert(!"support for property type not implemented");
1126 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(%s prop %s)", caller
,
1127 _mesa_enum_to_string(res
->Type
),
1128 _mesa_enum_to_string(prop
));
1134 _mesa_program_resource_prop(struct gl_shader_program
*shProg
,
1135 struct gl_program_resource
*res
, GLuint index
,
1136 const GLenum prop
, GLint
*val
, const char *caller
)
1138 GET_CURRENT_CONTEXT(ctx
);
1140 #define VALIDATE_TYPE(type)\
1141 if (res->Type != type)\
1142 goto invalid_operation;
1144 #define VALIDATE_TYPE_2(type1, type2)\
1145 if (res->Type != type1 && res->Type != type2)\
1146 goto invalid_operation;
1149 case GL_NAME_LENGTH
:
1150 switch (res
->Type
) {
1151 case GL_ATOMIC_COUNTER_BUFFER
:
1152 case GL_TRANSFORM_FEEDBACK_BUFFER
:
1153 goto invalid_operation
;
1155 /* Resource name length + terminator. */
1156 *val
= _mesa_program_resource_name_len(res
) + 1;
1160 switch (res
->Type
) {
1162 case GL_BUFFER_VARIABLE
:
1163 *val
= RESOURCE_UNI(res
)->type
->gl_type
;
1165 case GL_PROGRAM_INPUT
:
1166 case GL_PROGRAM_OUTPUT
:
1167 *val
= RESOURCE_VAR(res
)->type
->gl_type
;
1169 case GL_TRANSFORM_FEEDBACK_VARYING
:
1170 *val
= RESOURCE_XFV(res
)->Type
;
1173 goto invalid_operation
;
1176 switch (res
->Type
) {
1178 case GL_BUFFER_VARIABLE
:
1179 case GL_VERTEX_SUBROUTINE_UNIFORM
:
1180 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
1181 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
1182 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
1183 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
1184 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
1186 /* Test if a buffer variable is an array or an unsized array.
1187 * Unsized arrays return zero as array size.
1189 if (RESOURCE_UNI(res
)->is_shader_storage
&&
1190 RESOURCE_UNI(res
)->array_stride
> 0)
1191 *val
= RESOURCE_UNI(res
)->array_elements
;
1193 *val
= MAX2(RESOURCE_UNI(res
)->array_elements
, 1);
1195 case GL_PROGRAM_INPUT
:
1196 case GL_PROGRAM_OUTPUT
:
1197 *val
= MAX2(_mesa_program_resource_array_size(res
), 1);
1199 case GL_TRANSFORM_FEEDBACK_VARYING
:
1200 *val
= RESOURCE_XFV(res
)->Size
;
1203 goto invalid_operation
;
1206 switch (res
->Type
) {
1208 case GL_BUFFER_VARIABLE
:
1209 *val
= RESOURCE_UNI(res
)->offset
;
1211 case GL_TRANSFORM_FEEDBACK_VARYING
:
1212 *val
= RESOURCE_XFV(res
)->Offset
;
1215 goto invalid_operation
;
1217 case GL_BLOCK_INDEX
:
1218 VALIDATE_TYPE_2(GL_UNIFORM
, GL_BUFFER_VARIABLE
);
1219 *val
= RESOURCE_UNI(res
)->block_index
;
1221 case GL_ARRAY_STRIDE
:
1222 VALIDATE_TYPE_2(GL_UNIFORM
, GL_BUFFER_VARIABLE
);
1223 *val
= RESOURCE_UNI(res
)->array_stride
;
1225 case GL_MATRIX_STRIDE
:
1226 VALIDATE_TYPE_2(GL_UNIFORM
, GL_BUFFER_VARIABLE
);
1227 *val
= RESOURCE_UNI(res
)->matrix_stride
;
1229 case GL_IS_ROW_MAJOR
:
1230 VALIDATE_TYPE_2(GL_UNIFORM
, GL_BUFFER_VARIABLE
);
1231 *val
= RESOURCE_UNI(res
)->row_major
;
1233 case GL_ATOMIC_COUNTER_BUFFER_INDEX
:
1234 VALIDATE_TYPE(GL_UNIFORM
);
1235 *val
= RESOURCE_UNI(res
)->atomic_buffer_index
;
1237 case GL_BUFFER_BINDING
:
1238 case GL_BUFFER_DATA_SIZE
:
1239 case GL_NUM_ACTIVE_VARIABLES
:
1240 case GL_ACTIVE_VARIABLES
:
1241 return get_buffer_property(shProg
, res
, prop
, val
, caller
);
1242 case GL_REFERENCED_BY_COMPUTE_SHADER
:
1243 if (!_mesa_has_compute_shaders(ctx
))
1246 case GL_REFERENCED_BY_VERTEX_SHADER
:
1247 case GL_REFERENCED_BY_TESS_CONTROL_SHADER
:
1248 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER
:
1249 case GL_REFERENCED_BY_GEOMETRY_SHADER
:
1250 case GL_REFERENCED_BY_FRAGMENT_SHADER
:
1251 switch (res
->Type
) {
1253 case GL_PROGRAM_INPUT
:
1254 case GL_PROGRAM_OUTPUT
:
1255 case GL_UNIFORM_BLOCK
:
1256 case GL_BUFFER_VARIABLE
:
1257 case GL_SHADER_STORAGE_BLOCK
:
1258 case GL_ATOMIC_COUNTER_BUFFER
:
1259 *val
= is_resource_referenced(shProg
, res
, index
,
1260 stage_from_enum(prop
));
1263 goto invalid_operation
;
1266 switch (res
->Type
) {
1268 case GL_VERTEX_SUBROUTINE_UNIFORM
:
1269 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
1270 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
1271 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
1272 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
1273 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
1274 case GL_PROGRAM_INPUT
:
1275 case GL_PROGRAM_OUTPUT
:
1276 *val
= program_resource_location(res
, 0);
1279 goto invalid_operation
;
1281 case GL_LOCATION_COMPONENT
:
1282 switch (res
->Type
) {
1283 case GL_PROGRAM_INPUT
:
1284 case GL_PROGRAM_OUTPUT
:
1285 *val
= RESOURCE_VAR(res
)->component
;
1288 goto invalid_operation
;
1290 case GL_LOCATION_INDEX
: {
1292 if (res
->Type
!= GL_PROGRAM_OUTPUT
)
1293 goto invalid_operation
;
1294 tmp
= program_resource_location(res
, 0);
1298 *val
= _mesa_program_resource_location_index(shProg
, res
->Type
,
1299 RESOURCE_VAR(res
)->name
);
1302 case GL_NUM_COMPATIBLE_SUBROUTINES
:
1303 if (res
->Type
!= GL_VERTEX_SUBROUTINE_UNIFORM
&&
1304 res
->Type
!= GL_FRAGMENT_SUBROUTINE_UNIFORM
&&
1305 res
->Type
!= GL_GEOMETRY_SUBROUTINE_UNIFORM
&&
1306 res
->Type
!= GL_COMPUTE_SUBROUTINE_UNIFORM
&&
1307 res
->Type
!= GL_TESS_CONTROL_SUBROUTINE_UNIFORM
&&
1308 res
->Type
!= GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
)
1309 goto invalid_operation
;
1310 *val
= RESOURCE_UNI(res
)->num_compatible_subroutines
;
1312 case GL_COMPATIBLE_SUBROUTINES
: {
1313 const struct gl_uniform_storage
*uni
;
1314 struct gl_program
*p
;
1318 if (res
->Type
!= GL_VERTEX_SUBROUTINE_UNIFORM
&&
1319 res
->Type
!= GL_FRAGMENT_SUBROUTINE_UNIFORM
&&
1320 res
->Type
!= GL_GEOMETRY_SUBROUTINE_UNIFORM
&&
1321 res
->Type
!= GL_COMPUTE_SUBROUTINE_UNIFORM
&&
1322 res
->Type
!= GL_TESS_CONTROL_SUBROUTINE_UNIFORM
&&
1323 res
->Type
!= GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
)
1324 goto invalid_operation
;
1325 uni
= RESOURCE_UNI(res
);
1327 p
= shProg
->_LinkedShaders
[_mesa_shader_stage_from_subroutine_uniform(res
->Type
)]->Program
;
1329 for (i
= 0; i
< p
->sh
.NumSubroutineFunctions
; i
++) {
1330 struct gl_subroutine_function
*fn
= &p
->sh
.SubroutineFunctions
[i
];
1331 for (j
= 0; j
< fn
->num_compat_types
; j
++) {
1332 if (fn
->types
[j
] == uni
->type
) {
1341 case GL_TOP_LEVEL_ARRAY_SIZE
:
1342 VALIDATE_TYPE(GL_BUFFER_VARIABLE
);
1343 *val
= RESOURCE_UNI(res
)->top_level_array_size
;
1346 case GL_TOP_LEVEL_ARRAY_STRIDE
:
1347 VALIDATE_TYPE(GL_BUFFER_VARIABLE
);
1348 *val
= RESOURCE_UNI(res
)->top_level_array_stride
;
1351 /* GL_ARB_tessellation_shader */
1352 case GL_IS_PER_PATCH
:
1353 switch (res
->Type
) {
1354 case GL_PROGRAM_INPUT
:
1355 case GL_PROGRAM_OUTPUT
:
1356 *val
= RESOURCE_VAR(res
)->patch
;
1359 goto invalid_operation
;
1362 case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX
:
1363 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING
);
1364 *val
= RESOURCE_XFV(res
)->BufferIndex
;
1366 case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE
:
1367 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER
);
1368 *val
= RESOURCE_XFB(res
)->Stride
* 4;
1375 #undef VALIDATE_TYPE
1376 #undef VALIDATE_TYPE_2
1379 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(%s prop %s)", caller
,
1380 _mesa_enum_to_string(res
->Type
),
1381 _mesa_enum_to_string(prop
));
1385 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(%s prop %s)", caller
,
1386 _mesa_enum_to_string(res
->Type
),
1387 _mesa_enum_to_string(prop
));
1392 _mesa_get_program_resourceiv(struct gl_shader_program
*shProg
,
1393 GLenum programInterface
, GLuint index
, GLsizei propCount
,
1394 const GLenum
*props
, GLsizei bufSize
,
1395 GLsizei
*length
, GLint
*params
)
1397 GET_CURRENT_CONTEXT(ctx
);
1398 GLint
*val
= (GLint
*) params
;
1399 const GLenum
*prop
= props
;
1402 struct gl_program_resource
*res
=
1403 _mesa_program_resource_find_index(shProg
, programInterface
, index
);
1405 /* No such resource found or bufSize negative. */
1406 if (!res
|| bufSize
< 0) {
1407 _mesa_error(ctx
, GL_INVALID_VALUE
,
1408 "glGetProgramResourceiv(%s index %d bufSize %d)",
1409 _mesa_enum_to_string(programInterface
), index
, bufSize
);
1413 /* Write propCount values until error occurs or bufSize reached. */
1414 for (int i
= 0; i
< propCount
&& i
< bufSize
; i
++, val
++, prop
++) {
1416 _mesa_program_resource_prop(shProg
, res
, index
, *prop
, val
,
1417 "glGetProgramResourceiv");
1419 /* Error happened. */
1420 if (props_written
== 0)
1423 amount
+= props_written
;
1426 /* If <length> is not NULL, the actual number of integer values
1427 * written to <params> will be written to <length>.
1434 validate_io(struct gl_program
*producer
, struct gl_program
*consumer
)
1436 if (producer
->sh
.data
->linked_stages
== consumer
->sh
.data
->linked_stages
)
1439 const bool producer_is_array_stage
=
1440 producer
->info
.stage
== MESA_SHADER_TESS_CTRL
;
1441 const bool consumer_is_array_stage
=
1442 consumer
->info
.stage
== MESA_SHADER_GEOMETRY
||
1443 consumer
->info
.stage
== MESA_SHADER_TESS_CTRL
||
1444 consumer
->info
.stage
== MESA_SHADER_TESS_EVAL
;
1448 gl_shader_variable
const **outputs
=
1449 (gl_shader_variable
const **) calloc(producer
->sh
.data
->NumProgramResourceList
,
1450 sizeof(gl_shader_variable
*));
1451 if (outputs
== NULL
)
1454 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1457 * At an interface between program objects, the set of inputs and
1458 * outputs are considered to match exactly if and only if:
1460 * - Every declared input variable has a matching output, as described
1462 * - There are no user-defined output variables declared without a
1463 * matching input variable declaration.
1465 * Every input has an output, and every output has an input. Scan the list
1466 * of producer resources once, and generate the list of outputs. As inputs
1467 * and outputs are matched, remove the matched outputs from the set. At
1468 * the end, the set must be empty. If the set is not empty, then there is
1469 * some output that did not have an input.
1471 unsigned num_outputs
= 0;
1472 for (unsigned i
= 0; i
< producer
->sh
.data
->NumProgramResourceList
; i
++) {
1473 struct gl_program_resource
*res
=
1474 &producer
->sh
.data
->ProgramResourceList
[i
];
1476 if (res
->Type
!= GL_PROGRAM_OUTPUT
)
1479 gl_shader_variable
const *const var
= RESOURCE_VAR(res
);
1481 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1484 * Built-in inputs or outputs do not affect interface matching.
1486 if (is_gl_identifier(var
->name
))
1489 outputs
[num_outputs
++] = var
;
1492 unsigned match_index
= 0;
1493 for (unsigned i
= 0; i
< consumer
->sh
.data
->NumProgramResourceList
; i
++) {
1494 struct gl_program_resource
*res
=
1495 &consumer
->sh
.data
->ProgramResourceList
[i
];
1497 if (res
->Type
!= GL_PROGRAM_INPUT
)
1500 gl_shader_variable
const *const consumer_var
= RESOURCE_VAR(res
);
1501 gl_shader_variable
const *producer_var
= NULL
;
1503 if (is_gl_identifier(consumer_var
->name
))
1506 /* Inputs with explicit locations match other outputs with explicit
1507 * locations by location instead of by name.
1509 if (consumer_var
->explicit_location
) {
1510 for (unsigned j
= 0; j
< num_outputs
; j
++) {
1511 const gl_shader_variable
*const var
= outputs
[j
];
1513 if (var
->explicit_location
&&
1514 consumer_var
->location
== var
->location
) {
1521 for (unsigned j
= 0; j
< num_outputs
; j
++) {
1522 const gl_shader_variable
*const var
= outputs
[j
];
1524 if (!var
->explicit_location
&&
1525 strcmp(consumer_var
->name
, var
->name
) == 0) {
1533 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1536 * - An output variable is considered to match an input variable in
1537 * the subsequent shader if:
1539 * - the two variables match in name, type, and qualification; or
1541 * - the two variables are declared with the same location
1542 * qualifier and match in type and qualification.
1544 if (producer_var
== NULL
) {
1549 /* An output cannot match more than one input, so remove the output from
1550 * the set of possible outputs.
1552 outputs
[match_index
] = NULL
;
1554 if (match_index
< num_outputs
)
1555 outputs
[match_index
] = outputs
[num_outputs
];
1557 /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
1559 * "Tessellation control shader per-vertex output variables and
1560 * blocks and tessellation control, tessellation evaluation, and
1561 * geometry shader per-vertex input variables and blocks are
1562 * required to be declared as arrays, with each element representing
1563 * input or output values for a single vertex of a multi-vertex
1564 * primitive. For the purposes of interface matching, such variables
1565 * and blocks are treated as though they were not declared as
1568 * So we unwrap those types before matching.
1570 const glsl_type
*consumer_type
= consumer_var
->type
;
1571 const glsl_type
*consumer_interface_type
= consumer_var
->interface_type
;
1572 const glsl_type
*producer_type
= producer_var
->type
;
1573 const glsl_type
*producer_interface_type
= producer_var
->interface_type
;
1575 if (consumer_is_array_stage
) {
1576 if (consumer_interface_type
) {
1577 /* the interface is the array; the underlying types should match */
1578 if (consumer_interface_type
->is_array() && !consumer_var
->patch
)
1579 consumer_interface_type
= consumer_interface_type
->fields
.array
;
1581 if (consumer_type
->is_array() && !consumer_var
->patch
)
1582 consumer_type
= consumer_type
->fields
.array
;
1586 if (producer_is_array_stage
) {
1587 if (producer_interface_type
) {
1588 /* the interface is the array; the underlying types should match */
1589 if (producer_interface_type
->is_array() && !producer_var
->patch
)
1590 producer_interface_type
= producer_interface_type
->fields
.array
;
1592 if (producer_type
->is_array() && !producer_var
->patch
)
1593 producer_type
= producer_type
->fields
.array
;
1597 if (producer_type
!= consumer_type
) {
1602 if (producer_interface_type
!= consumer_interface_type
) {
1607 /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
1609 * Qualifier Class| Qualifier |in/out
1610 * ---------------+-------------+------
1614 * ---------------+-------------+------
1615 * Auxiliary | centroid | No
1616 * ---------------+-------------+------
1618 * | Block layout| N/A
1622 * ---------------+-------------+------
1623 * Interpolation | smooth |
1625 * ---------------+-------------+------
1627 * Precision | mediump | Yes
1629 * ---------------+-------------+------
1630 * Variance | invariant | No
1631 * ---------------+-------------+------
1632 * Memory | all | N/A
1634 * Note that location mismatches are detected by the loops above that
1635 * find the producer variable that goes with the consumer variable.
1637 unsigned producer_interpolation
= producer_var
->interpolation
;
1638 unsigned consumer_interpolation
= consumer_var
->interpolation
;
1639 if (producer_interpolation
== INTERP_MODE_NONE
)
1640 producer_interpolation
= INTERP_MODE_SMOOTH
;
1641 if (consumer_interpolation
== INTERP_MODE_NONE
)
1642 consumer_interpolation
= INTERP_MODE_SMOOTH
;
1643 if (producer_interpolation
!= consumer_interpolation
) {
1648 if (producer_var
->precision
!= consumer_var
->precision
) {
1653 if (producer_var
->outermost_struct_type
!= consumer_var
->outermost_struct_type
) {
1661 return valid
&& num_outputs
== 0;
1665 * Validate inputs against outputs in a program pipeline.
1668 _mesa_validate_pipeline_io(struct gl_pipeline_object
*pipeline
)
1670 struct gl_program
**prog
= (struct gl_program
**) pipeline
->CurrentProgram
;
1672 /* Find first active stage in pipeline. */
1673 unsigned idx
, prev
= 0;
1674 for (idx
= 0; idx
< ARRAY_SIZE(pipeline
->CurrentProgram
); idx
++) {
1681 for (idx
= prev
+ 1; idx
< ARRAY_SIZE(pipeline
->CurrentProgram
); idx
++) {
1683 /* Pipeline might include both non-compute and a compute program, do
1684 * not attempt to validate varyings between non-compute and compute
1687 if (prog
[idx
]->info
.stage
== MESA_SHADER_COMPUTE
)
1690 if (!validate_io(prog
[prev
], prog
[idx
]))