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/core.h"
32 #include "glsl_symbol_table.h"
34 #include "shaderobj.h"
35 #include "program/hash_table.h"
36 #include "../glsl/program.h"
38 #include "main/enums.h"
41 #include "shaderapi.h"
45 * Declare convenience functions to return resource data in a given type.
46 * Warning! this is not type safe so be *very* careful when using these.
48 #define DECL_RESOURCE_FUNC(name, type) \
49 const type * RESOURCE_ ## name (gl_program_resource *res) { \
51 return (type *) res->Data; \
54 DECL_RESOURCE_FUNC(VAR
, ir_variable
);
55 DECL_RESOURCE_FUNC(UBO
, gl_uniform_block
);
56 DECL_RESOURCE_FUNC(UNI
, gl_uniform_storage
);
57 DECL_RESOURCE_FUNC(ATC
, gl_active_atomic_buffer
);
58 DECL_RESOURCE_FUNC(XFB
, gl_transform_feedback_varying_info
);
61 _mesa_BindAttribLocation(GLhandleARB program
, GLuint index
,
62 const GLcharARB
*name
)
64 GET_CURRENT_CONTEXT(ctx
);
66 struct gl_shader_program
*const shProg
=
67 _mesa_lookup_shader_program_err(ctx
, program
, "glBindAttribLocation");
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(index)");
85 /* Replace the current value if it's already in the list. Add
86 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
87 * between built-in attributes and user-defined attributes.
89 shProg
->AttributeBindings
->put(index
+ VERT_ATTRIB_GENERIC0
, name
);
92 * Note that this attribute binding won't go into effect until
93 * glLinkProgram is called again.
98 is_active_attrib(const ir_variable
*var
)
103 switch (var
->data
.mode
) {
104 case ir_var_shader_in
:
105 return var
->data
.location
!= -1;
107 case ir_var_system_value
:
108 /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
109 * "For GetActiveAttrib, all active vertex shader input variables
110 * are enumerated, including the special built-in inputs gl_VertexID
111 * and gl_InstanceID."
113 return var
->data
.location
== SYSTEM_VALUE_VERTEX_ID
||
114 var
->data
.location
== SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
||
115 var
->data
.location
== SYSTEM_VALUE_INSTANCE_ID
;
123 _mesa_GetActiveAttrib(GLhandleARB program
, GLuint desired_index
,
124 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
125 GLenum
* type
, GLcharARB
* name
)
127 GET_CURRENT_CONTEXT(ctx
);
128 struct gl_shader_program
*shProg
;
131 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(maxLength < 0)");
135 shProg
= _mesa_lookup_shader_program_err(ctx
, program
, "glGetActiveAttrib");
139 if (!shProg
->LinkStatus
) {
140 _mesa_error(ctx
, GL_INVALID_VALUE
,
141 "glGetActiveAttrib(program not linked)");
145 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
146 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(no vertex shader)");
150 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
151 unsigned current_index
= 0;
153 foreach_in_list(ir_instruction
, node
, ir
) {
154 const ir_variable
*const var
= node
->as_variable();
156 if (!is_active_attrib(var
))
159 if (current_index
== desired_index
) {
160 const char *var_name
= var
->name
;
162 /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
163 * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
166 if (var
->data
.mode
== ir_var_system_value
&&
167 var
->data
.location
== SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
) {
168 var_name
= "gl_VertexID";
171 _mesa_copy_string(name
, maxLength
, length
, var_name
);
174 *size
= (var
->type
->is_array()) ? var
->type
->length
: 1;
177 *type
= var
->type
->gl_type
;
185 /* If the loop did not return early, the caller must have asked for
186 * an index that did not exit. Set an error.
188 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(index)");
191 /* Locations associated with shader variables (array or non-array) can be
192 * queried using its base name or using the base name appended with the
193 * valid array index. For example, in case of below vertex shader, valid
194 * queries can be made to know the location of "xyz", "array", "array[0]",
195 * "array[1]", "array[2]" and "array[3]". In this example index reurned
196 * will be 0, 0, 0, 1, 2, 3 respectively.
199 * layout(location=0) in vec4 xyz;
200 * layout(location=1) in vec4[4] array;
204 * This requirement came up with the addition of ARB_program_interface_query
205 * to OpenGL 4.3 specification. See page 101 (page 122 of the PDF) for details.
207 * This utility function is used by:
208 * _mesa_GetAttribLocation
209 * _mesa_GetFragDataLocation
210 * _mesa_GetFragDataIndex
213 * if the 'name' string matches var->name.
214 * Returns 'matched index':
215 * if the 'name' string matches var->name appended with valid array index.
218 get_matching_index(const ir_variable
*const var
, const char *name
) {
220 const char *const paren
= strchr(name
, '[');
221 const unsigned len
= (paren
!= NULL
) ? paren
- name
: strlen(name
);
224 if (!var
->type
->is_array())
228 idx
= (unsigned) strtol(paren
+ 1, &endptr
, 10);
229 const unsigned idx_len
= endptr
!= (paren
+ 1) ? endptr
- paren
- 1 : 0;
231 /* Validate the sub string representing index in 'name' string */
232 if ((idx
> 0 && paren
[1] == '0') /* leading zeroes */
233 || (idx
== 0 && idx_len
> 1) /* all zeroes */
234 || paren
[1] == ' ' /* whitespace */
235 || endptr
[0] != ']' /* closing brace */
236 || endptr
[1] != '\0' /* null char */
237 || idx_len
== 0 /* missing index */
238 || idx
>= var
->type
->length
) /* exceeding array bound */
242 if (strncmp(var
->name
, name
, len
) == 0 && var
->name
[len
] == '\0')
249 _mesa_GetAttribLocation(GLhandleARB program
, const GLcharARB
* name
)
251 GET_CURRENT_CONTEXT(ctx
);
252 struct gl_shader_program
*const shProg
=
253 _mesa_lookup_shader_program_err(ctx
, program
, "glGetAttribLocation");
259 if (!shProg
->LinkStatus
) {
260 _mesa_error(ctx
, GL_INVALID_OPERATION
,
261 "glGetAttribLocation(program not linked)");
268 /* Not having a vertex shader is not an error.
270 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
)
273 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
274 foreach_in_list(ir_instruction
, node
, ir
) {
275 const ir_variable
*const var
= node
->as_variable();
277 /* The extra check against VERT_ATTRIB_GENERIC0 is because
278 * glGetAttribLocation cannot be used on "conventional" attributes.
280 * From page 95 of the OpenGL 3.0 spec:
282 * "If name is not an active attribute, if name is a conventional
283 * attribute, or if an error occurs, -1 will be returned."
286 || var
->data
.mode
!= ir_var_shader_in
287 || var
->data
.location
== -1
288 || var
->data
.location
< VERT_ATTRIB_GENERIC0
)
291 int index
= get_matching_index(var
, (const char *) name
);
294 return var
->data
.location
+ index
- VERT_ATTRIB_GENERIC0
;
302 _mesa_count_active_attribs(struct gl_shader_program
*shProg
)
304 if (!shProg
->LinkStatus
305 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
309 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
312 foreach_in_list(ir_instruction
, node
, ir
) {
313 const ir_variable
*const var
= node
->as_variable();
315 if (!is_active_attrib(var
))
326 _mesa_longest_attribute_name_length(struct gl_shader_program
*shProg
)
328 if (!shProg
->LinkStatus
329 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
333 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
336 foreach_in_list(ir_instruction
, node
, ir
) {
337 const ir_variable
*const var
= node
->as_variable();
340 || var
->data
.mode
!= ir_var_shader_in
341 || var
->data
.location
== -1)
344 const size_t len
= strlen(var
->name
);
353 _mesa_BindFragDataLocation(GLuint program
, GLuint colorNumber
,
356 _mesa_BindFragDataLocationIndexed(program
, colorNumber
, 0, name
);
360 _mesa_BindFragDataLocationIndexed(GLuint program
, GLuint colorNumber
,
361 GLuint index
, const GLchar
*name
)
363 GET_CURRENT_CONTEXT(ctx
);
365 struct gl_shader_program
*const shProg
=
366 _mesa_lookup_shader_program_err(ctx
, program
, "glBindFragDataLocationIndexed");
373 if (strncmp(name
, "gl_", 3) == 0) {
374 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindFragDataLocationIndexed(illegal name)");
379 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(index)");
383 if (index
== 0 && colorNumber
>= ctx
->Const
.MaxDrawBuffers
) {
384 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
388 if (index
== 1 && colorNumber
>= ctx
->Const
.MaxDualSourceDrawBuffers
) {
389 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
393 /* Replace the current value if it's already in the list. Add
394 * FRAG_RESULT_DATA0 because that's how the linker differentiates
395 * between built-in attributes and user-defined attributes.
397 shProg
->FragDataBindings
->put(colorNumber
+ FRAG_RESULT_DATA0
, name
);
398 shProg
->FragDataIndexBindings
->put(index
, name
);
400 * Note that this binding won't go into effect until
401 * glLinkProgram is called again.
407 _mesa_GetFragDataIndex(GLuint program
, const GLchar
*name
)
409 GET_CURRENT_CONTEXT(ctx
);
410 struct gl_shader_program
*const shProg
=
411 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataIndex");
417 if (!shProg
->LinkStatus
) {
418 _mesa_error(ctx
, GL_INVALID_OPERATION
,
419 "glGetFragDataIndex(program not linked)");
426 if (strncmp(name
, "gl_", 3) == 0) {
427 _mesa_error(ctx
, GL_INVALID_OPERATION
,
428 "glGetFragDataIndex(illegal name)");
432 /* Not having a fragment shader is not an error.
434 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
437 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
438 foreach_in_list(ir_instruction
, node
, ir
) {
439 const ir_variable
*const var
= node
->as_variable();
441 /* The extra check against FRAG_RESULT_DATA0 is because
442 * glGetFragDataLocation cannot be used on "conventional" attributes.
444 * From page 95 of the OpenGL 3.0 spec:
446 * "If name is not an active attribute, if name is a conventional
447 * attribute, or if an error occurs, -1 will be returned."
450 || var
->data
.mode
!= ir_var_shader_out
451 || var
->data
.location
== -1
452 || var
->data
.location
< FRAG_RESULT_DATA0
)
455 if (get_matching_index(var
, (const char *) name
) >= 0)
456 return var
->data
.index
;
463 _mesa_GetFragDataLocation(GLuint program
, const GLchar
*name
)
465 GET_CURRENT_CONTEXT(ctx
);
466 struct gl_shader_program
*const shProg
=
467 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataLocation");
473 if (!shProg
->LinkStatus
) {
474 _mesa_error(ctx
, GL_INVALID_OPERATION
,
475 "glGetFragDataLocation(program not linked)");
482 if (strncmp(name
, "gl_", 3) == 0) {
483 _mesa_error(ctx
, GL_INVALID_OPERATION
,
484 "glGetFragDataLocation(illegal name)");
488 /* Not having a fragment shader is not an error.
490 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
493 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
494 foreach_in_list(ir_instruction
, node
, ir
) {
495 const ir_variable
*const var
= node
->as_variable();
497 /* The extra check against FRAG_RESULT_DATA0 is because
498 * glGetFragDataLocation cannot be used on "conventional" attributes.
500 * From page 95 of the OpenGL 3.0 spec:
502 * "If name is not an active attribute, if name is a conventional
503 * attribute, or if an error occurs, -1 will be returned."
506 || var
->data
.mode
!= ir_var_shader_out
507 || var
->data
.location
== -1
508 || var
->data
.location
< FRAG_RESULT_DATA0
)
511 int index
= get_matching_index(var
, (const char *) name
);
514 return var
->data
.location
+ index
- FRAG_RESULT_DATA0
;
521 _mesa_program_resource_name(struct gl_program_resource
*res
)
524 case GL_UNIFORM_BLOCK
:
525 return RESOURCE_UBO(res
)->Name
;
526 case GL_TRANSFORM_FEEDBACK_VARYING
:
527 return RESOURCE_XFB(res
)->Name
;
528 case GL_PROGRAM_INPUT
:
529 case GL_PROGRAM_OUTPUT
:
530 return RESOURCE_VAR(res
)->name
;
532 return RESOURCE_UNI(res
)->name
;
534 assert(!"support for resource type not implemented");
541 _mesa_program_resource_array_size(struct gl_program_resource
*res
)
544 case GL_TRANSFORM_FEEDBACK_VARYING
:
545 return RESOURCE_XFB(res
)->Size
> 1 ?
546 RESOURCE_XFB(res
)->Size
: 0;
547 case GL_PROGRAM_INPUT
:
548 case GL_PROGRAM_OUTPUT
:
549 return RESOURCE_VAR(res
)->data
.max_array_access
;
551 return RESOURCE_UNI(res
)->array_elements
;
552 case GL_ATOMIC_COUNTER_BUFFER
:
553 case GL_UNIFORM_BLOCK
:
556 assert(!"support for resource type not implemented");