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"
36 supported_interface_enum(struct gl_context
*ctx
, GLenum iface
)
40 case GL_UNIFORM_BLOCK
:
41 case GL_PROGRAM_INPUT
:
42 case GL_PROGRAM_OUTPUT
:
43 case GL_TRANSFORM_FEEDBACK_BUFFER
:
44 case GL_TRANSFORM_FEEDBACK_VARYING
:
45 case GL_ATOMIC_COUNTER_BUFFER
:
46 case GL_BUFFER_VARIABLE
:
47 case GL_SHADER_STORAGE_BLOCK
:
49 case GL_VERTEX_SUBROUTINE
:
50 case GL_FRAGMENT_SUBROUTINE
:
51 case GL_VERTEX_SUBROUTINE_UNIFORM
:
52 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
53 return _mesa_has_ARB_shader_subroutine(ctx
);
54 case GL_GEOMETRY_SUBROUTINE
:
55 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
56 return _mesa_has_geometry_shaders(ctx
) && _mesa_has_ARB_shader_subroutine(ctx
);
57 case GL_COMPUTE_SUBROUTINE
:
58 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
59 return _mesa_has_compute_shaders(ctx
) && _mesa_has_ARB_shader_subroutine(ctx
);
60 case GL_TESS_CONTROL_SUBROUTINE
:
61 case GL_TESS_EVALUATION_SUBROUTINE
:
62 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
63 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
64 return _mesa_has_tessellation(ctx
) && _mesa_has_ARB_shader_subroutine(ctx
);
70 static struct gl_shader_program
*
71 lookup_linked_program(GLuint program
, const char *caller
)
73 GET_CURRENT_CONTEXT(ctx
);
74 struct gl_shader_program
*prog
=
75 _mesa_lookup_shader_program_err(ctx
, program
, caller
);
80 if (prog
->data
->LinkStatus
== LINKING_FAILURE
) {
81 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)",
89 _mesa_GetProgramInterfaceiv(GLuint program
, GLenum programInterface
,
90 GLenum pname
, GLint
*params
)
92 GET_CURRENT_CONTEXT(ctx
);
94 if (MESA_VERBOSE
& VERBOSE_API
) {
95 _mesa_debug(ctx
, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
96 program
, _mesa_enum_to_string(programInterface
),
97 _mesa_enum_to_string(pname
), params
);
101 struct gl_shader_program
*shProg
=
102 _mesa_lookup_shader_program_err(ctx
, program
,
103 "glGetProgramInterfaceiv");
108 _mesa_error(ctx
, GL_INVALID_OPERATION
,
109 "glGetProgramInterfaceiv(params NULL)");
113 /* Validate interface. */
114 if (!supported_interface_enum(ctx
, programInterface
)) {
115 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramInterfaceiv(%s)",
116 _mesa_enum_to_string(programInterface
));
120 /* Validate pname against interface. */
122 case GL_ACTIVE_RESOURCES
:
123 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++)
124 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
)
127 case GL_MAX_NAME_LENGTH
:
128 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
129 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
) {
130 _mesa_error(ctx
, GL_INVALID_OPERATION
,
131 "glGetProgramInterfaceiv(%s pname %s)",
132 _mesa_enum_to_string(programInterface
),
133 _mesa_enum_to_string(pname
));
136 /* Name length consists of base name, 3 additional chars '[0]' if
137 * resource is an array and finally 1 char for string terminator.
139 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
140 if (shProg
->data
->ProgramResourceList
[i
].Type
!= programInterface
)
143 _mesa_program_resource_name_len(&shProg
->data
->ProgramResourceList
[i
]);
144 *params
= MAX2(*params
, len
+ 1);
147 case GL_MAX_NUM_ACTIVE_VARIABLES
:
148 switch (programInterface
) {
149 case GL_UNIFORM_BLOCK
:
150 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
151 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
) {
152 struct gl_uniform_block
*block
=
153 (struct gl_uniform_block
*)
154 shProg
->data
->ProgramResourceList
[i
].Data
;
155 *params
= MAX2(*params
, block
->NumUniforms
);
159 case GL_SHADER_STORAGE_BLOCK
:
160 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
161 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
) {
162 struct gl_uniform_block
*block
=
163 (struct gl_uniform_block
*)
164 shProg
->data
->ProgramResourceList
[i
].Data
;
165 GLint block_params
= 0;
166 for (unsigned j
= 0; j
< block
->NumUniforms
; j
++) {
167 const char *iname
= block
->Uniforms
[j
].IndexName
;
168 struct gl_program_resource
*uni
=
169 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
175 *params
= MAX2(*params
, block_params
);
179 case GL_ATOMIC_COUNTER_BUFFER
:
180 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
181 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
) {
182 struct gl_active_atomic_buffer
*buffer
=
183 (struct gl_active_atomic_buffer
*)
184 shProg
->data
->ProgramResourceList
[i
].Data
;
185 *params
= MAX2(*params
, buffer
->NumUniforms
);
189 case GL_TRANSFORM_FEEDBACK_BUFFER
:
190 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
191 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
) {
192 struct gl_transform_feedback_buffer
*buffer
=
193 (struct gl_transform_feedback_buffer
*)
194 shProg
->data
->ProgramResourceList
[i
].Data
;
195 *params
= MAX2(*params
, buffer
->NumVaryings
);
200 _mesa_error(ctx
, GL_INVALID_OPERATION
,
201 "glGetProgramInterfaceiv(%s pname %s)",
202 _mesa_enum_to_string(programInterface
),
203 _mesa_enum_to_string(pname
));
206 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES
:
207 switch (programInterface
) {
208 case GL_VERTEX_SUBROUTINE_UNIFORM
:
209 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
210 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
211 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
212 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
213 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
: {
214 for (i
= 0, *params
= 0; i
< shProg
->data
->NumProgramResourceList
; i
++) {
215 if (shProg
->data
->ProgramResourceList
[i
].Type
== programInterface
) {
216 struct gl_uniform_storage
*uni
=
217 (struct gl_uniform_storage
*)
218 shProg
->data
->ProgramResourceList
[i
].Data
;
219 *params
= MAX2(*params
, uni
->num_compatible_subroutines
);
226 _mesa_error(ctx
, GL_INVALID_OPERATION
,
227 "glGetProgramInterfaceiv(%s pname %s)",
228 _mesa_enum_to_string(programInterface
),
229 _mesa_enum_to_string(pname
));
233 _mesa_error(ctx
, GL_INVALID_OPERATION
,
234 "glGetProgramInterfaceiv(pname %s)",
235 _mesa_enum_to_string(pname
));
240 is_xfb_marker(const char *str
)
242 static const char *markers
[] = {
244 "gl_SkipComponents1",
245 "gl_SkipComponents2",
246 "gl_SkipComponents3",
247 "gl_SkipComponents4",
250 const char **m
= markers
;
252 if (strncmp(str
, "gl_", 3) != 0)
256 if (strcmp(*m
, str
) == 0)
263 _mesa_GetProgramResourceIndex(GLuint program
, GLenum programInterface
,
266 GET_CURRENT_CONTEXT(ctx
);
268 if (MESA_VERBOSE
& VERBOSE_API
) {
269 _mesa_debug(ctx
, "glGetProgramResourceIndex(%u, %s, %s)\n",
270 program
, _mesa_enum_to_string(programInterface
), name
);
273 unsigned array_index
= 0;
274 struct gl_program_resource
*res
;
275 struct gl_shader_program
*shProg
=
276 _mesa_lookup_shader_program_err(ctx
, program
,
277 "glGetProgramResourceIndex");
278 if (!shProg
|| !name
)
279 return GL_INVALID_INDEX
;
281 if (!supported_interface_enum(ctx
, programInterface
)) {
282 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
283 _mesa_enum_to_string(programInterface
));
284 return GL_INVALID_INDEX
;
287 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
288 * should be returned when querying the index assigned to the special names
289 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
290 * "gl_SkipComponents3", and "gl_SkipComponents4".
292 if (programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
&&
294 return GL_INVALID_INDEX
;
296 switch (programInterface
) {
297 case GL_TESS_CONTROL_SUBROUTINE
:
298 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
299 case GL_TESS_EVALUATION_SUBROUTINE
:
300 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
301 case GL_COMPUTE_SUBROUTINE
:
302 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
303 case GL_GEOMETRY_SUBROUTINE
:
304 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
305 case GL_VERTEX_SUBROUTINE
:
306 case GL_FRAGMENT_SUBROUTINE
:
307 case GL_VERTEX_SUBROUTINE_UNIFORM
:
308 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
309 case GL_PROGRAM_INPUT
:
310 case GL_PROGRAM_OUTPUT
:
312 case GL_BUFFER_VARIABLE
:
313 case GL_TRANSFORM_FEEDBACK_VARYING
:
314 case GL_UNIFORM_BLOCK
:
315 case GL_SHADER_STORAGE_BLOCK
:
316 res
= _mesa_program_resource_find_name(shProg
, programInterface
, name
,
318 if (!res
|| array_index
> 0)
319 return GL_INVALID_INDEX
;
321 return _mesa_program_resource_index(shProg
, res
);
322 case GL_ATOMIC_COUNTER_BUFFER
:
323 case GL_TRANSFORM_FEEDBACK_BUFFER
:
325 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
326 _mesa_enum_to_string(programInterface
));
329 return GL_INVALID_INDEX
;
333 _mesa_GetProgramResourceName(GLuint program
, GLenum programInterface
,
334 GLuint index
, GLsizei bufSize
, GLsizei
*length
,
337 GET_CURRENT_CONTEXT(ctx
);
339 if (MESA_VERBOSE
& VERBOSE_API
) {
340 _mesa_debug(ctx
, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
341 program
, _mesa_enum_to_string(programInterface
), index
,
342 bufSize
, length
, name
);
345 struct gl_shader_program
*shProg
=
346 _mesa_lookup_shader_program_err(ctx
, program
,
347 "glGetProgramResourceName");
349 if (!shProg
|| !name
)
352 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
353 programInterface
== GL_TRANSFORM_FEEDBACK_BUFFER
||
354 !supported_interface_enum(ctx
, programInterface
)) {
355 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceName(%s)",
356 _mesa_enum_to_string(programInterface
));
360 _mesa_get_program_resource_name(shProg
, programInterface
, index
, bufSize
,
361 length
, name
, "glGetProgramResourceName");
365 _mesa_GetProgramResourceiv(GLuint program
, GLenum programInterface
,
366 GLuint index
, GLsizei propCount
,
367 const GLenum
*props
, GLsizei bufSize
,
368 GLsizei
*length
, GLint
*params
)
370 GET_CURRENT_CONTEXT(ctx
);
372 if (MESA_VERBOSE
& VERBOSE_API
) {
373 _mesa_debug(ctx
, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
374 program
, _mesa_enum_to_string(programInterface
), index
,
375 propCount
, props
, bufSize
, length
, params
);
378 struct gl_shader_program
*shProg
=
379 _mesa_lookup_shader_program_err(ctx
, program
, "glGetProgramResourceiv");
381 if (!shProg
|| !params
)
384 /* The error INVALID_VALUE is generated if <propCount> is zero.
385 * Note that we check < 0 here because it makes sense to bail early.
387 if (propCount
<= 0) {
388 _mesa_error(ctx
, GL_INVALID_VALUE
,
389 "glGetProgramResourceiv(propCount <= 0)");
393 _mesa_get_program_resourceiv(shProg
, programInterface
, index
,
394 propCount
, props
, bufSize
, length
, params
);
398 _mesa_GetProgramResourceLocation(GLuint program
, GLenum programInterface
,
401 GET_CURRENT_CONTEXT(ctx
);
403 if (MESA_VERBOSE
& VERBOSE_API
) {
404 _mesa_debug(ctx
, "glGetProgramResourceLocation(%u, %s, %s)\n",
405 program
, _mesa_enum_to_string(programInterface
), name
);
408 struct gl_shader_program
*shProg
=
409 lookup_linked_program(program
, "glGetProgramResourceLocation");
411 if (!shProg
|| !name
)
414 /* Validate programInterface. */
415 switch (programInterface
) {
417 case GL_PROGRAM_INPUT
:
418 case GL_PROGRAM_OUTPUT
:
421 case GL_VERTEX_SUBROUTINE_UNIFORM
:
422 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
423 if (!_mesa_has_ARB_shader_subroutine(ctx
))
426 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
427 if (!_mesa_has_geometry_shaders(ctx
) || !_mesa_has_ARB_shader_subroutine(ctx
))
430 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
431 if (!_mesa_has_compute_shaders(ctx
) || !_mesa_has_ARB_shader_subroutine(ctx
))
434 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
435 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
436 if (!_mesa_has_tessellation(ctx
) || !_mesa_has_ARB_shader_subroutine(ctx
))
443 return _mesa_program_resource_location(shProg
, programInterface
, name
);
445 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceLocation(%s %s)",
446 _mesa_enum_to_string(programInterface
), name
);
451 * Returns output index for dual source blending.
454 _mesa_GetProgramResourceLocationIndex(GLuint program
, GLenum programInterface
,
457 GET_CURRENT_CONTEXT(ctx
);
459 if (MESA_VERBOSE
& VERBOSE_API
) {
460 _mesa_debug(ctx
, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
461 program
, _mesa_enum_to_string(programInterface
), name
);
464 struct gl_shader_program
*shProg
=
465 lookup_linked_program(program
, "glGetProgramResourceLocationIndex");
467 if (!shProg
|| !name
)
470 /* From the GL_ARB_program_interface_query spec:
472 * "For GetProgramResourceLocationIndex, <programInterface> must be
475 if (programInterface
!= GL_PROGRAM_OUTPUT
) {
476 _mesa_error(ctx
, GL_INVALID_ENUM
,
477 "glGetProgramResourceLocationIndex(%s)",
478 _mesa_enum_to_string(programInterface
));
482 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,