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_VARYING
:
43 case GL_ATOMIC_COUNTER_BUFFER
:
44 case GL_BUFFER_VARIABLE
:
45 case GL_SHADER_STORAGE_BLOCK
:
47 case GL_VERTEX_SUBROUTINE
:
48 case GL_FRAGMENT_SUBROUTINE
:
49 case GL_VERTEX_SUBROUTINE_UNIFORM
:
50 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
51 return _mesa_has_shader_subroutine(ctx
);
52 case GL_GEOMETRY_SUBROUTINE
:
53 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
54 return _mesa_has_geometry_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
55 case GL_COMPUTE_SUBROUTINE
:
56 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
57 return _mesa_has_compute_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
58 case GL_TESS_CONTROL_SUBROUTINE
:
59 case GL_TESS_EVALUATION_SUBROUTINE
:
60 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
61 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
62 return _mesa_has_tessellation(ctx
) && _mesa_has_shader_subroutine(ctx
);
69 _mesa_GetProgramInterfaceiv(GLuint program
, GLenum programInterface
,
70 GLenum pname
, GLint
*params
)
72 GET_CURRENT_CONTEXT(ctx
);
74 if (MESA_VERBOSE
& VERBOSE_API
) {
75 _mesa_debug(ctx
, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
76 program
, _mesa_enum_to_string(programInterface
),
77 _mesa_enum_to_string(pname
), params
);
81 struct gl_shader_program
*shProg
=
82 _mesa_lookup_shader_program_err(ctx
, program
,
83 "glGetProgramInterfaceiv");
88 _mesa_error(ctx
, GL_INVALID_OPERATION
,
89 "glGetProgramInterfaceiv(params NULL)");
93 /* Validate interface. */
94 if (!supported_interface_enum(ctx
, programInterface
)) {
95 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramInterfaceiv(%s)",
96 _mesa_enum_to_string(programInterface
));
100 /* Validate pname against interface. */
102 case GL_ACTIVE_RESOURCES
:
103 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++)
104 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
)
107 case GL_MAX_NAME_LENGTH
:
108 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
) {
109 _mesa_error(ctx
, GL_INVALID_OPERATION
,
110 "glGetProgramInterfaceiv(%s pname %s)",
111 _mesa_enum_to_string(programInterface
),
112 _mesa_enum_to_string(pname
));
115 /* Name length consists of base name, 3 additional chars '[0]' if
116 * resource is an array and finally 1 char for string terminator.
118 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
119 if (shProg
->ProgramResourceList
[i
].Type
!= programInterface
)
122 _mesa_program_resource_name_len(&shProg
->ProgramResourceList
[i
]);
123 *params
= MAX2(*params
, len
+ 1);
126 case GL_MAX_NUM_ACTIVE_VARIABLES
:
127 switch (programInterface
) {
128 case GL_UNIFORM_BLOCK
:
129 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
130 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
131 struct gl_uniform_block
*block
=
132 (struct gl_uniform_block
*)
133 shProg
->ProgramResourceList
[i
].Data
;
134 *params
= MAX2(*params
, block
->NumUniforms
);
138 case GL_SHADER_STORAGE_BLOCK
:
139 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
140 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
141 struct gl_uniform_block
*block
=
142 (struct gl_uniform_block
*)
143 shProg
->ProgramResourceList
[i
].Data
;
144 GLint block_params
= 0;
145 for (unsigned j
= 0; j
< block
->NumUniforms
; j
++) {
146 const char *iname
= block
->Uniforms
[j
].IndexName
;
147 struct gl_program_resource
*uni
=
148 _mesa_program_resource_find_name(shProg
, GL_BUFFER_VARIABLE
,
154 *params
= MAX2(*params
, block_params
);
158 case GL_ATOMIC_COUNTER_BUFFER
:
159 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
160 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
161 struct gl_active_atomic_buffer
*buffer
=
162 (struct gl_active_atomic_buffer
*)
163 shProg
->ProgramResourceList
[i
].Data
;
164 *params
= MAX2(*params
, buffer
->NumUniforms
);
169 _mesa_error(ctx
, GL_INVALID_OPERATION
,
170 "glGetProgramInterfaceiv(%s pname %s)",
171 _mesa_enum_to_string(programInterface
),
172 _mesa_enum_to_string(pname
));
175 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES
:
176 switch (programInterface
) {
177 case GL_VERTEX_SUBROUTINE_UNIFORM
:
178 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
179 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
180 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
181 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
182 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
: {
183 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
184 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
185 struct gl_uniform_storage
*uni
=
186 (struct gl_uniform_storage
*)
187 shProg
->ProgramResourceList
[i
].Data
;
188 *params
= MAX2(*params
, uni
->num_compatible_subroutines
);
195 _mesa_error(ctx
, GL_INVALID_OPERATION
,
196 "glGetProgramInterfaceiv(%s pname %s)",
197 _mesa_enum_to_string(programInterface
),
198 _mesa_enum_to_string(pname
));
202 _mesa_error(ctx
, GL_INVALID_OPERATION
,
203 "glGetProgramInterfaceiv(pname %s)",
204 _mesa_enum_to_string(pname
));
209 is_xfb_marker(const char *str
)
211 static const char *markers
[] = {
213 "gl_SkipComponents1",
214 "gl_SkipComponents2",
215 "gl_SkipComponents3",
216 "gl_SkipComponents4",
219 const char **m
= markers
;
221 if (strncmp(str
, "gl_", 3) != 0)
225 if (strcmp(*m
, str
) == 0)
232 _mesa_GetProgramResourceIndex(GLuint program
, GLenum programInterface
,
235 GET_CURRENT_CONTEXT(ctx
);
237 if (MESA_VERBOSE
& VERBOSE_API
) {
238 _mesa_debug(ctx
, "glGetProgramResourceIndex(%u, %s, %s)\n",
239 program
, _mesa_enum_to_string(programInterface
), name
);
242 unsigned array_index
= 0;
243 struct gl_program_resource
*res
;
244 struct gl_shader_program
*shProg
=
245 _mesa_lookup_shader_program_err(ctx
, program
,
246 "glGetProgramResourceIndex");
247 if (!shProg
|| !name
)
248 return GL_INVALID_INDEX
;
250 if (!supported_interface_enum(ctx
, programInterface
)) {
251 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
252 _mesa_enum_to_string(programInterface
));
253 return GL_INVALID_INDEX
;
256 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
257 * should be returned when querying the index assigned to the special names
258 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
259 * "gl_SkipComponents3", and "gl_SkipComponents4".
261 if (programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
&&
263 return GL_INVALID_INDEX
;
265 switch (programInterface
) {
266 case GL_TESS_CONTROL_SUBROUTINE
:
267 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
268 case GL_TESS_EVALUATION_SUBROUTINE
:
269 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
270 case GL_COMPUTE_SUBROUTINE
:
271 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
272 case GL_GEOMETRY_SUBROUTINE
:
273 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
274 case GL_VERTEX_SUBROUTINE
:
275 case GL_FRAGMENT_SUBROUTINE
:
276 case GL_VERTEX_SUBROUTINE_UNIFORM
:
277 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
278 case GL_PROGRAM_INPUT
:
279 case GL_PROGRAM_OUTPUT
:
281 case GL_BUFFER_VARIABLE
:
282 case GL_TRANSFORM_FEEDBACK_VARYING
:
283 case GL_UNIFORM_BLOCK
:
284 case GL_SHADER_STORAGE_BLOCK
:
285 res
= _mesa_program_resource_find_name(shProg
, programInterface
, name
,
287 if (!res
|| array_index
> 0)
288 return GL_INVALID_INDEX
;
290 return _mesa_program_resource_index(shProg
, res
);
291 case GL_ATOMIC_COUNTER_BUFFER
:
293 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
294 _mesa_enum_to_string(programInterface
));
297 return GL_INVALID_INDEX
;
301 _mesa_GetProgramResourceName(GLuint program
, GLenum programInterface
,
302 GLuint index
, GLsizei bufSize
, GLsizei
*length
,
305 GET_CURRENT_CONTEXT(ctx
);
307 if (MESA_VERBOSE
& VERBOSE_API
) {
308 _mesa_debug(ctx
, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
309 program
, _mesa_enum_to_string(programInterface
), index
,
310 bufSize
, length
, name
);
313 struct gl_shader_program
*shProg
=
314 _mesa_lookup_shader_program_err(ctx
, program
,
315 "glGetProgramResourceName");
317 if (!shProg
|| !name
)
320 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
321 !supported_interface_enum(ctx
, programInterface
)) {
322 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceName(%s)",
323 _mesa_enum_to_string(programInterface
));
327 _mesa_get_program_resource_name(shProg
, programInterface
, index
, bufSize
,
328 length
, name
, "glGetProgramResourceName");
332 _mesa_GetProgramResourceiv(GLuint program
, GLenum programInterface
,
333 GLuint index
, GLsizei propCount
,
334 const GLenum
*props
, GLsizei bufSize
,
335 GLsizei
*length
, GLint
*params
)
337 GET_CURRENT_CONTEXT(ctx
);
339 if (MESA_VERBOSE
& VERBOSE_API
) {
340 _mesa_debug(ctx
, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
341 program
, _mesa_enum_to_string(programInterface
), index
,
342 propCount
, props
, bufSize
, length
, params
);
345 struct gl_shader_program
*shProg
=
346 _mesa_lookup_shader_program_err(ctx
, program
, "glGetProgramResourceiv");
348 if (!shProg
|| !params
)
351 /* The error INVALID_VALUE is generated if <propCount> is zero.
352 * Note that we check < 0 here because it makes sense to bail early.
354 if (propCount
<= 0) {
355 _mesa_error(ctx
, GL_INVALID_VALUE
,
356 "glGetProgramResourceiv(propCount <= 0)");
360 /* No need to write any properties, user requested none. */
364 _mesa_get_program_resourceiv(shProg
, programInterface
, index
,
365 propCount
, props
, bufSize
, length
, params
);
368 static struct gl_shader_program
*
369 lookup_linked_program(GLuint program
, const char *caller
)
371 GET_CURRENT_CONTEXT(ctx
);
372 struct gl_shader_program
*prog
=
373 _mesa_lookup_shader_program_err(ctx
, program
, caller
);
378 if (prog
->LinkStatus
== GL_FALSE
) {
379 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)",
387 _mesa_GetProgramResourceLocation(GLuint program
, GLenum programInterface
,
390 GET_CURRENT_CONTEXT(ctx
);
392 if (MESA_VERBOSE
& VERBOSE_API
) {
393 _mesa_debug(ctx
, "glGetProgramResourceLocation(%u, %s, %s)\n",
394 program
, _mesa_enum_to_string(programInterface
), name
);
397 struct gl_shader_program
*shProg
=
398 lookup_linked_program(program
, "glGetProgramResourceLocation");
400 if (!shProg
|| !name
)
403 /* Validate programInterface. */
404 switch (programInterface
) {
406 case GL_PROGRAM_INPUT
:
407 case GL_PROGRAM_OUTPUT
:
410 case GL_VERTEX_SUBROUTINE_UNIFORM
:
411 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
412 if (!_mesa_has_shader_subroutine(ctx
))
415 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
416 if (!_mesa_has_geometry_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
419 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
420 if (!_mesa_has_compute_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
423 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
424 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
425 if (!_mesa_has_tessellation(ctx
) || !_mesa_has_shader_subroutine(ctx
))
432 return _mesa_program_resource_location(shProg
, programInterface
, name
);
434 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceLocation(%s %s)",
435 _mesa_enum_to_string(programInterface
), name
);
440 * Returns output index for dual source blending.
443 _mesa_GetProgramResourceLocationIndex(GLuint program
, GLenum programInterface
,
446 GET_CURRENT_CONTEXT(ctx
);
448 if (MESA_VERBOSE
& VERBOSE_API
) {
449 _mesa_debug(ctx
, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
450 program
, _mesa_enum_to_string(programInterface
), name
);
453 struct gl_shader_program
*shProg
=
454 lookup_linked_program(program
, "glGetProgramResourceLocationIndex");
456 if (!shProg
|| !name
)
459 /* From the GL_ARB_program_interface_query spec:
461 * "For GetProgramResourceLocationIndex, <programInterface> must be
464 if (programInterface
!= GL_PROGRAM_OUTPUT
) {
465 _mesa_error(ctx
, GL_INVALID_ENUM
,
466 "glGetProgramResourceLocationIndex(%s)",
467 _mesa_enum_to_string(programInterface
));
471 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,