2 * Mesa 3-D graphics library
4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "main/enums.h"
27 #include "main/macros.h"
28 #include "main/mtypes.h"
29 #include "main/shaderapi.h"
30 #include "main/shaderobj.h"
31 #include "main/context.h"
32 #include "program_resource.h"
33 #include "compiler/glsl/ir_uniform.h"
35 supported_interface_enum(struct gl_context
*ctx
, GLenum iface
)
39 case GL_UNIFORM_BLOCK
:
40 case GL_PROGRAM_INPUT
:
41 case GL_PROGRAM_OUTPUT
:
42 case GL_TRANSFORM_FEEDBACK_BUFFER
:
43 case GL_TRANSFORM_FEEDBACK_VARYING
:
44 case GL_ATOMIC_COUNTER_BUFFER
:
45 case GL_BUFFER_VARIABLE
:
46 case GL_SHADER_STORAGE_BLOCK
:
48 case GL_VERTEX_SUBROUTINE
:
49 case GL_FRAGMENT_SUBROUTINE
:
50 case GL_VERTEX_SUBROUTINE_UNIFORM
:
51 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
52 return _mesa_has_shader_subroutine(ctx
);
53 case GL_GEOMETRY_SUBROUTINE
:
54 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
55 return _mesa_has_geometry_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
56 case GL_COMPUTE_SUBROUTINE
:
57 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
58 return _mesa_has_compute_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
59 case GL_TESS_CONTROL_SUBROUTINE
:
60 case GL_TESS_EVALUATION_SUBROUTINE
:
61 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
62 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
63 return _mesa_has_tessellation(ctx
) && _mesa_has_shader_subroutine(ctx
);
69 static struct gl_shader_program
*
70 lookup_linked_program(GLuint program
,
72 bool raise_link_error
)
74 GET_CURRENT_CONTEXT(ctx
);
75 struct gl_shader_program
*prog
=
76 _mesa_lookup_shader_program_err(ctx
, program
, caller
);
81 if (prog
->LinkStatus
== GL_FALSE
) {
83 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)",
91 stage_from_program_interface(GLenum programInterface
)
93 switch(programInterface
) {
94 case GL_VERTEX_SUBROUTINE_UNIFORM
:
95 return MESA_SHADER_VERTEX
;
96 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
97 return MESA_SHADER_TESS_CTRL
;
98 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
99 return MESA_SHADER_TESS_EVAL
;
100 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
101 return MESA_SHADER_GEOMETRY
;
102 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
103 return MESA_SHADER_FRAGMENT
;
104 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
105 return MESA_SHADER_COMPUTE
;
107 assert(!"unexpected programInterface value");
111 static struct gl_linked_shader
*
112 lookup_linked_shader(GLuint program
,
113 GLenum programInterface
,
116 struct gl_shader_program
*shLinkedProg
=
117 lookup_linked_program(program
, caller
, false);
118 gl_shader_stage stage
= stage_from_program_interface(programInterface
);
123 return shLinkedProg
->_LinkedShaders
[stage
];
127 is_subroutine_uniform_program_interface(GLenum programInterface
)
129 switch(programInterface
) {
130 case GL_VERTEX_SUBROUTINE_UNIFORM
:
131 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
132 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
133 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
134 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
135 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
143 _mesa_GetProgramInterfaceiv(GLuint program
, GLenum programInterface
,
144 GLenum pname
, GLint
*params
)
146 GET_CURRENT_CONTEXT(ctx
);
148 if (MESA_VERBOSE
& VERBOSE_API
) {
149 _mesa_debug(ctx
, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
150 program
, _mesa_enum_to_string(programInterface
),
151 _mesa_enum_to_string(pname
), params
);
155 struct gl_shader_program
*shProg
=
156 _mesa_lookup_shader_program_err(ctx
, program
,
157 "glGetProgramInterfaceiv");
162 _mesa_error(ctx
, GL_INVALID_OPERATION
,
163 "glGetProgramInterfaceiv(params NULL)");
167 /* Validate interface. */
168 if (!supported_interface_enum(ctx
, programInterface
)) {
169 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramInterfaceiv(%s)",
170 _mesa_enum_to_string(programInterface
));
174 /* Validate pname against interface. */
176 case GL_ACTIVE_RESOURCES
:
177 if (is_subroutine_uniform_program_interface(programInterface
)) {
178 /* ARB_program_interface_query doesn't explicitly says that those
179 * uniforms would need a linked shader, or that should fail if it is
180 * not the case, but Section 7.6 (Uniform Variables) of the OpenGL
181 * 4.4 Core Profile says:
183 * "A uniform is considered an active uniform if the compiler and
184 * linker determine that the uniform will actually be accessed
185 * when the executable code is executed. In cases where the
186 * compiler and linker cannot make a conclusive determination,
187 * the uniform will be considered active."
189 * So in order to know the real number of active subroutine uniforms
190 * we would need a linked shader .
192 * At the same time, Section 7.3 (Program Objects) of the OpenGL 4.4
195 * "The GL provides various commands allowing applications to
196 * enumerate and query properties of active variables and in-
197 * terface blocks for a specified program. If one of these
198 * commands is called with a program for which LinkProgram
199 * succeeded, the information recorded when the program was
200 * linked is returned. If one of these commands is called with a
201 * program for which LinkProgram failed, no error is generated
202 * unless otherwise noted."
204 * "If one of these commands is called with a program for which
205 * LinkProgram had never been called, no error is generated
206 * unless otherwise noted, and the program object is considered
207 * to have no active variables or interface blocks."
209 * So if the program is not linked we will return 0.
211 struct gl_linked_shader
*sh
=
212 lookup_linked_shader(program
, programInterface
, "glGetProgramInterfaceiv");
214 *params
= sh
? sh
->NumSubroutineUniforms
: 0;
216 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++)
217 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
)
221 case GL_MAX_NAME_LENGTH
:
222 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
223 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
) {
224 _mesa_error(ctx
, GL_INVALID_OPERATION
,
225 "glGetProgramInterfaceiv(%s pname %s)",
226 _mesa_enum_to_string(programInterface
),
227 _mesa_enum_to_string(pname
));
230 /* Name length consists of base name, 3 additional chars '[0]' if
231 * resource is an array and finally 1 char for string terminator.
233 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
234 if (shProg
->ProgramResourceList
[i
].Type
!= programInterface
)
237 _mesa_program_resource_name_len(&shProg
->ProgramResourceList
[i
]);
238 *params
= MAX2(*params
, len
+ 1);
241 case GL_MAX_NUM_ACTIVE_VARIABLES
:
242 switch (programInterface
) {
243 case GL_UNIFORM_BLOCK
:
244 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
245 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
246 struct gl_uniform_block
*block
=
247 (struct gl_uniform_block
*)
248 shProg
->ProgramResourceList
[i
].Data
;
249 *params
= MAX2(*params
, block
->NumUniforms
);
253 case GL_SHADER_STORAGE_BLOCK
:
254 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
255 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
256 struct gl_uniform_block
*block
=
257 (struct gl_uniform_block
*)
258 shProg
->ProgramResourceList
[i
].Data
;
259 GLint block_params
= 0;
260 for (unsigned j
= 0; j
< block
->NumUniforms
; j
++) {
261 const char *iname
= block
->Uniforms
[j
].IndexName
;
262 struct gl_program_resource
*uni
=
263 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
269 *params
= MAX2(*params
, block_params
);
273 case GL_ATOMIC_COUNTER_BUFFER
:
274 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
275 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
276 struct gl_active_atomic_buffer
*buffer
=
277 (struct gl_active_atomic_buffer
*)
278 shProg
->ProgramResourceList
[i
].Data
;
279 *params
= MAX2(*params
, buffer
->NumUniforms
);
283 case GL_TRANSFORM_FEEDBACK_BUFFER
:
284 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
285 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
286 struct gl_transform_feedback_buffer
*buffer
=
287 (struct gl_transform_feedback_buffer
*)
288 shProg
->ProgramResourceList
[i
].Data
;
289 *params
= MAX2(*params
, buffer
->NumVaryings
);
294 _mesa_error(ctx
, GL_INVALID_OPERATION
,
295 "glGetProgramInterfaceiv(%s pname %s)",
296 _mesa_enum_to_string(programInterface
),
297 _mesa_enum_to_string(pname
));
300 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES
:
301 switch (programInterface
) {
302 case GL_VERTEX_SUBROUTINE_UNIFORM
:
303 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
304 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
305 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
306 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
307 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
: {
308 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
309 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
310 struct gl_uniform_storage
*uni
=
311 (struct gl_uniform_storage
*)
312 shProg
->ProgramResourceList
[i
].Data
;
313 *params
= MAX2(*params
, uni
->num_compatible_subroutines
);
320 _mesa_error(ctx
, GL_INVALID_OPERATION
,
321 "glGetProgramInterfaceiv(%s pname %s)",
322 _mesa_enum_to_string(programInterface
),
323 _mesa_enum_to_string(pname
));
327 _mesa_error(ctx
, GL_INVALID_OPERATION
,
328 "glGetProgramInterfaceiv(pname %s)",
329 _mesa_enum_to_string(pname
));
334 is_xfb_marker(const char *str
)
336 static const char *markers
[] = {
338 "gl_SkipComponents1",
339 "gl_SkipComponents2",
340 "gl_SkipComponents3",
341 "gl_SkipComponents4",
344 const char **m
= markers
;
346 if (strncmp(str
, "gl_", 3) != 0)
350 if (strcmp(*m
, str
) == 0)
357 _mesa_GetProgramResourceIndex(GLuint program
, GLenum programInterface
,
360 GET_CURRENT_CONTEXT(ctx
);
362 if (MESA_VERBOSE
& VERBOSE_API
) {
363 _mesa_debug(ctx
, "glGetProgramResourceIndex(%u, %s, %s)\n",
364 program
, _mesa_enum_to_string(programInterface
), name
);
367 unsigned array_index
= 0;
368 struct gl_program_resource
*res
;
369 struct gl_shader_program
*shProg
=
370 _mesa_lookup_shader_program_err(ctx
, program
,
371 "glGetProgramResourceIndex");
372 if (!shProg
|| !name
)
373 return GL_INVALID_INDEX
;
375 if (!supported_interface_enum(ctx
, programInterface
)) {
376 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
377 _mesa_enum_to_string(programInterface
));
378 return GL_INVALID_INDEX
;
381 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
382 * should be returned when querying the index assigned to the special names
383 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
384 * "gl_SkipComponents3", and "gl_SkipComponents4".
386 if (programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
&&
388 return GL_INVALID_INDEX
;
390 switch (programInterface
) {
391 case GL_TESS_CONTROL_SUBROUTINE
:
392 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
393 case GL_TESS_EVALUATION_SUBROUTINE
:
394 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
395 case GL_COMPUTE_SUBROUTINE
:
396 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
397 case GL_GEOMETRY_SUBROUTINE
:
398 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
399 case GL_VERTEX_SUBROUTINE
:
400 case GL_FRAGMENT_SUBROUTINE
:
401 case GL_VERTEX_SUBROUTINE_UNIFORM
:
402 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
403 case GL_PROGRAM_INPUT
:
404 case GL_PROGRAM_OUTPUT
:
406 case GL_BUFFER_VARIABLE
:
407 case GL_TRANSFORM_FEEDBACK_VARYING
:
408 case GL_UNIFORM_BLOCK
:
409 case GL_SHADER_STORAGE_BLOCK
:
410 res
= _mesa_program_resource_find_name(shProg
, programInterface
, name
,
412 if (!res
|| array_index
> 0)
413 return GL_INVALID_INDEX
;
415 return _mesa_program_resource_index(shProg
, res
);
416 case GL_ATOMIC_COUNTER_BUFFER
:
417 case GL_TRANSFORM_FEEDBACK_BUFFER
:
419 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
420 _mesa_enum_to_string(programInterface
));
423 return GL_INVALID_INDEX
;
427 _mesa_GetProgramResourceName(GLuint program
, GLenum programInterface
,
428 GLuint index
, GLsizei bufSize
, GLsizei
*length
,
431 GET_CURRENT_CONTEXT(ctx
);
433 if (MESA_VERBOSE
& VERBOSE_API
) {
434 _mesa_debug(ctx
, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
435 program
, _mesa_enum_to_string(programInterface
), index
,
436 bufSize
, length
, name
);
439 struct gl_shader_program
*shProg
=
440 _mesa_lookup_shader_program_err(ctx
, program
,
441 "glGetProgramResourceName");
443 if (!shProg
|| !name
)
446 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
447 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
||
448 !supported_interface_enum(ctx
, programInterface
)) {
449 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceName(%s)",
450 _mesa_enum_to_string(programInterface
));
454 _mesa_get_program_resource_name(shProg
, programInterface
, index
, bufSize
,
455 length
, name
, "glGetProgramResourceName");
459 _mesa_GetProgramResourceiv(GLuint program
, GLenum programInterface
,
460 GLuint index
, GLsizei propCount
,
461 const GLenum
*props
, GLsizei bufSize
,
462 GLsizei
*length
, GLint
*params
)
464 GET_CURRENT_CONTEXT(ctx
);
466 if (MESA_VERBOSE
& VERBOSE_API
) {
467 _mesa_debug(ctx
, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
468 program
, _mesa_enum_to_string(programInterface
), index
,
469 propCount
, props
, bufSize
, length
, params
);
472 struct gl_shader_program
*shProg
=
473 _mesa_lookup_shader_program_err(ctx
, program
, "glGetProgramResourceiv");
475 if (!shProg
|| !params
)
478 /* The error INVALID_VALUE is generated if <propCount> is zero.
479 * Note that we check < 0 here because it makes sense to bail early.
481 if (propCount
<= 0) {
482 _mesa_error(ctx
, GL_INVALID_VALUE
,
483 "glGetProgramResourceiv(propCount <= 0)");
487 _mesa_get_program_resourceiv(shProg
, programInterface
, index
,
488 propCount
, props
, bufSize
, length
, params
);
492 _mesa_GetProgramResourceLocation(GLuint program
, GLenum programInterface
,
495 GET_CURRENT_CONTEXT(ctx
);
497 if (MESA_VERBOSE
& VERBOSE_API
) {
498 _mesa_debug(ctx
, "glGetProgramResourceLocation(%u, %s, %s)\n",
499 program
, _mesa_enum_to_string(programInterface
), name
);
502 struct gl_shader_program
*shProg
=
503 lookup_linked_program(program
, "glGetProgramResourceLocation", true);
505 if (!shProg
|| !name
)
508 /* Validate programInterface. */
509 switch (programInterface
) {
511 case GL_PROGRAM_INPUT
:
512 case GL_PROGRAM_OUTPUT
:
515 case GL_VERTEX_SUBROUTINE_UNIFORM
:
516 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
517 if (!_mesa_has_shader_subroutine(ctx
))
520 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
521 if (!_mesa_has_geometry_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
524 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
525 if (!_mesa_has_compute_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
528 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
529 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
530 if (!_mesa_has_tessellation(ctx
) || !_mesa_has_shader_subroutine(ctx
))
537 return _mesa_program_resource_location(shProg
, programInterface
, name
);
539 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceLocation(%s %s)",
540 _mesa_enum_to_string(programInterface
), name
);
545 * Returns output index for dual source blending.
548 _mesa_GetProgramResourceLocationIndex(GLuint program
, GLenum programInterface
,
551 GET_CURRENT_CONTEXT(ctx
);
553 if (MESA_VERBOSE
& VERBOSE_API
) {
554 _mesa_debug(ctx
, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
555 program
, _mesa_enum_to_string(programInterface
), name
);
558 struct gl_shader_program
*shProg
=
559 lookup_linked_program(program
, "glGetProgramResourceLocationIndex", true);
561 if (!shProg
|| !name
)
564 /* From the GL_ARB_program_interface_query spec:
566 * "For GetProgramResourceLocationIndex, <programInterface> must be
569 if (programInterface
!= GL_PROGRAM_OUTPUT
) {
570 _mesa_error(ctx
, GL_INVALID_ENUM
,
571 "glGetProgramResourceLocationIndex(%s)",
572 _mesa_enum_to_string(programInterface
));
576 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,