1848b8605Smrg/*
2848b8605Smrg * Copyright © 2011 Intel Corporation
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5848b8605Smrg * copy of this software and associated documentation files (the "Software"),
6848b8605Smrg * to deal in the Software without restriction, including without limitation
7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
9848b8605Smrg * Software is furnished to do so, subject to the following conditions:
10848b8605Smrg *
11848b8605Smrg * The above copyright notice and this permission notice (including the next
12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
13848b8605Smrg * Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21848b8605Smrg * DEALINGS IN THE SOFTWARE.
22848b8605Smrg */
23848b8605Smrg
24848b8605Smrg/**
25848b8605Smrg * \file shader_query.cpp
26848b8605Smrg * C-to-C++ bridge functions to query GLSL shader data
27848b8605Smrg *
28848b8605Smrg * \author Ian Romanick <ian.d.romanick@intel.com>
29848b8605Smrg */
30848b8605Smrg
31b8e80941Smrg#include "main/context.h"
32b8e80941Smrg#include "main/enums.h"
33b8e80941Smrg#include "main/shaderapi.h"
34b8e80941Smrg#include "main/shaderobj.h"
35b8e80941Smrg#include "main/uniforms.h"
36b8e80941Smrg#include "compiler/glsl/glsl_symbol_table.h"
37b8e80941Smrg#include "compiler/glsl/ir.h"
38b8e80941Smrg#include "compiler/glsl/program.h"
39b8e80941Smrg#include "compiler/glsl/string_to_uint_map.h"
40848b8605Smrg
41848b8605Smrg
42b8e80941Smrgstatic GLint
43b8e80941Smrgprogram_resource_location(struct gl_program_resource *res,
44b8e80941Smrg                          unsigned array_index);
45848b8605Smrg
46b8e80941Smrg/**
47b8e80941Smrg * Declare convenience functions to return resource data in a given type.
48b8e80941Smrg * Warning! this is not type safe so be *very* careful when using these.
49b8e80941Smrg */
50b8e80941Smrg#define DECL_RESOURCE_FUNC(name, type) \
51b8e80941Smrgconst type * RESOURCE_ ## name (gl_program_resource *res) { \
52b8e80941Smrg   assert(res->Data); \
53b8e80941Smrg   return (type *) res->Data; \
54b8e80941Smrg}
55848b8605Smrg
56b8e80941SmrgDECL_RESOURCE_FUNC(VAR, gl_shader_variable);
57b8e80941SmrgDECL_RESOURCE_FUNC(UBO, gl_uniform_block);
58b8e80941SmrgDECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
59b8e80941SmrgDECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
60b8e80941SmrgDECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info);
61b8e80941SmrgDECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer);
62b8e80941SmrgDECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
63b8e80941Smrg
64b8e80941Smrgstatic void
65b8e80941Smrgbind_attrib_location(struct gl_context *ctx,
66b8e80941Smrg                     struct gl_shader_program *const shProg, GLuint index,
67b8e80941Smrg                     const GLchar *name, bool no_error)
68b8e80941Smrg{
69848b8605Smrg   if (!name)
70848b8605Smrg      return;
71848b8605Smrg
72b8e80941Smrg   if (!no_error) {
73b8e80941Smrg      if (strncmp(name, "gl_", 3) == 0) {
74b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
75b8e80941Smrg                     "glBindAttribLocation(illegal name)");
76b8e80941Smrg         return;
77b8e80941Smrg      }
78848b8605Smrg
79b8e80941Smrg      if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
80b8e80941Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
81b8e80941Smrg                     index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
82b8e80941Smrg         return;
83b8e80941Smrg      }
84848b8605Smrg   }
85848b8605Smrg
86848b8605Smrg   /* Replace the current value if it's already in the list.  Add
87848b8605Smrg    * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
88848b8605Smrg    * between built-in attributes and user-defined attributes.
89848b8605Smrg    */
90848b8605Smrg   shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
91848b8605Smrg
92848b8605Smrg   /*
93848b8605Smrg    * Note that this attribute binding won't go into effect until
94848b8605Smrg    * glLinkProgram is called again.
95848b8605Smrg    */
96848b8605Smrg}
97848b8605Smrg
98b8e80941Smrgvoid GLAPIENTRY
99b8e80941Smrg_mesa_BindAttribLocation_no_error(GLuint program, GLuint index,
100b8e80941Smrg                                  const GLchar *name)
101848b8605Smrg{
102b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
103848b8605Smrg
104b8e80941Smrg   struct gl_shader_program *const shProg =
105b8e80941Smrg      _mesa_lookup_shader_program(ctx, program);
106b8e80941Smrg   bind_attrib_location(ctx, shProg, index, name, true);
107b8e80941Smrg}
108848b8605Smrg
109b8e80941Smrgvoid GLAPIENTRY
110b8e80941Smrg_mesa_BindAttribLocation(GLuint program, GLuint index,
111b8e80941Smrg                         const GLchar *name)
112b8e80941Smrg{
113b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
114848b8605Smrg
115b8e80941Smrg   struct gl_shader_program *const shProg =
116b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
117b8e80941Smrg   if (!shProg)
118b8e80941Smrg      return;
119b8e80941Smrg
120b8e80941Smrg   bind_attrib_location(ctx, shProg, index, name, false);
121848b8605Smrg}
122848b8605Smrg
123848b8605Smrgvoid GLAPIENTRY
124b8e80941Smrg_mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
125b8e80941Smrg                      GLsizei maxLength, GLsizei * length, GLint * size,
126b8e80941Smrg                      GLenum * type, GLchar * name)
127848b8605Smrg{
128848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
129848b8605Smrg   struct gl_shader_program *shProg;
130848b8605Smrg
131b8e80941Smrg   if (maxLength < 0) {
132b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
133b8e80941Smrg      return;
134b8e80941Smrg   }
135b8e80941Smrg
136848b8605Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
137848b8605Smrg   if (!shProg)
138848b8605Smrg      return;
139848b8605Smrg
140b8e80941Smrg   if (!shProg->data->LinkStatus) {
141848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
142848b8605Smrg                  "glGetActiveAttrib(program not linked)");
143848b8605Smrg      return;
144848b8605Smrg   }
145848b8605Smrg
146848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
147848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
148848b8605Smrg      return;
149848b8605Smrg   }
150848b8605Smrg
151b8e80941Smrg   struct gl_program_resource *res =
152b8e80941Smrg      _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
153b8e80941Smrg                                        desired_index);
154848b8605Smrg
155b8e80941Smrg   /* User asked for index that does not exist. */
156b8e80941Smrg   if (!res) {
157b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
158b8e80941Smrg      return;
159848b8605Smrg   }
160848b8605Smrg
161b8e80941Smrg   const gl_shader_variable *const var = RESOURCE_VAR(res);
162848b8605Smrg
163b8e80941Smrg   const char *var_name = var->name;
164848b8605Smrg
165b8e80941Smrg   _mesa_copy_string(name, maxLength, length, var_name);
166848b8605Smrg
167b8e80941Smrg   if (size)
168b8e80941Smrg      _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
169b8e80941Smrg                                  size, "glGetActiveAttrib");
170848b8605Smrg
171b8e80941Smrg   if (type)
172b8e80941Smrg      _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
173b8e80941Smrg                                  (GLint *) type, "glGetActiveAttrib");
174848b8605Smrg}
175848b8605Smrg
176848b8605SmrgGLint GLAPIENTRY
177b8e80941Smrg_mesa_GetAttribLocation(GLuint program, const GLchar * name)
178848b8605Smrg{
179848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
180848b8605Smrg   struct gl_shader_program *const shProg =
181848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
182848b8605Smrg
183848b8605Smrg   if (!shProg) {
184848b8605Smrg      return -1;
185848b8605Smrg   }
186848b8605Smrg
187b8e80941Smrg   if (!shProg->data->LinkStatus) {
188848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
189848b8605Smrg                  "glGetAttribLocation(program not linked)");
190848b8605Smrg      return -1;
191848b8605Smrg   }
192848b8605Smrg
193848b8605Smrg   if (!name)
194848b8605Smrg      return -1;
195848b8605Smrg
196848b8605Smrg   /* Not having a vertex shader is not an error.
197848b8605Smrg    */
198848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
199848b8605Smrg      return -1;
200848b8605Smrg
201b8e80941Smrg   unsigned array_index = 0;
202b8e80941Smrg   struct gl_program_resource *res =
203b8e80941Smrg      _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
204b8e80941Smrg                                       &array_index);
205848b8605Smrg
206b8e80941Smrg   if (!res)
207b8e80941Smrg      return -1;
208848b8605Smrg
209b8e80941Smrg   return program_resource_location(res, array_index);
210848b8605Smrg}
211848b8605Smrg
212848b8605Smrgunsigned
213848b8605Smrg_mesa_count_active_attribs(struct gl_shader_program *shProg)
214848b8605Smrg{
215b8e80941Smrg   if (!shProg->data->LinkStatus
216848b8605Smrg       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
217848b8605Smrg      return 0;
218848b8605Smrg   }
219848b8605Smrg
220b8e80941Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
221b8e80941Smrg   unsigned count = 0;
222b8e80941Smrg   for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
223b8e80941Smrg        j++, res++) {
224b8e80941Smrg      if (res->Type == GL_PROGRAM_INPUT &&
225b8e80941Smrg          res->StageReferences & (1 << MESA_SHADER_VERTEX))
226b8e80941Smrg         count++;
227848b8605Smrg   }
228b8e80941Smrg   return count;
229848b8605Smrg}
230848b8605Smrg
231848b8605Smrg
232848b8605Smrgsize_t
233848b8605Smrg_mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
234848b8605Smrg{
235b8e80941Smrg   if (!shProg->data->LinkStatus
236848b8605Smrg       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
237848b8605Smrg      return 0;
238848b8605Smrg   }
239848b8605Smrg
240b8e80941Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
241848b8605Smrg   size_t longest = 0;
242b8e80941Smrg   for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
243b8e80941Smrg        j++, res++) {
244b8e80941Smrg      if (res->Type == GL_PROGRAM_INPUT &&
245b8e80941Smrg          res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
246b8e80941Smrg
247b8e80941Smrg          const size_t length = strlen(RESOURCE_VAR(res)->name);
248b8e80941Smrg          if (length >= longest)
249b8e80941Smrg             longest = length + 1;
250b8e80941Smrg      }
251848b8605Smrg   }
252848b8605Smrg
253848b8605Smrg   return longest;
254848b8605Smrg}
255848b8605Smrg
256b8e80941Smrgvoid static
257b8e80941Smrgbind_frag_data_location(struct gl_shader_program *const shProg,
258b8e80941Smrg                        const char *name, unsigned colorNumber,
259b8e80941Smrg                        unsigned index)
260b8e80941Smrg{
261b8e80941Smrg   /* Replace the current value if it's already in the list.  Add
262b8e80941Smrg    * FRAG_RESULT_DATA0 because that's how the linker differentiates
263b8e80941Smrg    * between built-in attributes and user-defined attributes.
264b8e80941Smrg    */
265b8e80941Smrg   shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
266b8e80941Smrg   shProg->FragDataIndexBindings->put(index, name);
267b8e80941Smrg
268b8e80941Smrg   /*
269b8e80941Smrg    * Note that this binding won't go into effect until
270b8e80941Smrg    * glLinkProgram is called again.
271b8e80941Smrg    */
272b8e80941Smrg}
273b8e80941Smrg
274848b8605Smrgvoid GLAPIENTRY
275848b8605Smrg_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
276848b8605Smrg			   const GLchar *name)
277848b8605Smrg{
278848b8605Smrg   _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
279848b8605Smrg}
280848b8605Smrg
281b8e80941Smrgvoid GLAPIENTRY
282b8e80941Smrg_mesa_BindFragDataLocation_no_error(GLuint program, GLuint colorNumber,
283b8e80941Smrg                                    const GLchar *name)
284b8e80941Smrg{
285b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
286b8e80941Smrg
287b8e80941Smrg   if (!name)
288b8e80941Smrg      return;
289b8e80941Smrg
290b8e80941Smrg   struct gl_shader_program *const shProg =
291b8e80941Smrg      _mesa_lookup_shader_program(ctx, program);
292b8e80941Smrg
293b8e80941Smrg   bind_frag_data_location(shProg, name, colorNumber, 0);
294b8e80941Smrg}
295b8e80941Smrg
296848b8605Smrgvoid GLAPIENTRY
297848b8605Smrg_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
298848b8605Smrg                                  GLuint index, const GLchar *name)
299848b8605Smrg{
300848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
301848b8605Smrg
302848b8605Smrg   struct gl_shader_program *const shProg =
303848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
304848b8605Smrg   if (!shProg)
305848b8605Smrg      return;
306848b8605Smrg
307848b8605Smrg   if (!name)
308848b8605Smrg      return;
309848b8605Smrg
310848b8605Smrg   if (strncmp(name, "gl_", 3) == 0) {
311848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
312848b8605Smrg      return;
313848b8605Smrg   }
314848b8605Smrg
315848b8605Smrg   if (index > 1) {
316848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
317848b8605Smrg      return;
318848b8605Smrg   }
319848b8605Smrg
320848b8605Smrg   if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
321848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
322848b8605Smrg      return;
323848b8605Smrg   }
324848b8605Smrg
325848b8605Smrg   if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
326848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
327848b8605Smrg      return;
328848b8605Smrg   }
329848b8605Smrg
330b8e80941Smrg   bind_frag_data_location(shProg, name, colorNumber, index);
331b8e80941Smrg}
332848b8605Smrg
333b8e80941Smrgvoid GLAPIENTRY
334b8e80941Smrg_mesa_BindFragDataLocationIndexed_no_error(GLuint program, GLuint colorNumber,
335b8e80941Smrg                                           GLuint index, const GLchar *name)
336b8e80941Smrg{
337b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
338b8e80941Smrg
339b8e80941Smrg   if (!name)
340b8e80941Smrg      return;
341b8e80941Smrg
342b8e80941Smrg   struct gl_shader_program *const shProg =
343b8e80941Smrg      _mesa_lookup_shader_program(ctx, program);
344b8e80941Smrg
345b8e80941Smrg   bind_frag_data_location(shProg, name, colorNumber, index);
346848b8605Smrg}
347848b8605Smrg
348848b8605SmrgGLint GLAPIENTRY
349848b8605Smrg_mesa_GetFragDataIndex(GLuint program, const GLchar *name)
350848b8605Smrg{
351848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
352848b8605Smrg   struct gl_shader_program *const shProg =
353848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
354848b8605Smrg
355848b8605Smrg   if (!shProg) {
356848b8605Smrg      return -1;
357848b8605Smrg   }
358848b8605Smrg
359b8e80941Smrg   if (!shProg->data->LinkStatus) {
360848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
361848b8605Smrg                  "glGetFragDataIndex(program not linked)");
362848b8605Smrg      return -1;
363848b8605Smrg   }
364848b8605Smrg
365848b8605Smrg   if (!name)
366848b8605Smrg      return -1;
367848b8605Smrg
368848b8605Smrg   if (strncmp(name, "gl_", 3) == 0) {
369848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
370848b8605Smrg                  "glGetFragDataIndex(illegal name)");
371848b8605Smrg      return -1;
372848b8605Smrg   }
373848b8605Smrg
374848b8605Smrg   /* Not having a fragment shader is not an error.
375848b8605Smrg    */
376848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
377848b8605Smrg      return -1;
378848b8605Smrg
379b8e80941Smrg   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
380b8e80941Smrg                                                name);
381848b8605Smrg}
382848b8605Smrg
383848b8605SmrgGLint GLAPIENTRY
384848b8605Smrg_mesa_GetFragDataLocation(GLuint program, const GLchar *name)
385848b8605Smrg{
386848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
387848b8605Smrg   struct gl_shader_program *const shProg =
388848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
389848b8605Smrg
390848b8605Smrg   if (!shProg) {
391848b8605Smrg      return -1;
392848b8605Smrg   }
393848b8605Smrg
394b8e80941Smrg   if (!shProg->data->LinkStatus) {
395848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
396848b8605Smrg                  "glGetFragDataLocation(program not linked)");
397848b8605Smrg      return -1;
398848b8605Smrg   }
399848b8605Smrg
400848b8605Smrg   if (!name)
401848b8605Smrg      return -1;
402848b8605Smrg
403848b8605Smrg   if (strncmp(name, "gl_", 3) == 0) {
404848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
405848b8605Smrg                  "glGetFragDataLocation(illegal name)");
406848b8605Smrg      return -1;
407848b8605Smrg   }
408848b8605Smrg
409848b8605Smrg   /* Not having a fragment shader is not an error.
410848b8605Smrg    */
411848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
412848b8605Smrg      return -1;
413848b8605Smrg
414b8e80941Smrg   unsigned array_index = 0;
415b8e80941Smrg   struct gl_program_resource *res =
416b8e80941Smrg      _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
417b8e80941Smrg                                       &array_index);
418b8e80941Smrg
419b8e80941Smrg   if (!res)
420b8e80941Smrg      return -1;
421b8e80941Smrg
422b8e80941Smrg   return program_resource_location(res, array_index);
423b8e80941Smrg}
424b8e80941Smrg
425b8e80941Smrgconst char*
426b8e80941Smrg_mesa_program_resource_name(struct gl_program_resource *res)
427b8e80941Smrg{
428b8e80941Smrg   switch (res->Type) {
429b8e80941Smrg   case GL_UNIFORM_BLOCK:
430b8e80941Smrg   case GL_SHADER_STORAGE_BLOCK:
431b8e80941Smrg      return RESOURCE_UBO(res)->Name;
432b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_VARYING:
433b8e80941Smrg      return RESOURCE_XFV(res)->Name;
434b8e80941Smrg   case GL_PROGRAM_INPUT:
435b8e80941Smrg   case GL_PROGRAM_OUTPUT:
436b8e80941Smrg      return RESOURCE_VAR(res)->name;
437b8e80941Smrg   case GL_UNIFORM:
438b8e80941Smrg   case GL_BUFFER_VARIABLE:
439b8e80941Smrg      return RESOURCE_UNI(res)->name;
440b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
441b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
442b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
443b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
444b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
445b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
446b8e80941Smrg      return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
447b8e80941Smrg   case GL_VERTEX_SUBROUTINE:
448b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE:
449b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE:
450b8e80941Smrg   case GL_COMPUTE_SUBROUTINE:
451b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE:
452b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE:
453b8e80941Smrg      return RESOURCE_SUB(res)->name;
454b8e80941Smrg   default:
455b8e80941Smrg      assert(!"support for resource type not implemented");
456b8e80941Smrg   }
457b8e80941Smrg   return NULL;
458b8e80941Smrg}
459b8e80941Smrg
460b8e80941Smrg
461b8e80941Smrgunsigned
462b8e80941Smrg_mesa_program_resource_array_size(struct gl_program_resource *res)
463b8e80941Smrg{
464b8e80941Smrg   switch (res->Type) {
465b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_VARYING:
466b8e80941Smrg      return RESOURCE_XFV(res)->Size > 1 ?
467b8e80941Smrg             RESOURCE_XFV(res)->Size : 0;
468b8e80941Smrg   case GL_PROGRAM_INPUT:
469b8e80941Smrg   case GL_PROGRAM_OUTPUT:
470b8e80941Smrg      return RESOURCE_VAR(res)->type->length;
471b8e80941Smrg   case GL_UNIFORM:
472b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
473b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
474b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
475b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
476b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
477b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
478b8e80941Smrg      return RESOURCE_UNI(res)->array_elements;
479b8e80941Smrg   case GL_BUFFER_VARIABLE:
480b8e80941Smrg      /* Unsized arrays */
481b8e80941Smrg      if (RESOURCE_UNI(res)->array_stride > 0 &&
482b8e80941Smrg          RESOURCE_UNI(res)->array_elements == 0)
483b8e80941Smrg         return 1;
484b8e80941Smrg      else
485b8e80941Smrg         return RESOURCE_UNI(res)->array_elements;
486b8e80941Smrg   case GL_VERTEX_SUBROUTINE:
487b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE:
488b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE:
489b8e80941Smrg   case GL_COMPUTE_SUBROUTINE:
490b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE:
491b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE:
492b8e80941Smrg   case GL_ATOMIC_COUNTER_BUFFER:
493b8e80941Smrg   case GL_UNIFORM_BLOCK:
494b8e80941Smrg   case GL_SHADER_STORAGE_BLOCK:
495b8e80941Smrg      return 0;
496b8e80941Smrg   default:
497b8e80941Smrg      assert(!"support for resource type not implemented");
498b8e80941Smrg   }
499b8e80941Smrg   return 0;
500b8e80941Smrg}
501b8e80941Smrg
502b8e80941Smrg/**
503b8e80941Smrg * Checks if array subscript is valid and if so sets array_index.
504b8e80941Smrg */
505b8e80941Smrgstatic bool
506b8e80941Smrgvalid_array_index(const GLchar *name, unsigned *array_index)
507b8e80941Smrg{
508b8e80941Smrg   long idx = 0;
509b8e80941Smrg   const GLchar *out_base_name_end;
510b8e80941Smrg
511b8e80941Smrg   idx = parse_program_resource_name(name, &out_base_name_end);
512b8e80941Smrg   if (idx < 0)
513b8e80941Smrg      return false;
514b8e80941Smrg
515b8e80941Smrg   if (array_index)
516b8e80941Smrg      *array_index = idx;
517b8e80941Smrg
518b8e80941Smrg   return true;
519b8e80941Smrg}
520b8e80941Smrg
521b8e80941Smrg/* Find a program resource with specific name in given interface.
522b8e80941Smrg */
523b8e80941Smrgstruct gl_program_resource *
524b8e80941Smrg_mesa_program_resource_find_name(struct gl_shader_program *shProg,
525b8e80941Smrg                                 GLenum programInterface, const char *name,
526b8e80941Smrg                                 unsigned *array_index)
527b8e80941Smrg{
528b8e80941Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
529b8e80941Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
530b8e80941Smrg        i++, res++) {
531b8e80941Smrg      if (res->Type != programInterface)
532b8e80941Smrg         continue;
533b8e80941Smrg
534b8e80941Smrg      /* Resource basename. */
535b8e80941Smrg      const char *rname = _mesa_program_resource_name(res);
536b8e80941Smrg
537b8e80941Smrg      /* Since ARB_gl_spirv lack of name reflections is a possibility */
538b8e80941Smrg      if (rname == NULL)
539b8e80941Smrg         continue;
540848b8605Smrg
541b8e80941Smrg      unsigned baselen = strlen(rname);
542b8e80941Smrg      unsigned baselen_without_array_index = baselen;
543b8e80941Smrg      const char *rname_last_square_bracket = strrchr(rname, '[');
544b8e80941Smrg      bool found = false;
545b8e80941Smrg      bool rname_has_array_index_zero = false;
546b8e80941Smrg      /* From ARB_program_interface_query spec:
547848b8605Smrg       *
548b8e80941Smrg       * "uint GetProgramResourceIndex(uint program, enum programInterface,
549b8e80941Smrg       *                               const char *name);
550b8e80941Smrg       *  [...]
551b8e80941Smrg       *  If <name> exactly matches the name string of one of the active
552b8e80941Smrg       *  resources for <programInterface>, the index of the matched resource is
553b8e80941Smrg       *  returned. Additionally, if <name> would exactly match the name string
554b8e80941Smrg       *  of an active resource if "[0]" were appended to <name>, the index of
555b8e80941Smrg       *  the matched resource is returned. [...]"
556848b8605Smrg       *
557b8e80941Smrg       * "A string provided to GetProgramResourceLocation or
558b8e80941Smrg       * GetProgramResourceLocationIndex is considered to match an active variable
559b8e80941Smrg       * if:
560b8e80941Smrg       *
561b8e80941Smrg       *  * the string exactly matches the name of the active variable;
562b8e80941Smrg       *
563b8e80941Smrg       *  * if the string identifies the base name of an active array, where the
564b8e80941Smrg       *    string would exactly match the name of the variable if the suffix
565b8e80941Smrg       *    "[0]" were appended to the string; [...]"
566848b8605Smrg       */
567b8e80941Smrg      /* Remove array's index from interface block name comparison only if
568b8e80941Smrg       * array's index is zero and the resulting string length is the same
569b8e80941Smrg       * than the provided name's length.
570b8e80941Smrg       */
571b8e80941Smrg      if (rname_last_square_bracket) {
572b8e80941Smrg         baselen_without_array_index -= strlen(rname_last_square_bracket);
573b8e80941Smrg         rname_has_array_index_zero =
574b8e80941Smrg            (strcmp(rname_last_square_bracket, "[0]") == 0) &&
575b8e80941Smrg            (baselen_without_array_index == strlen(name));
576b8e80941Smrg      }
577848b8605Smrg
578b8e80941Smrg      if (strncmp(rname, name, baselen) == 0)
579b8e80941Smrg         found = true;
580b8e80941Smrg      else if (rname_has_array_index_zero &&
581b8e80941Smrg               strncmp(rname, name, baselen_without_array_index) == 0)
582b8e80941Smrg         found = true;
583b8e80941Smrg
584b8e80941Smrg      if (found) {
585b8e80941Smrg         switch (programInterface) {
586b8e80941Smrg         case GL_UNIFORM_BLOCK:
587b8e80941Smrg         case GL_SHADER_STORAGE_BLOCK:
588b8e80941Smrg            /* Basename match, check if array or struct. */
589b8e80941Smrg            if (rname_has_array_index_zero ||
590b8e80941Smrg                name[baselen] == '\0' ||
591b8e80941Smrg                name[baselen] == '[' ||
592b8e80941Smrg                name[baselen] == '.') {
593b8e80941Smrg               return res;
594b8e80941Smrg            }
595b8e80941Smrg            break;
596b8e80941Smrg         case GL_TRANSFORM_FEEDBACK_VARYING:
597b8e80941Smrg         case GL_BUFFER_VARIABLE:
598b8e80941Smrg         case GL_UNIFORM:
599b8e80941Smrg         case GL_VERTEX_SUBROUTINE_UNIFORM:
600b8e80941Smrg         case GL_GEOMETRY_SUBROUTINE_UNIFORM:
601b8e80941Smrg         case GL_FRAGMENT_SUBROUTINE_UNIFORM:
602b8e80941Smrg         case GL_COMPUTE_SUBROUTINE_UNIFORM:
603b8e80941Smrg         case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
604b8e80941Smrg         case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
605b8e80941Smrg         case GL_VERTEX_SUBROUTINE:
606b8e80941Smrg         case GL_GEOMETRY_SUBROUTINE:
607b8e80941Smrg         case GL_FRAGMENT_SUBROUTINE:
608b8e80941Smrg         case GL_COMPUTE_SUBROUTINE:
609b8e80941Smrg         case GL_TESS_CONTROL_SUBROUTINE:
610b8e80941Smrg         case GL_TESS_EVALUATION_SUBROUTINE:
611b8e80941Smrg            if (name[baselen] == '.') {
612b8e80941Smrg               return res;
613b8e80941Smrg            }
614b8e80941Smrg            /* fall-through */
615b8e80941Smrg         case GL_PROGRAM_INPUT:
616b8e80941Smrg         case GL_PROGRAM_OUTPUT:
617b8e80941Smrg            if (name[baselen] == '\0') {
618b8e80941Smrg               return res;
619b8e80941Smrg            } else if (name[baselen] == '[' &&
620b8e80941Smrg                valid_array_index(name, array_index)) {
621b8e80941Smrg               return res;
622b8e80941Smrg            }
623b8e80941Smrg            break;
624b8e80941Smrg         default:
625b8e80941Smrg            assert(!"not implemented for given interface");
626b8e80941Smrg         }
627b8e80941Smrg      }
628b8e80941Smrg   }
629b8e80941Smrg   return NULL;
630b8e80941Smrg}
631848b8605Smrg
632b8e80941Smrgstatic GLuint
633b8e80941Smrgcalc_resource_index(struct gl_shader_program *shProg,
634b8e80941Smrg                    struct gl_program_resource *res)
635b8e80941Smrg{
636b8e80941Smrg   unsigned i;
637b8e80941Smrg   GLuint index = 0;
638b8e80941Smrg   for (i = 0; i < shProg->data->NumProgramResourceList; i++) {
639b8e80941Smrg      if (&shProg->data->ProgramResourceList[i] == res)
640b8e80941Smrg         return index;
641b8e80941Smrg      if (shProg->data->ProgramResourceList[i].Type == res->Type)
642b8e80941Smrg         index++;
643848b8605Smrg   }
644b8e80941Smrg   return GL_INVALID_INDEX;
645b8e80941Smrg}
646b8e80941Smrg
647b8e80941Smrg/**
648b8e80941Smrg * Calculate index for the given resource.
649b8e80941Smrg */
650b8e80941SmrgGLuint
651b8e80941Smrg_mesa_program_resource_index(struct gl_shader_program *shProg,
652b8e80941Smrg                             struct gl_program_resource *res)
653b8e80941Smrg{
654b8e80941Smrg   if (!res)
655b8e80941Smrg      return GL_INVALID_INDEX;
656b8e80941Smrg
657b8e80941Smrg   switch (res->Type) {
658b8e80941Smrg   case GL_ATOMIC_COUNTER_BUFFER:
659b8e80941Smrg      return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
660b8e80941Smrg   case GL_VERTEX_SUBROUTINE:
661b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE:
662b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE:
663b8e80941Smrg   case GL_COMPUTE_SUBROUTINE:
664b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE:
665b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE:
666b8e80941Smrg      return RESOURCE_SUB(res)->index;
667b8e80941Smrg   case GL_UNIFORM_BLOCK:
668b8e80941Smrg   case GL_SHADER_STORAGE_BLOCK:
669b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
670b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_VARYING:
671b8e80941Smrg   default:
672b8e80941Smrg      return calc_resource_index(shProg, res);
673b8e80941Smrg   }
674b8e80941Smrg}
675b8e80941Smrg
676b8e80941Smrg/**
677b8e80941Smrg * Find a program resource that points to given data.
678b8e80941Smrg */
679b8e80941Smrgstatic struct gl_program_resource*
680b8e80941Smrgprogram_resource_find_data(struct gl_shader_program *shProg, void *data)
681b8e80941Smrg{
682b8e80941Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
683b8e80941Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
684b8e80941Smrg        i++, res++) {
685b8e80941Smrg      if (res->Data == data)
686b8e80941Smrg         return res;
687b8e80941Smrg   }
688b8e80941Smrg   return NULL;
689b8e80941Smrg}
690b8e80941Smrg
691b8e80941Smrg/* Find a program resource with specific index in given interface.
692b8e80941Smrg */
693b8e80941Smrgstruct gl_program_resource *
694b8e80941Smrg_mesa_program_resource_find_index(struct gl_shader_program *shProg,
695b8e80941Smrg                                  GLenum programInterface, GLuint index)
696b8e80941Smrg{
697b8e80941Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
698b8e80941Smrg   int idx = -1;
699b8e80941Smrg
700b8e80941Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
701b8e80941Smrg        i++, res++) {
702b8e80941Smrg      if (res->Type != programInterface)
703b8e80941Smrg         continue;
704b8e80941Smrg
705b8e80941Smrg      switch (res->Type) {
706b8e80941Smrg      case GL_UNIFORM_BLOCK:
707b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
708b8e80941Smrg      case GL_SHADER_STORAGE_BLOCK:
709b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
710b8e80941Smrg         if (_mesa_program_resource_index(shProg, res) == index)
711b8e80941Smrg            return res;
712b8e80941Smrg         break;
713b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_VARYING:
714b8e80941Smrg      case GL_PROGRAM_INPUT:
715b8e80941Smrg      case GL_PROGRAM_OUTPUT:
716b8e80941Smrg      case GL_UNIFORM:
717b8e80941Smrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
718b8e80941Smrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
719b8e80941Smrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
720b8e80941Smrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
721b8e80941Smrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
722b8e80941Smrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
723b8e80941Smrg      case GL_VERTEX_SUBROUTINE:
724b8e80941Smrg      case GL_GEOMETRY_SUBROUTINE:
725b8e80941Smrg      case GL_FRAGMENT_SUBROUTINE:
726b8e80941Smrg      case GL_COMPUTE_SUBROUTINE:
727b8e80941Smrg      case GL_TESS_CONTROL_SUBROUTINE:
728b8e80941Smrg      case GL_TESS_EVALUATION_SUBROUTINE:
729b8e80941Smrg      case GL_BUFFER_VARIABLE:
730b8e80941Smrg         if (++idx == (int) index)
731b8e80941Smrg            return res;
732b8e80941Smrg         break;
733b8e80941Smrg      default:
734b8e80941Smrg         assert(!"not implemented for given interface");
735b8e80941Smrg      }
736b8e80941Smrg   }
737b8e80941Smrg   return NULL;
738b8e80941Smrg}
739b8e80941Smrg
740b8e80941Smrg/* Function returns if resource name is expected to have index
741b8e80941Smrg * appended into it.
742b8e80941Smrg *
743b8e80941Smrg *
744b8e80941Smrg * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
745b8e80941Smrg * spec says:
746b8e80941Smrg *
747b8e80941Smrg *     "If the active uniform is an array, the uniform name returned in
748b8e80941Smrg *     name will always be the name of the uniform array appended with
749b8e80941Smrg *     "[0]"."
750b8e80941Smrg *
751b8e80941Smrg * The same text also appears in the OpenGL 4.2 spec.  It does not,
752b8e80941Smrg * however, appear in any previous spec.  Previous specifications are
753b8e80941Smrg * ambiguous in this regard.  However, either name can later be passed
754b8e80941Smrg * to glGetUniformLocation (and related APIs), so there shouldn't be any
755b8e80941Smrg * harm in always appending "[0]" to uniform array names.
756b8e80941Smrg */
757b8e80941Smrgstatic bool
758b8e80941Smrgadd_index_to_name(struct gl_program_resource *res)
759b8e80941Smrg{
760b8e80941Smrg   /* Transform feedback varyings have array index already appended
761b8e80941Smrg    * in their names.
762b8e80941Smrg    */
763b8e80941Smrg   return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
764b8e80941Smrg}
765b8e80941Smrg
766b8e80941Smrg/* Get name length of a program resource. This consists of
767b8e80941Smrg * base name + 3 for '[0]' if resource is an array.
768b8e80941Smrg */
769b8e80941Smrgextern unsigned
770b8e80941Smrg_mesa_program_resource_name_len(struct gl_program_resource *res)
771b8e80941Smrg{
772b8e80941Smrg   unsigned length = strlen(_mesa_program_resource_name(res));
773b8e80941Smrg   if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
774b8e80941Smrg      length += 3;
775b8e80941Smrg   return length;
776b8e80941Smrg}
777848b8605Smrg
778b8e80941Smrg/* Get full name of a program resource.
779b8e80941Smrg */
780b8e80941Smrgbool
781b8e80941Smrg_mesa_get_program_resource_name(struct gl_shader_program *shProg,
782b8e80941Smrg                                GLenum programInterface, GLuint index,
783b8e80941Smrg                                GLsizei bufSize, GLsizei *length,
784b8e80941Smrg                                GLchar *name, const char *caller)
785b8e80941Smrg{
786b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
787b8e80941Smrg
788b8e80941Smrg   /* Find resource with given interface and index. */
789b8e80941Smrg   struct gl_program_resource *res =
790b8e80941Smrg      _mesa_program_resource_find_index(shProg, programInterface, index);
791b8e80941Smrg
792b8e80941Smrg   /* The error INVALID_VALUE is generated if <index> is greater than
793b8e80941Smrg   * or equal to the number of entries in the active resource list for
794b8e80941Smrg   * <programInterface>.
795b8e80941Smrg   */
796b8e80941Smrg   if (!res) {
797b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
798b8e80941Smrg      return false;
799b8e80941Smrg   }
800b8e80941Smrg
801b8e80941Smrg   if (bufSize < 0) {
802b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
803b8e80941Smrg      return false;
804b8e80941Smrg   }
805b8e80941Smrg
806b8e80941Smrg   GLsizei localLength;
807b8e80941Smrg
808b8e80941Smrg   if (length == NULL)
809b8e80941Smrg      length = &localLength;
810b8e80941Smrg
811b8e80941Smrg   _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
812b8e80941Smrg
813b8e80941Smrg   if (_mesa_program_resource_array_size(res) && add_index_to_name(res)) {
814b8e80941Smrg      int i;
815b8e80941Smrg
816b8e80941Smrg      /* The comparison is strange because *length does *NOT* include the
817b8e80941Smrg       * terminating NUL, but maxLength does.
818b8e80941Smrg       */
819b8e80941Smrg      for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
820b8e80941Smrg         name[*length + i] = "[0]"[i];
821b8e80941Smrg
822b8e80941Smrg      name[*length + i] = '\0';
823b8e80941Smrg      *length += i;
824b8e80941Smrg   }
825b8e80941Smrg   return true;
826b8e80941Smrg}
827b8e80941Smrg
828b8e80941Smrgstatic GLint
829b8e80941Smrgprogram_resource_location(struct gl_program_resource *res, unsigned array_index)
830b8e80941Smrg{
831b8e80941Smrg   switch (res->Type) {
832b8e80941Smrg   case GL_PROGRAM_INPUT: {
833b8e80941Smrg      const gl_shader_variable *var = RESOURCE_VAR(res);
834b8e80941Smrg
835b8e80941Smrg      if (var->location == -1)
836b8e80941Smrg         return -1;
837b8e80941Smrg
838b8e80941Smrg      /* If the input is an array, fail if the index is out of bounds. */
839b8e80941Smrg      if (array_index > 0
840b8e80941Smrg          && array_index >= var->type->length) {
841b8e80941Smrg         return -1;
842b8e80941Smrg      }
843b8e80941Smrg      return var->location +
844b8e80941Smrg	     (array_index * var->type->without_array()->matrix_columns);
845b8e80941Smrg   }
846b8e80941Smrg   case GL_PROGRAM_OUTPUT:
847b8e80941Smrg      if (RESOURCE_VAR(res)->location == -1)
848b8e80941Smrg         return -1;
849b8e80941Smrg
850b8e80941Smrg      /* If the output is an array, fail if the index is out of bounds. */
851b8e80941Smrg      if (array_index > 0
852b8e80941Smrg          && array_index >= RESOURCE_VAR(res)->type->length) {
853b8e80941Smrg         return -1;
854b8e80941Smrg      }
855b8e80941Smrg      return RESOURCE_VAR(res)->location + array_index;
856b8e80941Smrg   case GL_UNIFORM:
857b8e80941Smrg      /* If the uniform is built-in, fail. */
858b8e80941Smrg      if (RESOURCE_UNI(res)->builtin)
859b8e80941Smrg         return -1;
860b8e80941Smrg
861b8e80941Smrg     /* From page 79 of the OpenGL 4.2 spec:
862b8e80941Smrg      *
863b8e80941Smrg      *     "A valid name cannot be a structure, an array of structures, or any
864b8e80941Smrg      *     portion of a single vector or a matrix."
865b8e80941Smrg      */
866b8e80941Smrg      if (RESOURCE_UNI(res)->type->without_array()->is_struct())
867b8e80941Smrg         return -1;
868b8e80941Smrg
869b8e80941Smrg      /* From the GL_ARB_uniform_buffer_object spec:
870b8e80941Smrg       *
871b8e80941Smrg       *     "The value -1 will be returned if <name> does not correspond to an
872b8e80941Smrg       *     active uniform variable name in <program>, if <name> is associated
873b8e80941Smrg       *     with a named uniform block, or if <name> starts with the reserved
874b8e80941Smrg       *     prefix "gl_"."
875b8e80941Smrg       */
876b8e80941Smrg      if (RESOURCE_UNI(res)->block_index != -1 ||
877b8e80941Smrg          RESOURCE_UNI(res)->atomic_buffer_index != -1)
878b8e80941Smrg         return -1;
879b8e80941Smrg
880b8e80941Smrg      /* fallthrough */
881b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
882b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
883b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
884b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
885b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
886b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
887b8e80941Smrg      /* If the uniform is an array, fail if the index is out of bounds. */
888b8e80941Smrg      if (array_index > 0
889b8e80941Smrg          && array_index >= RESOURCE_UNI(res)->array_elements) {
890b8e80941Smrg         return -1;
891b8e80941Smrg      }
892b8e80941Smrg
893b8e80941Smrg      /* location in remap table + array element offset */
894b8e80941Smrg      return RESOURCE_UNI(res)->remap_location + array_index;
895b8e80941Smrg   default:
896b8e80941Smrg      return -1;
897b8e80941Smrg   }
898b8e80941Smrg}
899b8e80941Smrg
900b8e80941Smrg/**
901b8e80941Smrg * Function implements following location queries:
902b8e80941Smrg *    glGetUniformLocation
903b8e80941Smrg */
904b8e80941SmrgGLint
905b8e80941Smrg_mesa_program_resource_location(struct gl_shader_program *shProg,
906b8e80941Smrg                                GLenum programInterface, const char *name)
907b8e80941Smrg{
908b8e80941Smrg   unsigned array_index = 0;
909b8e80941Smrg   struct gl_program_resource *res =
910b8e80941Smrg      _mesa_program_resource_find_name(shProg, programInterface, name,
911b8e80941Smrg                                       &array_index);
912b8e80941Smrg
913b8e80941Smrg   /* Resource not found. */
914b8e80941Smrg   if (!res)
915b8e80941Smrg      return -1;
916b8e80941Smrg
917b8e80941Smrg   return program_resource_location(res, array_index);
918b8e80941Smrg}
919b8e80941Smrg
920b8e80941Smrg/**
921b8e80941Smrg * Function implements following index queries:
922b8e80941Smrg *    glGetFragDataIndex
923b8e80941Smrg */
924b8e80941SmrgGLint
925b8e80941Smrg_mesa_program_resource_location_index(struct gl_shader_program *shProg,
926b8e80941Smrg                                      GLenum programInterface, const char *name)
927b8e80941Smrg{
928b8e80941Smrg   struct gl_program_resource *res =
929b8e80941Smrg      _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
930b8e80941Smrg
931b8e80941Smrg   /* Non-existent variable or resource is not referenced by fragment stage. */
932b8e80941Smrg   if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
933b8e80941Smrg      return -1;
934b8e80941Smrg
935b8e80941Smrg   /* From OpenGL 4.5 spec, 7.3 Program Objects
936b8e80941Smrg    * "The value -1 will be returned by either command...
937b8e80941Smrg    *  ... or if name identifies an active variable that does not have a
938b8e80941Smrg    * valid location assigned.
939b8e80941Smrg    */
940b8e80941Smrg   if (RESOURCE_VAR(res)->location == -1)
941b8e80941Smrg      return -1;
942b8e80941Smrg   return RESOURCE_VAR(res)->index;
943b8e80941Smrg}
944b8e80941Smrg
945b8e80941Smrgstatic uint8_t
946b8e80941Smrgstage_from_enum(GLenum ref)
947b8e80941Smrg{
948b8e80941Smrg   switch (ref) {
949b8e80941Smrg   case GL_REFERENCED_BY_VERTEX_SHADER:
950b8e80941Smrg      return MESA_SHADER_VERTEX;
951b8e80941Smrg   case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
952b8e80941Smrg      return MESA_SHADER_TESS_CTRL;
953b8e80941Smrg   case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
954b8e80941Smrg      return MESA_SHADER_TESS_EVAL;
955b8e80941Smrg   case GL_REFERENCED_BY_GEOMETRY_SHADER:
956b8e80941Smrg      return MESA_SHADER_GEOMETRY;
957b8e80941Smrg   case GL_REFERENCED_BY_FRAGMENT_SHADER:
958b8e80941Smrg      return MESA_SHADER_FRAGMENT;
959b8e80941Smrg   case GL_REFERENCED_BY_COMPUTE_SHADER:
960b8e80941Smrg      return MESA_SHADER_COMPUTE;
961b8e80941Smrg   default:
962b8e80941Smrg      assert(!"shader stage not supported");
963b8e80941Smrg      return MESA_SHADER_STAGES;
964b8e80941Smrg   }
965b8e80941Smrg}
966b8e80941Smrg
967b8e80941Smrg/**
968b8e80941Smrg * Check if resource is referenced by given 'referenced by' stage enum.
969b8e80941Smrg * ATC and UBO resources hold stage references of their own.
970b8e80941Smrg */
971b8e80941Smrgstatic bool
972b8e80941Smrgis_resource_referenced(struct gl_shader_program *shProg,
973b8e80941Smrg                       struct gl_program_resource *res,
974b8e80941Smrg                       GLuint index, uint8_t stage)
975b8e80941Smrg{
976b8e80941Smrg   /* First, check if we even have such a stage active. */
977b8e80941Smrg   if (!shProg->_LinkedShaders[stage])
978b8e80941Smrg      return false;
979b8e80941Smrg
980b8e80941Smrg   if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
981b8e80941Smrg      return RESOURCE_ATC(res)->StageReferences[stage];
982b8e80941Smrg
983b8e80941Smrg   if (res->Type == GL_UNIFORM_BLOCK)
984b8e80941Smrg      return shProg->data->UniformBlocks[index].stageref & (1 << stage);
985b8e80941Smrg
986b8e80941Smrg   if (res->Type == GL_SHADER_STORAGE_BLOCK)
987b8e80941Smrg      return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
988b8e80941Smrg
989b8e80941Smrg   return res->StageReferences & (1 << stage);
990b8e80941Smrg}
991b8e80941Smrg
992b8e80941Smrgstatic unsigned
993b8e80941Smrgget_buffer_property(struct gl_shader_program *shProg,
994b8e80941Smrg                    struct gl_program_resource *res, const GLenum prop,
995b8e80941Smrg                    GLint *val, const char *caller)
996b8e80941Smrg{
997b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
998b8e80941Smrg   if (res->Type != GL_UNIFORM_BLOCK &&
999b8e80941Smrg       res->Type != GL_ATOMIC_COUNTER_BUFFER &&
1000b8e80941Smrg       res->Type != GL_SHADER_STORAGE_BLOCK &&
1001b8e80941Smrg       res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
1002b8e80941Smrg      goto invalid_operation;
1003b8e80941Smrg
1004b8e80941Smrg   if (res->Type == GL_UNIFORM_BLOCK) {
1005b8e80941Smrg      switch (prop) {
1006b8e80941Smrg      case GL_BUFFER_BINDING:
1007b8e80941Smrg         *val = RESOURCE_UBO(res)->Binding;
1008b8e80941Smrg         return 1;
1009b8e80941Smrg      case GL_BUFFER_DATA_SIZE:
1010b8e80941Smrg         *val = RESOURCE_UBO(res)->UniformBufferSize;
1011b8e80941Smrg         return 1;
1012b8e80941Smrg      case GL_NUM_ACTIVE_VARIABLES:
1013b8e80941Smrg         *val = 0;
1014b8e80941Smrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1015b8e80941Smrg            const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1016b8e80941Smrg            struct gl_program_resource *uni =
1017b8e80941Smrg               _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1018b8e80941Smrg                                                NULL);
1019b8e80941Smrg            if (!uni)
1020b8e80941Smrg               continue;
1021b8e80941Smrg            (*val)++;
1022b8e80941Smrg         }
1023b8e80941Smrg         return 1;
1024b8e80941Smrg      case GL_ACTIVE_VARIABLES: {
1025b8e80941Smrg         unsigned num_values = 0;
1026b8e80941Smrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1027b8e80941Smrg            const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1028b8e80941Smrg            struct gl_program_resource *uni =
1029b8e80941Smrg               _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
1030b8e80941Smrg                                                NULL);
1031b8e80941Smrg            if (!uni)
1032b8e80941Smrg               continue;
1033b8e80941Smrg            *val++ =
1034b8e80941Smrg               _mesa_program_resource_index(shProg, uni);
1035b8e80941Smrg            num_values++;
1036b8e80941Smrg         }
1037b8e80941Smrg         return num_values;
1038b8e80941Smrg      }
1039b8e80941Smrg      }
1040b8e80941Smrg   } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
1041b8e80941Smrg      switch (prop) {
1042b8e80941Smrg      case GL_BUFFER_BINDING:
1043b8e80941Smrg         *val = RESOURCE_UBO(res)->Binding;
1044b8e80941Smrg         return 1;
1045b8e80941Smrg      case GL_BUFFER_DATA_SIZE:
1046b8e80941Smrg         *val = RESOURCE_UBO(res)->UniformBufferSize;
1047b8e80941Smrg         return 1;
1048b8e80941Smrg      case GL_NUM_ACTIVE_VARIABLES:
1049b8e80941Smrg         *val = 0;
1050b8e80941Smrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1051b8e80941Smrg            const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1052b8e80941Smrg            struct gl_program_resource *uni =
1053b8e80941Smrg               _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1054b8e80941Smrg                                                iname, NULL);
1055b8e80941Smrg            if (!uni)
1056b8e80941Smrg               continue;
1057b8e80941Smrg            (*val)++;
1058b8e80941Smrg         }
1059b8e80941Smrg         return 1;
1060b8e80941Smrg      case GL_ACTIVE_VARIABLES: {
1061b8e80941Smrg         unsigned num_values = 0;
1062b8e80941Smrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1063b8e80941Smrg            const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
1064b8e80941Smrg            struct gl_program_resource *uni =
1065b8e80941Smrg               _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
1066b8e80941Smrg                                                iname, NULL);
1067b8e80941Smrg            if (!uni)
1068b8e80941Smrg               continue;
1069b8e80941Smrg            *val++ =
1070b8e80941Smrg               _mesa_program_resource_index(shProg, uni);
1071b8e80941Smrg            num_values++;
1072b8e80941Smrg         }
1073b8e80941Smrg         return num_values;
1074b8e80941Smrg      }
1075b8e80941Smrg      }
1076b8e80941Smrg   } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1077b8e80941Smrg      switch (prop) {
1078b8e80941Smrg      case GL_BUFFER_BINDING:
1079b8e80941Smrg         *val = RESOURCE_ATC(res)->Binding;
1080b8e80941Smrg         return 1;
1081b8e80941Smrg      case GL_BUFFER_DATA_SIZE:
1082b8e80941Smrg         *val = RESOURCE_ATC(res)->MinimumSize;
1083b8e80941Smrg         return 1;
1084b8e80941Smrg      case GL_NUM_ACTIVE_VARIABLES:
1085b8e80941Smrg         *val = RESOURCE_ATC(res)->NumUniforms;
1086b8e80941Smrg         return 1;
1087b8e80941Smrg      case GL_ACTIVE_VARIABLES:
1088b8e80941Smrg         for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
1089b8e80941Smrg            /* Active atomic buffer contains index to UniformStorage. Find
1090b8e80941Smrg             * out gl_program_resource via data pointer and then calculate
1091b8e80941Smrg             * index of that uniform.
1092b8e80941Smrg             */
1093b8e80941Smrg            unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
1094b8e80941Smrg            struct gl_program_resource *uni =
1095b8e80941Smrg               program_resource_find_data(shProg,
1096b8e80941Smrg                                          &shProg->data->UniformStorage[idx]);
1097b8e80941Smrg            assert(uni);
1098b8e80941Smrg            *val++ = _mesa_program_resource_index(shProg, uni);
1099b8e80941Smrg         }
1100b8e80941Smrg         return RESOURCE_ATC(res)->NumUniforms;
1101b8e80941Smrg      }
1102b8e80941Smrg   } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
1103b8e80941Smrg      switch (prop) {
1104b8e80941Smrg      case GL_BUFFER_BINDING:
1105b8e80941Smrg         *val = RESOURCE_XFB(res)->Binding;
1106b8e80941Smrg         return 1;
1107b8e80941Smrg      case GL_NUM_ACTIVE_VARIABLES:
1108b8e80941Smrg         *val = RESOURCE_XFB(res)->NumVaryings;
1109b8e80941Smrg         return 1;
1110b8e80941Smrg      case GL_ACTIVE_VARIABLES:
1111b8e80941Smrg         struct gl_transform_feedback_info *linked_xfb =
1112b8e80941Smrg            shProg->last_vert_prog->sh.LinkedTransformFeedback;
1113b8e80941Smrg         for (int i = 0; i < linked_xfb->NumVarying; i++) {
1114b8e80941Smrg            unsigned index = linked_xfb->Varyings[i].BufferIndex;
1115b8e80941Smrg            struct gl_program_resource *buf_res =
1116b8e80941Smrg               _mesa_program_resource_find_index(shProg,
1117b8e80941Smrg                                                 GL_TRANSFORM_FEEDBACK_BUFFER,
1118b8e80941Smrg                                                 index);
1119b8e80941Smrg            assert(buf_res);
1120b8e80941Smrg            if (res == buf_res) {
1121b8e80941Smrg               *val++ = i;
1122b8e80941Smrg            }
1123b8e80941Smrg         }
1124b8e80941Smrg         return RESOURCE_XFB(res)->NumVaryings;
1125b8e80941Smrg      }
1126b8e80941Smrg   }
1127b8e80941Smrg   assert(!"support for property type not implemented");
1128b8e80941Smrg
1129b8e80941Smrginvalid_operation:
1130b8e80941Smrg   _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1131b8e80941Smrg               _mesa_enum_to_string(res->Type),
1132b8e80941Smrg               _mesa_enum_to_string(prop));
1133b8e80941Smrg
1134b8e80941Smrg   return 0;
1135b8e80941Smrg}
1136b8e80941Smrg
1137b8e80941Smrgunsigned
1138b8e80941Smrg_mesa_program_resource_prop(struct gl_shader_program *shProg,
1139b8e80941Smrg                            struct gl_program_resource *res, GLuint index,
1140b8e80941Smrg                            const GLenum prop, GLint *val, const char *caller)
1141b8e80941Smrg{
1142b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1143b8e80941Smrg
1144b8e80941Smrg#define VALIDATE_TYPE(type)\
1145b8e80941Smrg   if (res->Type != type)\
1146b8e80941Smrg      goto invalid_operation;
1147b8e80941Smrg
1148b8e80941Smrg#define VALIDATE_TYPE_2(type1, type2)\
1149b8e80941Smrg   if (res->Type != type1 && res->Type != type2)\
1150b8e80941Smrg      goto invalid_operation;
1151b8e80941Smrg
1152b8e80941Smrg   switch(prop) {
1153b8e80941Smrg   case GL_NAME_LENGTH:
1154b8e80941Smrg      switch (res->Type) {
1155b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
1156b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
1157b8e80941Smrg         goto invalid_operation;
1158b8e80941Smrg      default:
1159b8e80941Smrg         /* Resource name length + terminator. */
1160b8e80941Smrg         *val = _mesa_program_resource_name_len(res) + 1;
1161b8e80941Smrg      }
1162b8e80941Smrg      return 1;
1163b8e80941Smrg   case GL_TYPE:
1164b8e80941Smrg      switch (res->Type) {
1165b8e80941Smrg      case GL_UNIFORM:
1166b8e80941Smrg      case GL_BUFFER_VARIABLE:
1167b8e80941Smrg         *val = RESOURCE_UNI(res)->type->gl_type;
1168b8e80941Smrg         return 1;
1169b8e80941Smrg      case GL_PROGRAM_INPUT:
1170b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1171b8e80941Smrg         *val = RESOURCE_VAR(res)->type->gl_type;
1172b8e80941Smrg         return 1;
1173b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_VARYING:
1174b8e80941Smrg         *val = RESOURCE_XFV(res)->Type;
1175b8e80941Smrg         return 1;
1176b8e80941Smrg      default:
1177b8e80941Smrg         goto invalid_operation;
1178b8e80941Smrg      }
1179b8e80941Smrg   case GL_ARRAY_SIZE:
1180b8e80941Smrg      switch (res->Type) {
1181b8e80941Smrg      case GL_UNIFORM:
1182b8e80941Smrg      case GL_BUFFER_VARIABLE:
1183b8e80941Smrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
1184b8e80941Smrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1185b8e80941Smrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1186b8e80941Smrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
1187b8e80941Smrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1188b8e80941Smrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1189b8e80941Smrg
1190b8e80941Smrg         /* Test if a buffer variable is an array or an unsized array.
1191b8e80941Smrg          * Unsized arrays return zero as array size.
1192b8e80941Smrg          */
1193b8e80941Smrg         if (RESOURCE_UNI(res)->is_shader_storage &&
1194b8e80941Smrg             RESOURCE_UNI(res)->array_stride > 0)
1195b8e80941Smrg            *val = RESOURCE_UNI(res)->array_elements;
1196b8e80941Smrg         else
1197b8e80941Smrg            *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1198b8e80941Smrg         return 1;
1199b8e80941Smrg      case GL_PROGRAM_INPUT:
1200b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1201b8e80941Smrg         *val = MAX2(_mesa_program_resource_array_size(res), 1);
1202b8e80941Smrg         return 1;
1203b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_VARYING:
1204b8e80941Smrg         *val = RESOURCE_XFV(res)->Size;
1205b8e80941Smrg         return 1;
1206b8e80941Smrg      default:
1207b8e80941Smrg         goto invalid_operation;
1208b8e80941Smrg      }
1209b8e80941Smrg   case GL_OFFSET:
1210b8e80941Smrg      switch (res->Type) {
1211b8e80941Smrg      case GL_UNIFORM:
1212b8e80941Smrg      case GL_BUFFER_VARIABLE:
1213b8e80941Smrg         *val = RESOURCE_UNI(res)->offset;
1214b8e80941Smrg         return 1;
1215b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_VARYING:
1216b8e80941Smrg         *val = RESOURCE_XFV(res)->Offset;
1217b8e80941Smrg         return 1;
1218b8e80941Smrg      default:
1219b8e80941Smrg         goto invalid_operation;
1220b8e80941Smrg      }
1221b8e80941Smrg   case GL_BLOCK_INDEX:
1222b8e80941Smrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1223b8e80941Smrg      *val = RESOURCE_UNI(res)->block_index;
1224b8e80941Smrg      return 1;
1225b8e80941Smrg   case GL_ARRAY_STRIDE:
1226b8e80941Smrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1227b8e80941Smrg      *val = RESOURCE_UNI(res)->array_stride;
1228b8e80941Smrg      return 1;
1229b8e80941Smrg   case GL_MATRIX_STRIDE:
1230b8e80941Smrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1231b8e80941Smrg      *val = RESOURCE_UNI(res)->matrix_stride;
1232b8e80941Smrg      return 1;
1233b8e80941Smrg   case GL_IS_ROW_MAJOR:
1234b8e80941Smrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1235b8e80941Smrg      *val = RESOURCE_UNI(res)->row_major;
1236b8e80941Smrg      return 1;
1237b8e80941Smrg   case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1238b8e80941Smrg      VALIDATE_TYPE(GL_UNIFORM);
1239b8e80941Smrg      *val = RESOURCE_UNI(res)->atomic_buffer_index;
1240b8e80941Smrg      return 1;
1241b8e80941Smrg   case GL_BUFFER_BINDING:
1242b8e80941Smrg   case GL_BUFFER_DATA_SIZE:
1243b8e80941Smrg   case GL_NUM_ACTIVE_VARIABLES:
1244b8e80941Smrg   case GL_ACTIVE_VARIABLES:
1245b8e80941Smrg      return get_buffer_property(shProg, res, prop, val, caller);
1246b8e80941Smrg   case GL_REFERENCED_BY_COMPUTE_SHADER:
1247b8e80941Smrg      if (!_mesa_has_compute_shaders(ctx))
1248b8e80941Smrg         goto invalid_enum;
1249b8e80941Smrg      /* fallthrough */
1250b8e80941Smrg   case GL_REFERENCED_BY_VERTEX_SHADER:
1251b8e80941Smrg   case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1252b8e80941Smrg   case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1253b8e80941Smrg   case GL_REFERENCED_BY_GEOMETRY_SHADER:
1254b8e80941Smrg   case GL_REFERENCED_BY_FRAGMENT_SHADER:
1255b8e80941Smrg      switch (res->Type) {
1256b8e80941Smrg      case GL_UNIFORM:
1257b8e80941Smrg      case GL_PROGRAM_INPUT:
1258b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1259b8e80941Smrg      case GL_UNIFORM_BLOCK:
1260b8e80941Smrg      case GL_BUFFER_VARIABLE:
1261b8e80941Smrg      case GL_SHADER_STORAGE_BLOCK:
1262b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
1263b8e80941Smrg         *val = is_resource_referenced(shProg, res, index,
1264b8e80941Smrg                                       stage_from_enum(prop));
1265b8e80941Smrg         return 1;
1266b8e80941Smrg      default:
1267b8e80941Smrg         goto invalid_operation;
1268b8e80941Smrg      }
1269b8e80941Smrg   case GL_LOCATION:
1270b8e80941Smrg      switch (res->Type) {
1271b8e80941Smrg      case GL_UNIFORM:
1272b8e80941Smrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
1273b8e80941Smrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1274b8e80941Smrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1275b8e80941Smrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
1276b8e80941Smrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1277b8e80941Smrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1278b8e80941Smrg      case GL_PROGRAM_INPUT:
1279b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1280b8e80941Smrg         *val = program_resource_location(res, 0);
1281b8e80941Smrg         return 1;
1282b8e80941Smrg      default:
1283b8e80941Smrg         goto invalid_operation;
1284b8e80941Smrg      }
1285b8e80941Smrg   case GL_LOCATION_COMPONENT:
1286b8e80941Smrg      switch (res->Type) {
1287b8e80941Smrg      case GL_PROGRAM_INPUT:
1288b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1289b8e80941Smrg         *val = RESOURCE_VAR(res)->component;
1290b8e80941Smrg         return 1;
1291b8e80941Smrg      default:
1292b8e80941Smrg         goto invalid_operation;
1293b8e80941Smrg      }
1294b8e80941Smrg   case GL_LOCATION_INDEX: {
1295b8e80941Smrg      int tmp;
1296b8e80941Smrg      if (res->Type != GL_PROGRAM_OUTPUT)
1297b8e80941Smrg         goto invalid_operation;
1298b8e80941Smrg      tmp = program_resource_location(res, 0);
1299b8e80941Smrg      if (tmp == -1)
1300b8e80941Smrg         *val = -1;
1301b8e80941Smrg      else
1302b8e80941Smrg         *val = _mesa_program_resource_location_index(shProg, res->Type,
1303b8e80941Smrg                                                      RESOURCE_VAR(res)->name);
1304b8e80941Smrg      return 1;
1305b8e80941Smrg   }
1306b8e80941Smrg   case GL_NUM_COMPATIBLE_SUBROUTINES:
1307b8e80941Smrg      if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1308b8e80941Smrg          res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1309b8e80941Smrg          res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1310b8e80941Smrg          res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1311b8e80941Smrg          res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1312b8e80941Smrg          res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1313b8e80941Smrg         goto invalid_operation;
1314b8e80941Smrg      *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1315b8e80941Smrg      return 1;
1316b8e80941Smrg   case GL_COMPATIBLE_SUBROUTINES: {
1317b8e80941Smrg      const struct gl_uniform_storage *uni;
1318b8e80941Smrg      struct gl_program *p;
1319b8e80941Smrg      unsigned count, i;
1320b8e80941Smrg      int j;
1321b8e80941Smrg
1322b8e80941Smrg      if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1323b8e80941Smrg          res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1324b8e80941Smrg          res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1325b8e80941Smrg          res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1326b8e80941Smrg          res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1327b8e80941Smrg          res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1328b8e80941Smrg         goto invalid_operation;
1329b8e80941Smrg      uni = RESOURCE_UNI(res);
1330b8e80941Smrg
1331b8e80941Smrg      p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
1332b8e80941Smrg      count = 0;
1333b8e80941Smrg      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
1334b8e80941Smrg         struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
1335b8e80941Smrg         for (j = 0; j < fn->num_compat_types; j++) {
1336b8e80941Smrg            if (fn->types[j] == uni->type) {
1337b8e80941Smrg               val[count++] = i;
1338b8e80941Smrg               break;
1339b8e80941Smrg            }
1340b8e80941Smrg         }
1341b8e80941Smrg      }
1342b8e80941Smrg      return count;
1343b8e80941Smrg   }
1344b8e80941Smrg
1345b8e80941Smrg   case GL_TOP_LEVEL_ARRAY_SIZE:
1346b8e80941Smrg      VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1347b8e80941Smrg      *val = RESOURCE_UNI(res)->top_level_array_size;
1348b8e80941Smrg      return 1;
1349b8e80941Smrg
1350b8e80941Smrg   case GL_TOP_LEVEL_ARRAY_STRIDE:
1351b8e80941Smrg      VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1352b8e80941Smrg      *val = RESOURCE_UNI(res)->top_level_array_stride;
1353b8e80941Smrg      return 1;
1354b8e80941Smrg
1355b8e80941Smrg   /* GL_ARB_tessellation_shader */
1356b8e80941Smrg   case GL_IS_PER_PATCH:
1357b8e80941Smrg      switch (res->Type) {
1358b8e80941Smrg      case GL_PROGRAM_INPUT:
1359b8e80941Smrg      case GL_PROGRAM_OUTPUT:
1360b8e80941Smrg         *val = RESOURCE_VAR(res)->patch;
1361b8e80941Smrg         return 1;
1362b8e80941Smrg      default:
1363b8e80941Smrg         goto invalid_operation;
1364b8e80941Smrg      }
1365b8e80941Smrg
1366b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
1367b8e80941Smrg      VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
1368b8e80941Smrg      *val = RESOURCE_XFV(res)->BufferIndex;
1369b8e80941Smrg      return 1;
1370b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
1371b8e80941Smrg      VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
1372b8e80941Smrg      *val = RESOURCE_XFB(res)->Stride * 4;
1373b8e80941Smrg      return 1;
1374b8e80941Smrg
1375b8e80941Smrg   default:
1376b8e80941Smrg      goto invalid_enum;
1377b8e80941Smrg   }
1378b8e80941Smrg
1379b8e80941Smrg#undef VALIDATE_TYPE
1380b8e80941Smrg#undef VALIDATE_TYPE_2
1381b8e80941Smrg
1382b8e80941Smrginvalid_enum:
1383b8e80941Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1384b8e80941Smrg               _mesa_enum_to_string(res->Type),
1385b8e80941Smrg               _mesa_enum_to_string(prop));
1386b8e80941Smrg   return 0;
1387b8e80941Smrg
1388b8e80941Smrginvalid_operation:
1389b8e80941Smrg   _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1390b8e80941Smrg               _mesa_enum_to_string(res->Type),
1391b8e80941Smrg               _mesa_enum_to_string(prop));
1392b8e80941Smrg   return 0;
1393b8e80941Smrg}
1394b8e80941Smrg
1395b8e80941Smrgextern void
1396b8e80941Smrg_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1397b8e80941Smrg                             GLenum programInterface, GLuint index, GLsizei propCount,
1398b8e80941Smrg                             const GLenum *props, GLsizei bufSize,
1399b8e80941Smrg                             GLsizei *length, GLint *params)
1400b8e80941Smrg{
1401b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1402b8e80941Smrg   GLint *val = (GLint *) params;
1403b8e80941Smrg   const GLenum *prop = props;
1404b8e80941Smrg   GLsizei amount = 0;
1405b8e80941Smrg
1406b8e80941Smrg   struct gl_program_resource *res =
1407b8e80941Smrg      _mesa_program_resource_find_index(shProg, programInterface, index);
1408b8e80941Smrg
1409b8e80941Smrg   /* No such resource found or bufSize negative. */
1410b8e80941Smrg   if (!res || bufSize < 0) {
1411b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
1412b8e80941Smrg                  "glGetProgramResourceiv(%s index %d bufSize %d)",
1413b8e80941Smrg                  _mesa_enum_to_string(programInterface), index, bufSize);
1414b8e80941Smrg      return;
1415b8e80941Smrg   }
1416b8e80941Smrg
1417b8e80941Smrg   /* Write propCount values until error occurs or bufSize reached. */
1418b8e80941Smrg   for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1419b8e80941Smrg      int props_written =
1420b8e80941Smrg         _mesa_program_resource_prop(shProg, res, index, *prop, val,
1421b8e80941Smrg                                     "glGetProgramResourceiv");
1422b8e80941Smrg
1423b8e80941Smrg      /* Error happened. */
1424b8e80941Smrg      if (props_written == 0)
1425b8e80941Smrg         return;
1426b8e80941Smrg
1427b8e80941Smrg      amount += props_written;
1428b8e80941Smrg   }
1429b8e80941Smrg
1430b8e80941Smrg   /* If <length> is not NULL, the actual number of integer values
1431b8e80941Smrg    * written to <params> will be written to <length>.
1432b8e80941Smrg    */
1433b8e80941Smrg   if (length)
1434b8e80941Smrg      *length = amount;
1435b8e80941Smrg}
1436b8e80941Smrg
1437b8e80941Smrgstatic bool
1438b8e80941Smrgvalidate_io(struct gl_program *producer, struct gl_program *consumer)
1439b8e80941Smrg{
1440b8e80941Smrg   if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages)
1441b8e80941Smrg      return true;
1442b8e80941Smrg
1443b8e80941Smrg   const bool producer_is_array_stage =
1444b8e80941Smrg      producer->info.stage == MESA_SHADER_TESS_CTRL;
1445b8e80941Smrg   const bool consumer_is_array_stage =
1446b8e80941Smrg      consumer->info.stage == MESA_SHADER_GEOMETRY ||
1447b8e80941Smrg      consumer->info.stage == MESA_SHADER_TESS_CTRL ||
1448b8e80941Smrg      consumer->info.stage == MESA_SHADER_TESS_EVAL;
1449b8e80941Smrg
1450b8e80941Smrg   bool valid = true;
1451b8e80941Smrg
1452b8e80941Smrg   gl_shader_variable const **outputs =
1453b8e80941Smrg      (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList,
1454b8e80941Smrg                                           sizeof(gl_shader_variable *));
1455b8e80941Smrg   if (outputs == NULL)
1456b8e80941Smrg      return false;
1457b8e80941Smrg
1458b8e80941Smrg   /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1459b8e80941Smrg    * says:
1460b8e80941Smrg    *
1461b8e80941Smrg    *    At an interface between program objects, the set of inputs and
1462b8e80941Smrg    *    outputs are considered to match exactly if and only if:
1463b8e80941Smrg    *
1464b8e80941Smrg    *    - Every declared input variable has a matching output, as described
1465b8e80941Smrg    *      above.
1466b8e80941Smrg    *    - There are no user-defined output variables declared without a
1467b8e80941Smrg    *      matching input variable declaration.
1468b8e80941Smrg    *
1469b8e80941Smrg    * Every input has an output, and every output has an input.  Scan the list
1470b8e80941Smrg    * of producer resources once, and generate the list of outputs.  As inputs
1471b8e80941Smrg    * and outputs are matched, remove the matched outputs from the set.  At
1472b8e80941Smrg    * the end, the set must be empty.  If the set is not empty, then there is
1473b8e80941Smrg    * some output that did not have an input.
1474b8e80941Smrg    */
1475b8e80941Smrg   unsigned num_outputs = 0;
1476b8e80941Smrg   for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) {
1477b8e80941Smrg      struct gl_program_resource *res =
1478b8e80941Smrg         &producer->sh.data->ProgramResourceList[i];
1479b8e80941Smrg
1480b8e80941Smrg      if (res->Type != GL_PROGRAM_OUTPUT)
1481b8e80941Smrg         continue;
1482b8e80941Smrg
1483b8e80941Smrg      gl_shader_variable const *const var = RESOURCE_VAR(res);
1484b8e80941Smrg
1485b8e80941Smrg      /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1486b8e80941Smrg       * says:
1487b8e80941Smrg       *
1488b8e80941Smrg       *    Built-in inputs or outputs do not affect interface matching.
1489b8e80941Smrg       */
1490b8e80941Smrg      if (is_gl_identifier(var->name))
1491b8e80941Smrg         continue;
1492b8e80941Smrg
1493b8e80941Smrg      outputs[num_outputs++] = var;
1494b8e80941Smrg   }
1495b8e80941Smrg
1496b8e80941Smrg   unsigned match_index = 0;
1497b8e80941Smrg   for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) {
1498b8e80941Smrg      struct gl_program_resource *res =
1499b8e80941Smrg         &consumer->sh.data->ProgramResourceList[i];
1500b8e80941Smrg
1501b8e80941Smrg      if (res->Type != GL_PROGRAM_INPUT)
1502b8e80941Smrg         continue;
1503b8e80941Smrg
1504b8e80941Smrg      gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
1505b8e80941Smrg      gl_shader_variable const *producer_var = NULL;
1506b8e80941Smrg
1507b8e80941Smrg      if (is_gl_identifier(consumer_var->name))
1508b8e80941Smrg         continue;
1509b8e80941Smrg
1510b8e80941Smrg      /* Inputs with explicit locations match other outputs with explicit
1511b8e80941Smrg       * locations by location instead of by name.
1512b8e80941Smrg       */
1513b8e80941Smrg      if (consumer_var->explicit_location) {
1514b8e80941Smrg         for (unsigned j = 0; j < num_outputs; j++) {
1515b8e80941Smrg            const gl_shader_variable *const var = outputs[j];
1516b8e80941Smrg
1517b8e80941Smrg            if (var->explicit_location &&
1518b8e80941Smrg                consumer_var->location == var->location) {
1519b8e80941Smrg               producer_var = var;
1520b8e80941Smrg               match_index = j;
1521b8e80941Smrg               break;
1522b8e80941Smrg            }
1523b8e80941Smrg         }
1524b8e80941Smrg      } else {
1525b8e80941Smrg         for (unsigned j = 0; j < num_outputs; j++) {
1526b8e80941Smrg            const gl_shader_variable *const var = outputs[j];
1527b8e80941Smrg
1528b8e80941Smrg            if (!var->explicit_location &&
1529b8e80941Smrg                strcmp(consumer_var->name, var->name) == 0) {
1530b8e80941Smrg               producer_var = var;
1531b8e80941Smrg               match_index = j;
1532b8e80941Smrg               break;
1533b8e80941Smrg            }
1534b8e80941Smrg         }
1535b8e80941Smrg      }
1536b8e80941Smrg
1537b8e80941Smrg      /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1538b8e80941Smrg       * says:
1539b8e80941Smrg       *
1540b8e80941Smrg       *    - An output variable is considered to match an input variable in
1541b8e80941Smrg       *      the subsequent shader if:
1542b8e80941Smrg       *
1543b8e80941Smrg       *      - the two variables match in name, type, and qualification; or
1544b8e80941Smrg       *
1545b8e80941Smrg       *      - the two variables are declared with the same location
1546b8e80941Smrg       *        qualifier and match in type and qualification.
1547b8e80941Smrg       */
1548b8e80941Smrg      if (producer_var == NULL) {
1549b8e80941Smrg         valid = false;
1550b8e80941Smrg         goto out;
1551b8e80941Smrg      }
1552b8e80941Smrg
1553b8e80941Smrg      /* An output cannot match more than one input, so remove the output from
1554b8e80941Smrg       * the set of possible outputs.
1555b8e80941Smrg       */
1556b8e80941Smrg      outputs[match_index] = NULL;
1557b8e80941Smrg      num_outputs--;
1558b8e80941Smrg      if (match_index < num_outputs)
1559b8e80941Smrg         outputs[match_index] = outputs[num_outputs];
1560b8e80941Smrg
1561b8e80941Smrg      /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
1562b8e80941Smrg       *
1563b8e80941Smrg       *    "Tessellation control shader per-vertex output variables and
1564b8e80941Smrg       *     blocks and tessellation control, tessellation evaluation, and
1565b8e80941Smrg       *     geometry shader per-vertex input variables and blocks are
1566b8e80941Smrg       *     required to be declared as arrays, with each element representing
1567b8e80941Smrg       *     input or output values for a single vertex of a multi-vertex
1568b8e80941Smrg       *     primitive. For the purposes of interface matching, such variables
1569b8e80941Smrg       *     and blocks are treated as though they were not declared as
1570b8e80941Smrg       *     arrays."
1571b8e80941Smrg       *
1572b8e80941Smrg       * So we unwrap those types before matching.
1573b8e80941Smrg       */
1574b8e80941Smrg      const glsl_type *consumer_type = consumer_var->type;
1575b8e80941Smrg      const glsl_type *consumer_interface_type = consumer_var->interface_type;
1576b8e80941Smrg      const glsl_type *producer_type = producer_var->type;
1577b8e80941Smrg      const glsl_type *producer_interface_type = producer_var->interface_type;
1578b8e80941Smrg
1579b8e80941Smrg      if (consumer_is_array_stage) {
1580b8e80941Smrg         if (consumer_interface_type) {
1581b8e80941Smrg            /* the interface is the array; the underlying types should match */
1582b8e80941Smrg            if (consumer_interface_type->is_array() && !consumer_var->patch)
1583b8e80941Smrg               consumer_interface_type = consumer_interface_type->fields.array;
1584b8e80941Smrg         } else {
1585b8e80941Smrg            if (consumer_type->is_array() && !consumer_var->patch)
1586b8e80941Smrg               consumer_type = consumer_type->fields.array;
1587b8e80941Smrg         }
1588b8e80941Smrg      }
1589b8e80941Smrg
1590b8e80941Smrg      if (producer_is_array_stage) {
1591b8e80941Smrg         if (producer_interface_type) {
1592b8e80941Smrg            /* the interface is the array; the underlying types should match */
1593b8e80941Smrg            if (producer_interface_type->is_array() && !producer_var->patch)
1594b8e80941Smrg               producer_interface_type = producer_interface_type->fields.array;
1595b8e80941Smrg         } else {
1596b8e80941Smrg            if (producer_type->is_array() && !producer_var->patch)
1597b8e80941Smrg               producer_type = producer_type->fields.array;
1598b8e80941Smrg         }
1599b8e80941Smrg      }
1600b8e80941Smrg
1601b8e80941Smrg      if (producer_type != consumer_type) {
1602b8e80941Smrg         valid = false;
1603b8e80941Smrg         goto out;
1604b8e80941Smrg      }
1605b8e80941Smrg
1606b8e80941Smrg      if (producer_interface_type != consumer_interface_type) {
1607b8e80941Smrg         valid = false;
1608b8e80941Smrg         goto out;
1609b8e80941Smrg      }
1610b8e80941Smrg
1611b8e80941Smrg      /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
1612b8e80941Smrg       *
1613b8e80941Smrg       *    Qualifier Class|  Qualifier  |in/out
1614b8e80941Smrg       *    ---------------+-------------+------
1615b8e80941Smrg       *    Storage        |     in      |
1616b8e80941Smrg       *                   |     out     |  N/A
1617b8e80941Smrg       *                   |   uniform   |
1618b8e80941Smrg       *    ---------------+-------------+------
1619b8e80941Smrg       *    Auxiliary      |   centroid  |   No
1620b8e80941Smrg       *    ---------------+-------------+------
1621b8e80941Smrg       *                   |   location  |  Yes
1622b8e80941Smrg       *                   | Block layout|  N/A
1623b8e80941Smrg       *                   |   binding   |  N/A
1624b8e80941Smrg       *                   |   offset    |  N/A
1625b8e80941Smrg       *                   |   format    |  N/A
1626b8e80941Smrg       *    ---------------+-------------+------
1627b8e80941Smrg       *    Interpolation  |   smooth    |
1628b8e80941Smrg       *                   |    flat     |  Yes
1629b8e80941Smrg       *    ---------------+-------------+------
1630b8e80941Smrg       *                   |    lowp     |
1631b8e80941Smrg       *    Precision      |   mediump   |  Yes
1632b8e80941Smrg       *                   |    highp    |
1633b8e80941Smrg       *    ---------------+-------------+------
1634b8e80941Smrg       *    Variance       |  invariant  |   No
1635b8e80941Smrg       *    ---------------+-------------+------
1636b8e80941Smrg       *    Memory         |     all     |  N/A
1637b8e80941Smrg       *
1638b8e80941Smrg       * Note that location mismatches are detected by the loops above that
1639b8e80941Smrg       * find the producer variable that goes with the consumer variable.
1640b8e80941Smrg       */
1641b8e80941Smrg      unsigned producer_interpolation = producer_var->interpolation;
1642b8e80941Smrg      unsigned consumer_interpolation = consumer_var->interpolation;
1643b8e80941Smrg      if (producer_interpolation == INTERP_MODE_NONE)
1644b8e80941Smrg         producer_interpolation = INTERP_MODE_SMOOTH;
1645b8e80941Smrg      if (consumer_interpolation == INTERP_MODE_NONE)
1646b8e80941Smrg         consumer_interpolation = INTERP_MODE_SMOOTH;
1647b8e80941Smrg      if (producer_interpolation != consumer_interpolation) {
1648b8e80941Smrg         valid = false;
1649b8e80941Smrg         goto out;
1650b8e80941Smrg      }
1651b8e80941Smrg
1652b8e80941Smrg      if (producer_var->precision != consumer_var->precision) {
1653b8e80941Smrg         valid = false;
1654b8e80941Smrg         goto out;
1655b8e80941Smrg      }
1656b8e80941Smrg
1657b8e80941Smrg      if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
1658b8e80941Smrg         valid = false;
1659b8e80941Smrg         goto out;
1660b8e80941Smrg      }
1661b8e80941Smrg   }
1662b8e80941Smrg
1663b8e80941Smrg out:
1664b8e80941Smrg   free(outputs);
1665b8e80941Smrg   return valid && num_outputs == 0;
1666b8e80941Smrg}
1667b8e80941Smrg
1668b8e80941Smrg/**
1669b8e80941Smrg * Validate inputs against outputs in a program pipeline.
1670b8e80941Smrg */
1671b8e80941Smrgextern "C" bool
1672b8e80941Smrg_mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
1673b8e80941Smrg{
1674b8e80941Smrg   struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram;
1675b8e80941Smrg
1676b8e80941Smrg   /* Find first active stage in pipeline. */
1677b8e80941Smrg   unsigned idx, prev = 0;
1678b8e80941Smrg   for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1679b8e80941Smrg      if (prog[idx]) {
1680b8e80941Smrg         prev = idx;
1681b8e80941Smrg         break;
1682b8e80941Smrg      }
1683b8e80941Smrg   }
1684b8e80941Smrg
1685b8e80941Smrg   for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1686b8e80941Smrg      if (prog[idx]) {
1687b8e80941Smrg         /* Pipeline might include both non-compute and a compute program, do
1688b8e80941Smrg          * not attempt to validate varyings between non-compute and compute
1689b8e80941Smrg          * stage.
1690b8e80941Smrg          */
1691b8e80941Smrg         if (prog[idx]->info.stage == MESA_SHADER_COMPUTE)
1692b8e80941Smrg            break;
1693b8e80941Smrg
1694b8e80941Smrg         if (!validate_io(prog[prev], prog[idx]))
1695b8e80941Smrg            return false;
1696b8e80941Smrg
1697b8e80941Smrg         prev = idx;
1698b8e80941Smrg      }
1699b8e80941Smrg   }
1700b8e80941Smrg   return true;
1701848b8605Smrg}
1702