• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * \file shader_query.cpp
26  * C-to-C++ bridge functions to query GLSL shader data
27  *
28  * \author Ian Romanick <ian.d.romanick@intel.com>
29  */
30 
31 #include "main/context.h"
32 #include "main/enums.h"
33 #include "main/shaderapi.h"
34 #include "main/shaderobj.h"
35 #include "main/uniforms.h"
36 #include "compiler/glsl/glsl_symbol_table.h"
37 #include "compiler/glsl/ir.h"
38 #include "compiler/glsl/linker_util.h"
39 #include "compiler/glsl/string_to_uint_map.h"
40 #include "util/mesa-sha1.h"
41 #include "c99_alloca.h"
42 #include "api_exec_decl.h"
43 
44 static GLint
45 program_resource_location(struct gl_program_resource *res,
46                           unsigned array_index);
47 
48 /**
49  * Declare convenience functions to return resource data in a given type.
50  * Warning! this is not type safe so be *very* careful when using these.
51  */
52 #define DECL_RESOURCE_FUNC(name, type) \
53 const type * RESOURCE_ ## name (gl_program_resource *res) { \
54    assert(res->Data); \
55    return (type *) res->Data; \
56 }
57 
58 DECL_RESOURCE_FUNC(VAR, gl_shader_variable);
59 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
60 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
61 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
62 DECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info);
63 DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer);
64 DECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
65 
66 static GLenum
mediump_to_highp_type(struct gl_shader_program * shProg,GLenum type)67 mediump_to_highp_type(struct gl_shader_program *shProg, GLenum type)
68 {
69    if (!shProg->IsES)
70       return type;
71 
72    switch (type) {
73    case GL_FLOAT16_NV:
74       return GL_FLOAT;
75    case GL_FLOAT16_VEC2_NV:
76       return GL_FLOAT_VEC2;
77    case GL_FLOAT16_VEC3_NV:
78       return GL_FLOAT_VEC3;
79    case GL_FLOAT16_VEC4_NV:
80       return GL_FLOAT_VEC4;
81    case GL_FLOAT16_MAT2_AMD:
82       return GL_FLOAT_MAT2;
83    case GL_FLOAT16_MAT3_AMD:
84       return GL_FLOAT_MAT3;
85    case GL_FLOAT16_MAT4_AMD:
86       return GL_FLOAT_MAT4;
87    case GL_FLOAT16_MAT2x3_AMD:
88       return GL_FLOAT_MAT2x3;
89    case GL_FLOAT16_MAT2x4_AMD:
90       return GL_FLOAT_MAT2x4;
91    case GL_FLOAT16_MAT3x2_AMD:
92       return GL_FLOAT_MAT3x2;
93    case GL_FLOAT16_MAT3x4_AMD:
94       return GL_FLOAT_MAT3x4;
95    case GL_FLOAT16_MAT4x2_AMD:
96       return GL_FLOAT_MAT4x2;
97    case GL_FLOAT16_MAT4x3_AMD:
98       return GL_FLOAT_MAT4x3;
99    default:
100       return type;
101    }
102 }
103 
104 static void
bind_attrib_location(struct gl_context * ctx,struct gl_shader_program * const shProg,GLuint index,const GLchar * name,bool no_error)105 bind_attrib_location(struct gl_context *ctx,
106                      struct gl_shader_program *const shProg, GLuint index,
107                      const GLchar *name, bool no_error)
108 {
109    if (!name)
110       return;
111 
112    if (!no_error) {
113       if (strncmp(name, "gl_", 3) == 0) {
114          _mesa_error(ctx, GL_INVALID_OPERATION,
115                      "glBindAttribLocation(illegal name)");
116          return;
117       }
118 
119       if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
120          _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
121                      index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
122          return;
123       }
124    }
125 
126    /* Replace the current value if it's already in the list.  Add
127     * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
128     * between built-in attributes and user-defined attributes.
129     */
130    shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
131 
132    /*
133     * Note that this attribute binding won't go into effect until
134     * glLinkProgram is called again.
135     */
136 }
137 
138 void GLAPIENTRY
_mesa_BindAttribLocation_no_error(GLuint program,GLuint index,const GLchar * name)139 _mesa_BindAttribLocation_no_error(GLuint program, GLuint index,
140                                   const GLchar *name)
141 {
142    GET_CURRENT_CONTEXT(ctx);
143 
144    struct gl_shader_program *const shProg =
145       _mesa_lookup_shader_program(ctx, program);
146    bind_attrib_location(ctx, shProg, index, name, true);
147 }
148 
149 void GLAPIENTRY
_mesa_BindAttribLocation(GLuint program,GLuint index,const GLchar * name)150 _mesa_BindAttribLocation(GLuint program, GLuint index,
151                          const GLchar *name)
152 {
153    GET_CURRENT_CONTEXT(ctx);
154 
155    struct gl_shader_program *const shProg =
156       _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
157    if (!shProg)
158       return;
159 
160    bind_attrib_location(ctx, shProg, index, name, false);
161 }
162 
163 void GLAPIENTRY
_mesa_GetActiveAttrib(GLuint program,GLuint desired_index,GLsizei maxLength,GLsizei * length,GLint * size,GLenum * type,GLchar * name)164 _mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
165                       GLsizei maxLength, GLsizei * length, GLint * size,
166                       GLenum * type, GLchar * name)
167 {
168    GET_CURRENT_CONTEXT(ctx);
169    struct gl_shader_program *shProg;
170 
171    if (maxLength < 0) {
172       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
173       return;
174    }
175 
176    shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
177    if (!shProg)
178       return;
179 
180    if (!shProg->data->LinkStatus) {
181       _mesa_error(ctx, GL_INVALID_VALUE,
182                   "glGetActiveAttrib(program not linked)");
183       return;
184    }
185 
186    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
187       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
188       return;
189    }
190 
191    struct gl_program_resource *res =
192       _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
193                                         desired_index);
194 
195    /* User asked for index that does not exist. */
196    if (!res) {
197       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
198       return;
199    }
200 
201    const gl_shader_variable *const var = RESOURCE_VAR(res);
202 
203    const char *var_name = var->name.string;
204 
205    _mesa_copy_string(name, maxLength, length, var_name);
206 
207    if (size)
208       _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
209                                   size, false, "glGetActiveAttrib");
210 
211    if (type)
212       _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
213                                   (GLint *) type, false, "glGetActiveAttrib");
214 }
215 
216 GLint GLAPIENTRY
_mesa_GetAttribLocation(GLuint program,const GLchar * name)217 _mesa_GetAttribLocation(GLuint program, const GLchar * name)
218 {
219    GET_CURRENT_CONTEXT(ctx);
220    struct gl_shader_program *const shProg =
221       _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
222 
223    if (!shProg) {
224       return -1;
225    }
226 
227    if (!shProg->data->LinkStatus) {
228       _mesa_error(ctx, GL_INVALID_OPERATION,
229                   "glGetAttribLocation(program not linked)");
230       return -1;
231    }
232 
233    if (!name)
234       return -1;
235 
236    /* Not having a vertex shader is not an error.
237     */
238    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
239       return -1;
240 
241    unsigned array_index = 0;
242    struct gl_program_resource *res =
243       _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
244                                        &array_index);
245 
246    if (!res)
247       return -1;
248 
249    return program_resource_location(res, array_index);
250 }
251 
252 unsigned
_mesa_count_active_attribs(struct gl_shader_program * shProg)253 _mesa_count_active_attribs(struct gl_shader_program *shProg)
254 {
255    if (!shProg->data->LinkStatus
256        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
257       return 0;
258    }
259 
260    struct gl_program_resource *res = shProg->data->ProgramResourceList;
261    unsigned count = 0;
262    for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
263         j++, res++) {
264       if (res->Type == GL_PROGRAM_INPUT &&
265           res->StageReferences & (1 << MESA_SHADER_VERTEX))
266          count++;
267    }
268    return count;
269 }
270 
271 
272 size_t
_mesa_longest_attribute_name_length(struct gl_shader_program * shProg)273 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
274 {
275    if (!shProg->data->LinkStatus
276        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
277       return 0;
278    }
279 
280    struct gl_program_resource *res = shProg->data->ProgramResourceList;
281    size_t longest = 0;
282    for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
283         j++, res++) {
284       if (res->Type == GL_PROGRAM_INPUT &&
285           res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
286 
287          /* From the ARB_gl_spirv spec:
288           *
289           *   "If pname is ACTIVE_ATTRIBUTE_MAX_LENGTH, the length of the
290           *    longest active attribute name, including a null terminator, is
291           *    returned.  If no active attributes exist, zero is returned. If
292           *    no name reflection information is available, one is returned."
293           */
294          const size_t length = RESOURCE_VAR(res)->name.length;
295 
296          if (length >= longest)
297             longest = length + 1;
298       }
299    }
300 
301    return longest;
302 }
303 
304 void static
bind_frag_data_location(struct gl_shader_program * const shProg,const char * name,unsigned colorNumber,unsigned index)305 bind_frag_data_location(struct gl_shader_program *const shProg,
306                         const char *name, unsigned colorNumber,
307                         unsigned index)
308 {
309    /* Replace the current value if it's already in the list.  Add
310     * FRAG_RESULT_DATA0 because that's how the linker differentiates
311     * between built-in attributes and user-defined attributes.
312     */
313    shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
314    shProg->FragDataIndexBindings->put(index, name);
315 
316    /*
317     * Note that this binding won't go into effect until
318     * glLinkProgram is called again.
319     */
320 }
321 
322 void GLAPIENTRY
_mesa_BindFragDataLocation(GLuint program,GLuint colorNumber,const GLchar * name)323 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
324 			   const GLchar *name)
325 {
326    _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
327 }
328 
329 void GLAPIENTRY
_mesa_BindFragDataLocation_no_error(GLuint program,GLuint colorNumber,const GLchar * name)330 _mesa_BindFragDataLocation_no_error(GLuint program, GLuint colorNumber,
331                                     const GLchar *name)
332 {
333    GET_CURRENT_CONTEXT(ctx);
334 
335    if (!name)
336       return;
337 
338    struct gl_shader_program *const shProg =
339       _mesa_lookup_shader_program(ctx, program);
340 
341    bind_frag_data_location(shProg, name, colorNumber, 0);
342 }
343 
344 void GLAPIENTRY
_mesa_BindFragDataLocationIndexed(GLuint program,GLuint colorNumber,GLuint index,const GLchar * name)345 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
346                                   GLuint index, const GLchar *name)
347 {
348    GET_CURRENT_CONTEXT(ctx);
349 
350    struct gl_shader_program *const shProg =
351       _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
352    if (!shProg)
353       return;
354 
355    if (!name)
356       return;
357 
358    if (strncmp(name, "gl_", 3) == 0) {
359       _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
360       return;
361    }
362 
363    if (index > 1) {
364       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
365       return;
366    }
367 
368    if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
369       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
370       return;
371    }
372 
373    if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
374       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
375       return;
376    }
377 
378    bind_frag_data_location(shProg, name, colorNumber, index);
379 }
380 
381 void GLAPIENTRY
_mesa_BindFragDataLocationIndexed_no_error(GLuint program,GLuint colorNumber,GLuint index,const GLchar * name)382 _mesa_BindFragDataLocationIndexed_no_error(GLuint program, GLuint colorNumber,
383                                            GLuint index, const GLchar *name)
384 {
385    GET_CURRENT_CONTEXT(ctx);
386 
387    if (!name)
388       return;
389 
390    struct gl_shader_program *const shProg =
391       _mesa_lookup_shader_program(ctx, program);
392 
393    bind_frag_data_location(shProg, name, colorNumber, index);
394 }
395 
396 GLint GLAPIENTRY
_mesa_GetFragDataIndex(GLuint program,const GLchar * name)397 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
398 {
399    GET_CURRENT_CONTEXT(ctx);
400    struct gl_shader_program *const shProg =
401       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
402 
403    if (!shProg) {
404       return -1;
405    }
406 
407    if (!shProg->data->LinkStatus) {
408       _mesa_error(ctx, GL_INVALID_OPERATION,
409                   "glGetFragDataIndex(program not linked)");
410       return -1;
411    }
412 
413    if (!name)
414       return -1;
415 
416    /* Not having a fragment shader is not an error.
417     */
418    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
419       return -1;
420 
421    return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
422                                                 name);
423 }
424 
425 GLint GLAPIENTRY
_mesa_GetFragDataLocation(GLuint program,const GLchar * name)426 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
427 {
428    GET_CURRENT_CONTEXT(ctx);
429    struct gl_shader_program *const shProg =
430       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
431 
432    if (!shProg) {
433       return -1;
434    }
435 
436    if (!shProg->data->LinkStatus) {
437       _mesa_error(ctx, GL_INVALID_OPERATION,
438                   "glGetFragDataLocation(program not linked)");
439       return -1;
440    }
441 
442    if (!name)
443       return -1;
444 
445    /* Not having a fragment shader is not an error.
446     */
447    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
448       return -1;
449 
450    unsigned array_index = 0;
451    struct gl_program_resource *res =
452       _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
453                                        &array_index);
454 
455    if (!res)
456       return -1;
457 
458    return program_resource_location(res, array_index);
459 }
460 
461 const char*
_mesa_program_resource_name(struct gl_program_resource * res)462 _mesa_program_resource_name(struct gl_program_resource *res)
463 {
464    switch (res->Type) {
465    case GL_UNIFORM_BLOCK:
466    case GL_SHADER_STORAGE_BLOCK:
467       return RESOURCE_UBO(res)->name.string;
468    case GL_TRANSFORM_FEEDBACK_VARYING:
469       return RESOURCE_XFV(res)->name.string;
470    case GL_PROGRAM_INPUT:
471    case GL_PROGRAM_OUTPUT:
472       return RESOURCE_VAR(res)->name.string;
473    case GL_UNIFORM:
474    case GL_BUFFER_VARIABLE:
475       return RESOURCE_UNI(res)->name.string;
476    case GL_VERTEX_SUBROUTINE_UNIFORM:
477    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
478    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
479    case GL_COMPUTE_SUBROUTINE_UNIFORM:
480    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
481    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
482       return RESOURCE_UNI(res)->name.string + MESA_SUBROUTINE_PREFIX_LEN;
483    case GL_VERTEX_SUBROUTINE:
484    case GL_GEOMETRY_SUBROUTINE:
485    case GL_FRAGMENT_SUBROUTINE:
486    case GL_COMPUTE_SUBROUTINE:
487    case GL_TESS_CONTROL_SUBROUTINE:
488    case GL_TESS_EVALUATION_SUBROUTINE:
489       return RESOURCE_SUB(res)->name.string;
490    default:
491       break;
492    }
493    return NULL;
494 }
495 
496 int
_mesa_program_resource_name_length(struct gl_program_resource * res)497 _mesa_program_resource_name_length(struct gl_program_resource *res)
498 {
499    switch (res->Type) {
500    case GL_UNIFORM_BLOCK:
501    case GL_SHADER_STORAGE_BLOCK:
502       return RESOURCE_UBO(res)->name.length;
503    case GL_TRANSFORM_FEEDBACK_VARYING:
504       return RESOURCE_XFV(res)->name.length;
505    case GL_PROGRAM_INPUT:
506    case GL_PROGRAM_OUTPUT:
507       return RESOURCE_VAR(res)->name.length;
508    case GL_UNIFORM:
509    case GL_BUFFER_VARIABLE:
510       return RESOURCE_UNI(res)->name.length;
511    case GL_VERTEX_SUBROUTINE_UNIFORM:
512    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
513    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
514    case GL_COMPUTE_SUBROUTINE_UNIFORM:
515    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
516    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
517       return RESOURCE_UNI(res)->name.length - MESA_SUBROUTINE_PREFIX_LEN;
518    case GL_VERTEX_SUBROUTINE:
519    case GL_GEOMETRY_SUBROUTINE:
520    case GL_FRAGMENT_SUBROUTINE:
521    case GL_COMPUTE_SUBROUTINE:
522    case GL_TESS_CONTROL_SUBROUTINE:
523    case GL_TESS_EVALUATION_SUBROUTINE:
524       return RESOURCE_SUB(res)->name.length;
525    default:
526       break;
527    }
528    return 0;
529 }
530 
531 bool
_mesa_program_get_resource_name(struct gl_program_resource * res,struct gl_resource_name * out)532 _mesa_program_get_resource_name(struct gl_program_resource *res,
533                                 struct gl_resource_name *out)
534 {
535    switch (res->Type) {
536    case GL_UNIFORM_BLOCK:
537    case GL_SHADER_STORAGE_BLOCK:
538       *out = RESOURCE_UBO(res)->name;
539       return out->string != NULL;
540    case GL_TRANSFORM_FEEDBACK_VARYING:
541       *out = RESOURCE_XFV(res)->name;
542       return out->string != NULL;
543    case GL_PROGRAM_INPUT:
544    case GL_PROGRAM_OUTPUT:
545       *out = RESOURCE_VAR(res)->name;
546       return out->string != NULL;
547    case GL_UNIFORM:
548    case GL_BUFFER_VARIABLE:
549       *out = RESOURCE_UNI(res)->name;
550       return out->string != NULL;
551    case GL_VERTEX_SUBROUTINE_UNIFORM:
552    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
553    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
554    case GL_COMPUTE_SUBROUTINE_UNIFORM:
555    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
556    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
557       *out = RESOURCE_UNI(res)->name;
558       out->string += MESA_SUBROUTINE_PREFIX_LEN;
559       out->length -= MESA_SUBROUTINE_PREFIX_LEN;
560       assert(out->string); /* always non-NULL */
561       return true;
562    case GL_VERTEX_SUBROUTINE:
563    case GL_GEOMETRY_SUBROUTINE:
564    case GL_FRAGMENT_SUBROUTINE:
565    case GL_COMPUTE_SUBROUTINE:
566    case GL_TESS_CONTROL_SUBROUTINE:
567    case GL_TESS_EVALUATION_SUBROUTINE:
568       *out = RESOURCE_SUB(res)->name;
569       return out->string != NULL;
570    default:
571       return false;
572    }
573 }
574 
575 unsigned
_mesa_program_resource_array_size(struct gl_program_resource * res)576 _mesa_program_resource_array_size(struct gl_program_resource *res)
577 {
578    switch (res->Type) {
579    case GL_TRANSFORM_FEEDBACK_VARYING:
580       return RESOURCE_XFV(res)->Size > 1 ?
581              RESOURCE_XFV(res)->Size : 0;
582    case GL_PROGRAM_INPUT:
583    case GL_PROGRAM_OUTPUT:
584       return RESOURCE_VAR(res)->type->length;
585    case GL_UNIFORM:
586    case GL_VERTEX_SUBROUTINE_UNIFORM:
587    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
588    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
589    case GL_COMPUTE_SUBROUTINE_UNIFORM:
590    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
591    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
592       return RESOURCE_UNI(res)->array_elements;
593    case GL_BUFFER_VARIABLE:
594       /* Unsized arrays */
595       if (RESOURCE_UNI(res)->array_stride > 0 &&
596           RESOURCE_UNI(res)->array_elements == 0)
597          return 1;
598       else
599          return RESOURCE_UNI(res)->array_elements;
600    case GL_VERTEX_SUBROUTINE:
601    case GL_GEOMETRY_SUBROUTINE:
602    case GL_FRAGMENT_SUBROUTINE:
603    case GL_COMPUTE_SUBROUTINE:
604    case GL_TESS_CONTROL_SUBROUTINE:
605    case GL_TESS_EVALUATION_SUBROUTINE:
606    case GL_ATOMIC_COUNTER_BUFFER:
607    case GL_UNIFORM_BLOCK:
608    case GL_SHADER_STORAGE_BLOCK:
609       return 0;
610    default:
611       assert(!"support for resource type not implemented");
612    }
613    return 0;
614 }
615 
616 /**
617  * Checks if array subscript is valid and if so sets array_index.
618  */
619 static bool
valid_array_index(const GLchar * name,int len,unsigned * array_index)620 valid_array_index(const GLchar *name, int len, unsigned *array_index)
621 {
622    long idx = 0;
623    const GLchar *out_base_name_end;
624 
625    idx = link_util_parse_program_resource_name(name, len, &out_base_name_end);
626    if (idx < 0)
627       return false;
628 
629    if (array_index)
630       *array_index = idx;
631 
632    return true;
633 }
634 
635 static struct gl_program_resource *
search_resource_hash(struct gl_shader_program * shProg,GLenum programInterface,const char * name,int len,unsigned * array_index)636 search_resource_hash(struct gl_shader_program *shProg,
637                      GLenum programInterface, const char *name, int len,
638                      unsigned *array_index)
639 {
640    unsigned type = GET_PROGRAM_RESOURCE_TYPE_FROM_GLENUM(programInterface);
641    assert(type < ARRAY_SIZE(shProg->data->ProgramResourceHash));
642 
643    if (!shProg->data->ProgramResourceHash[type])
644       return NULL;
645 
646    const char *base_name_end;
647    long index = link_util_parse_program_resource_name(name, len, &base_name_end);
648    char *name_copy;
649 
650    /* If dealing with array, we need to get the basename. */
651    if (index >= 0) {
652       name_copy = (char *) alloca(base_name_end - name + 1);
653       memcpy(name_copy, name, base_name_end - name);
654       name_copy[base_name_end - name] = '\0';
655       len = base_name_end - name;
656    } else {
657       name_copy = (char*) name;
658    }
659 
660    uint32_t hash = _mesa_hash_string_with_length(name_copy, len);
661    struct hash_entry *entry =
662       _mesa_hash_table_search_pre_hashed(shProg->data->ProgramResourceHash[type],
663                                          hash, name_copy);
664    if (!entry)
665       return NULL;
666 
667    if (array_index)
668       *array_index = index >= 0 ? index : 0;
669 
670    return (struct gl_program_resource *)entry->data;
671 }
672 
673 /* Find a program resource with specific name in given interface.
674  */
675 struct gl_program_resource *
_mesa_program_resource_find_name(struct gl_shader_program * shProg,GLenum programInterface,const char * name,unsigned * array_index)676 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
677                                  GLenum programInterface, const char *name,
678                                  unsigned *array_index)
679 {
680    if (name == NULL)
681       return NULL;
682 
683    int len = strlen(name);
684 
685    /* If we have a name, try the ProgramResourceHash first. */
686    struct gl_program_resource *res =
687       search_resource_hash(shProg, programInterface, name, len, array_index);
688 
689    if (res)
690       return res;
691 
692    res = shProg->data->ProgramResourceList;
693    for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
694       if (res->Type != programInterface)
695          continue;
696 
697       struct gl_resource_name rname;
698 
699       /* Since ARB_gl_spirv lack of name reflections is a possibility */
700       if (!_mesa_program_get_resource_name(res, &rname))
701          continue;
702 
703       bool found = false;
704 
705       /* From ARB_program_interface_query spec:
706        *
707        * "uint GetProgramResourceIndex(uint program, enum programInterface,
708        *                               const char *name);
709        *  [...]
710        *  If <name> exactly matches the name string of one of the active
711        *  resources for <programInterface>, the index of the matched resource is
712        *  returned. Additionally, if <name> would exactly match the name string
713        *  of an active resource if "[0]" were appended to <name>, the index of
714        *  the matched resource is returned. [...]"
715        *
716        * "A string provided to GetProgramResourceLocation or
717        * GetProgramResourceLocationIndex is considered to match an active variable
718        * if:
719        *
720        *  * the string exactly matches the name of the active variable;
721        *
722        *  * if the string identifies the base name of an active array, where the
723        *    string would exactly match the name of the variable if the suffix
724        *    "[0]" were appended to the string; [...]"
725        */
726       /* Remove array's index from interface block name comparison only if
727        * array's index is zero and the resulting string length is the same
728        * than the provided name's length.
729        */
730       int length_without_array_index =
731          rname.last_square_bracket >= 0 ? rname.last_square_bracket : rname.length;
732       bool rname_has_array_index_zero = rname.suffix_is_zero_square_bracketed &&
733                                         rname.last_square_bracket == len;
734 
735       if (len >= rname.length && strncmp(rname.string, name, rname.length) == 0)
736          found = true;
737       else if (rname_has_array_index_zero &&
738                strncmp(rname.string, name, length_without_array_index) == 0)
739          found = true;
740 
741       if (found) {
742          switch (programInterface) {
743          case GL_UNIFORM_BLOCK:
744          case GL_SHADER_STORAGE_BLOCK:
745             /* Basename match, check if array or struct. */
746             if (rname_has_array_index_zero ||
747                 name[rname.length] == '\0' ||
748                 name[rname.length] == '[' ||
749                 name[rname.length] == '.') {
750                return res;
751             }
752             break;
753          case GL_TRANSFORM_FEEDBACK_VARYING:
754          case GL_BUFFER_VARIABLE:
755          case GL_UNIFORM:
756          case GL_VERTEX_SUBROUTINE_UNIFORM:
757          case GL_GEOMETRY_SUBROUTINE_UNIFORM:
758          case GL_FRAGMENT_SUBROUTINE_UNIFORM:
759          case GL_COMPUTE_SUBROUTINE_UNIFORM:
760          case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
761          case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
762          case GL_VERTEX_SUBROUTINE:
763          case GL_GEOMETRY_SUBROUTINE:
764          case GL_FRAGMENT_SUBROUTINE:
765          case GL_COMPUTE_SUBROUTINE:
766          case GL_TESS_CONTROL_SUBROUTINE:
767          case GL_TESS_EVALUATION_SUBROUTINE:
768             if (name[rname.length] == '.') {
769                return res;
770             }
771             FALLTHROUGH;
772          case GL_PROGRAM_INPUT:
773          case GL_PROGRAM_OUTPUT:
774             if (name[rname.length] == '\0') {
775                return res;
776             } else if (name[rname.length] == '[' &&
777                 valid_array_index(name, len, array_index)) {
778                return res;
779             }
780             break;
781          default:
782             assert(!"not implemented for given interface");
783          }
784       }
785    }
786    return NULL;
787 }
788 
789 /* Find an uniform or buffer variable program resource with an specific offset
790  * inside a block with an specific binding.
791  *
792  * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
793  */
794 static struct gl_program_resource *
program_resource_find_binding_offset(struct gl_shader_program * shProg,GLenum programInterface,const GLuint binding,const GLint offset)795 program_resource_find_binding_offset(struct gl_shader_program *shProg,
796                                      GLenum programInterface,
797                                      const GLuint binding,
798                                      const GLint offset)
799 {
800 
801    /* First we need to get the BLOCK_INDEX from the BUFFER_BINDING */
802    GLenum blockInterface;
803 
804    switch (programInterface) {
805    case GL_BUFFER_VARIABLE:
806       blockInterface = GL_SHADER_STORAGE_BLOCK;
807       break;
808    case GL_UNIFORM:
809       blockInterface = GL_UNIFORM_BLOCK;
810       break;
811    default:
812       assert("Invalid program interface");
813       return NULL;
814    }
815 
816    int block_index = -1;
817    int starting_index = -1;
818    struct gl_program_resource *res = shProg->data->ProgramResourceList;
819 
820    /* Blocks are added to the resource list in the same order that they are
821     * added to UniformBlocks/ShaderStorageBlocks. Furthermore, all the blocks
822     * of each type (UBO/SSBO) are contiguous, so we can infer block_index from
823     * the resource list.
824     */
825    for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
826       if (res->Type != blockInterface)
827          continue;
828 
829       /* Store the first index where a resource of the specific interface is. */
830       if (starting_index == -1)
831          starting_index = i;
832 
833       const struct gl_uniform_block *block = RESOURCE_UBO(res);
834 
835       if (block->Binding == binding) {
836          /* For arrays, or arrays of arrays of blocks, we want the resource
837           * for the block with base index. Most properties for members of each
838           * block are inherited from the block with the base index, including
839           * a uniform being active or not.
840           */
841          block_index = i - starting_index - block->linearized_array_index;
842          break;
843       }
844    }
845 
846    if (block_index == -1)
847       return NULL;
848 
849    /* We now look for the resource corresponding to the uniform or buffer
850     * variable using the BLOCK_INDEX and OFFSET.
851     */
852    res = shProg->data->ProgramResourceList;
853    for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
854       if (res->Type != programInterface)
855          continue;
856 
857       const struct gl_uniform_storage *uniform = RESOURCE_UNI(res);
858 
859       if (uniform->block_index == block_index && uniform->offset == offset) {
860          return res;
861       }
862    }
863 
864    return NULL;
865 }
866 
867 /* Checks if an uniform or buffer variable is in the active program resource
868  * list.
869  *
870  * It takes into accout that for variables coming from SPIR-V binaries their
871  * names could not be available (ARB_gl_spirv). In that case, it will use the
872  * the offset and the block binding to locate the resource.
873  *
874  * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
875  */
876 struct gl_program_resource *
_mesa_program_resource_find_active_variable(struct gl_shader_program * shProg,GLenum programInterface,const gl_uniform_block * block,unsigned index)877 _mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
878                                             GLenum programInterface,
879                                             const gl_uniform_block *block,
880                                             unsigned index)
881 {
882    struct gl_program_resource *res;
883    struct gl_uniform_buffer_variable uni = block->Uniforms[index];
884 
885    assert(programInterface == GL_UNIFORM ||
886           programInterface == GL_BUFFER_VARIABLE);
887 
888    if (uni.IndexName) {
889       res = _mesa_program_resource_find_name(shProg, programInterface, uni.IndexName,
890                                              NULL);
891    } else {
892       /* As the resource has no associated name (ARB_gl_spirv),
893        * we can use the UBO/SSBO binding and offset to find it.
894        */
895       res = program_resource_find_binding_offset(shProg, programInterface,
896                                                  block->Binding, uni.Offset);
897    }
898 
899    return res;
900 }
901 
902 static GLuint
calc_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)903 calc_resource_index(struct gl_shader_program *shProg,
904                     struct gl_program_resource *res)
905 {
906    unsigned i;
907    GLuint index = 0;
908    for (i = 0; i < shProg->data->NumProgramResourceList; i++) {
909       if (&shProg->data->ProgramResourceList[i] == res)
910          return index;
911       if (shProg->data->ProgramResourceList[i].Type == res->Type)
912          index++;
913    }
914    return GL_INVALID_INDEX;
915 }
916 
917 /**
918  * Calculate index for the given resource.
919  */
920 GLuint
_mesa_program_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)921 _mesa_program_resource_index(struct gl_shader_program *shProg,
922                              struct gl_program_resource *res)
923 {
924    if (!res)
925       return GL_INVALID_INDEX;
926 
927    switch (res->Type) {
928    case GL_ATOMIC_COUNTER_BUFFER:
929       return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
930    case GL_VERTEX_SUBROUTINE:
931    case GL_GEOMETRY_SUBROUTINE:
932    case GL_FRAGMENT_SUBROUTINE:
933    case GL_COMPUTE_SUBROUTINE:
934    case GL_TESS_CONTROL_SUBROUTINE:
935    case GL_TESS_EVALUATION_SUBROUTINE:
936       return RESOURCE_SUB(res)->index;
937    case GL_UNIFORM_BLOCK:
938    case GL_SHADER_STORAGE_BLOCK:
939    case GL_TRANSFORM_FEEDBACK_BUFFER:
940    case GL_TRANSFORM_FEEDBACK_VARYING:
941    default:
942       return calc_resource_index(shProg, res);
943    }
944 }
945 
946 /**
947  * Find a program resource that points to given data.
948  */
949 static struct gl_program_resource*
program_resource_find_data(struct gl_shader_program * shProg,void * data)950 program_resource_find_data(struct gl_shader_program *shProg, void *data)
951 {
952    struct gl_program_resource *res = shProg->data->ProgramResourceList;
953    for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
954         i++, res++) {
955       if (res->Data == data)
956          return res;
957    }
958    return NULL;
959 }
960 
961 /* Find a program resource with specific index in given interface.
962  */
963 struct gl_program_resource *
_mesa_program_resource_find_index(struct gl_shader_program * shProg,GLenum programInterface,GLuint index)964 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
965                                   GLenum programInterface, GLuint index)
966 {
967    struct gl_program_resource *res = shProg->data->ProgramResourceList;
968    int idx = -1;
969 
970    for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
971         i++, res++) {
972       if (res->Type != programInterface)
973          continue;
974 
975       switch (res->Type) {
976       case GL_UNIFORM_BLOCK:
977       case GL_ATOMIC_COUNTER_BUFFER:
978       case GL_SHADER_STORAGE_BLOCK:
979       case GL_TRANSFORM_FEEDBACK_BUFFER:
980          if (_mesa_program_resource_index(shProg, res) == index)
981             return res;
982          break;
983       case GL_TRANSFORM_FEEDBACK_VARYING:
984       case GL_PROGRAM_INPUT:
985       case GL_PROGRAM_OUTPUT:
986       case GL_UNIFORM:
987       case GL_VERTEX_SUBROUTINE_UNIFORM:
988       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
989       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
990       case GL_COMPUTE_SUBROUTINE_UNIFORM:
991       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
992       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
993       case GL_VERTEX_SUBROUTINE:
994       case GL_GEOMETRY_SUBROUTINE:
995       case GL_FRAGMENT_SUBROUTINE:
996       case GL_COMPUTE_SUBROUTINE:
997       case GL_TESS_CONTROL_SUBROUTINE:
998       case GL_TESS_EVALUATION_SUBROUTINE:
999       case GL_BUFFER_VARIABLE:
1000          if (++idx == (int) index)
1001             return res;
1002          break;
1003       default:
1004          assert(!"not implemented for given interface");
1005       }
1006    }
1007    return NULL;
1008 }
1009 
1010 /* Function returns if resource name is expected to have index
1011  * appended into it.
1012  *
1013  *
1014  * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
1015  * spec says:
1016  *
1017  *     "If the active uniform is an array, the uniform name returned in
1018  *     name will always be the name of the uniform array appended with
1019  *     "[0]"."
1020  *
1021  * The same text also appears in the OpenGL 4.2 spec.  It does not,
1022  * however, appear in any previous spec.  Previous specifications are
1023  * ambiguous in this regard.  However, either name can later be passed
1024  * to glGetUniformLocation (and related APIs), so there shouldn't be any
1025  * harm in always appending "[0]" to uniform array names.
1026  */
1027 static bool
add_index_to_name(struct gl_program_resource * res)1028 add_index_to_name(struct gl_program_resource *res)
1029 {
1030    /* Transform feedback varyings have array index already appended
1031     * in their names.
1032     */
1033    return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
1034 }
1035 
1036 /* Get name length of a program resource. This consists of
1037  * base name + 3 for '[0]' if resource is an array.
1038  */
1039 extern unsigned
_mesa_program_resource_name_length_array(struct gl_program_resource * res)1040 _mesa_program_resource_name_length_array(struct gl_program_resource *res)
1041 {
1042    int length = _mesa_program_resource_name_length(res);
1043 
1044    /* For shaders constructed from SPIR-V binaries, variables may not
1045     * have names associated with them.
1046     */
1047    if (!length)
1048       return 0;
1049 
1050    if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
1051       length += 3;
1052    return length;
1053 }
1054 
1055 /* Get full name of a program resource.
1056  */
1057 bool
_mesa_get_program_resource_name(struct gl_shader_program * shProg,GLenum programInterface,GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name,bool glthread,const char * caller)1058 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
1059                                 GLenum programInterface, GLuint index,
1060                                 GLsizei bufSize, GLsizei *length,
1061                                 GLchar *name, bool glthread,
1062                                 const char *caller)
1063 {
1064    GET_CURRENT_CONTEXT(ctx);
1065 
1066    /* Find resource with given interface and index. */
1067    struct gl_program_resource *res =
1068       _mesa_program_resource_find_index(shProg, programInterface, index);
1069 
1070    /* The error INVALID_VALUE is generated if <index> is greater than
1071    * or equal to the number of entries in the active resource list for
1072    * <programInterface>.
1073    */
1074    if (!res) {
1075       _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
1076                                 "%s(index %u)", caller, index);
1077       return false;
1078    }
1079 
1080    if (bufSize < 0) {
1081       _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
1082                                 "%s(bufSize %d)", caller, bufSize);
1083       return false;
1084    }
1085 
1086    GLsizei localLength;
1087 
1088    if (length == NULL)
1089       length = &localLength;
1090 
1091    _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
1092 
1093    /* The resource name can be NULL for shaders constructed from SPIR-V
1094     * binaries. In that case, we do not add the '[0]'.
1095     */
1096    if (name && name[0] != '\0' &&
1097        _mesa_program_resource_array_size(res) && add_index_to_name(res)) {
1098       int i;
1099 
1100       /* The comparison is strange because *length does *NOT* include the
1101        * terminating NUL, but maxLength does.
1102        */
1103       for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
1104          name[*length + i] = "[0]"[i];
1105 
1106       name[*length + i] = '\0';
1107       *length += i;
1108    }
1109    return true;
1110 }
1111 
1112 static GLint
program_resource_location(struct gl_program_resource * res,unsigned array_index)1113 program_resource_location(struct gl_program_resource *res, unsigned array_index)
1114 {
1115    switch (res->Type) {
1116    case GL_PROGRAM_INPUT: {
1117       const gl_shader_variable *var = RESOURCE_VAR(res);
1118 
1119       if (var->location == -1)
1120          return -1;
1121 
1122       /* If the input is an array, fail if the index is out of bounds. */
1123       if (array_index > 0
1124           && array_index >= var->type->length) {
1125          return -1;
1126       }
1127       return var->location +
1128 	     (array_index * glsl_without_array(var->type)->matrix_columns);
1129    }
1130    case GL_PROGRAM_OUTPUT:
1131       if (RESOURCE_VAR(res)->location == -1)
1132          return -1;
1133 
1134       /* If the output is an array, fail if the index is out of bounds. */
1135       if (array_index > 0
1136           && array_index >= RESOURCE_VAR(res)->type->length) {
1137          return -1;
1138       }
1139       return RESOURCE_VAR(res)->location + array_index;
1140    case GL_UNIFORM:
1141       /* If the uniform is built-in, fail. */
1142       if (RESOURCE_UNI(res)->builtin)
1143          return -1;
1144 
1145      /* From page 79 of the OpenGL 4.2 spec:
1146       *
1147       *     "A valid name cannot be a structure, an array of structures, or any
1148       *     portion of a single vector or a matrix."
1149       */
1150       if (glsl_type_is_struct(glsl_without_array(RESOURCE_UNI(res)->type)))
1151          return -1;
1152 
1153       /* From the GL_ARB_uniform_buffer_object spec:
1154        *
1155        *     "The value -1 will be returned if <name> does not correspond to an
1156        *     active uniform variable name in <program>, if <name> is associated
1157        *     with a named uniform block, or if <name> starts with the reserved
1158        *     prefix "gl_"."
1159        */
1160       if (RESOURCE_UNI(res)->block_index != -1 ||
1161           RESOURCE_UNI(res)->atomic_buffer_index != -1)
1162          return -1;
1163 
1164       FALLTHROUGH;
1165    case GL_VERTEX_SUBROUTINE_UNIFORM:
1166    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1167    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1168    case GL_COMPUTE_SUBROUTINE_UNIFORM:
1169    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1170    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1171       /* If the uniform is an array, fail if the index is out of bounds. */
1172       if (array_index > 0
1173           && array_index >= RESOURCE_UNI(res)->array_elements) {
1174          return -1;
1175       }
1176 
1177       /* location in remap table + array element offset */
1178       return RESOURCE_UNI(res)->remap_location + array_index;
1179    default:
1180       return -1;
1181    }
1182 }
1183 
1184 /**
1185  * Function implements following location queries:
1186  *    glGetUniformLocation
1187  */
1188 GLint
_mesa_program_resource_location(struct gl_shader_program * shProg,GLenum programInterface,const char * name)1189 _mesa_program_resource_location(struct gl_shader_program *shProg,
1190                                 GLenum programInterface, const char *name)
1191 {
1192    unsigned array_index = 0;
1193    struct gl_program_resource *res =
1194       _mesa_program_resource_find_name(shProg, programInterface, name,
1195                                        &array_index);
1196 
1197    /* Resource not found. */
1198    if (!res)
1199       return -1;
1200 
1201    return program_resource_location(res, array_index);
1202 }
1203 
1204 static GLint
_get_resource_location_index(struct gl_program_resource * res)1205 _get_resource_location_index(struct gl_program_resource *res)
1206 {
1207    /* Non-existent variable or resource is not referenced by fragment stage. */
1208    if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
1209       return -1;
1210 
1211    /* From OpenGL 4.5 spec, 7.3 Program Objects
1212     * "The value -1 will be returned by either command...
1213     *  ... or if name identifies an active variable that does not have a
1214     * valid location assigned.
1215     */
1216    if (RESOURCE_VAR(res)->location == -1)
1217       return -1;
1218    return RESOURCE_VAR(res)->index;
1219 }
1220 
1221 /**
1222  * Function implements following index queries:
1223  *    glGetFragDataIndex
1224  */
1225 GLint
_mesa_program_resource_location_index(struct gl_shader_program * shProg,GLenum programInterface,const char * name)1226 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
1227                                       GLenum programInterface, const char *name)
1228 {
1229    struct gl_program_resource *res =
1230       _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
1231 
1232    return _get_resource_location_index(res);
1233 }
1234 
1235 static uint8_t
stage_from_enum(GLenum ref)1236 stage_from_enum(GLenum ref)
1237 {
1238    switch (ref) {
1239    case GL_REFERENCED_BY_VERTEX_SHADER:
1240       return MESA_SHADER_VERTEX;
1241    case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1242       return MESA_SHADER_TESS_CTRL;
1243    case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1244       return MESA_SHADER_TESS_EVAL;
1245    case GL_REFERENCED_BY_GEOMETRY_SHADER:
1246       return MESA_SHADER_GEOMETRY;
1247    case GL_REFERENCED_BY_FRAGMENT_SHADER:
1248       return MESA_SHADER_FRAGMENT;
1249    case GL_REFERENCED_BY_COMPUTE_SHADER:
1250       return MESA_SHADER_COMPUTE;
1251    default:
1252       assert(!"shader stage not supported");
1253       return MESA_SHADER_STAGES;
1254    }
1255 }
1256 
1257 /**
1258  * Check if resource is referenced by given 'referenced by' stage enum.
1259  * ATC and UBO resources hold stage references of their own.
1260  */
1261 static bool
is_resource_referenced(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,uint8_t stage)1262 is_resource_referenced(struct gl_shader_program *shProg,
1263                        struct gl_program_resource *res,
1264                        GLuint index, uint8_t stage)
1265 {
1266    /* First, check if we even have such a stage active. */
1267    if (!shProg->_LinkedShaders[stage])
1268       return false;
1269 
1270    if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
1271       return RESOURCE_ATC(res)->StageReferences[stage];
1272 
1273    if (res->Type == GL_UNIFORM_BLOCK)
1274       return shProg->data->UniformBlocks[index].stageref & (1 << stage);
1275 
1276    if (res->Type == GL_SHADER_STORAGE_BLOCK)
1277       return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
1278 
1279    return res->StageReferences & (1 << stage);
1280 }
1281 
1282 static unsigned
get_buffer_property(struct gl_shader_program * shProg,struct gl_program_resource * res,const GLenum prop,GLint * val,bool glthread,const char * caller)1283 get_buffer_property(struct gl_shader_program *shProg,
1284                     struct gl_program_resource *res, const GLenum prop,
1285                     GLint *val, bool glthread, const char *caller)
1286 {
1287    GET_CURRENT_CONTEXT(ctx);
1288    if (res->Type != GL_UNIFORM_BLOCK &&
1289        res->Type != GL_ATOMIC_COUNTER_BUFFER &&
1290        res->Type != GL_SHADER_STORAGE_BLOCK &&
1291        res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
1292       goto invalid_operation;
1293 
1294    if (res->Type == GL_UNIFORM_BLOCK) {
1295       switch (prop) {
1296       case GL_BUFFER_BINDING:
1297          *val = RESOURCE_UBO(res)->Binding;
1298          return 1;
1299       case GL_BUFFER_DATA_SIZE:
1300          *val = RESOURCE_UBO(res)->UniformBufferSize;
1301          return 1;
1302       case GL_NUM_ACTIVE_VARIABLES:
1303          *val = 0;
1304          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1305             struct gl_program_resource *uni =
1306                _mesa_program_resource_find_active_variable(
1307                   shProg,
1308                   GL_UNIFORM,
1309                   RESOURCE_UBO(res),
1310                   i);
1311 
1312             if (!uni)
1313                continue;
1314             (*val)++;
1315          }
1316          return 1;
1317       case GL_ACTIVE_VARIABLES: {
1318          unsigned num_values = 0;
1319          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1320             struct gl_program_resource *uni =
1321                _mesa_program_resource_find_active_variable(
1322                   shProg,
1323                   GL_UNIFORM,
1324                   RESOURCE_UBO(res),
1325                   i);
1326 
1327             if (!uni)
1328                continue;
1329             *val++ =
1330                _mesa_program_resource_index(shProg, uni);
1331             num_values++;
1332          }
1333          return num_values;
1334       }
1335       }
1336    } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
1337       switch (prop) {
1338       case GL_BUFFER_BINDING:
1339          *val = RESOURCE_UBO(res)->Binding;
1340          return 1;
1341       case GL_BUFFER_DATA_SIZE:
1342          *val = RESOURCE_UBO(res)->UniformBufferSize;
1343          return 1;
1344       case GL_NUM_ACTIVE_VARIABLES:
1345          *val = 0;
1346          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1347             struct gl_program_resource *uni =
1348                _mesa_program_resource_find_active_variable(
1349                   shProg,
1350                   GL_BUFFER_VARIABLE,
1351                   RESOURCE_UBO(res),
1352                   i);
1353 
1354             if (!uni)
1355                continue;
1356             (*val)++;
1357          }
1358          return 1;
1359       case GL_ACTIVE_VARIABLES: {
1360          unsigned num_values = 0;
1361          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1362             struct gl_program_resource *uni =
1363                _mesa_program_resource_find_active_variable(
1364                   shProg,
1365                   GL_BUFFER_VARIABLE,
1366                   RESOURCE_UBO(res),
1367                   i);
1368 
1369             if (!uni)
1370                continue;
1371             *val++ =
1372                _mesa_program_resource_index(shProg, uni);
1373             num_values++;
1374          }
1375          return num_values;
1376       }
1377       }
1378    } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1379       switch (prop) {
1380       case GL_BUFFER_BINDING:
1381          *val = RESOURCE_ATC(res)->Binding;
1382          return 1;
1383       case GL_BUFFER_DATA_SIZE:
1384          *val = RESOURCE_ATC(res)->MinimumSize;
1385          return 1;
1386       case GL_NUM_ACTIVE_VARIABLES:
1387          *val = RESOURCE_ATC(res)->NumUniforms;
1388          return 1;
1389       case GL_ACTIVE_VARIABLES:
1390          for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
1391             /* Active atomic buffer contains index to UniformStorage. Find
1392              * out gl_program_resource via data pointer and then calculate
1393              * index of that uniform.
1394              */
1395             unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
1396             struct gl_program_resource *uni =
1397                program_resource_find_data(shProg,
1398                                           &shProg->data->UniformStorage[idx]);
1399             assert(uni);
1400             *val++ = _mesa_program_resource_index(shProg, uni);
1401          }
1402          return RESOURCE_ATC(res)->NumUniforms;
1403       }
1404    } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
1405       switch (prop) {
1406       case GL_BUFFER_BINDING:
1407          *val = RESOURCE_XFB(res)->Binding;
1408          return 1;
1409       case GL_NUM_ACTIVE_VARIABLES:
1410          *val = RESOURCE_XFB(res)->NumVaryings;
1411          return 1;
1412       case GL_ACTIVE_VARIABLES:
1413          struct gl_transform_feedback_info *linked_xfb =
1414             shProg->last_vert_prog->sh.LinkedTransformFeedback;
1415          for (int i = 0; i < linked_xfb->NumVarying; i++) {
1416             unsigned index = linked_xfb->Varyings[i].BufferIndex;
1417             struct gl_program_resource *buf_res =
1418                _mesa_program_resource_find_index(shProg,
1419                                                  GL_TRANSFORM_FEEDBACK_BUFFER,
1420                                                  index);
1421             assert(buf_res);
1422             if (res == buf_res) {
1423                *val++ = i;
1424             }
1425          }
1426          return RESOURCE_XFB(res)->NumVaryings;
1427       }
1428    }
1429    assert(!"support for property type not implemented");
1430 
1431 invalid_operation:
1432    _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
1433                              "%s(%s prop %s)", caller,
1434                              _mesa_enum_to_string(res->Type),
1435                              _mesa_enum_to_string(prop));
1436 
1437    return 0;
1438 }
1439 
1440 unsigned
_mesa_program_resource_prop(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,const GLenum prop,GLint * val,bool glthread,const char * caller)1441 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1442                             struct gl_program_resource *res, GLuint index,
1443                             const GLenum prop, GLint *val, bool glthread,
1444                             const char *caller)
1445 {
1446    GET_CURRENT_CONTEXT(ctx);
1447 
1448 #define VALIDATE_TYPE(type)\
1449    if (res->Type != type)\
1450       goto invalid_operation;
1451 
1452 #define VALIDATE_TYPE_2(type1, type2)\
1453    if (res->Type != type1 && res->Type != type2)\
1454       goto invalid_operation;
1455 
1456    switch(prop) {
1457    case GL_NAME_LENGTH:
1458       switch (res->Type) {
1459       case GL_ATOMIC_COUNTER_BUFFER:
1460       case GL_TRANSFORM_FEEDBACK_BUFFER:
1461          goto invalid_operation;
1462       default:
1463          /* Resource name length + terminator. */
1464          *val = _mesa_program_resource_name_length_array(res) + 1;
1465       }
1466       return 1;
1467    case GL_TYPE:
1468       switch (res->Type) {
1469       case GL_UNIFORM:
1470       case GL_BUFFER_VARIABLE:
1471          *val = RESOURCE_UNI(res)->type->gl_type;
1472          *val = mediump_to_highp_type(shProg, *val);
1473          return 1;
1474       case GL_PROGRAM_INPUT:
1475       case GL_PROGRAM_OUTPUT:
1476          *val = RESOURCE_VAR(res)->type->gl_type;
1477          *val = mediump_to_highp_type(shProg, *val);
1478          return 1;
1479       case GL_TRANSFORM_FEEDBACK_VARYING:
1480          *val = RESOURCE_XFV(res)->Type;
1481          *val = mediump_to_highp_type(shProg, *val);
1482          return 1;
1483       default:
1484          goto invalid_operation;
1485       }
1486    case GL_ARRAY_SIZE:
1487       switch (res->Type) {
1488       case GL_UNIFORM:
1489       case GL_BUFFER_VARIABLE:
1490       case GL_VERTEX_SUBROUTINE_UNIFORM:
1491       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1492       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1493       case GL_COMPUTE_SUBROUTINE_UNIFORM:
1494       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1495       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1496 
1497          /* Test if a buffer variable is an array or an unsized array.
1498           * Unsized arrays return zero as array size.
1499           */
1500          if (RESOURCE_UNI(res)->is_shader_storage &&
1501              RESOURCE_UNI(res)->array_stride > 0)
1502             *val = RESOURCE_UNI(res)->array_elements;
1503          else
1504             *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1505          return 1;
1506       case GL_PROGRAM_INPUT:
1507       case GL_PROGRAM_OUTPUT:
1508          *val = MAX2(_mesa_program_resource_array_size(res), 1);
1509          return 1;
1510       case GL_TRANSFORM_FEEDBACK_VARYING:
1511          *val = RESOURCE_XFV(res)->Size;
1512          return 1;
1513       default:
1514          goto invalid_operation;
1515       }
1516    case GL_OFFSET:
1517       switch (res->Type) {
1518       case GL_UNIFORM:
1519       case GL_BUFFER_VARIABLE:
1520          *val = RESOURCE_UNI(res)->offset;
1521          return 1;
1522       case GL_TRANSFORM_FEEDBACK_VARYING:
1523          *val = RESOURCE_XFV(res)->Offset;
1524          return 1;
1525       default:
1526          goto invalid_operation;
1527       }
1528    case GL_BLOCK_INDEX:
1529       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1530       *val = RESOURCE_UNI(res)->block_index;
1531       return 1;
1532    case GL_ARRAY_STRIDE:
1533       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1534       *val = RESOURCE_UNI(res)->array_stride;
1535       return 1;
1536    case GL_MATRIX_STRIDE:
1537       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1538       *val = RESOURCE_UNI(res)->matrix_stride;
1539       return 1;
1540    case GL_IS_ROW_MAJOR:
1541       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1542       *val = RESOURCE_UNI(res)->row_major;
1543       return 1;
1544    case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1545       VALIDATE_TYPE(GL_UNIFORM);
1546       *val = RESOURCE_UNI(res)->atomic_buffer_index;
1547       return 1;
1548    case GL_BUFFER_BINDING:
1549    case GL_BUFFER_DATA_SIZE:
1550    case GL_NUM_ACTIVE_VARIABLES:
1551    case GL_ACTIVE_VARIABLES:
1552       return get_buffer_property(shProg, res, prop, val, glthread, caller);
1553    case GL_REFERENCED_BY_COMPUTE_SHADER:
1554       if (!_mesa_has_compute_shaders(ctx))
1555          goto invalid_enum;
1556       FALLTHROUGH;
1557    case GL_REFERENCED_BY_VERTEX_SHADER:
1558    case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1559    case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1560    case GL_REFERENCED_BY_GEOMETRY_SHADER:
1561    case GL_REFERENCED_BY_FRAGMENT_SHADER:
1562       switch (res->Type) {
1563       case GL_UNIFORM:
1564       case GL_PROGRAM_INPUT:
1565       case GL_PROGRAM_OUTPUT:
1566       case GL_UNIFORM_BLOCK:
1567       case GL_BUFFER_VARIABLE:
1568       case GL_SHADER_STORAGE_BLOCK:
1569       case GL_ATOMIC_COUNTER_BUFFER:
1570          *val = is_resource_referenced(shProg, res, index,
1571                                        stage_from_enum(prop));
1572          return 1;
1573       default:
1574          goto invalid_operation;
1575       }
1576    case GL_LOCATION:
1577       switch (res->Type) {
1578       case GL_UNIFORM:
1579       case GL_VERTEX_SUBROUTINE_UNIFORM:
1580       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1581       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1582       case GL_COMPUTE_SUBROUTINE_UNIFORM:
1583       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1584       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1585       case GL_PROGRAM_INPUT:
1586       case GL_PROGRAM_OUTPUT:
1587          *val = program_resource_location(res, 0);
1588          return 1;
1589       default:
1590          goto invalid_operation;
1591       }
1592    case GL_LOCATION_COMPONENT:
1593       switch (res->Type) {
1594       case GL_PROGRAM_INPUT:
1595       case GL_PROGRAM_OUTPUT:
1596          *val = RESOURCE_VAR(res)->component;
1597          return 1;
1598       default:
1599          goto invalid_operation;
1600       }
1601    case GL_LOCATION_INDEX: {
1602       int tmp;
1603       if (res->Type != GL_PROGRAM_OUTPUT)
1604          goto invalid_operation;
1605       tmp = program_resource_location(res, 0);
1606       if (tmp == -1)
1607          *val = -1;
1608       else
1609          *val = _get_resource_location_index(res);
1610       return 1;
1611    }
1612    case GL_NUM_COMPATIBLE_SUBROUTINES:
1613       if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1614           res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1615           res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1616           res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1617           res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1618           res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1619          goto invalid_operation;
1620       *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1621       return 1;
1622    case GL_COMPATIBLE_SUBROUTINES: {
1623       const struct gl_uniform_storage *uni;
1624       struct gl_program *p;
1625       unsigned count, i;
1626       int j;
1627 
1628       if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1629           res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1630           res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1631           res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1632           res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1633           res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1634          goto invalid_operation;
1635       uni = RESOURCE_UNI(res);
1636 
1637       p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
1638       count = 0;
1639       for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
1640          struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
1641          for (j = 0; j < fn->num_compat_types; j++) {
1642             if (fn->types[j] == uni->type) {
1643                val[count++] = i;
1644                break;
1645             }
1646          }
1647       }
1648       return count;
1649    }
1650 
1651    case GL_TOP_LEVEL_ARRAY_SIZE:
1652       VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1653       *val = RESOURCE_UNI(res)->top_level_array_size;
1654       return 1;
1655 
1656    case GL_TOP_LEVEL_ARRAY_STRIDE:
1657       VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1658       *val = RESOURCE_UNI(res)->top_level_array_stride;
1659       return 1;
1660 
1661    /* GL_ARB_tessellation_shader */
1662    case GL_IS_PER_PATCH:
1663       switch (res->Type) {
1664       case GL_PROGRAM_INPUT:
1665       case GL_PROGRAM_OUTPUT:
1666          *val = RESOURCE_VAR(res)->patch;
1667          return 1;
1668       default:
1669          goto invalid_operation;
1670       }
1671 
1672    case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
1673       VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
1674       *val = RESOURCE_XFV(res)->BufferIndex;
1675       return 1;
1676    case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
1677       VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
1678       *val = RESOURCE_XFB(res)->Stride * 4;
1679       return 1;
1680 
1681    default:
1682       goto invalid_enum;
1683    }
1684 
1685 #undef VALIDATE_TYPE
1686 #undef VALIDATE_TYPE_2
1687 
1688 invalid_enum:
1689    _mesa_error_glthread_safe(ctx, GL_INVALID_ENUM, glthread,
1690                              "%s(%s prop %s)", caller,
1691                              _mesa_enum_to_string(res->Type),
1692                              _mesa_enum_to_string(prop));
1693    return 0;
1694 
1695 invalid_operation:
1696    _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
1697                              "%s(%s prop %s)", caller,
1698                              _mesa_enum_to_string(res->Type),
1699                              _mesa_enum_to_string(prop));
1700    return 0;
1701 }
1702 
1703 extern void
_mesa_get_program_resourceiv(struct gl_shader_program * shProg,GLenum programInterface,GLuint index,GLsizei propCount,const GLenum * props,GLsizei bufSize,GLsizei * length,GLint * params)1704 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1705                              GLenum programInterface, GLuint index, GLsizei propCount,
1706                              const GLenum *props, GLsizei bufSize,
1707                              GLsizei *length, GLint *params)
1708 {
1709    GET_CURRENT_CONTEXT(ctx);
1710    GLint *val = (GLint *) params;
1711    const GLenum *prop = props;
1712    GLsizei amount = 0;
1713 
1714    struct gl_program_resource *res =
1715       _mesa_program_resource_find_index(shProg, programInterface, index);
1716 
1717    /* No such resource found or bufSize negative. */
1718    if (!res || bufSize < 0) {
1719       _mesa_error(ctx, GL_INVALID_VALUE,
1720                   "glGetProgramResourceiv(%s index %d bufSize %d)",
1721                   _mesa_enum_to_string(programInterface), index, bufSize);
1722       return;
1723    }
1724 
1725    /* Write propCount values until error occurs or bufSize reached. */
1726    for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1727       int props_written =
1728          _mesa_program_resource_prop(shProg, res, index, *prop, val,
1729                                      false, "glGetProgramResourceiv");
1730 
1731       /* Error happened. */
1732       if (props_written == 0)
1733          return;
1734 
1735       amount += props_written;
1736    }
1737 
1738    /* If <length> is not NULL, the actual number of integer values
1739     * written to <params> will be written to <length>.
1740     */
1741    if (length)
1742       *length = amount;
1743 }
1744 
1745 extern void
_mesa_get_program_interfaceiv(struct gl_shader_program * shProg,GLenum programInterface,GLenum pname,GLint * params)1746 _mesa_get_program_interfaceiv(struct gl_shader_program *shProg,
1747                               GLenum programInterface, GLenum pname,
1748                               GLint *params)
1749 {
1750    GET_CURRENT_CONTEXT(ctx);
1751    unsigned i;
1752 
1753    /* Validate pname against interface. */
1754    switch(pname) {
1755    case GL_ACTIVE_RESOURCES:
1756       for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++)
1757          if (shProg->data->ProgramResourceList[i].Type == programInterface)
1758             (*params)++;
1759       break;
1760    case GL_MAX_NAME_LENGTH:
1761       if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
1762           programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) {
1763          _mesa_error(ctx, GL_INVALID_OPERATION,
1764                      "glGetProgramInterfaceiv(%s pname %s)",
1765                      _mesa_enum_to_string(programInterface),
1766                      _mesa_enum_to_string(pname));
1767          return;
1768       }
1769       /* Name length consists of base name, 3 additional chars '[0]' if
1770        * resource is an array and finally 1 char for string terminator.
1771        */
1772       for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1773          if (shProg->data->ProgramResourceList[i].Type != programInterface)
1774             continue;
1775          unsigned len =
1776             _mesa_program_resource_name_length_array(&shProg->data->ProgramResourceList[i]);
1777          *params = MAX2((unsigned)*params, len + 1);
1778       }
1779       break;
1780    case GL_MAX_NUM_ACTIVE_VARIABLES:
1781       switch (programInterface) {
1782       case GL_UNIFORM_BLOCK:
1783          for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1784             if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1785                struct gl_uniform_block *block =
1786                   (struct gl_uniform_block *)
1787                   shProg->data->ProgramResourceList[i].Data;
1788                *params = MAX2((unsigned)*params, block->NumUniforms);
1789             }
1790          }
1791          break;
1792       case GL_SHADER_STORAGE_BLOCK:
1793          for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1794             if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1795                struct gl_uniform_block *block =
1796                   (struct gl_uniform_block *)
1797                   shProg->data->ProgramResourceList[i].Data;
1798                GLint block_params = 0;
1799                for (unsigned j = 0; j < block->NumUniforms; j++) {
1800                   struct gl_program_resource *uni =
1801                      _mesa_program_resource_find_active_variable(
1802                         shProg,
1803                         GL_BUFFER_VARIABLE,
1804                         block,
1805                         j);
1806                   if (!uni)
1807                      continue;
1808                   block_params++;
1809                }
1810                *params = MAX2(*params, block_params);
1811             }
1812          }
1813          break;
1814       case GL_ATOMIC_COUNTER_BUFFER:
1815          for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1816             if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1817                struct gl_active_atomic_buffer *buffer =
1818                   (struct gl_active_atomic_buffer *)
1819                   shProg->data->ProgramResourceList[i].Data;
1820                *params = MAX2((unsigned)*params, buffer->NumUniforms);
1821             }
1822          }
1823          break;
1824       case GL_TRANSFORM_FEEDBACK_BUFFER:
1825          for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1826             if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1827                struct gl_transform_feedback_buffer *buffer =
1828                   (struct gl_transform_feedback_buffer *)
1829                   shProg->data->ProgramResourceList[i].Data;
1830                *params = MAX2((unsigned)*params, buffer->NumVaryings);
1831             }
1832          }
1833          break;
1834       default:
1835         _mesa_error(ctx, GL_INVALID_OPERATION,
1836                     "glGetProgramInterfaceiv(%s pname %s)",
1837                     _mesa_enum_to_string(programInterface),
1838                     _mesa_enum_to_string(pname));
1839       }
1840       break;
1841    case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1842       switch (programInterface) {
1843       case GL_VERTEX_SUBROUTINE_UNIFORM:
1844       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1845       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1846       case GL_COMPUTE_SUBROUTINE_UNIFORM:
1847       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1848       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
1849          for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1850             if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1851                struct gl_uniform_storage *uni =
1852                   (struct gl_uniform_storage *)
1853                   shProg->data->ProgramResourceList[i].Data;
1854                *params = MAX2((unsigned)*params, uni->num_compatible_subroutines);
1855             }
1856          }
1857          break;
1858       }
1859 
1860       default:
1861          _mesa_error(ctx, GL_INVALID_OPERATION,
1862                      "glGetProgramInterfaceiv(%s pname %s)",
1863                      _mesa_enum_to_string(programInterface),
1864                      _mesa_enum_to_string(pname));
1865       }
1866       break;
1867    default:
1868       _mesa_error(ctx, GL_INVALID_OPERATION,
1869                   "glGetProgramInterfaceiv(pname %s)",
1870                   _mesa_enum_to_string(pname));
1871    }
1872 }
1873 
1874 static bool
validate_io(struct gl_program * producer,struct gl_program * consumer)1875 validate_io(struct gl_program *producer, struct gl_program *consumer)
1876 {
1877    if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages)
1878       return true;
1879 
1880    const bool producer_is_array_stage =
1881       producer->info.stage == MESA_SHADER_TESS_CTRL;
1882    const bool consumer_is_array_stage =
1883       consumer->info.stage == MESA_SHADER_GEOMETRY ||
1884       consumer->info.stage == MESA_SHADER_TESS_CTRL ||
1885       consumer->info.stage == MESA_SHADER_TESS_EVAL;
1886 
1887    bool valid = true;
1888 
1889    gl_shader_variable const **outputs =
1890       (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList,
1891                                            sizeof(gl_shader_variable *));
1892    if (outputs == NULL)
1893       return false;
1894 
1895    /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1896     * says:
1897     *
1898     *    At an interface between program objects, the set of inputs and
1899     *    outputs are considered to match exactly if and only if:
1900     *
1901     *    - Every declared input variable has a matching output, as described
1902     *      above.
1903     *    - There are no user-defined output variables declared without a
1904     *      matching input variable declaration.
1905     *
1906     * Every input has an output, and every output has an input.  Scan the list
1907     * of producer resources once, and generate the list of outputs.  As inputs
1908     * and outputs are matched, remove the matched outputs from the set.  At
1909     * the end, the set must be empty.  If the set is not empty, then there is
1910     * some output that did not have an input.
1911     */
1912    unsigned num_outputs = 0;
1913    for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) {
1914       struct gl_program_resource *res =
1915          &producer->sh.data->ProgramResourceList[i];
1916 
1917       if (res->Type != GL_PROGRAM_OUTPUT)
1918          continue;
1919 
1920       gl_shader_variable const *const var = RESOURCE_VAR(res);
1921 
1922       /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1923        * says:
1924        *
1925        *    Built-in inputs or outputs do not affect interface matching.
1926        */
1927       if (is_gl_identifier(var->name.string))
1928          continue;
1929 
1930       outputs[num_outputs++] = var;
1931    }
1932 
1933    unsigned match_index = 0;
1934    for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) {
1935       struct gl_program_resource *res =
1936          &consumer->sh.data->ProgramResourceList[i];
1937 
1938       if (res->Type != GL_PROGRAM_INPUT)
1939          continue;
1940 
1941       gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
1942       gl_shader_variable const *producer_var = NULL;
1943 
1944       if (is_gl_identifier(consumer_var->name.string))
1945          continue;
1946 
1947       /* Inputs with explicit locations match other outputs with explicit
1948        * locations by location instead of by name.
1949        */
1950       if (consumer_var->explicit_location) {
1951          for (unsigned j = 0; j < num_outputs; j++) {
1952             const gl_shader_variable *const var = outputs[j];
1953 
1954             if (var->explicit_location &&
1955                 consumer_var->location == var->location) {
1956                producer_var = var;
1957                match_index = j;
1958                break;
1959             }
1960          }
1961       } else {
1962          for (unsigned j = 0; j < num_outputs; j++) {
1963             const gl_shader_variable *const var = outputs[j];
1964 
1965             if (!var->explicit_location &&
1966                 strcmp(consumer_var->name.string, var->name.string) == 0) {
1967                producer_var = var;
1968                match_index = j;
1969                break;
1970             }
1971          }
1972       }
1973 
1974       /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1975        * says:
1976        *
1977        *    - An output variable is considered to match an input variable in
1978        *      the subsequent shader if:
1979        *
1980        *      - the two variables match in name, type, and qualification; or
1981        *
1982        *      - the two variables are declared with the same location
1983        *        qualifier and match in type and qualification.
1984        */
1985       if (producer_var == NULL) {
1986          valid = false;
1987          goto out;
1988       }
1989 
1990       /* An output cannot match more than one input, so remove the output from
1991        * the set of possible outputs.
1992        */
1993       outputs[match_index] = NULL;
1994       num_outputs--;
1995       if (match_index < num_outputs)
1996          outputs[match_index] = outputs[num_outputs];
1997 
1998       /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
1999        *
2000        *    "Tessellation control shader per-vertex output variables and
2001        *     blocks and tessellation control, tessellation evaluation, and
2002        *     geometry shader per-vertex input variables and blocks are
2003        *     required to be declared as arrays, with each element representing
2004        *     input or output values for a single vertex of a multi-vertex
2005        *     primitive. For the purposes of interface matching, such variables
2006        *     and blocks are treated as though they were not declared as
2007        *     arrays."
2008        *
2009        * So we unwrap those types before matching.
2010        */
2011       const glsl_type *consumer_type = consumer_var->type;
2012       const glsl_type *consumer_interface_type = consumer_var->interface_type;
2013       const glsl_type *producer_type = producer_var->type;
2014       const glsl_type *producer_interface_type = producer_var->interface_type;
2015 
2016       if (consumer_is_array_stage) {
2017          if (consumer_interface_type) {
2018             /* the interface is the array; the underlying types should match */
2019             if (glsl_type_is_array(consumer_interface_type) && !consumer_var->patch)
2020                consumer_interface_type = consumer_interface_type->fields.array;
2021          } else {
2022             if (glsl_type_is_array(consumer_type) && !consumer_var->patch)
2023                consumer_type = consumer_type->fields.array;
2024          }
2025       }
2026 
2027       if (producer_is_array_stage) {
2028          if (producer_interface_type) {
2029             /* the interface is the array; the underlying types should match */
2030             if (glsl_type_is_array(producer_interface_type) && !producer_var->patch)
2031                producer_interface_type = producer_interface_type->fields.array;
2032          } else {
2033             if (glsl_type_is_array(producer_type) && !producer_var->patch)
2034                producer_type = producer_type->fields.array;
2035          }
2036       }
2037 
2038       if (producer_type != consumer_type) {
2039          valid = false;
2040          goto out;
2041       }
2042 
2043       if (producer_interface_type != consumer_interface_type) {
2044          valid = false;
2045          goto out;
2046       }
2047 
2048       /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
2049        *
2050        *    Qualifier Class|  Qualifier  |in/out
2051        *    ---------------+-------------+------
2052        *    Storage        |     in      |
2053        *                   |     out     |  N/A
2054        *                   |   uniform   |
2055        *    ---------------+-------------+------
2056        *    Auxiliary      |   centroid  |   No
2057        *    ---------------+-------------+------
2058        *                   |   location  |  Yes
2059        *                   | Block layout|  N/A
2060        *                   |   binding   |  N/A
2061        *                   |   offset    |  N/A
2062        *                   |   format    |  N/A
2063        *    ---------------+-------------+------
2064        *    Interpolation  |   smooth    |
2065        *                   |    flat     |  Yes
2066        *    ---------------+-------------+------
2067        *                   |    lowp     |
2068        *    Precision      |   mediump   |  Yes
2069        *                   |    highp    |
2070        *    ---------------+-------------+------
2071        *    Variance       |  invariant  |   No
2072        *    ---------------+-------------+------
2073        *    Memory         |     all     |  N/A
2074        *
2075        * Note that location mismatches are detected by the loops above that
2076        * find the producer variable that goes with the consumer variable.
2077        */
2078       unsigned producer_interpolation = producer_var->interpolation;
2079       unsigned consumer_interpolation = consumer_var->interpolation;
2080       if (producer_interpolation == INTERP_MODE_NONE)
2081          producer_interpolation = INTERP_MODE_SMOOTH;
2082       if (consumer_interpolation == INTERP_MODE_NONE)
2083          consumer_interpolation = INTERP_MODE_SMOOTH;
2084       if (producer_interpolation != consumer_interpolation) {
2085          valid = false;
2086          goto out;
2087       }
2088 
2089       if (producer_var->precision != consumer_var->precision) {
2090          valid = false;
2091          goto out;
2092       }
2093 
2094       if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
2095          valid = false;
2096          goto out;
2097       }
2098    }
2099 
2100  out:
2101    free(outputs);
2102    return valid && num_outputs == 0;
2103 }
2104 
2105 /**
2106  * Validate inputs against outputs in a program pipeline.
2107  */
2108 extern "C" bool
_mesa_validate_pipeline_io(struct gl_pipeline_object * pipeline)2109 _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
2110 {
2111    struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram;
2112 
2113    /* Find first active stage in pipeline. */
2114    unsigned idx, prev = 0;
2115    for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
2116       if (prog[idx]) {
2117          prev = idx;
2118          break;
2119       }
2120    }
2121 
2122    for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
2123       if (prog[idx]) {
2124          /* Pipeline might include both non-compute and a compute program, do
2125           * not attempt to validate varyings between non-compute and compute
2126           * stage.
2127           */
2128          if (prog[idx]->info.stage == MESA_SHADER_COMPUTE)
2129             break;
2130 
2131          if (!validate_io(prog[prev], prog[idx]))
2132             return false;
2133 
2134          prev = idx;
2135       }
2136    }
2137    return true;
2138 }
2139 
2140 extern "C" void
_mesa_program_resource_hash_destroy(struct gl_shader_program * shProg)2141 _mesa_program_resource_hash_destroy(struct gl_shader_program *shProg)
2142 {
2143    for (unsigned i = 0; i < ARRAY_SIZE(shProg->data->ProgramResourceHash); i++) {
2144       if (shProg->data->ProgramResourceHash[i]) {
2145          _mesa_hash_table_destroy(shProg->data->ProgramResourceHash[i], NULL);
2146          shProg->data->ProgramResourceHash[i] = NULL;
2147       }
2148    }
2149 }
2150 
2151 extern "C" void
_mesa_create_program_resource_hash(struct gl_shader_program * shProg)2152 _mesa_create_program_resource_hash(struct gl_shader_program *shProg)
2153 {
2154    /* Rebuild resource hash. */
2155    _mesa_program_resource_hash_destroy(shProg);
2156 
2157    struct gl_program_resource *res = shProg->data->ProgramResourceList;
2158    for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
2159       struct gl_resource_name name;
2160       if (_mesa_program_get_resource_name(res, &name)) {
2161          unsigned type = GET_PROGRAM_RESOURCE_TYPE_FROM_GLENUM(res->Type);
2162          assert(type < ARRAY_SIZE(shProg->data->ProgramResourceHash));
2163 
2164          if (!shProg->data->ProgramResourceHash[type]) {
2165             shProg->data->ProgramResourceHash[type] =
2166                _mesa_hash_table_create(shProg, _mesa_hash_string,
2167                                        _mesa_key_string_equal);
2168          }
2169 
2170          _mesa_hash_table_insert(shProg->data->ProgramResourceHash[type],
2171                                  name.string, res);
2172       }
2173    }
2174 }
2175