mesa: Remove redundant _mesa_has_shader_subroutine
[mesa.git] / src / mesa / main / program_resource.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 */
25
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"
34 static bool
35 supported_interface_enum(struct gl_context *ctx, GLenum iface)
36 {
37 switch (iface) {
38 case GL_UNIFORM:
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:
47 return true;
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_ARB_shader_subroutine(ctx);
53 case GL_GEOMETRY_SUBROUTINE:
54 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
55 return _mesa_has_geometry_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
56 case GL_COMPUTE_SUBROUTINE:
57 case GL_COMPUTE_SUBROUTINE_UNIFORM:
58 return _mesa_has_compute_shaders(ctx) && _mesa_has_ARB_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_ARB_shader_subroutine(ctx);
64 default:
65 return false;
66 }
67 }
68
69 static struct gl_shader_program *
70 lookup_linked_program(GLuint program,
71 const char *caller,
72 bool raise_link_error)
73 {
74 GET_CURRENT_CONTEXT(ctx);
75 struct gl_shader_program *prog =
76 _mesa_lookup_shader_program_err(ctx, program, caller);
77
78 if (!prog)
79 return NULL;
80
81 if (prog->LinkStatus == GL_FALSE) {
82 if (raise_link_error)
83 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
84 caller);
85 return NULL;
86 }
87 return prog;
88 }
89
90 static GLenum
91 stage_from_program_interface(GLenum programInterface)
92 {
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;
106 default:
107 unreachable("unexpected programInterface value");
108 }
109 }
110
111 static struct gl_linked_shader *
112 lookup_linked_shader(GLuint program,
113 GLenum programInterface,
114 const char *caller)
115 {
116 struct gl_shader_program *shLinkedProg =
117 lookup_linked_program(program, caller, false);
118 gl_shader_stage stage = stage_from_program_interface(programInterface);
119
120 if (!shLinkedProg)
121 return NULL;
122
123 return shLinkedProg->_LinkedShaders[stage];
124 }
125
126 static bool
127 is_subroutine_uniform_program_interface(GLenum programInterface)
128 {
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:
136 return true;
137 default:
138 return false;
139 }
140 }
141
142 void GLAPIENTRY
143 _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
144 GLenum pname, GLint *params)
145 {
146 GET_CURRENT_CONTEXT(ctx);
147
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);
152 }
153
154 unsigned i;
155 struct gl_shader_program *shProg =
156 _mesa_lookup_shader_program_err(ctx, program,
157 "glGetProgramInterfaceiv");
158 if (!shProg)
159 return;
160
161 if (!params) {
162 _mesa_error(ctx, GL_INVALID_OPERATION,
163 "glGetProgramInterfaceiv(params NULL)");
164 return;
165 }
166
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));
171 return;
172 }
173
174 /* Validate pname against interface. */
175 switch(pname) {
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:
182 *
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."
188 *
189 * So in order to know the real number of active subroutine uniforms
190 * we would need a linked shader .
191 *
192 * At the same time, Section 7.3 (Program Objects) of the OpenGL 4.4
193 * Core Profile says:
194 *
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."
203 * <skip>
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."
208 *
209 * So if the program is not linked we will return 0.
210 */
211 struct gl_linked_shader *sh =
212 lookup_linked_shader(program, programInterface, "glGetProgramInterfaceiv");
213
214 *params = sh ? sh->NumSubroutineUniforms : 0;
215 } else {
216 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
217 if (shProg->ProgramResourceList[i].Type == programInterface)
218 (*params)++;
219 }
220 break;
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));
228 return;
229 }
230 /* Name length consists of base name, 3 additional chars '[0]' if
231 * resource is an array and finally 1 char for string terminator.
232 */
233 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
234 if (shProg->ProgramResourceList[i].Type != programInterface)
235 continue;
236 unsigned len =
237 _mesa_program_resource_name_len(&shProg->ProgramResourceList[i]);
238 *params = MAX2(*params, len + 1);
239 }
240 break;
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);
250 }
251 }
252 break;
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,
264 iname, NULL);
265 if (!uni)
266 continue;
267 block_params++;
268 }
269 *params = MAX2(*params, block_params);
270 }
271 }
272 break;
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);
280 }
281 }
282 break;
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);
290 }
291 }
292 break;
293 default:
294 _mesa_error(ctx, GL_INVALID_OPERATION,
295 "glGetProgramInterfaceiv(%s pname %s)",
296 _mesa_enum_to_string(programInterface),
297 _mesa_enum_to_string(pname));
298 };
299 break;
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);
314 }
315 }
316 break;
317 }
318
319 default:
320 _mesa_error(ctx, GL_INVALID_OPERATION,
321 "glGetProgramInterfaceiv(%s pname %s)",
322 _mesa_enum_to_string(programInterface),
323 _mesa_enum_to_string(pname));
324 }
325 break;
326 default:
327 _mesa_error(ctx, GL_INVALID_OPERATION,
328 "glGetProgramInterfaceiv(pname %s)",
329 _mesa_enum_to_string(pname));
330 }
331 }
332
333 static bool
334 is_xfb_marker(const char *str)
335 {
336 static const char *markers[] = {
337 "gl_NextBuffer",
338 "gl_SkipComponents1",
339 "gl_SkipComponents2",
340 "gl_SkipComponents3",
341 "gl_SkipComponents4",
342 NULL
343 };
344 const char **m = markers;
345
346 if (strncmp(str, "gl_", 3) != 0)
347 return false;
348
349 for (; *m; m++)
350 if (strcmp(*m, str) == 0)
351 return true;
352
353 return false;
354 }
355
356 GLuint GLAPIENTRY
357 _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
358 const GLchar *name)
359 {
360 GET_CURRENT_CONTEXT(ctx);
361
362 if (MESA_VERBOSE & VERBOSE_API) {
363 _mesa_debug(ctx, "glGetProgramResourceIndex(%u, %s, %s)\n",
364 program, _mesa_enum_to_string(programInterface), name);
365 }
366
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;
374
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;
379 }
380 /*
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".
385 */
386 if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
387 is_xfb_marker(name))
388 return GL_INVALID_INDEX;
389
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:
405 case GL_UNIFORM:
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,
411 &array_index);
412 if (!res || array_index > 0)
413 return GL_INVALID_INDEX;
414
415 return _mesa_program_resource_index(shProg, res);
416 case GL_ATOMIC_COUNTER_BUFFER:
417 case GL_TRANSFORM_FEEDBACK_BUFFER:
418 default:
419 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
420 _mesa_enum_to_string(programInterface));
421 }
422
423 return GL_INVALID_INDEX;
424 }
425
426 void GLAPIENTRY
427 _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
428 GLuint index, GLsizei bufSize, GLsizei *length,
429 GLchar *name)
430 {
431 GET_CURRENT_CONTEXT(ctx);
432
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);
437 }
438
439 struct gl_shader_program *shProg =
440 _mesa_lookup_shader_program_err(ctx, program,
441 "glGetProgramResourceName");
442
443 if (!shProg || !name)
444 return;
445
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));
451 return;
452 }
453
454 _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
455 length, name, "glGetProgramResourceName");
456 }
457
458 void GLAPIENTRY
459 _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
460 GLuint index, GLsizei propCount,
461 const GLenum *props, GLsizei bufSize,
462 GLsizei *length, GLint *params)
463 {
464 GET_CURRENT_CONTEXT(ctx);
465
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);
470 }
471
472 struct gl_shader_program *shProg =
473 _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
474
475 if (!shProg || !params)
476 return;
477
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.
480 */
481 if (propCount <= 0) {
482 _mesa_error(ctx, GL_INVALID_VALUE,
483 "glGetProgramResourceiv(propCount <= 0)");
484 return;
485 }
486
487 _mesa_get_program_resourceiv(shProg, programInterface, index,
488 propCount, props, bufSize, length, params);
489 }
490
491 GLint GLAPIENTRY
492 _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
493 const GLchar *name)
494 {
495 GET_CURRENT_CONTEXT(ctx);
496
497 if (MESA_VERBOSE & VERBOSE_API) {
498 _mesa_debug(ctx, "glGetProgramResourceLocation(%u, %s, %s)\n",
499 program, _mesa_enum_to_string(programInterface), name);
500 }
501
502 struct gl_shader_program *shProg =
503 lookup_linked_program(program, "glGetProgramResourceLocation", true);
504
505 if (!shProg || !name)
506 return -1;
507
508 /* Validate programInterface. */
509 switch (programInterface) {
510 case GL_UNIFORM:
511 case GL_PROGRAM_INPUT:
512 case GL_PROGRAM_OUTPUT:
513 break;
514
515 case GL_VERTEX_SUBROUTINE_UNIFORM:
516 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
517 if (!_mesa_has_ARB_shader_subroutine(ctx))
518 goto fail;
519 break;
520 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
521 if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
522 goto fail;
523 break;
524 case GL_COMPUTE_SUBROUTINE_UNIFORM:
525 if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
526 goto fail;
527 break;
528 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
529 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
530 if (!_mesa_has_tessellation(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
531 goto fail;
532 break;
533 default:
534 goto fail;
535 }
536
537 return _mesa_program_resource_location(shProg, programInterface, name);
538 fail:
539 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
540 _mesa_enum_to_string(programInterface), name);
541 return -1;
542 }
543
544 /**
545 * Returns output index for dual source blending.
546 */
547 GLint GLAPIENTRY
548 _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
549 const GLchar *name)
550 {
551 GET_CURRENT_CONTEXT(ctx);
552
553 if (MESA_VERBOSE & VERBOSE_API) {
554 _mesa_debug(ctx, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
555 program, _mesa_enum_to_string(programInterface), name);
556 }
557
558 struct gl_shader_program *shProg =
559 lookup_linked_program(program, "glGetProgramResourceLocationIndex", true);
560
561 if (!shProg || !name)
562 return -1;
563
564 /* From the GL_ARB_program_interface_query spec:
565 *
566 * "For GetProgramResourceLocationIndex, <programInterface> must be
567 * PROGRAM_OUTPUT."
568 */
569 if (programInterface != GL_PROGRAM_OUTPUT) {
570 _mesa_error(ctx, GL_INVALID_ENUM,
571 "glGetProgramResourceLocationIndex(%s)",
572 _mesa_enum_to_string(programInterface));
573 return -1;
574 }
575
576 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
577 name);
578 }