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
);
70 _mesa_GetProgramInterfaceiv(GLuint program
, GLenum programInterface
,
71 GLenum pname
, GLint
*params
)
73 GET_CURRENT_CONTEXT(ctx
);
75 if (MESA_VERBOSE
& VERBOSE_API
) {
76 _mesa_debug(ctx
, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
77 program
, _mesa_enum_to_string(programInterface
),
78 _mesa_enum_to_string(pname
), params
);
82 struct gl_shader_program
*shProg
=
83 _mesa_lookup_shader_program_err(ctx
, program
,
84 "glGetProgramInterfaceiv");
89 _mesa_error(ctx
, GL_INVALID_OPERATION
,
90 "glGetProgramInterfaceiv(params NULL)");
94 /* Validate interface. */
95 if (!supported_interface_enum(ctx
, programInterface
)) {
96 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramInterfaceiv(%s)",
97 _mesa_enum_to_string(programInterface
));
101 /* Validate pname against interface. */
103 case GL_ACTIVE_RESOURCES
:
104 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++)
105 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
)
108 case GL_MAX_NAME_LENGTH
:
109 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
110 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
) {
111 _mesa_error(ctx
, GL_INVALID_OPERATION
,
112 "glGetProgramInterfaceiv(%s pname %s)",
113 _mesa_enum_to_string(programInterface
),
114 _mesa_enum_to_string(pname
));
117 /* Name length consists of base name, 3 additional chars '[0]' if
118 * resource is an array and finally 1 char for string terminator.
120 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
121 if (shProg
->ProgramResourceList
[i
].Type
!= programInterface
)
124 _mesa_program_resource_name_len(&shProg
->ProgramResourceList
[i
]);
125 *params
= MAX2(*params
, len
+ 1);
128 case GL_MAX_NUM_ACTIVE_VARIABLES
:
129 switch (programInterface
) {
130 case GL_UNIFORM_BLOCK
:
131 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
132 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
133 struct gl_uniform_block
*block
=
134 (struct gl_uniform_block
*)
135 shProg
->ProgramResourceList
[i
].Data
;
136 *params
= MAX2(*params
, block
->NumUniforms
);
140 case GL_SHADER_STORAGE_BLOCK
:
141 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
142 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
143 struct gl_uniform_block
*block
=
144 (struct gl_uniform_block
*)
145 shProg
->ProgramResourceList
[i
].Data
;
146 GLint block_params
= 0;
147 for (unsigned j
= 0; j
< block
->NumUniforms
; j
++) {
148 const char *iname
= block
->Uniforms
[j
].IndexName
;
149 struct gl_program_resource
*uni
=
150 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
156 *params
= MAX2(*params
, block_params
);
160 case GL_ATOMIC_COUNTER_BUFFER
:
161 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
162 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
163 struct gl_active_atomic_buffer
*buffer
=
164 (struct gl_active_atomic_buffer
*)
165 shProg
->ProgramResourceList
[i
].Data
;
166 *params
= MAX2(*params
, buffer
->NumUniforms
);
170 case GL_TRANSFORM_FEEDBACK_BUFFER
:
171 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
172 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
173 struct gl_transform_feedback_buffer
*buffer
=
174 (struct gl_transform_feedback_buffer
*)
175 shProg
->ProgramResourceList
[i
].Data
;
176 *params
= MAX2(*params
, buffer
->NumVaryings
);
181 _mesa_error(ctx
, GL_INVALID_OPERATION
,
182 "glGetProgramInterfaceiv(%s pname %s)",
183 _mesa_enum_to_string(programInterface
),
184 _mesa_enum_to_string(pname
));
187 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES
:
188 switch (programInterface
) {
189 case GL_VERTEX_SUBROUTINE_UNIFORM
:
190 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
191 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
192 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
193 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
194 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
: {
195 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
196 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
197 struct gl_uniform_storage
*uni
=
198 (struct gl_uniform_storage
*)
199 shProg
->ProgramResourceList
[i
].Data
;
200 *params
= MAX2(*params
, uni
->num_compatible_subroutines
);
207 _mesa_error(ctx
, GL_INVALID_OPERATION
,
208 "glGetProgramInterfaceiv(%s pname %s)",
209 _mesa_enum_to_string(programInterface
),
210 _mesa_enum_to_string(pname
));
214 _mesa_error(ctx
, GL_INVALID_OPERATION
,
215 "glGetProgramInterfaceiv(pname %s)",
216 _mesa_enum_to_string(pname
));
221 is_xfb_marker(const char *str
)
223 static const char *markers
[] = {
225 "gl_SkipComponents1",
226 "gl_SkipComponents2",
227 "gl_SkipComponents3",
228 "gl_SkipComponents4",
231 const char **m
= markers
;
233 if (strncmp(str
, "gl_", 3) != 0)
237 if (strcmp(*m
, str
) == 0)
244 _mesa_GetProgramResourceIndex(GLuint program
, GLenum programInterface
,
247 GET_CURRENT_CONTEXT(ctx
);
249 if (MESA_VERBOSE
& VERBOSE_API
) {
250 _mesa_debug(ctx
, "glGetProgramResourceIndex(%u, %s, %s)\n",
251 program
, _mesa_enum_to_string(programInterface
), name
);
254 unsigned array_index
= 0;
255 struct gl_program_resource
*res
;
256 struct gl_shader_program
*shProg
=
257 _mesa_lookup_shader_program_err(ctx
, program
,
258 "glGetProgramResourceIndex");
259 if (!shProg
|| !name
)
260 return GL_INVALID_INDEX
;
262 if (!supported_interface_enum(ctx
, programInterface
)) {
263 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
264 _mesa_enum_to_string(programInterface
));
265 return GL_INVALID_INDEX
;
268 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
269 * should be returned when querying the index assigned to the special names
270 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
271 * "gl_SkipComponents3", and "gl_SkipComponents4".
273 if (programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
&&
275 return GL_INVALID_INDEX
;
277 switch (programInterface
) {
278 case GL_TESS_CONTROL_SUBROUTINE
:
279 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
280 case GL_TESS_EVALUATION_SUBROUTINE
:
281 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
282 case GL_COMPUTE_SUBROUTINE
:
283 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
284 case GL_GEOMETRY_SUBROUTINE
:
285 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
286 case GL_VERTEX_SUBROUTINE
:
287 case GL_FRAGMENT_SUBROUTINE
:
288 case GL_VERTEX_SUBROUTINE_UNIFORM
:
289 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
290 case GL_PROGRAM_INPUT
:
291 case GL_PROGRAM_OUTPUT
:
293 case GL_BUFFER_VARIABLE
:
294 case GL_TRANSFORM_FEEDBACK_VARYING
:
295 case GL_UNIFORM_BLOCK
:
296 case GL_SHADER_STORAGE_BLOCK
:
297 res
= _mesa_program_resource_find_name(shProg
, programInterface
, name
,
299 if (!res
|| array_index
> 0)
300 return GL_INVALID_INDEX
;
302 return _mesa_program_resource_index(shProg
, res
);
303 case GL_ATOMIC_COUNTER_BUFFER
:
304 case GL_TRANSFORM_FEEDBACK_BUFFER
:
306 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
307 _mesa_enum_to_string(programInterface
));
310 return GL_INVALID_INDEX
;
314 _mesa_GetProgramResourceName(GLuint program
, GLenum programInterface
,
315 GLuint index
, GLsizei bufSize
, GLsizei
*length
,
318 GET_CURRENT_CONTEXT(ctx
);
320 if (MESA_VERBOSE
& VERBOSE_API
) {
321 _mesa_debug(ctx
, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
322 program
, _mesa_enum_to_string(programInterface
), index
,
323 bufSize
, length
, name
);
326 struct gl_shader_program
*shProg
=
327 _mesa_lookup_shader_program_err(ctx
, program
,
328 "glGetProgramResourceName");
330 if (!shProg
|| !name
)
333 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
334 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
||
335 !supported_interface_enum(ctx
, programInterface
)) {
336 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceName(%s)",
337 _mesa_enum_to_string(programInterface
));
341 _mesa_get_program_resource_name(shProg
, programInterface
, index
, bufSize
,
342 length
, name
, "glGetProgramResourceName");
346 _mesa_GetProgramResourceiv(GLuint program
, GLenum programInterface
,
347 GLuint index
, GLsizei propCount
,
348 const GLenum
*props
, GLsizei bufSize
,
349 GLsizei
*length
, GLint
*params
)
351 GET_CURRENT_CONTEXT(ctx
);
353 if (MESA_VERBOSE
& VERBOSE_API
) {
354 _mesa_debug(ctx
, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
355 program
, _mesa_enum_to_string(programInterface
), index
,
356 propCount
, props
, bufSize
, length
, params
);
359 struct gl_shader_program
*shProg
=
360 _mesa_lookup_shader_program_err(ctx
, program
, "glGetProgramResourceiv");
362 if (!shProg
|| !params
)
365 /* The error INVALID_VALUE is generated if <propCount> is zero.
366 * Note that we check < 0 here because it makes sense to bail early.
368 if (propCount
<= 0) {
369 _mesa_error(ctx
, GL_INVALID_VALUE
,
370 "glGetProgramResourceiv(propCount <= 0)");
374 _mesa_get_program_resourceiv(shProg
, programInterface
, index
,
375 propCount
, props
, bufSize
, length
, params
);
378 static struct gl_shader_program
*
379 lookup_linked_program(GLuint program
, const char *caller
)
381 GET_CURRENT_CONTEXT(ctx
);
382 struct gl_shader_program
*prog
=
383 _mesa_lookup_shader_program_err(ctx
, program
, caller
);
388 if (prog
->LinkStatus
== GL_FALSE
) {
389 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)",
397 _mesa_GetProgramResourceLocation(GLuint program
, GLenum programInterface
,
400 GET_CURRENT_CONTEXT(ctx
);
402 if (MESA_VERBOSE
& VERBOSE_API
) {
403 _mesa_debug(ctx
, "glGetProgramResourceLocation(%u, %s, %s)\n",
404 program
, _mesa_enum_to_string(programInterface
), name
);
407 struct gl_shader_program
*shProg
=
408 lookup_linked_program(program
, "glGetProgramResourceLocation");
410 if (!shProg
|| !name
)
413 /* Validate programInterface. */
414 switch (programInterface
) {
416 case GL_PROGRAM_INPUT
:
417 case GL_PROGRAM_OUTPUT
:
420 case GL_VERTEX_SUBROUTINE_UNIFORM
:
421 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
422 if (!_mesa_has_shader_subroutine(ctx
))
425 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
426 if (!_mesa_has_geometry_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
429 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
430 if (!_mesa_has_compute_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
433 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
434 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
435 if (!_mesa_has_tessellation(ctx
) || !_mesa_has_shader_subroutine(ctx
))
442 return _mesa_program_resource_location(shProg
, programInterface
, name
);
444 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceLocation(%s %s)",
445 _mesa_enum_to_string(programInterface
), name
);
450 * Returns output index for dual source blending.
453 _mesa_GetProgramResourceLocationIndex(GLuint program
, GLenum programInterface
,
456 GET_CURRENT_CONTEXT(ctx
);
458 if (MESA_VERBOSE
& VERBOSE_API
) {
459 _mesa_debug(ctx
, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
460 program
, _mesa_enum_to_string(programInterface
), name
);
463 struct gl_shader_program
*shProg
=
464 lookup_linked_program(program
, "glGetProgramResourceLocationIndex");
466 if (!shProg
|| !name
)
469 /* From the GL_ARB_program_interface_query spec:
471 * "For GetProgramResourceLocationIndex, <programInterface> must be
474 if (programInterface
!= GL_PROGRAM_OUTPUT
) {
475 _mesa_error(ctx
, GL_INVALID_ENUM
,
476 "glGetProgramResourceLocationIndex(%s)",
477 _mesa_enum_to_string(programInterface
));
481 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,