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 "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 struct gl_shader_program *shProg =
75 _mesa_lookup_shader_program_err(ctx, program,
76 "glGetProgramInterfaceiv");
81 _mesa_error(ctx, GL_INVALID_OPERATION,
82 "glGetProgramInterfaceiv(params NULL)");
86 /* Validate interface. */
87 if (!supported_interface_enum(ctx, programInterface)) {
88 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
89 _mesa_enum_to_string(programInterface));
93 /* Validate pname against interface. */
95 case GL_ACTIVE_RESOURCES:
96 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
97 if (shProg->ProgramResourceList[i].Type == programInterface)
100 case GL_MAX_NAME_LENGTH:
101 if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
102 _mesa_error(ctx, GL_INVALID_OPERATION,
103 "glGetProgramInterfaceiv(%s pname %s)",
104 _mesa_enum_to_string(programInterface),
105 _mesa_enum_to_string(pname));
108 /* Name length consists of base name, 3 additional chars '[0]' if
109 * resource is an array and finally 1 char for string terminator.
111 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
112 if (shProg->ProgramResourceList[i].Type != programInterface)
115 _mesa_program_resource_name(&shProg->ProgramResourceList[i]);
116 unsigned array_size =
117 _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]);
118 *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1);
121 case GL_MAX_NUM_ACTIVE_VARIABLES:
122 switch (programInterface) {
123 case GL_UNIFORM_BLOCK:
124 case GL_SHADER_STORAGE_BLOCK:
125 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
126 if (shProg->ProgramResourceList[i].Type == programInterface) {
127 struct gl_uniform_block *block =
128 (struct gl_uniform_block *)
129 shProg->ProgramResourceList[i].Data;
130 *params = MAX2(*params, block->NumUniforms);
134 case GL_ATOMIC_COUNTER_BUFFER:
135 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
136 if (shProg->ProgramResourceList[i].Type == programInterface) {
137 struct gl_active_atomic_buffer *buffer =
138 (struct gl_active_atomic_buffer *)
139 shProg->ProgramResourceList[i].Data;
140 *params = MAX2(*params, buffer->NumUniforms);
145 _mesa_error(ctx, GL_INVALID_OPERATION,
146 "glGetProgramInterfaceiv(%s pname %s)",
147 _mesa_enum_to_string(programInterface),
148 _mesa_enum_to_string(pname));
151 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
152 switch (programInterface) {
153 case GL_VERTEX_SUBROUTINE_UNIFORM:
154 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
155 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
156 case GL_COMPUTE_SUBROUTINE_UNIFORM:
157 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
158 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
159 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
160 if (shProg->ProgramResourceList[i].Type == programInterface) {
161 struct gl_uniform_storage *uni =
162 (struct gl_uniform_storage *)
163 shProg->ProgramResourceList[i].Data;
164 *params = MAX2(*params, uni->num_compatible_subroutines);
171 _mesa_error(ctx, GL_INVALID_OPERATION,
172 "glGetProgramInterfaceiv(%s pname %s)",
173 _mesa_enum_to_string(programInterface),
174 _mesa_enum_to_string(pname));
178 _mesa_error(ctx, GL_INVALID_OPERATION,
179 "glGetProgramInterfaceiv(pname %s)",
180 _mesa_enum_to_string(pname));
185 is_xfb_marker(const char *str)
187 static const char *markers[] = {
189 "gl_SkipComponents1",
190 "gl_SkipComponents2",
191 "gl_SkipComponents3",
192 "gl_SkipComponents4",
195 const char **m = markers;
197 if (strncmp(str, "gl_", 3) != 0)
201 if (strcmp(*m, str) == 0)
208 _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
211 GET_CURRENT_CONTEXT(ctx);
212 unsigned array_index = 0;
213 struct gl_program_resource *res;
214 struct gl_shader_program *shProg =
215 _mesa_lookup_shader_program_err(ctx, program,
216 "glGetProgramResourceIndex");
217 if (!shProg || !name)
218 return GL_INVALID_INDEX;
220 if (!supported_interface_enum(ctx, programInterface)) {
221 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
222 _mesa_enum_to_string(programInterface));
223 return GL_INVALID_INDEX;
226 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
227 * should be returned when querying the index assigned to the special names
228 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
229 * "gl_SkipComponents3", and "gl_SkipComponents4".
231 if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
233 return GL_INVALID_INDEX;
235 switch (programInterface) {
236 case GL_TESS_CONTROL_SUBROUTINE:
237 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
238 case GL_TESS_EVALUATION_SUBROUTINE:
239 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
240 case GL_COMPUTE_SUBROUTINE:
241 case GL_COMPUTE_SUBROUTINE_UNIFORM:
242 case GL_GEOMETRY_SUBROUTINE:
243 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
244 case GL_VERTEX_SUBROUTINE:
245 case GL_FRAGMENT_SUBROUTINE:
246 case GL_VERTEX_SUBROUTINE_UNIFORM:
247 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
248 case GL_PROGRAM_INPUT:
249 case GL_PROGRAM_OUTPUT:
251 case GL_BUFFER_VARIABLE:
252 case GL_TRANSFORM_FEEDBACK_VARYING:
253 case GL_UNIFORM_BLOCK:
254 case GL_SHADER_STORAGE_BLOCK:
255 res = _mesa_program_resource_find_name(shProg, programInterface, name,
257 if (!res || array_index > 0)
258 return GL_INVALID_INDEX;
260 return _mesa_program_resource_index(shProg, res);
261 case GL_ATOMIC_COUNTER_BUFFER:
263 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
264 _mesa_enum_to_string(programInterface));
267 return GL_INVALID_INDEX;
271 _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
272 GLuint index, GLsizei bufSize, GLsizei *length,
275 GET_CURRENT_CONTEXT(ctx);
276 struct gl_shader_program *shProg =
277 _mesa_lookup_shader_program_err(ctx, program,
278 "glGetProgramResourceName");
280 if (!shProg || !name)
283 if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
284 !supported_interface_enum(ctx, programInterface)) {
285 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
286 _mesa_enum_to_string(programInterface));
290 _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
291 length, name, "glGetProgramResourceName");
295 _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
296 GLuint index, GLsizei propCount,
297 const GLenum *props, GLsizei bufSize,
298 GLsizei *length, GLint *params)
300 GET_CURRENT_CONTEXT(ctx);
301 struct gl_shader_program *shProg =
302 _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
304 if (!shProg || !params)
307 /* The error INVALID_VALUE is generated if <propCount> is zero.
308 * Note that we check < 0 here because it makes sense to bail early.
310 if (propCount <= 0) {
311 _mesa_error(ctx, GL_INVALID_VALUE,
312 "glGetProgramResourceiv(propCount <= 0)");
316 /* No need to write any properties, user requested none. */
320 _mesa_get_program_resourceiv(shProg, programInterface, index,
321 propCount, props, bufSize, length, params);
324 static struct gl_shader_program *
325 lookup_linked_program(GLuint program, const char *caller)
327 GET_CURRENT_CONTEXT(ctx);
328 struct gl_shader_program *prog =
329 _mesa_lookup_shader_program_err(ctx, program, caller);
334 if (prog->LinkStatus == GL_FALSE) {
335 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
343 _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
346 GET_CURRENT_CONTEXT(ctx);
347 struct gl_shader_program *shProg =
348 lookup_linked_program(program, "glGetProgramResourceLocation");
350 if (!shProg || !name)
353 /* Validate programInterface. */
354 switch (programInterface) {
356 case GL_PROGRAM_INPUT:
357 case GL_PROGRAM_OUTPUT:
360 case GL_VERTEX_SUBROUTINE_UNIFORM:
361 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
362 if (!_mesa_has_shader_subroutine(ctx))
365 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
366 if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
369 case GL_COMPUTE_SUBROUTINE_UNIFORM:
370 if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
373 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
374 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
375 if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx))
382 return _mesa_program_resource_location(shProg, programInterface, name);
384 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
385 _mesa_enum_to_string(programInterface), name);
390 * Returns output index for dual source blending.
393 _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
396 GET_CURRENT_CONTEXT(ctx);
397 struct gl_shader_program *shProg =
398 lookup_linked_program(program, "glGetProgramResourceLocationIndex");
400 if (!shProg || !name)
403 /* From the GL_ARB_program_interface_query spec:
405 * "For GetProgramResourceLocationIndex, <programInterface> must be
408 if (programInterface != GL_PROGRAM_OUTPUT) {
409 _mesa_error(ctx, GL_INVALID_ENUM,
410 "glGetProgramResourceLocationIndex(%s)",
411 _mesa_enum_to_string(programInterface));
415 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,