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