1af69d88dSmrg/*
2af69d88dSmrg * Mesa 3-D graphics library
3af69d88dSmrg *
4af69d88dSmrg * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5af69d88dSmrg * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6af69d88dSmrg * Copyright © 2010, 2011 Intel Corporation
7af69d88dSmrg *
8af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
9af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
10af69d88dSmrg * to deal in the Software without restriction, including without limitation
11af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
13af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
14af69d88dSmrg *
15af69d88dSmrg * The above copyright notice and this permission notice shall be included
16af69d88dSmrg * in all copies or substantial portions of the Software.
17af69d88dSmrg *
18af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
25af69d88dSmrg */
26af69d88dSmrg
27af69d88dSmrg#include <stdlib.h>
2801e04c3fSmrg#include <inttypes.h>  /* for PRIx64 macro */
2901e04c3fSmrg#include <math.h>
30af69d88dSmrg
31af69d88dSmrg#include "main/context.h"
327ec681f3Smrg#include "main/draw_validate.h"
33af69d88dSmrg#include "main/shaderapi.h"
34af69d88dSmrg#include "main/shaderobj.h"
3501e04c3fSmrg#include "main/uniforms.h"
3601e04c3fSmrg#include "compiler/glsl/ir.h"
3701e04c3fSmrg#include "compiler/glsl/ir_uniform.h"
3801e04c3fSmrg#include "compiler/glsl/glsl_parser_extras.h"
3901e04c3fSmrg#include "compiler/glsl/program.h"
4001e04c3fSmrg#include "util/bitscan.h"
41af69d88dSmrg
42af69d88dSmrg
437ec681f3Smrg/* This is one of the few glGet that can be called from the app thread safely.
447ec681f3Smrg * Only these conditions must be met:
457ec681f3Smrg * - There are no unfinished glLinkProgram and glDeleteProgram calls
467ec681f3Smrg *   for the program object. This assures that the program object is immutable.
477ec681f3Smrg * - glthread=true for GL errors to be passed to the driver thread safely
487ec681f3Smrg *
497ec681f3Smrg * Program objects can be looked up from any thread because they are part
507ec681f3Smrg * of the multi-context shared state.
517ec681f3Smrg */
527ec681f3Smrgextern "C" void
537ec681f3Smrg_mesa_GetActiveUniform_impl(GLuint program, GLuint index,
547ec681f3Smrg                            GLsizei maxLength, GLsizei *length, GLint *size,
557ec681f3Smrg                            GLenum *type, GLcharARB *nameOut, bool glthread)
56af69d88dSmrg{
57af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
5801e04c3fSmrg   struct gl_shader_program *shProg;
5901e04c3fSmrg   struct gl_program_resource *res;
60af69d88dSmrg
6101e04c3fSmrg   if (maxLength < 0) {
627ec681f3Smrg      _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
637ec681f3Smrg                                "glGetActiveUniform(maxLength < 0)");
64af69d88dSmrg      return;
6501e04c3fSmrg   }
66af69d88dSmrg
677ec681f3Smrg   shProg = _mesa_lookup_shader_program_err_glthread(ctx, program, glthread,
687ec681f3Smrg                                                     "glGetActiveUniform");
6901e04c3fSmrg   if (!shProg)
70af69d88dSmrg      return;
71af69d88dSmrg
7201e04c3fSmrg   res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
7301e04c3fSmrg                                           GL_UNIFORM, index);
74af69d88dSmrg
7501e04c3fSmrg   if (!res) {
767ec681f3Smrg      _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
777ec681f3Smrg                                "glGetActiveUniform(index)");
7801e04c3fSmrg      return;
79af69d88dSmrg   }
80af69d88dSmrg
8101e04c3fSmrg   if (nameOut)
8201e04c3fSmrg      _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength,
837ec681f3Smrg                                      length, nameOut, glthread,
847ec681f3Smrg                                      "glGetActiveUniform");
8501e04c3fSmrg   if (type)
8601e04c3fSmrg      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
8701e04c3fSmrg                                  res, index, GL_TYPE, (GLint*) type,
887ec681f3Smrg                                  glthread, "glGetActiveUniform");
8901e04c3fSmrg   if (size)
9001e04c3fSmrg      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
9101e04c3fSmrg                                  res, index, GL_ARRAY_SIZE, (GLint*) size,
927ec681f3Smrg                                  glthread, "glGetActiveUniform");
937ec681f3Smrg}
947ec681f3Smrg
957ec681f3Smrgextern "C" void GLAPIENTRY
967ec681f3Smrg_mesa_GetActiveUniform(GLuint program, GLuint index,
977ec681f3Smrg                       GLsizei maxLength, GLsizei *length, GLint *size,
987ec681f3Smrg                       GLenum *type, GLcharARB *nameOut)
997ec681f3Smrg{
1007ec681f3Smrg   _mesa_GetActiveUniform_impl(program, index, maxLength, length, size,
1017ec681f3Smrg                               type, nameOut, false);
10201e04c3fSmrg}
103af69d88dSmrg
10401e04c3fSmrgstatic GLenum
10501e04c3fSmrgresource_prop_from_uniform_prop(GLenum uni_prop)
10601e04c3fSmrg{
10701e04c3fSmrg   switch (uni_prop) {
10801e04c3fSmrg   case GL_UNIFORM_TYPE:
10901e04c3fSmrg      return GL_TYPE;
11001e04c3fSmrg   case GL_UNIFORM_SIZE:
11101e04c3fSmrg      return GL_ARRAY_SIZE;
11201e04c3fSmrg   case GL_UNIFORM_NAME_LENGTH:
11301e04c3fSmrg      return GL_NAME_LENGTH;
11401e04c3fSmrg   case GL_UNIFORM_BLOCK_INDEX:
11501e04c3fSmrg      return GL_BLOCK_INDEX;
11601e04c3fSmrg   case GL_UNIFORM_OFFSET:
11701e04c3fSmrg      return GL_OFFSET;
11801e04c3fSmrg   case GL_UNIFORM_ARRAY_STRIDE:
11901e04c3fSmrg      return GL_ARRAY_STRIDE;
12001e04c3fSmrg   case GL_UNIFORM_MATRIX_STRIDE:
12101e04c3fSmrg      return GL_MATRIX_STRIDE;
12201e04c3fSmrg   case GL_UNIFORM_IS_ROW_MAJOR:
12301e04c3fSmrg      return GL_IS_ROW_MAJOR;
12401e04c3fSmrg   case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
12501e04c3fSmrg      return GL_ATOMIC_COUNTER_BUFFER_INDEX;
12601e04c3fSmrg   default:
12701e04c3fSmrg      return 0;
128af69d88dSmrg   }
129af69d88dSmrg}
130af69d88dSmrg
131af69d88dSmrgextern "C" void GLAPIENTRY
132af69d88dSmrg_mesa_GetActiveUniformsiv(GLuint program,
133af69d88dSmrg			  GLsizei uniformCount,
134af69d88dSmrg			  const GLuint *uniformIndices,
135af69d88dSmrg			  GLenum pname,
136af69d88dSmrg			  GLint *params)
137af69d88dSmrg{
138af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
139af69d88dSmrg   struct gl_shader_program *shProg;
14001e04c3fSmrg   struct gl_program_resource *res;
14101e04c3fSmrg   GLenum res_prop;
142af69d88dSmrg
143af69d88dSmrg   if (uniformCount < 0) {
144af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
145af69d88dSmrg		  "glGetActiveUniformsiv(uniformCount < 0)");
146af69d88dSmrg      return;
147af69d88dSmrg   }
148af69d88dSmrg
14901e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
15001e04c3fSmrg   if (!shProg)
15101e04c3fSmrg      return;
15201e04c3fSmrg
15301e04c3fSmrg   res_prop = resource_prop_from_uniform_prop(pname);
154af69d88dSmrg
15501e04c3fSmrg   /* We need to first verify that each entry exists as active uniform. If
15601e04c3fSmrg    * not, generate error and do not cause any other side effects.
15701e04c3fSmrg    *
15801e04c3fSmrg    * In the case of and error condition, Page 16 (section 2.3.1 Errors)
15901e04c3fSmrg    * of the OpenGL 4.5 spec says:
16001e04c3fSmrg    *
16101e04c3fSmrg    *     "If the generating command modifies values through a pointer argu-
16201e04c3fSmrg    *     ment, no change is made to these values."
16301e04c3fSmrg    */
16401e04c3fSmrg   for (int i = 0; i < uniformCount; i++) {
16501e04c3fSmrg      if (!_mesa_program_resource_find_index(shProg, GL_UNIFORM,
16601e04c3fSmrg                                              uniformIndices[i])) {
16701e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
16801e04c3fSmrg         return;
169af69d88dSmrg      }
170af69d88dSmrg   }
171af69d88dSmrg
17201e04c3fSmrg   for (int i = 0; i < uniformCount; i++) {
17301e04c3fSmrg      res = _mesa_program_resource_find_index(shProg, GL_UNIFORM,
17401e04c3fSmrg                                              uniformIndices[i]);
17501e04c3fSmrg      if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
17601e04c3fSmrg                                       res_prop, &params[i],
1777ec681f3Smrg                                       false, "glGetActiveUniformsiv"))
178af69d88dSmrg         break;
179af69d88dSmrg   }
180af69d88dSmrg}
181af69d88dSmrg
182af69d88dSmrgstatic struct gl_uniform_storage *
18301e04c3fSmrgvalidate_uniform_parameters(GLint location, GLsizei count,
18401e04c3fSmrg                            unsigned *array_index,
18501e04c3fSmrg                            struct gl_context *ctx,
18601e04c3fSmrg                            struct gl_shader_program *shProg,
18701e04c3fSmrg                            const char *caller)
188af69d88dSmrg{
18901e04c3fSmrg   if (shProg == NULL) {
190af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
191af69d88dSmrg      return NULL;
192af69d88dSmrg   }
193af69d88dSmrg
194af69d88dSmrg   /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
195af69d88dSmrg    *
196af69d88dSmrg    *     "If a negative number is provided where an argument of type sizei or
197af69d88dSmrg    *     sizeiptr is specified, the error INVALID_VALUE is generated."
198af69d88dSmrg    */
199af69d88dSmrg   if (count < 0) {
200af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
201af69d88dSmrg      return NULL;
202af69d88dSmrg   }
203af69d88dSmrg
20401e04c3fSmrg   /* Check that the given location is in bounds of uniform remap table.
20501e04c3fSmrg    * Unlinked programs will have NumUniformRemapTable == 0, so we can take
20601e04c3fSmrg    * the shProg->data->LinkStatus check out of the main path.
20701e04c3fSmrg    */
20801e04c3fSmrg   if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
20901e04c3fSmrg      if (!shProg->data->LinkStatus)
21001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
21101e04c3fSmrg                     caller);
21201e04c3fSmrg      else
21301e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
21401e04c3fSmrg                     caller, location);
21501e04c3fSmrg
21601e04c3fSmrg      return NULL;
21701e04c3fSmrg   }
21801e04c3fSmrg
21901e04c3fSmrg   if (location == -1) {
22001e04c3fSmrg      if (!shProg->data->LinkStatus)
22101e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
22201e04c3fSmrg                     caller);
22301e04c3fSmrg
224af69d88dSmrg      return NULL;
225af69d88dSmrg   }
226af69d88dSmrg
227af69d88dSmrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
228af69d88dSmrg    *
229af69d88dSmrg    *     "If any of the following conditions occur, an INVALID_OPERATION
230af69d88dSmrg    *     error is generated by the Uniform* commands, and no uniform values
231af69d88dSmrg    *     are changed:
232af69d88dSmrg    *
233af69d88dSmrg    *     ...
234af69d88dSmrg    *
235af69d88dSmrg    *         - if no variable with a location of location exists in the
236af69d88dSmrg    *           program object currently in use and location is not -1,
237af69d88dSmrg    *         - if count is greater than one, and the uniform declared in the
238af69d88dSmrg    *           shader is not an array variable,
239af69d88dSmrg    */
240af69d88dSmrg   if (location < -1 || !shProg->UniformRemapTable[location]) {
241af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
242af69d88dSmrg                  caller, location);
243af69d88dSmrg      return NULL;
244af69d88dSmrg   }
245af69d88dSmrg
246af69d88dSmrg   /* If the driver storage pointer in remap table is -1, we ignore silently.
247af69d88dSmrg    *
248af69d88dSmrg    * GL_ARB_explicit_uniform_location spec says:
249af69d88dSmrg    *     "What happens if Uniform* is called with an explicitly defined
250af69d88dSmrg    *     uniform location, but that uniform is deemed inactive by the
251af69d88dSmrg    *     linker?
252af69d88dSmrg    *
253af69d88dSmrg    *     RESOLVED: The call is ignored for inactive uniform variables and
254af69d88dSmrg    *     no error is generated."
255af69d88dSmrg    *
256af69d88dSmrg    */
257af69d88dSmrg   if (shProg->UniformRemapTable[location] ==
258af69d88dSmrg       INACTIVE_UNIFORM_EXPLICIT_LOCATION)
259af69d88dSmrg      return NULL;
260af69d88dSmrg
261af69d88dSmrg   struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location];
262af69d88dSmrg
26301e04c3fSmrg   /* Even though no location is assigned to a built-in uniform and this
26401e04c3fSmrg    * function should already have returned NULL, this test makes it explicit
26501e04c3fSmrg    * that we are not allowing to update the value of a built-in.
26601e04c3fSmrg    */
26701e04c3fSmrg   if (uni->builtin)
268af69d88dSmrg      return NULL;
269af69d88dSmrg
27001e04c3fSmrg   if (uni->array_elements == 0) {
27101e04c3fSmrg      if (count > 1) {
27201e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
27301e04c3fSmrg                     "%s(count = %u for non-array \"%s\"@%d)",
27401e04c3fSmrg                     caller, count, uni->name, location);
27501e04c3fSmrg         return NULL;
27601e04c3fSmrg      }
277af69d88dSmrg
27801e04c3fSmrg      assert((location - uni->remap_location) == 0);
27901e04c3fSmrg      *array_index = 0;
28001e04c3fSmrg   } else {
28101e04c3fSmrg      /* The array index specified by the uniform location is just the uniform
28201e04c3fSmrg       * location minus the base location of of the uniform.
28301e04c3fSmrg       */
28401e04c3fSmrg      *array_index = location - uni->remap_location;
28501e04c3fSmrg
28601e04c3fSmrg      /* If the uniform is an array, check that array_index is in bounds.
28701e04c3fSmrg       * array_index is unsigned so no need to check for less than zero.
28801e04c3fSmrg       */
28901e04c3fSmrg      if (*array_index >= uni->array_elements) {
29001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
29101e04c3fSmrg                     caller, location);
29201e04c3fSmrg         return NULL;
29301e04c3fSmrg      }
294af69d88dSmrg   }
295af69d88dSmrg   return uni;
296af69d88dSmrg}
297af69d88dSmrg
298af69d88dSmrg/**
299af69d88dSmrg * Called via glGetUniform[fiui]v() to get the current value of a uniform.
300af69d88dSmrg */
301af69d88dSmrgextern "C" void
302af69d88dSmrg_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
303af69d88dSmrg		  GLsizei bufSize, enum glsl_base_type returnType,
304af69d88dSmrg		  GLvoid *paramsOut)
305af69d88dSmrg{
306af69d88dSmrg   struct gl_shader_program *shProg =
307af69d88dSmrg      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
308af69d88dSmrg   unsigned offset;
309af69d88dSmrg
310af69d88dSmrg   struct gl_uniform_storage *const uni =
31101e04c3fSmrg      validate_uniform_parameters(location, 1, &offset,
31201e04c3fSmrg                                  ctx, shProg, "glGetUniform");
31301e04c3fSmrg   if (uni == NULL) {
31401e04c3fSmrg      /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
31501e04c3fSmrg       * spec says:
31601e04c3fSmrg       *
31701e04c3fSmrg       *     "The error INVALID_OPERATION is generated if program has not been
31801e04c3fSmrg       *     linked successfully, or if location is not a valid location for
31901e04c3fSmrg       *     program."
32001e04c3fSmrg       *
32101e04c3fSmrg       * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
32201e04c3fSmrg       * says:
32301e04c3fSmrg       *
32401e04c3fSmrg       *     "If the value of location is -1, the Uniform* commands will
32501e04c3fSmrg       *     silently ignore the data passed in, and the current uniform
32601e04c3fSmrg       *     values will not be changed."
32701e04c3fSmrg       *
32801e04c3fSmrg       * Allowing -1 for the location parameter of glUniform allows
32901e04c3fSmrg       * applications to avoid error paths in the case that, for example, some
33001e04c3fSmrg       * uniform variable is removed by the compiler / linker after
33101e04c3fSmrg       * optimization.  In this case, the new value of the uniform is dropped
33201e04c3fSmrg       * on the floor.  For the case of glGetUniform, there is nothing
33301e04c3fSmrg       * sensible to do for a location of -1.
33401e04c3fSmrg       *
33501e04c3fSmrg       * If the location was -1, validate_unfirom_parameters will return NULL
33601e04c3fSmrg       * without raising an error.  Raise the error here.
33701e04c3fSmrg       */
33801e04c3fSmrg      if (location == -1) {
33901e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniform(location=%d)",
34001e04c3fSmrg                     location);
34101e04c3fSmrg      }
34201e04c3fSmrg
343af69d88dSmrg      return;
34401e04c3fSmrg   }
345af69d88dSmrg
346af69d88dSmrg   {
34701e04c3fSmrg      unsigned elements = uni->type->components();
3487ec681f3Smrg      unsigned components = uni->type->vector_elements;
3497ec681f3Smrg
35001e04c3fSmrg      const int rmul = glsl_base_type_is_64bit(returnType) ? 2 : 1;
35101e04c3fSmrg      int dmul = (uni->type->is_64bit()) ? 2 : 1;
35201e04c3fSmrg
35301e04c3fSmrg      if ((uni->type->is_sampler() || uni->type->is_image()) &&
35401e04c3fSmrg          !uni->is_bindless) {
35501e04c3fSmrg         /* Non-bindless samplers/images are represented using unsigned integer
35601e04c3fSmrg          * 32-bit, while bindless handles are 64-bit.
35701e04c3fSmrg          */
35801e04c3fSmrg         dmul = 1;
35901e04c3fSmrg      }
360af69d88dSmrg
361af69d88dSmrg      /* Calculate the source base address *BEFORE* modifying elements to
362af69d88dSmrg       * account for the size of the user's buffer.
363af69d88dSmrg       */
36401e04c3fSmrg      const union gl_constant_value *src;
36501e04c3fSmrg      if (ctx->Const.PackedDriverUniformStorage &&
36601e04c3fSmrg          (uni->is_bindless || !uni->type->contains_opaque())) {
3677ec681f3Smrg         unsigned dword_elements = elements;
3687ec681f3Smrg
3697ec681f3Smrg         /* 16-bit uniforms are packed. */
3707ec681f3Smrg         if (glsl_base_type_is_16bit(uni->type->base_type)) {
3717ec681f3Smrg            dword_elements = DIV_ROUND_UP(components, 2) *
3727ec681f3Smrg                             uni->type->matrix_columns;
3737ec681f3Smrg         }
3747ec681f3Smrg
37501e04c3fSmrg         src = (gl_constant_value *) uni->driver_storage[0].data +
3767ec681f3Smrg            (offset * dword_elements * dmul);
37701e04c3fSmrg      } else {
37801e04c3fSmrg         src = &uni->storage[offset * elements * dmul];
37901e04c3fSmrg      }
380af69d88dSmrg
381af69d88dSmrg      assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
38201e04c3fSmrg             returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE ||
38301e04c3fSmrg             returnType == GLSL_TYPE_UINT64 || returnType == GLSL_TYPE_INT64);
38401e04c3fSmrg
38501e04c3fSmrg      /* doubles have a different size than the other 3 types */
38601e04c3fSmrg      unsigned bytes = sizeof(src[0]) * elements * rmul;
387af69d88dSmrg      if (bufSize < 0 || bytes > (unsigned) bufSize) {
38801e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
38901e04c3fSmrg                     "glGetnUniform*vARB(out of bounds: bufSize is %d,"
39001e04c3fSmrg                     " but %u bytes are required)", bufSize, bytes);
39101e04c3fSmrg         return;
392af69d88dSmrg      }
393af69d88dSmrg
394af69d88dSmrg      /* If the return type and the uniform's native type are "compatible,"
395af69d88dSmrg       * just memcpy the data.  If the types are not compatible, perform a
396af69d88dSmrg       * slower convert-and-copy process.
397af69d88dSmrg       */
39801e04c3fSmrg      if (returnType == uni->type->base_type ||
39901e04c3fSmrg          ((returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT) &&
40001e04c3fSmrg           (uni->type->is_sampler() || uni->type->is_image())) ||
40101e04c3fSmrg          (returnType == GLSL_TYPE_UINT64 && uni->is_bindless)) {
40201e04c3fSmrg         memcpy(paramsOut, src, bytes);
403af69d88dSmrg      } else {
40401e04c3fSmrg         union gl_constant_value *const dst =
40501e04c3fSmrg            (union gl_constant_value *) paramsOut;
40601e04c3fSmrg         /* This code could be optimized by putting the loop inside the switch
40701e04c3fSmrg          * statements.  However, this is not expected to be
40801e04c3fSmrg          * performance-critical code.
40901e04c3fSmrg          */
41001e04c3fSmrg         for (unsigned i = 0; i < elements; i++) {
41101e04c3fSmrg            int sidx = i * dmul;
41201e04c3fSmrg            int didx = i * rmul;
41301e04c3fSmrg
4147ec681f3Smrg            if (glsl_base_type_is_16bit(uni->type->base_type)) {
4157ec681f3Smrg               unsigned column = i / components;
4167ec681f3Smrg               unsigned row = i % components;
4177ec681f3Smrg               sidx = column * align(components, 2) + row;
4187ec681f3Smrg            }
4197ec681f3Smrg
42001e04c3fSmrg            switch (returnType) {
42101e04c3fSmrg            case GLSL_TYPE_FLOAT:
42201e04c3fSmrg               switch (uni->type->base_type) {
4237ec681f3Smrg               case GLSL_TYPE_FLOAT16:
4247ec681f3Smrg                  dst[didx].f = _mesa_half_to_float(((uint16_t*)src)[sidx]);
4257ec681f3Smrg                  break;
42601e04c3fSmrg               case GLSL_TYPE_UINT:
42701e04c3fSmrg                  dst[didx].f = (float) src[sidx].u;
42801e04c3fSmrg                  break;
42901e04c3fSmrg               case GLSL_TYPE_INT:
43001e04c3fSmrg               case GLSL_TYPE_SAMPLER:
43101e04c3fSmrg               case GLSL_TYPE_IMAGE:
43201e04c3fSmrg                  dst[didx].f = (float) src[sidx].i;
43301e04c3fSmrg                  break;
43401e04c3fSmrg               case GLSL_TYPE_BOOL:
43501e04c3fSmrg                  dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
43601e04c3fSmrg                  break;
43701e04c3fSmrg               case GLSL_TYPE_DOUBLE: {
43801e04c3fSmrg                  double tmp;
43901e04c3fSmrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
44001e04c3fSmrg                  dst[didx].f = tmp;
44101e04c3fSmrg                  break;
44201e04c3fSmrg               }
44301e04c3fSmrg               case GLSL_TYPE_UINT64: {
44401e04c3fSmrg                  uint64_t tmp;
44501e04c3fSmrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
44601e04c3fSmrg                  dst[didx].f = tmp;
44701e04c3fSmrg                  break;
44801e04c3fSmrg                }
44901e04c3fSmrg               case GLSL_TYPE_INT64: {
45001e04c3fSmrg                  uint64_t tmp;
45101e04c3fSmrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
45201e04c3fSmrg                  dst[didx].f = tmp;
45301e04c3fSmrg                  break;
45401e04c3fSmrg               }
45501e04c3fSmrg               default:
45601e04c3fSmrg                  assert(!"Should not get here.");
45701e04c3fSmrg                  break;
45801e04c3fSmrg               }
45901e04c3fSmrg               break;
46001e04c3fSmrg
46101e04c3fSmrg            case GLSL_TYPE_DOUBLE:
46201e04c3fSmrg               switch (uni->type->base_type) {
4637ec681f3Smrg               case GLSL_TYPE_FLOAT16: {
4647ec681f3Smrg                  double f = _mesa_half_to_float(((uint16_t*)src)[sidx]);
4657ec681f3Smrg                  memcpy(&dst[didx].f, &f, sizeof(f));
4667ec681f3Smrg                  break;
4677ec681f3Smrg               }
46801e04c3fSmrg               case GLSL_TYPE_UINT: {
46901e04c3fSmrg                  double tmp = src[sidx].u;
47001e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
47101e04c3fSmrg                  break;
47201e04c3fSmrg               }
47301e04c3fSmrg               case GLSL_TYPE_INT:
47401e04c3fSmrg               case GLSL_TYPE_SAMPLER:
47501e04c3fSmrg               case GLSL_TYPE_IMAGE: {
47601e04c3fSmrg                  double tmp = src[sidx].i;
47701e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
47801e04c3fSmrg                  break;
47901e04c3fSmrg               }
48001e04c3fSmrg               case GLSL_TYPE_BOOL: {
48101e04c3fSmrg                  double tmp = src[sidx].i ? 1.0 : 0.0;
48201e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
48301e04c3fSmrg                  break;
48401e04c3fSmrg               }
48501e04c3fSmrg               case GLSL_TYPE_FLOAT: {
48601e04c3fSmrg                  double tmp = src[sidx].f;
48701e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
48801e04c3fSmrg                  break;
48901e04c3fSmrg               }
49001e04c3fSmrg               case GLSL_TYPE_UINT64: {
49101e04c3fSmrg                  uint64_t tmpu;
49201e04c3fSmrg                  double tmp;
49301e04c3fSmrg                  memcpy(&tmpu, &src[sidx].u, sizeof(tmpu));
49401e04c3fSmrg                  tmp = tmpu;
49501e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
49601e04c3fSmrg                  break;
49701e04c3fSmrg               }
49801e04c3fSmrg               case GLSL_TYPE_INT64: {
49901e04c3fSmrg                  int64_t tmpi;
50001e04c3fSmrg                  double tmp;
50101e04c3fSmrg                  memcpy(&tmpi, &src[sidx].i, sizeof(tmpi));
50201e04c3fSmrg                  tmp = tmpi;
50301e04c3fSmrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
50401e04c3fSmrg                  break;
50501e04c3fSmrg               }
50601e04c3fSmrg               default:
50701e04c3fSmrg                  assert(!"Should not get here.");
50801e04c3fSmrg                  break;
50901e04c3fSmrg               }
51001e04c3fSmrg               break;
51101e04c3fSmrg
51201e04c3fSmrg            case GLSL_TYPE_INT:
51301e04c3fSmrg               switch (uni->type->base_type) {
51401e04c3fSmrg               case GLSL_TYPE_FLOAT:
51501e04c3fSmrg                  /* While the GL 3.2 core spec doesn't explicitly
51601e04c3fSmrg                   * state how conversion of float uniforms to integer
51701e04c3fSmrg                   * values works, in section 6.2 "State Tables" on
51801e04c3fSmrg                   * page 267 it says:
51901e04c3fSmrg                   *
52001e04c3fSmrg                   *     "Unless otherwise specified, when floating
52101e04c3fSmrg                   *      point state is returned as integer values or
52201e04c3fSmrg                   *      integer state is returned as floating-point
52301e04c3fSmrg                   *      values it is converted in the fashion
52401e04c3fSmrg                   *      described in section 6.1.2"
52501e04c3fSmrg                   *
52601e04c3fSmrg                   * That section, on page 248, says:
52701e04c3fSmrg                   *
52801e04c3fSmrg                   *     "If GetIntegerv or GetInteger64v are called,
52901e04c3fSmrg                   *      a floating-point value is rounded to the
53001e04c3fSmrg                   *      nearest integer..."
53101e04c3fSmrg                   */
53201e04c3fSmrg                  dst[didx].i = (int64_t) roundf(src[sidx].f);
53301e04c3fSmrg                  break;
5347ec681f3Smrg               case GLSL_TYPE_FLOAT16:
5357ec681f3Smrg                  dst[didx].i =
5367ec681f3Smrg                     (int64_t)roundf(_mesa_half_to_float(((uint16_t*)src)[sidx]));
5377ec681f3Smrg                  break;
53801e04c3fSmrg               case GLSL_TYPE_BOOL:
53901e04c3fSmrg                  dst[didx].i = src[sidx].i ? 1 : 0;
54001e04c3fSmrg                  break;
54101e04c3fSmrg               case GLSL_TYPE_UINT:
54201e04c3fSmrg                  dst[didx].i = MIN2(src[sidx].i, INT_MAX);
54301e04c3fSmrg                  break;
54401e04c3fSmrg               case GLSL_TYPE_DOUBLE: {
54501e04c3fSmrg                  double tmp;
54601e04c3fSmrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
54701e04c3fSmrg                  dst[didx].i = (int64_t) round(tmp);
54801e04c3fSmrg                  break;
54901e04c3fSmrg               }
55001e04c3fSmrg               case GLSL_TYPE_UINT64: {
55101e04c3fSmrg                  uint64_t tmp;
55201e04c3fSmrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
55301e04c3fSmrg                  dst[didx].i = tmp;
55401e04c3fSmrg                  break;
55501e04c3fSmrg               }
55601e04c3fSmrg               case GLSL_TYPE_INT64: {
55701e04c3fSmrg                  int64_t tmp;
55801e04c3fSmrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
55901e04c3fSmrg                  dst[didx].i = tmp;
56001e04c3fSmrg                  break;
56101e04c3fSmrg               }
56201e04c3fSmrg               default:
56301e04c3fSmrg                  assert(!"Should not get here.");
56401e04c3fSmrg                  break;
56501e04c3fSmrg               }
56601e04c3fSmrg               break;
56701e04c3fSmrg
56801e04c3fSmrg            case GLSL_TYPE_UINT:
56901e04c3fSmrg               switch (uni->type->base_type) {
57001e04c3fSmrg               case GLSL_TYPE_FLOAT:
57101e04c3fSmrg                  /* The spec isn't terribly clear how to handle negative
57201e04c3fSmrg                   * values with an unsigned return type.
57301e04c3fSmrg                   *
57401e04c3fSmrg                   * GL 4.5 section 2.2.2 ("Data Conversions for State
57501e04c3fSmrg                   * Query Commands") says:
57601e04c3fSmrg                   *
57701e04c3fSmrg                   * "If a value is so large in magnitude that it cannot be
57801e04c3fSmrg                   *  represented by the returned data type, then the nearest
57901e04c3fSmrg                   *  value representable using the requested type is
58001e04c3fSmrg                   *  returned."
58101e04c3fSmrg                   */
58201e04c3fSmrg                  dst[didx].u = src[sidx].f < 0.0f ?
58301e04c3fSmrg                     0u : (uint32_t) roundf(src[sidx].f);
58401e04c3fSmrg                  break;
5857ec681f3Smrg               case GLSL_TYPE_FLOAT16: {
5867ec681f3Smrg                  float f = _mesa_half_to_float(((uint16_t*)src)[sidx]);
5877ec681f3Smrg                  dst[didx].u = f < 0.0f ? 0u : (uint32_t)roundf(f);
5887ec681f3Smrg                  break;
5897ec681f3Smrg               }
59001e04c3fSmrg               case GLSL_TYPE_BOOL:
59101e04c3fSmrg                  dst[didx].i = src[sidx].i ? 1 : 0;
59201e04c3fSmrg                  break;
59301e04c3fSmrg               case GLSL_TYPE_INT:
59401e04c3fSmrg                  dst[didx].i = MAX2(src[sidx].i, 0);
59501e04c3fSmrg                  break;
59601e04c3fSmrg               case GLSL_TYPE_DOUBLE: {
59701e04c3fSmrg                  double tmp;
59801e04c3fSmrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
59901e04c3fSmrg                  dst[didx].u = tmp < 0.0 ? 0u : (uint32_t) round(tmp);
60001e04c3fSmrg                  break;
60101e04c3fSmrg               }
60201e04c3fSmrg               case GLSL_TYPE_UINT64: {
60301e04c3fSmrg                  uint64_t tmp;
60401e04c3fSmrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
60501e04c3fSmrg                  dst[didx].i = MIN2(tmp, INT_MAX);
60601e04c3fSmrg                  break;
60701e04c3fSmrg               }
60801e04c3fSmrg               case GLSL_TYPE_INT64: {
60901e04c3fSmrg                  int64_t tmp;
61001e04c3fSmrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
61101e04c3fSmrg                  dst[didx].i = MAX2(tmp, 0);
61201e04c3fSmrg                  break;
61301e04c3fSmrg               }
61401e04c3fSmrg               default:
61501e04c3fSmrg                  unreachable("invalid uniform type");
61601e04c3fSmrg               }
61701e04c3fSmrg               break;
61801e04c3fSmrg
61901e04c3fSmrg            case GLSL_TYPE_INT64:
62001e04c3fSmrg               switch (uni->type->base_type) {
62101e04c3fSmrg               case GLSL_TYPE_UINT: {
62201e04c3fSmrg                  uint64_t tmp = src[sidx].u;
62301e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
62401e04c3fSmrg                  break;
62501e04c3fSmrg               }
62601e04c3fSmrg               case GLSL_TYPE_INT:
62701e04c3fSmrg               case GLSL_TYPE_SAMPLER:
62801e04c3fSmrg               case GLSL_TYPE_IMAGE: {
62901e04c3fSmrg                  int64_t tmp = src[sidx].i;
63001e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
63101e04c3fSmrg                  break;
63201e04c3fSmrg               }
63301e04c3fSmrg               case GLSL_TYPE_BOOL: {
63401e04c3fSmrg                  int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
63501e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
63601e04c3fSmrg                  break;
63701e04c3fSmrg               }
63801e04c3fSmrg               case GLSL_TYPE_UINT64: {
63901e04c3fSmrg                  uint64_t u64;
64001e04c3fSmrg                  memcpy(&u64, &src[sidx].u, sizeof(u64));
64101e04c3fSmrg                  int64_t tmp = MIN2(u64, INT_MAX);
64201e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
64301e04c3fSmrg                  break;
64401e04c3fSmrg               }
64501e04c3fSmrg               case GLSL_TYPE_FLOAT: {
64601e04c3fSmrg                  int64_t tmp = (int64_t) roundf(src[sidx].f);
64701e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
64801e04c3fSmrg                  break;
64901e04c3fSmrg               }
6507ec681f3Smrg               case GLSL_TYPE_FLOAT16: {
6517ec681f3Smrg                  float f = _mesa_half_to_float(((uint16_t*)src)[sidx]);
6527ec681f3Smrg                  int64_t tmp = (int64_t) roundf(f);
6537ec681f3Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
6547ec681f3Smrg                  break;
6557ec681f3Smrg               }
65601e04c3fSmrg               case GLSL_TYPE_DOUBLE: {
65701e04c3fSmrg                  double d;
65801e04c3fSmrg                  memcpy(&d, &src[sidx].f, sizeof(d));
65901e04c3fSmrg                  int64_t tmp = (int64_t) round(d);
66001e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
66101e04c3fSmrg                  break;
66201e04c3fSmrg               }
66301e04c3fSmrg               default:
66401e04c3fSmrg                  assert(!"Should not get here.");
66501e04c3fSmrg                  break;
66601e04c3fSmrg               }
66701e04c3fSmrg               break;
66801e04c3fSmrg
66901e04c3fSmrg            case GLSL_TYPE_UINT64:
67001e04c3fSmrg               switch (uni->type->base_type) {
67101e04c3fSmrg               case GLSL_TYPE_UINT: {
67201e04c3fSmrg                  uint64_t tmp = src[sidx].u;
67301e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
67401e04c3fSmrg                  break;
67501e04c3fSmrg               }
67601e04c3fSmrg               case GLSL_TYPE_INT:
67701e04c3fSmrg               case GLSL_TYPE_SAMPLER:
67801e04c3fSmrg               case GLSL_TYPE_IMAGE: {
67901e04c3fSmrg                  int64_t tmp = MAX2(src[sidx].i, 0);
68001e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
68101e04c3fSmrg                  break;
68201e04c3fSmrg               }
68301e04c3fSmrg               case GLSL_TYPE_BOOL: {
68401e04c3fSmrg                  int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
68501e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
68601e04c3fSmrg                  break;
68701e04c3fSmrg               }
68801e04c3fSmrg               case GLSL_TYPE_INT64: {
68901e04c3fSmrg                  uint64_t i64;
69001e04c3fSmrg                  memcpy(&i64, &src[sidx].i, sizeof(i64));
69101e04c3fSmrg                  uint64_t tmp = MAX2(i64, 0);
69201e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
69301e04c3fSmrg                  break;
69401e04c3fSmrg               }
69501e04c3fSmrg               case GLSL_TYPE_FLOAT: {
69601e04c3fSmrg                  uint64_t tmp = src[sidx].f < 0.0f ?
69701e04c3fSmrg                     0ull : (uint64_t) roundf(src[sidx].f);
69801e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
69901e04c3fSmrg                  break;
70001e04c3fSmrg               }
7017ec681f3Smrg               case GLSL_TYPE_FLOAT16: {
7027ec681f3Smrg                  float f = _mesa_half_to_float(((uint16_t*)src)[sidx]);
7037ec681f3Smrg                  uint64_t tmp = f < 0.0f ? 0ull : (uint64_t) roundf(f);
7047ec681f3Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
7057ec681f3Smrg                  break;
7067ec681f3Smrg               }
70701e04c3fSmrg               case GLSL_TYPE_DOUBLE: {
70801e04c3fSmrg                  double d;
70901e04c3fSmrg                  memcpy(&d, &src[sidx].f, sizeof(d));
71001e04c3fSmrg                  uint64_t tmp = (d < 0.0) ? 0ull : (uint64_t) round(d);
71101e04c3fSmrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
71201e04c3fSmrg                  break;
71301e04c3fSmrg               }
71401e04c3fSmrg               default:
71501e04c3fSmrg                  assert(!"Should not get here.");
71601e04c3fSmrg                  break;
71701e04c3fSmrg               }
71801e04c3fSmrg               break;
71901e04c3fSmrg
72001e04c3fSmrg            default:
72101e04c3fSmrg               assert(!"Should not get here.");
72201e04c3fSmrg               break;
72301e04c3fSmrg            }
72401e04c3fSmrg         }
725af69d88dSmrg      }
726af69d88dSmrg   }
727af69d88dSmrg}
728af69d88dSmrg
729af69d88dSmrgstatic void
730af69d88dSmrglog_uniform(const void *values, enum glsl_base_type basicType,
731af69d88dSmrg	    unsigned rows, unsigned cols, unsigned count,
732af69d88dSmrg	    bool transpose,
733af69d88dSmrg	    const struct gl_shader_program *shProg,
734af69d88dSmrg	    GLint location,
735af69d88dSmrg	    const struct gl_uniform_storage *uni)
736af69d88dSmrg{
737af69d88dSmrg
738af69d88dSmrg   const union gl_constant_value *v = (const union gl_constant_value *) values;
739af69d88dSmrg   const unsigned elems = rows * cols * count;
740af69d88dSmrg   const char *const extra = (cols == 1) ? "uniform" : "uniform matrix";
741af69d88dSmrg
742af69d88dSmrg   printf("Mesa: set program %u %s \"%s\" (loc %d, type \"%s\", "
743af69d88dSmrg	  "transpose = %s) to: ",
744af69d88dSmrg	  shProg->Name, extra, uni->name, location, uni->type->name,
745af69d88dSmrg	  transpose ? "true" : "false");
746af69d88dSmrg   for (unsigned i = 0; i < elems; i++) {
747af69d88dSmrg      if (i != 0 && ((i % rows) == 0))
748af69d88dSmrg	 printf(", ");
749af69d88dSmrg
750af69d88dSmrg      switch (basicType) {
751af69d88dSmrg      case GLSL_TYPE_UINT:
752af69d88dSmrg	 printf("%u ", v[i].u);
753af69d88dSmrg	 break;
754af69d88dSmrg      case GLSL_TYPE_INT:
755af69d88dSmrg	 printf("%d ", v[i].i);
756af69d88dSmrg	 break;
75701e04c3fSmrg      case GLSL_TYPE_UINT64: {
75801e04c3fSmrg         uint64_t tmp;
75901e04c3fSmrg         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
76001e04c3fSmrg         printf("%" PRIu64 " ", tmp);
76101e04c3fSmrg         break;
76201e04c3fSmrg      }
76301e04c3fSmrg      case GLSL_TYPE_INT64: {
76401e04c3fSmrg         int64_t tmp;
76501e04c3fSmrg         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
76601e04c3fSmrg         printf("%" PRId64 " ", tmp);
76701e04c3fSmrg         break;
76801e04c3fSmrg      }
769af69d88dSmrg      case GLSL_TYPE_FLOAT:
770af69d88dSmrg	 printf("%g ", v[i].f);
771af69d88dSmrg	 break;
77201e04c3fSmrg      case GLSL_TYPE_DOUBLE: {
77301e04c3fSmrg         double tmp;
77401e04c3fSmrg         memcpy(&tmp, &v[i * 2].f, sizeof(tmp));
77501e04c3fSmrg         printf("%g ", tmp);
77601e04c3fSmrg         break;
77701e04c3fSmrg      }
778af69d88dSmrg      default:
779af69d88dSmrg	 assert(!"Should not get here.");
780af69d88dSmrg	 break;
781af69d88dSmrg      }
782af69d88dSmrg   }
783af69d88dSmrg   printf("\n");
784af69d88dSmrg   fflush(stdout);
785af69d88dSmrg}
786af69d88dSmrg
787af69d88dSmrg#if 0
788af69d88dSmrgstatic void
789af69d88dSmrglog_program_parameters(const struct gl_shader_program *shProg)
790af69d88dSmrg{
791af69d88dSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
792af69d88dSmrg      if (shProg->_LinkedShaders[i] == NULL)
793af69d88dSmrg	 continue;
794af69d88dSmrg
795af69d88dSmrg      const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
796af69d88dSmrg
797af69d88dSmrg      printf("Program %d %s shader parameters:\n",
798af69d88dSmrg             shProg->Name, _mesa_shader_stage_to_string(i));
799af69d88dSmrg      for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
80001e04c3fSmrg         unsigned pvo = prog->Parameters->ParameterValueOffset[j];
80101e04c3fSmrg         printf("%s: %u %p %f %f %f %f\n",
802af69d88dSmrg		prog->Parameters->Parameters[j].Name,
80301e04c3fSmrg                pvo,
80401e04c3fSmrg                prog->Parameters->ParameterValues + pvo,
80501e04c3fSmrg                prog->Parameters->ParameterValues[pvo].f,
80601e04c3fSmrg                prog->Parameters->ParameterValues[pvo + 1].f,
80701e04c3fSmrg                prog->Parameters->ParameterValues[pvo + 2].f,
80801e04c3fSmrg                prog->Parameters->ParameterValues[pvo + 3].f);
809af69d88dSmrg      }
810af69d88dSmrg   }
811af69d88dSmrg   fflush(stdout);
812af69d88dSmrg}
813af69d88dSmrg#endif
814af69d88dSmrg
815af69d88dSmrg/**
816af69d88dSmrg * Propagate some values from uniform backing storage to driver storage
817af69d88dSmrg *
818af69d88dSmrg * Values propagated from uniform backing storage to driver storage
819af69d88dSmrg * have all format / type conversions previously requested by the
820af69d88dSmrg * driver applied.  This function is most often called by the
821af69d88dSmrg * implementations of \c glUniform1f, etc. and \c glUniformMatrix2f,
822af69d88dSmrg * etc.
823af69d88dSmrg *
824af69d88dSmrg * \param uni          Uniform whose data is to be propagated to driver storage
825af69d88dSmrg * \param array_index  If \c uni is an array, this is the element of
826af69d88dSmrg *                     the array to be propagated.
827af69d88dSmrg * \param count        Number of array elements to propagate.
828af69d88dSmrg */
829af69d88dSmrgextern "C" void
830af69d88dSmrg_mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
831af69d88dSmrg					   unsigned array_index,
832af69d88dSmrg					   unsigned count)
833af69d88dSmrg{
834af69d88dSmrg   unsigned i;
835af69d88dSmrg
83601e04c3fSmrg   const unsigned components = uni->type->vector_elements;
83701e04c3fSmrg   const unsigned vectors = uni->type->matrix_columns;
83801e04c3fSmrg   const int dmul = uni->type->is_64bit() ? 2 : 1;
839af69d88dSmrg
840af69d88dSmrg   /* Store the data in the driver's requested type in the driver's storage
841af69d88dSmrg    * areas.
842af69d88dSmrg    */
84301e04c3fSmrg   unsigned src_vector_byte_stride = components * 4 * dmul;
844af69d88dSmrg
845af69d88dSmrg   for (i = 0; i < uni->num_driver_storage; i++) {
846af69d88dSmrg      struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
847af69d88dSmrg      uint8_t *dst = (uint8_t *) store->data;
848af69d88dSmrg      const unsigned extra_stride =
849af69d88dSmrg	 store->element_stride - (vectors * store->vector_stride);
850af69d88dSmrg      const uint8_t *src =
85101e04c3fSmrg	 (uint8_t *) (&uni->storage[array_index * (dmul * components * vectors)].i);
852af69d88dSmrg
853af69d88dSmrg#if 0
854af69d88dSmrg      printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
855af69d88dSmrg	     "extra_stride=%u\n",
856af69d88dSmrg	     __func__, dst, array_index, components,
857af69d88dSmrg	     vectors, count, store->vector_stride, extra_stride);
858af69d88dSmrg#endif
859af69d88dSmrg
860af69d88dSmrg      dst += array_index * store->element_stride;
861af69d88dSmrg
862af69d88dSmrg      switch (store->format) {
86301e04c3fSmrg      case uniform_native: {
864af69d88dSmrg	 unsigned j;
865af69d88dSmrg	 unsigned v;
866af69d88dSmrg
86701e04c3fSmrg	 if (src_vector_byte_stride == store->vector_stride) {
86801e04c3fSmrg	    if (extra_stride) {
86901e04c3fSmrg	       for (j = 0; j < count; j++) {
87001e04c3fSmrg	          memcpy(dst, src, src_vector_byte_stride * vectors);
87101e04c3fSmrg	          src += src_vector_byte_stride * vectors;
87201e04c3fSmrg	          dst += store->vector_stride * vectors;
873af69d88dSmrg
87401e04c3fSmrg	          dst += extra_stride;
875af69d88dSmrg	       }
87601e04c3fSmrg	    } else {
87701e04c3fSmrg	       /* Unigine Heaven benchmark gets here */
87801e04c3fSmrg	       memcpy(dst, src, src_vector_byte_stride * vectors * count);
87901e04c3fSmrg	       src += src_vector_byte_stride * vectors * count;
88001e04c3fSmrg	       dst += store->vector_stride * vectors * count;
881af69d88dSmrg	    }
88201e04c3fSmrg	 } else {
88301e04c3fSmrg	    for (j = 0; j < count; j++) {
88401e04c3fSmrg	       for (v = 0; v < vectors; v++) {
88501e04c3fSmrg	          memcpy(dst, src, src_vector_byte_stride);
88601e04c3fSmrg	          src += src_vector_byte_stride;
88701e04c3fSmrg	          dst += store->vector_stride;
88801e04c3fSmrg	       }
889af69d88dSmrg
89001e04c3fSmrg	       dst += extra_stride;
89101e04c3fSmrg	    }
892af69d88dSmrg	 }
893af69d88dSmrg	 break;
894af69d88dSmrg      }
895af69d88dSmrg
89601e04c3fSmrg      case uniform_int_float: {
897af69d88dSmrg	 const int *isrc = (const int *) src;
898af69d88dSmrg	 unsigned j;
899af69d88dSmrg	 unsigned v;
900af69d88dSmrg	 unsigned c;
901af69d88dSmrg
902af69d88dSmrg	 for (j = 0; j < count; j++) {
903af69d88dSmrg	    for (v = 0; v < vectors; v++) {
904af69d88dSmrg	       for (c = 0; c < components; c++) {
90501e04c3fSmrg		  ((float *) dst)[c] = (float) *isrc;
906af69d88dSmrg		  isrc++;
907af69d88dSmrg	       }
908af69d88dSmrg
909af69d88dSmrg	       dst += store->vector_stride;
910af69d88dSmrg	    }
911af69d88dSmrg
912af69d88dSmrg	    dst += extra_stride;
913af69d88dSmrg	 }
914af69d88dSmrg	 break;
915af69d88dSmrg      }
916af69d88dSmrg
917af69d88dSmrg      default:
918af69d88dSmrg	 assert(!"Should not get here.");
919af69d88dSmrg	 break;
920af69d88dSmrg      }
921af69d88dSmrg   }
922af69d88dSmrg}
923af69d88dSmrg
92401e04c3fSmrg
925af69d88dSmrg/**
92601e04c3fSmrg * Return printable string for a given GLSL_TYPE_x
927af69d88dSmrg */
92801e04c3fSmrgstatic const char *
92901e04c3fSmrgglsl_type_name(enum glsl_base_type type)
930af69d88dSmrg{
93101e04c3fSmrg   switch (type) {
93201e04c3fSmrg   case GLSL_TYPE_UINT:
93301e04c3fSmrg      return "uint";
93401e04c3fSmrg   case GLSL_TYPE_INT:
93501e04c3fSmrg      return "int";
93601e04c3fSmrg   case GLSL_TYPE_FLOAT:
93701e04c3fSmrg      return "float";
93801e04c3fSmrg   case GLSL_TYPE_DOUBLE:
93901e04c3fSmrg      return "double";
94001e04c3fSmrg   case GLSL_TYPE_UINT64:
94101e04c3fSmrg      return "uint64";
94201e04c3fSmrg   case GLSL_TYPE_INT64:
94301e04c3fSmrg      return "int64";
94401e04c3fSmrg   case GLSL_TYPE_BOOL:
94501e04c3fSmrg      return "bool";
94601e04c3fSmrg   case GLSL_TYPE_SAMPLER:
94701e04c3fSmrg      return "sampler";
94801e04c3fSmrg   case GLSL_TYPE_IMAGE:
94901e04c3fSmrg      return "image";
95001e04c3fSmrg   case GLSL_TYPE_ATOMIC_UINT:
95101e04c3fSmrg      return "atomic_uint";
95201e04c3fSmrg   case GLSL_TYPE_STRUCT:
95301e04c3fSmrg      return "struct";
95401e04c3fSmrg   case GLSL_TYPE_INTERFACE:
95501e04c3fSmrg      return "interface";
95601e04c3fSmrg   case GLSL_TYPE_ARRAY:
95701e04c3fSmrg      return "array";
95801e04c3fSmrg   case GLSL_TYPE_VOID:
95901e04c3fSmrg      return "void";
96001e04c3fSmrg   case GLSL_TYPE_ERROR:
96101e04c3fSmrg      return "error";
96201e04c3fSmrg   default:
96301e04c3fSmrg      return "other";
96401e04c3fSmrg   }
96501e04c3fSmrg}
966af69d88dSmrg
96701e04c3fSmrg
96801e04c3fSmrgstatic struct gl_uniform_storage *
96901e04c3fSmrgvalidate_uniform(GLint location, GLsizei count, const GLvoid *values,
97001e04c3fSmrg                 unsigned *offset, struct gl_context *ctx,
97101e04c3fSmrg                 struct gl_shader_program *shProg,
97201e04c3fSmrg                 enum glsl_base_type basicType, unsigned src_components)
97301e04c3fSmrg{
974af69d88dSmrg   struct gl_uniform_storage *const uni =
97501e04c3fSmrg      validate_uniform_parameters(location, count, offset,
97601e04c3fSmrg                                  ctx, shProg, "glUniform");
977af69d88dSmrg   if (uni == NULL)
97801e04c3fSmrg      return NULL;
979af69d88dSmrg
98001e04c3fSmrg   if (uni->type->is_matrix()) {
98101e04c3fSmrg      /* Can't set matrix uniforms (like mat4) with glUniform */
98201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
98301e04c3fSmrg                  "glUniform%u(uniform \"%s\"@%d is matrix)",
98401e04c3fSmrg                  src_components, uni->name, location);
98501e04c3fSmrg      return NULL;
986af69d88dSmrg   }
987af69d88dSmrg
98801e04c3fSmrg   /* Verify that the types are compatible. */
98901e04c3fSmrg   const unsigned components = uni->type->vector_elements;
99001e04c3fSmrg
99101e04c3fSmrg   if (components != src_components) {
99201e04c3fSmrg      /* glUniformN() must match float/vecN type */
99301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
99401e04c3fSmrg                  "glUniform%u(\"%s\"@%u has %u components, not %u)",
99501e04c3fSmrg                  src_components, uni->name, location,
99601e04c3fSmrg                  components, src_components);
99701e04c3fSmrg      return NULL;
998af69d88dSmrg   }
999af69d88dSmrg
1000af69d88dSmrg   bool match;
1001af69d88dSmrg   switch (uni->type->base_type) {
1002af69d88dSmrg   case GLSL_TYPE_BOOL:
100301e04c3fSmrg      match = (basicType != GLSL_TYPE_DOUBLE);
1004af69d88dSmrg      break;
1005af69d88dSmrg   case GLSL_TYPE_SAMPLER:
1006af69d88dSmrg      match = (basicType == GLSL_TYPE_INT);
1007af69d88dSmrg      break;
100801e04c3fSmrg   case GLSL_TYPE_IMAGE:
100901e04c3fSmrg      match = (basicType == GLSL_TYPE_INT && _mesa_is_desktop_gl(ctx));
101001e04c3fSmrg      break;
10117ec681f3Smrg   case GLSL_TYPE_FLOAT16:
10127ec681f3Smrg      match = basicType == GLSL_TYPE_FLOAT;
10137ec681f3Smrg      break;
1014af69d88dSmrg   default:
1015af69d88dSmrg      match = (basicType == uni->type->base_type);
1016af69d88dSmrg      break;
1017af69d88dSmrg   }
1018af69d88dSmrg
101901e04c3fSmrg   if (!match) {
102001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
102101e04c3fSmrg                  "glUniform%u(\"%s\"@%d is %s, not %s)",
102201e04c3fSmrg                  src_components, uni->name, location,
102301e04c3fSmrg                  glsl_type_name(uni->type->base_type),
102401e04c3fSmrg                  glsl_type_name(basicType));
102501e04c3fSmrg      return NULL;
1026af69d88dSmrg   }
1027af69d88dSmrg
102801e04c3fSmrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
1029af69d88dSmrg      log_uniform(values, basicType, components, 1, count,
103001e04c3fSmrg                  false, shProg, location, uni);
1031af69d88dSmrg   }
1032af69d88dSmrg
1033af69d88dSmrg   /* Page 100 (page 116 of the PDF) of the OpenGL 3.0 spec says:
1034af69d88dSmrg    *
1035af69d88dSmrg    *     "Setting a sampler's value to i selects texture image unit number
1036af69d88dSmrg    *     i. The values of i range from zero to the implementation- dependent
1037af69d88dSmrg    *     maximum supported number of texture image units."
1038af69d88dSmrg    *
1039af69d88dSmrg    * In addition, table 2.3, "Summary of GL errors," on page 17 (page 33 of
1040af69d88dSmrg    * the PDF) says:
1041af69d88dSmrg    *
1042af69d88dSmrg    *     "Error         Description                    Offending command
1043af69d88dSmrg    *                                                   ignored?
1044af69d88dSmrg    *     ...
1045af69d88dSmrg    *     INVALID_VALUE  Numeric argument out of range  Yes"
1046af69d88dSmrg    *
1047af69d88dSmrg    * Based on that, when an invalid sampler is specified, we generate a
1048af69d88dSmrg    * GL_INVALID_VALUE error and ignore the command.
1049af69d88dSmrg    */
1050af69d88dSmrg   if (uni->type->is_sampler()) {
105101e04c3fSmrg      for (int i = 0; i < count; i++) {
105201e04c3fSmrg         const unsigned texUnit = ((unsigned *) values)[i];
1053af69d88dSmrg
1054af69d88dSmrg         /* check that the sampler (tex unit index) is legal */
1055af69d88dSmrg         if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1056af69d88dSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
1057af69d88dSmrg                        "glUniform1i(invalid sampler/tex unit index for "
105801e04c3fSmrg                        "uniform %d)", location);
105901e04c3fSmrg            return NULL;
1060af69d88dSmrg         }
1061af69d88dSmrg      }
106201e04c3fSmrg      /* We need to reset the validate flag on changes to samplers in case
106301e04c3fSmrg       * two different sampler types are set to the same texture unit.
106401e04c3fSmrg       */
10657ec681f3Smrg      ctx->_Shader->Validated = ctx->_Shader->UserValidated = GL_FALSE;
1066af69d88dSmrg   }
1067af69d88dSmrg
1068af69d88dSmrg   if (uni->type->is_image()) {
106901e04c3fSmrg      for (int i = 0; i < count; i++) {
1070af69d88dSmrg         const int unit = ((GLint *) values)[i];
1071af69d88dSmrg
1072af69d88dSmrg         /* check that the image unit is legal */
1073af69d88dSmrg         if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) {
1074af69d88dSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
1075af69d88dSmrg                        "glUniform1i(invalid image unit index for uniform %d)",
1076af69d88dSmrg                        location);
107701e04c3fSmrg            return NULL;
1078af69d88dSmrg         }
1079af69d88dSmrg      }
1080af69d88dSmrg   }
1081af69d88dSmrg
108201e04c3fSmrg   return uni;
108301e04c3fSmrg}
108401e04c3fSmrg
108501e04c3fSmrgvoid
108601e04c3fSmrg_mesa_flush_vertices_for_uniforms(struct gl_context *ctx,
108701e04c3fSmrg                                  const struct gl_uniform_storage *uni)
108801e04c3fSmrg{
108901e04c3fSmrg   /* Opaque uniforms have no storage unless they are bindless */
109001e04c3fSmrg   if (!uni->is_bindless && uni->type->contains_opaque()) {
10917ec681f3Smrg      /* Samplers flush on demand and ignore redundant updates. */
10927ec681f3Smrg      if (!uni->type->is_sampler())
10937ec681f3Smrg         FLUSH_VERTICES(ctx, 0, 0);
109401e04c3fSmrg      return;
109501e04c3fSmrg   }
109601e04c3fSmrg
109701e04c3fSmrg   uint64_t new_driver_state = 0;
109801e04c3fSmrg   unsigned mask = uni->active_shader_mask;
109901e04c3fSmrg
110001e04c3fSmrg   while (mask) {
110101e04c3fSmrg      unsigned index = u_bit_scan(&mask);
110201e04c3fSmrg
110301e04c3fSmrg      assert(index < MESA_SHADER_STAGES);
110401e04c3fSmrg      new_driver_state |= ctx->DriverFlags.NewShaderConstants[index];
110501e04c3fSmrg   }
110601e04c3fSmrg
11077ec681f3Smrg   FLUSH_VERTICES(ctx, new_driver_state ? 0 : _NEW_PROGRAM_CONSTANTS, 0);
110801e04c3fSmrg   ctx->NewDriverState |= new_driver_state;
110901e04c3fSmrg}
111001e04c3fSmrg
11117ec681f3Smrgstatic bool
111201e04c3fSmrgcopy_uniforms_to_storage(gl_constant_value *storage,
111301e04c3fSmrg                         struct gl_uniform_storage *uni,
111401e04c3fSmrg                         struct gl_context *ctx, GLsizei count,
111501e04c3fSmrg                         const GLvoid *values, const int size_mul,
111601e04c3fSmrg                         const unsigned offset, const unsigned components,
11177ec681f3Smrg                         enum glsl_base_type basicType, bool flush)
111801e04c3fSmrg{
11197ec681f3Smrg   const gl_constant_value *src = (const gl_constant_value*)values;
11207ec681f3Smrg   bool copy_as_uint64 = uni->is_bindless &&
11217ec681f3Smrg                         (uni->type->is_sampler() || uni->type->is_image());
11227ec681f3Smrg   bool copy_to_float16 = uni->type->base_type == GLSL_TYPE_FLOAT16;
11237ec681f3Smrg
11247ec681f3Smrg   if (!uni->type->is_boolean() && !copy_as_uint64 && !copy_to_float16) {
11257ec681f3Smrg      unsigned size = sizeof(storage[0]) * components * count * size_mul;
11267ec681f3Smrg
11277ec681f3Smrg      if (!memcmp(storage, values, size))
11287ec681f3Smrg         return false;
112901e04c3fSmrg
11307ec681f3Smrg      if (flush)
11317ec681f3Smrg         _mesa_flush_vertices_for_uniforms(ctx, uni);
11327ec681f3Smrg
11337ec681f3Smrg      memcpy(storage, values, size);
11347ec681f3Smrg      return true;
11357ec681f3Smrg   } else if (copy_to_float16) {
11367ec681f3Smrg      assert(ctx->Const.PackedDriverUniformStorage);
11377ec681f3Smrg      const unsigned dst_components = align(components, 2);
11387ec681f3Smrg      uint16_t *dst = (uint16_t*)storage;
11397ec681f3Smrg
11407ec681f3Smrg      int i = 0;
11417ec681f3Smrg      unsigned c = 0;
11427ec681f3Smrg
11437ec681f3Smrg      if (flush) {
11447ec681f3Smrg         /* Find the first element that's different. */
11457ec681f3Smrg         for (; i < count; i++) {
11467ec681f3Smrg            for (; c < components; c++) {
11477ec681f3Smrg               if (dst[c] != _mesa_float_to_half(src[c].f)) {
11487ec681f3Smrg                  _mesa_flush_vertices_for_uniforms(ctx, uni);
11497ec681f3Smrg                  flush = false;
11507ec681f3Smrg                  goto break_loops;
11517ec681f3Smrg               }
11527ec681f3Smrg            }
11537ec681f3Smrg            c = 0;
11547ec681f3Smrg            dst += dst_components;
11557ec681f3Smrg            src += components;
11567ec681f3Smrg         }
11577ec681f3Smrg      break_loops:
11587ec681f3Smrg         if (flush)
11597ec681f3Smrg            return false; /* No change. */
116001e04c3fSmrg      }
11617ec681f3Smrg
11627ec681f3Smrg      /* Set the remaining elements. We know that at least 1 element is
11637ec681f3Smrg       * different and that we have flushed.
11647ec681f3Smrg       */
11657ec681f3Smrg      for (; i < count; i++) {
11667ec681f3Smrg         for (; c < components; c++)
11677ec681f3Smrg            dst[c] = _mesa_float_to_half(src[c].f);
11687ec681f3Smrg
11697ec681f3Smrg         c = 0;
11707ec681f3Smrg         dst += dst_components;
11717ec681f3Smrg         src += components;
11727ec681f3Smrg      }
11737ec681f3Smrg
11747ec681f3Smrg      return true;
11757ec681f3Smrg   } else if (copy_as_uint64) {
11767ec681f3Smrg      const unsigned elems = components * count;
11777ec681f3Smrg      uint64_t *dst = (uint64_t*)storage;
11787ec681f3Smrg      unsigned i = 0;
11797ec681f3Smrg
11807ec681f3Smrg      if (flush) {
11817ec681f3Smrg         /* Find the first element that's different. */
11827ec681f3Smrg         for (; i < elems; i++) {
11837ec681f3Smrg            if (dst[i] != src[i].u) {
11847ec681f3Smrg               _mesa_flush_vertices_for_uniforms(ctx, uni);
11857ec681f3Smrg               flush = false;
11867ec681f3Smrg               break;
11877ec681f3Smrg            }
11887ec681f3Smrg         }
11897ec681f3Smrg         if (flush)
11907ec681f3Smrg            return false; /* No change. */
11917ec681f3Smrg      }
11927ec681f3Smrg
11937ec681f3Smrg      /* Set the remaining elements. We know that at least 1 element is
11947ec681f3Smrg       * different and that we have flushed.
11957ec681f3Smrg       */
11967ec681f3Smrg      for (; i < elems; i++)
11977ec681f3Smrg         dst[i] = src[i].u;
11987ec681f3Smrg
11997ec681f3Smrg      return true;
120001e04c3fSmrg   } else {
120101e04c3fSmrg      const unsigned elems = components * count;
12027ec681f3Smrg      gl_constant_value *dst = storage;
12037ec681f3Smrg
12047ec681f3Smrg      if (basicType == GLSL_TYPE_FLOAT) {
12057ec681f3Smrg         unsigned i = 0;
12067ec681f3Smrg
12077ec681f3Smrg         if (flush) {
12087ec681f3Smrg            /* Find the first element that's different. */
12097ec681f3Smrg            for (; i < elems; i++) {
12107ec681f3Smrg               if (dst[i].u !=
12117ec681f3Smrg                   (src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0)) {
12127ec681f3Smrg                  _mesa_flush_vertices_for_uniforms(ctx, uni);
12137ec681f3Smrg                  flush = false;
12147ec681f3Smrg                  break;
12157ec681f3Smrg               }
12167ec681f3Smrg            }
12177ec681f3Smrg            if (flush)
12187ec681f3Smrg               return false; /* No change. */
12197ec681f3Smrg         }
12207ec681f3Smrg
12217ec681f3Smrg         /* Set the remaining elements. We know that at least 1 element is
12227ec681f3Smrg          * different and that we have flushed.
12237ec681f3Smrg          */
12247ec681f3Smrg         for (; i < elems; i++)
12257ec681f3Smrg            dst[i].u = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
122601e04c3fSmrg
12277ec681f3Smrg         return true;
12287ec681f3Smrg      } else {
12297ec681f3Smrg         unsigned i = 0;
12307ec681f3Smrg
12317ec681f3Smrg         if (flush) {
12327ec681f3Smrg            /* Find the first element that's different. */
12337ec681f3Smrg            for (; i < elems; i++) {
12347ec681f3Smrg               if (dst[i].u !=
12357ec681f3Smrg                   (src[i].u ? ctx->Const.UniformBooleanTrue : 0)) {
12367ec681f3Smrg                  _mesa_flush_vertices_for_uniforms(ctx, uni);
12377ec681f3Smrg                  flush = false;
12387ec681f3Smrg                  break;
12397ec681f3Smrg               }
12407ec681f3Smrg            }
12417ec681f3Smrg            if (flush)
12427ec681f3Smrg               return false; /* No change. */
124301e04c3fSmrg         }
12447ec681f3Smrg
12457ec681f3Smrg         /* Set the remaining elements. We know that at least 1 element is
12467ec681f3Smrg          * different and that we have flushed.
12477ec681f3Smrg          */
12487ec681f3Smrg         for (; i < elems; i++)
12497ec681f3Smrg            dst[i].u = src[i].u ? ctx->Const.UniformBooleanTrue : 0;
12507ec681f3Smrg
12517ec681f3Smrg         return true;
125201e04c3fSmrg      }
125301e04c3fSmrg   }
125401e04c3fSmrg}
125501e04c3fSmrg
125601e04c3fSmrg
125701e04c3fSmrg/**
125801e04c3fSmrg * Called via glUniform*() functions.
125901e04c3fSmrg */
126001e04c3fSmrgextern "C" void
126101e04c3fSmrg_mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
126201e04c3fSmrg              struct gl_context *ctx, struct gl_shader_program *shProg,
126301e04c3fSmrg              enum glsl_base_type basicType, unsigned src_components)
126401e04c3fSmrg{
126501e04c3fSmrg   unsigned offset;
126601e04c3fSmrg   int size_mul = glsl_base_type_is_64bit(basicType) ? 2 : 1;
126701e04c3fSmrg
126801e04c3fSmrg   struct gl_uniform_storage *uni;
126901e04c3fSmrg   if (_mesa_is_no_error_enabled(ctx)) {
127001e04c3fSmrg      /* From Seciton 7.6 (UNIFORM VARIABLES) of the OpenGL 4.5 spec:
127101e04c3fSmrg       *
127201e04c3fSmrg       *   "If the value of location is -1, the Uniform* commands will
127301e04c3fSmrg       *   silently ignore the data passed in, and the current uniform values
127401e04c3fSmrg       *   will not be changed.
127501e04c3fSmrg       */
127601e04c3fSmrg      if (location == -1)
127701e04c3fSmrg         return;
127801e04c3fSmrg
12797ec681f3Smrg      if (location >= (int)shProg->NumUniformRemapTable)
12807ec681f3Smrg         return;
12817ec681f3Smrg
128201e04c3fSmrg      uni = shProg->UniformRemapTable[location];
12837ec681f3Smrg      if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
12847ec681f3Smrg         return;
128501e04c3fSmrg
128601e04c3fSmrg      /* The array index specified by the uniform location is just the
128701e04c3fSmrg       * uniform location minus the base location of of the uniform.
128801e04c3fSmrg       */
128901e04c3fSmrg      assert(uni->array_elements > 0 || location == (int)uni->remap_location);
129001e04c3fSmrg      offset = location - uni->remap_location;
129101e04c3fSmrg   } else {
129201e04c3fSmrg      uni = validate_uniform(location, count, values, &offset, ctx, shProg,
129301e04c3fSmrg                             basicType, src_components);
129401e04c3fSmrg      if (!uni)
129501e04c3fSmrg         return;
129601e04c3fSmrg   }
129701e04c3fSmrg
129801e04c3fSmrg   const unsigned components = uni->type->vector_elements;
129901e04c3fSmrg
1300af69d88dSmrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
1301af69d88dSmrg    *
1302af69d88dSmrg    *     "When loading N elements starting at an arbitrary position k in a
1303af69d88dSmrg    *     uniform declared as an array, elements k through k + N - 1 in the
1304af69d88dSmrg    *     array will be replaced with the new values. Values for any array
1305af69d88dSmrg    *     element that exceeds the highest array element index used, as
1306af69d88dSmrg    *     reported by GetActiveUniform, will be ignored by the GL."
1307af69d88dSmrg    *
1308af69d88dSmrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
1309af69d88dSmrg    * will have already generated an error.
1310af69d88dSmrg    */
1311af69d88dSmrg   if (uni->array_elements != 0) {
1312af69d88dSmrg      count = MIN2(count, (int) (uni->array_elements - offset));
1313af69d88dSmrg   }
1314af69d88dSmrg
1315af69d88dSmrg   /* Store the data in the "actual type" backing storage for the uniform.
1316af69d88dSmrg    */
13177ec681f3Smrg   bool ctx_flushed = false;
131801e04c3fSmrg   gl_constant_value *storage;
131901e04c3fSmrg   if (ctx->Const.PackedDriverUniformStorage &&
132001e04c3fSmrg       (uni->is_bindless || !uni->type->contains_opaque())) {
132101e04c3fSmrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
13227ec681f3Smrg         unsigned dword_components = components;
13237ec681f3Smrg
13247ec681f3Smrg         /* 16-bit uniforms are packed. */
13257ec681f3Smrg         if (glsl_base_type_is_16bit(uni->type->base_type))
13267ec681f3Smrg            dword_components = DIV_ROUND_UP(dword_components, 2);
13277ec681f3Smrg
132801e04c3fSmrg         storage = (gl_constant_value *)
13297ec681f3Smrg            uni->driver_storage[s].data + (size_mul * offset * dword_components);
133001e04c3fSmrg
13317ec681f3Smrg         if (copy_uniforms_to_storage(storage, uni, ctx, count, values, size_mul,
13327ec681f3Smrg                                      offset, components, basicType, !ctx_flushed))
13337ec681f3Smrg            ctx_flushed = true;
133401e04c3fSmrg      }
1335af69d88dSmrg   } else {
133601e04c3fSmrg      storage = &uni->storage[size_mul * components * offset];
13377ec681f3Smrg      if (copy_uniforms_to_storage(storage, uni, ctx, count, values, size_mul,
13387ec681f3Smrg                                   offset, components, basicType, !ctx_flushed)) {
13397ec681f3Smrg         _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
13407ec681f3Smrg         ctx_flushed = true;
13417ec681f3Smrg      }
1342af69d88dSmrg   }
13437ec681f3Smrg   /* Return early if possible. Bindless samplers need to be processed
13447ec681f3Smrg    * because of the !sampler->bound codepath below.
13457ec681f3Smrg    */
13467ec681f3Smrg   if (!ctx_flushed && !(uni->type->is_sampler() && uni->is_bindless))
13477ec681f3Smrg      return; /* no change in uniform values */
1348af69d88dSmrg
1349af69d88dSmrg   /* If the uniform is a sampler, do the extra magic necessary to propagate
1350af69d88dSmrg    * the changes through.
1351af69d88dSmrg    */
1352af69d88dSmrg   if (uni->type->is_sampler()) {
13537ec681f3Smrg      /* Note that samplers are the only uniforms that don't call
13547ec681f3Smrg       * FLUSH_VERTICES above.
13557ec681f3Smrg       */
1356af69d88dSmrg      bool flushed = false;
13577ec681f3Smrg      bool any_changed = false;
1358af69d88dSmrg
135901e04c3fSmrg      shProg->SamplersValidated = GL_TRUE;
1360af69d88dSmrg
136101e04c3fSmrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
136201e04c3fSmrg         struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
1363af69d88dSmrg
136401e04c3fSmrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
136501e04c3fSmrg         if (!uni->opaque[i].active)
136601e04c3fSmrg            continue;
1367af69d88dSmrg
136801e04c3fSmrg         bool changed = false;
136901e04c3fSmrg         for (int j = 0; j < count; j++) {
137001e04c3fSmrg            unsigned unit = uni->opaque[i].index + offset + j;
137101e04c3fSmrg            unsigned value = ((unsigned *)values)[j];
137201e04c3fSmrg
137301e04c3fSmrg            if (uni->is_bindless) {
137401e04c3fSmrg               struct gl_bindless_sampler *sampler =
137501e04c3fSmrg                  &sh->Program->sh.BindlessSamplers[unit];
137601e04c3fSmrg
137701e04c3fSmrg               /* Mark this bindless sampler as bound to a texture unit.
137801e04c3fSmrg                */
137901e04c3fSmrg               if (sampler->unit != value || !sampler->bound) {
13807ec681f3Smrg                  if (!flushed) {
13817ec681f3Smrg                     FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT | _NEW_PROGRAM, 0);
13827ec681f3Smrg                     flushed = true;
13837ec681f3Smrg                  }
138401e04c3fSmrg                  sampler->unit = value;
138501e04c3fSmrg                  changed = true;
138601e04c3fSmrg               }
138701e04c3fSmrg               sampler->bound = true;
138801e04c3fSmrg               sh->Program->sh.HasBoundBindlessSampler = true;
138901e04c3fSmrg            } else {
139001e04c3fSmrg               if (sh->Program->SamplerUnits[unit] != value) {
13917ec681f3Smrg                  if (!flushed) {
13927ec681f3Smrg                     FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT | _NEW_PROGRAM, 0);
13937ec681f3Smrg                     flushed = true;
13947ec681f3Smrg                  }
139501e04c3fSmrg                  sh->Program->SamplerUnits[unit] = value;
139601e04c3fSmrg                  changed = true;
139701e04c3fSmrg               }
139801e04c3fSmrg            }
139901e04c3fSmrg         }
1400af69d88dSmrg
140101e04c3fSmrg         if (changed) {
140201e04c3fSmrg            struct gl_program *const prog = sh->Program;
140301e04c3fSmrg            _mesa_update_shader_textures_used(shProg, prog);
1404af69d88dSmrg            if (ctx->Driver.SamplerUniformChange)
140501e04c3fSmrg               ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
14067ec681f3Smrg            any_changed = true;
140701e04c3fSmrg         }
1408af69d88dSmrg      }
14097ec681f3Smrg
14107ec681f3Smrg      if (any_changed)
14117ec681f3Smrg         _mesa_update_valid_to_render_state(ctx);
1412af69d88dSmrg   }
1413af69d88dSmrg
1414af69d88dSmrg   /* If the uniform is an image, update the mapping from image
1415af69d88dSmrg    * uniforms to image units present in the shader data structure.
1416af69d88dSmrg    */
1417af69d88dSmrg   if (uni->type->is_image()) {
141801e04c3fSmrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
141901e04c3fSmrg         struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
1420af69d88dSmrg
142101e04c3fSmrg         /* If the shader stage doesn't use the image uniform, skip this. */
142201e04c3fSmrg         if (!uni->opaque[i].active)
142301e04c3fSmrg            continue;
1424af69d88dSmrg
142501e04c3fSmrg         for (int j = 0; j < count; j++) {
142601e04c3fSmrg            unsigned unit = uni->opaque[i].index + offset + j;
142701e04c3fSmrg            unsigned value = ((unsigned *)values)[j];
142801e04c3fSmrg
142901e04c3fSmrg            if (uni->is_bindless) {
143001e04c3fSmrg               struct gl_bindless_image *image =
143101e04c3fSmrg                  &sh->Program->sh.BindlessImages[unit];
143201e04c3fSmrg
143301e04c3fSmrg               /* Mark this bindless image as bound to an image unit.
143401e04c3fSmrg                */
143501e04c3fSmrg               image->unit = value;
143601e04c3fSmrg               image->bound = true;
143701e04c3fSmrg               sh->Program->sh.HasBoundBindlessImage = true;
143801e04c3fSmrg            } else {
143901e04c3fSmrg               sh->Program->sh.ImageUnits[unit] = value;
144001e04c3fSmrg            }
1441af69d88dSmrg         }
1442af69d88dSmrg      }
1443af69d88dSmrg
1444af69d88dSmrg      ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
1445af69d88dSmrg   }
1446af69d88dSmrg}
1447af69d88dSmrg
144801e04c3fSmrg
14497ec681f3Smrgstatic bool
14507ec681f3Smrgcopy_uniform_matrix_to_storage(struct gl_context *ctx,
14517ec681f3Smrg                               gl_constant_value *storage,
14527ec681f3Smrg                               struct gl_uniform_storage *const uni,
14537ec681f3Smrg                               unsigned count, const void *values,
145401e04c3fSmrg                               const unsigned size_mul, const unsigned offset,
145501e04c3fSmrg                               const unsigned components,
145601e04c3fSmrg                               const unsigned vectors, bool transpose,
145701e04c3fSmrg                               unsigned cols, unsigned rows,
14587ec681f3Smrg                               enum glsl_base_type basicType, bool flush)
145901e04c3fSmrg{
146001e04c3fSmrg   const unsigned elements = components * vectors;
14617ec681f3Smrg   const unsigned size = sizeof(storage[0]) * elements * count * size_mul;
14627ec681f3Smrg
14637ec681f3Smrg   if (uni->type->base_type == GLSL_TYPE_FLOAT16) {
14647ec681f3Smrg      assert(ctx->Const.PackedDriverUniformStorage);
14657ec681f3Smrg      const unsigned dst_components = align(components, 2);
14667ec681f3Smrg      const unsigned dst_elements = dst_components * vectors;
14677ec681f3Smrg
14687ec681f3Smrg      if (!transpose) {
14697ec681f3Smrg         const float *src = (const float *)values;
14707ec681f3Smrg         uint16_t *dst = (uint16_t*)storage;
14717ec681f3Smrg
14727ec681f3Smrg         unsigned i = 0, r = 0, c = 0;
14737ec681f3Smrg
14747ec681f3Smrg         if (flush) {
14757ec681f3Smrg            /* Find the first element that's different. */
14767ec681f3Smrg            for (; i < count; i++) {
14777ec681f3Smrg               for (; c < cols; c++) {
14787ec681f3Smrg                  for (; r < rows; r++) {
14797ec681f3Smrg                     if (dst[(c * dst_components) + r] !=
14807ec681f3Smrg                         _mesa_float_to_half(src[(c * components) + r])) {
14817ec681f3Smrg                        _mesa_flush_vertices_for_uniforms(ctx, uni);
14827ec681f3Smrg                        flush = false;
14837ec681f3Smrg                        goto break_loops_16bit;
14847ec681f3Smrg                     }
14857ec681f3Smrg                  }
14867ec681f3Smrg                  r = 0;
14877ec681f3Smrg               }
14887ec681f3Smrg               c = 0;
14897ec681f3Smrg               dst += dst_elements;
14907ec681f3Smrg               src += elements;
14917ec681f3Smrg            }
14927ec681f3Smrg
14937ec681f3Smrg         break_loops_16bit:
14947ec681f3Smrg            if (flush)
14957ec681f3Smrg               return false; /* No change. */
14967ec681f3Smrg         }
14977ec681f3Smrg
14987ec681f3Smrg         /* Set the remaining elements. We know that at least 1 element is
14997ec681f3Smrg          * different and that we have flushed.
15007ec681f3Smrg          */
15017ec681f3Smrg         for (; i < count; i++) {
15027ec681f3Smrg            for (; c < cols; c++) {
15037ec681f3Smrg               for (; r < rows; r++) {
15047ec681f3Smrg                  dst[(c * dst_components) + r] =
15057ec681f3Smrg                     _mesa_float_to_half(src[(c * components) + r]);
15067ec681f3Smrg               }
15077ec681f3Smrg               r = 0;
15087ec681f3Smrg            }
15097ec681f3Smrg            c = 0;
15107ec681f3Smrg            dst += dst_elements;
15117ec681f3Smrg            src += elements;
15127ec681f3Smrg         }
15137ec681f3Smrg         return true;
15147ec681f3Smrg      } else {
15157ec681f3Smrg         /* Transpose the matrix. */
15167ec681f3Smrg         const float *src = (const float *)values;
15177ec681f3Smrg         uint16_t *dst = (uint16_t*)storage;
15187ec681f3Smrg
15197ec681f3Smrg         unsigned i = 0, r = 0, c = 0;
15207ec681f3Smrg
15217ec681f3Smrg         if (flush) {
15227ec681f3Smrg            /* Find the first element that's different. */
15237ec681f3Smrg            for (; i < count; i++) {
15247ec681f3Smrg               for (; r < rows; r++) {
15257ec681f3Smrg                  for (; c < cols; c++) {
15267ec681f3Smrg                     if (dst[(c * dst_components) + r] !=
15277ec681f3Smrg                         _mesa_float_to_half(src[c + (r * vectors)])) {
15287ec681f3Smrg                        _mesa_flush_vertices_for_uniforms(ctx, uni);
15297ec681f3Smrg                        flush = false;
15307ec681f3Smrg                        goto break_loops_16bit_transpose;
15317ec681f3Smrg                     }
15327ec681f3Smrg                  }
15337ec681f3Smrg                  c = 0;
15347ec681f3Smrg               }
15357ec681f3Smrg               r = 0;
15367ec681f3Smrg               dst += elements;
15377ec681f3Smrg               src += elements;
15387ec681f3Smrg            }
15397ec681f3Smrg
15407ec681f3Smrg         break_loops_16bit_transpose:
15417ec681f3Smrg            if (flush)
15427ec681f3Smrg               return false; /* No change. */
15437ec681f3Smrg         }
15447ec681f3Smrg
15457ec681f3Smrg         /* Set the remaining elements. We know that at least 1 element is
15467ec681f3Smrg          * different and that we have flushed.
15477ec681f3Smrg          */
15487ec681f3Smrg         for (; i < count; i++) {
15497ec681f3Smrg            for (; r < rows; r++) {
15507ec681f3Smrg               for (; c < cols; c++) {
15517ec681f3Smrg                  dst[(c * dst_components) + r] =
15527ec681f3Smrg                     _mesa_float_to_half(src[c + (r * vectors)]);
15537ec681f3Smrg               }
15547ec681f3Smrg               c = 0;
15557ec681f3Smrg            }
15567ec681f3Smrg            r = 0;
15577ec681f3Smrg            dst += elements;
15587ec681f3Smrg            src += elements;
15597ec681f3Smrg         }
15607ec681f3Smrg         return true;
15617ec681f3Smrg      }
15627ec681f3Smrg   } else if (!transpose) {
15637ec681f3Smrg      if (!memcmp(storage, values, size))
15647ec681f3Smrg         return false;
156501e04c3fSmrg
15667ec681f3Smrg      if (flush)
15677ec681f3Smrg         _mesa_flush_vertices_for_uniforms(ctx, uni);
15687ec681f3Smrg
15697ec681f3Smrg      memcpy(storage, values, size);
15707ec681f3Smrg      return true;
157101e04c3fSmrg   } else if (basicType == GLSL_TYPE_FLOAT) {
15727ec681f3Smrg      /* Transpose the matrix. */
157301e04c3fSmrg      const float *src = (const float *)values;
15747ec681f3Smrg      float *dst = (float*)storage;
15757ec681f3Smrg
15767ec681f3Smrg      unsigned i = 0, r = 0, c = 0;
15777ec681f3Smrg
15787ec681f3Smrg      if (flush) {
15797ec681f3Smrg         /* Find the first element that's different. */
15807ec681f3Smrg         for (; i < count; i++) {
15817ec681f3Smrg            for (; r < rows; r++) {
15827ec681f3Smrg               for (; c < cols; c++) {
15837ec681f3Smrg                  if (dst[(c * components) + r] != src[c + (r * vectors)]) {
15847ec681f3Smrg                     _mesa_flush_vertices_for_uniforms(ctx, uni);
15857ec681f3Smrg                     flush = false;
15867ec681f3Smrg                     goto break_loops;
15877ec681f3Smrg                  }
15887ec681f3Smrg               }
15897ec681f3Smrg               c = 0;
159001e04c3fSmrg            }
15917ec681f3Smrg            r = 0;
15927ec681f3Smrg            dst += elements;
15937ec681f3Smrg            src += elements;
159401e04c3fSmrg         }
159501e04c3fSmrg
15967ec681f3Smrg      break_loops:
15977ec681f3Smrg         if (flush)
15987ec681f3Smrg            return false; /* No change. */
15997ec681f3Smrg      }
16007ec681f3Smrg
16017ec681f3Smrg      /* Set the remaining elements. We know that at least 1 element is
16027ec681f3Smrg       * different and that we have flushed.
16037ec681f3Smrg       */
16047ec681f3Smrg      for (; i < count; i++) {
16057ec681f3Smrg         for (; r < rows; r++) {
16067ec681f3Smrg            for (; c < cols; c++)
16077ec681f3Smrg               dst[(c * components) + r] = src[c + (r * vectors)];
16087ec681f3Smrg            c = 0;
16097ec681f3Smrg         }
16107ec681f3Smrg         r = 0;
161101e04c3fSmrg         dst += elements;
161201e04c3fSmrg         src += elements;
161301e04c3fSmrg      }
16147ec681f3Smrg      return true;
161501e04c3fSmrg   } else {
161601e04c3fSmrg      assert(basicType == GLSL_TYPE_DOUBLE);
161701e04c3fSmrg      const double *src = (const double *)values;
16187ec681f3Smrg      double *dst = (double*)storage;
16197ec681f3Smrg
16207ec681f3Smrg      unsigned i = 0, r = 0, c = 0;
16217ec681f3Smrg
16227ec681f3Smrg      if (flush) {
16237ec681f3Smrg         /* Find the first element that's different. */
16247ec681f3Smrg         for (; i < count; i++) {
16257ec681f3Smrg            for (; r < rows; r++) {
16267ec681f3Smrg               for (; c < cols; c++) {
16277ec681f3Smrg                  if (dst[(c * components) + r] != src[c + (r * vectors)]) {
16287ec681f3Smrg                     _mesa_flush_vertices_for_uniforms(ctx, uni);
16297ec681f3Smrg                     flush = false;
16307ec681f3Smrg                     goto break_loops2;
16317ec681f3Smrg                  }
16327ec681f3Smrg               }
16337ec681f3Smrg               c = 0;
163401e04c3fSmrg            }
16357ec681f3Smrg            r = 0;
16367ec681f3Smrg            dst += elements;
16377ec681f3Smrg            src += elements;
163801e04c3fSmrg         }
163901e04c3fSmrg
16407ec681f3Smrg      break_loops2:
16417ec681f3Smrg         if (flush)
16427ec681f3Smrg            return false; /* No change. */
16437ec681f3Smrg      }
16447ec681f3Smrg
16457ec681f3Smrg      /* Set the remaining elements. We know that at least 1 element is
16467ec681f3Smrg       * different and that we have flushed.
16477ec681f3Smrg       */
16487ec681f3Smrg      for (; i < count; i++) {
16497ec681f3Smrg         for (; r < rows; r++) {
16507ec681f3Smrg            for (; c < cols; c++)
16517ec681f3Smrg               dst[(c * components) + r] = src[c + (r * vectors)];
16527ec681f3Smrg            c = 0;
16537ec681f3Smrg         }
16547ec681f3Smrg         r = 0;
165501e04c3fSmrg         dst += elements;
165601e04c3fSmrg         src += elements;
165701e04c3fSmrg      }
16587ec681f3Smrg      return true;
165901e04c3fSmrg   }
166001e04c3fSmrg}
166101e04c3fSmrg
166201e04c3fSmrg
1663af69d88dSmrg/**
1664af69d88dSmrg * Called by glUniformMatrix*() functions.
1665af69d88dSmrg * Note: cols=2, rows=4  ==>  array[2] of vec4
1666af69d88dSmrg */
1667af69d88dSmrgextern "C" void
166801e04c3fSmrg_mesa_uniform_matrix(GLint location, GLsizei count,
166901e04c3fSmrg                     GLboolean transpose, const void *values,
167001e04c3fSmrg                     struct gl_context *ctx, struct gl_shader_program *shProg,
167101e04c3fSmrg                     GLuint cols, GLuint rows, enum glsl_base_type basicType)
1672af69d88dSmrg{
1673af69d88dSmrg   unsigned offset;
1674af69d88dSmrg   struct gl_uniform_storage *const uni =
167501e04c3fSmrg      validate_uniform_parameters(location, count, &offset,
167601e04c3fSmrg                                  ctx, shProg, "glUniformMatrix");
1677af69d88dSmrg   if (uni == NULL)
1678af69d88dSmrg      return;
1679af69d88dSmrg
16807ec681f3Smrg   /* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
16817ec681f3Smrg    * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
16827ec681f3Smrg    */
16837ec681f3Smrg   if (transpose) {
16847ec681f3Smrg      if (ctx->API == API_OPENGLES2 && ctx->Version < 30) {
16857ec681f3Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
16867ec681f3Smrg                     "glUniformMatrix(matrix transpose is not GL_FALSE)");
16877ec681f3Smrg         return;
16887ec681f3Smrg      }
16897ec681f3Smrg   }
16907ec681f3Smrg
1691af69d88dSmrg   if (!uni->type->is_matrix()) {
1692af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1693af69d88dSmrg		  "glUniformMatrix(non-matrix uniform)");
1694af69d88dSmrg      return;
1695af69d88dSmrg   }
1696af69d88dSmrg
169701e04c3fSmrg   assert(basicType == GLSL_TYPE_FLOAT || basicType == GLSL_TYPE_DOUBLE);
169801e04c3fSmrg   const unsigned size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
169901e04c3fSmrg
1700af69d88dSmrg   assert(!uni->type->is_sampler());
170101e04c3fSmrg   const unsigned vectors = uni->type->matrix_columns;
170201e04c3fSmrg   const unsigned components = uni->type->vector_elements;
1703af69d88dSmrg
1704af69d88dSmrg   /* Verify that the types are compatible.  This is greatly simplified for
1705af69d88dSmrg    * matrices because they can only have a float base type.
1706af69d88dSmrg    */
1707af69d88dSmrg   if (vectors != cols || components != rows) {
1708af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1709af69d88dSmrg		  "glUniformMatrix(matrix size mismatch)");
1710af69d88dSmrg      return;
1711af69d88dSmrg   }
1712af69d88dSmrg
171301e04c3fSmrg   /* Section 2.11.7 (Uniform Variables) of the OpenGL 4.2 Core Profile spec
171401e04c3fSmrg    * says:
171501e04c3fSmrg    *
171601e04c3fSmrg    *     "If any of the following conditions occur, an INVALID_OPERATION
171701e04c3fSmrg    *     error is generated by the Uniform* commands, and no uniform values
171801e04c3fSmrg    *     are changed:
171901e04c3fSmrg    *
172001e04c3fSmrg    *     ...
172101e04c3fSmrg    *
172201e04c3fSmrg    *     - if the uniform declared in the shader is not of type boolean and
172301e04c3fSmrg    *       the type indicated in the name of the Uniform* command used does
172401e04c3fSmrg    *       not match the type of the uniform"
172501e04c3fSmrg    *
172601e04c3fSmrg    * There are no Boolean matrix types, so we do not need to allow
172701e04c3fSmrg    * GLSL_TYPE_BOOL here (as _mesa_uniform does).
172801e04c3fSmrg    */
17297ec681f3Smrg   if (uni->type->base_type != basicType &&
17307ec681f3Smrg       !(uni->type->base_type == GLSL_TYPE_FLOAT16 &&
17317ec681f3Smrg         basicType == GLSL_TYPE_FLOAT)) {
173201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
173301e04c3fSmrg                  "glUniformMatrix%ux%u(\"%s\"@%d is %s, not %s)",
173401e04c3fSmrg                  cols, rows, uni->name, location,
173501e04c3fSmrg                  glsl_type_name(uni->type->base_type),
173601e04c3fSmrg                  glsl_type_name(basicType));
173701e04c3fSmrg      return;
173801e04c3fSmrg   }
173901e04c3fSmrg
174001e04c3fSmrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
174101e04c3fSmrg      log_uniform(values, uni->type->base_type, components, vectors, count,
1742af69d88dSmrg		  bool(transpose), shProg, location, uni);
1743af69d88dSmrg   }
1744af69d88dSmrg
1745af69d88dSmrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
1746af69d88dSmrg    *
1747af69d88dSmrg    *     "When loading N elements starting at an arbitrary position k in a
1748af69d88dSmrg    *     uniform declared as an array, elements k through k + N - 1 in the
1749af69d88dSmrg    *     array will be replaced with the new values. Values for any array
1750af69d88dSmrg    *     element that exceeds the highest array element index used, as
1751af69d88dSmrg    *     reported by GetActiveUniform, will be ignored by the GL."
1752af69d88dSmrg    *
1753af69d88dSmrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
1754af69d88dSmrg    * will have already generated an error.
1755af69d88dSmrg    */
1756af69d88dSmrg   if (uni->array_elements != 0) {
1757af69d88dSmrg      count = MIN2(count, (int) (uni->array_elements - offset));
1758af69d88dSmrg   }
1759af69d88dSmrg
1760af69d88dSmrg   /* Store the data in the "actual type" backing storage for the uniform.
1761af69d88dSmrg    */
176201e04c3fSmrg   gl_constant_value *storage;
176301e04c3fSmrg   const unsigned elements = components * vectors;
176401e04c3fSmrg   if (ctx->Const.PackedDriverUniformStorage) {
17657ec681f3Smrg      bool flushed = false;
17667ec681f3Smrg
176701e04c3fSmrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
17687ec681f3Smrg         unsigned dword_components = components;
17697ec681f3Smrg
17707ec681f3Smrg         /* 16-bit uniforms are packed. */
17717ec681f3Smrg         if (glsl_base_type_is_16bit(uni->type->base_type))
17727ec681f3Smrg            dword_components = DIV_ROUND_UP(dword_components, 2);
177301e04c3fSmrg
17747ec681f3Smrg         storage = (gl_constant_value *)
17757ec681f3Smrg            uni->driver_storage[s].data +
17767ec681f3Smrg            (size_mul * offset * dword_components * vectors);
17777ec681f3Smrg
17787ec681f3Smrg         if (copy_uniform_matrix_to_storage(ctx, storage, uni, count, values,
17797ec681f3Smrg                                            size_mul, offset, components,
17807ec681f3Smrg                                            vectors, transpose, cols, rows,
17817ec681f3Smrg                                            basicType, !flushed))
17827ec681f3Smrg            flushed = true;
178301e04c3fSmrg      }
1784af69d88dSmrg   } else {
178501e04c3fSmrg      storage =  &uni->storage[size_mul * elements * offset];
17867ec681f3Smrg      if (copy_uniform_matrix_to_storage(ctx, storage, uni, count, values,
17877ec681f3Smrg                                         size_mul, offset, components, vectors,
17887ec681f3Smrg                                         transpose, cols, rows, basicType,
17897ec681f3Smrg                                         true))
17907ec681f3Smrg         _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
1791af69d88dSmrg   }
179201e04c3fSmrg}
179301e04c3fSmrg
179401e04c3fSmrgstatic void
179501e04c3fSmrgupdate_bound_bindless_sampler_flag(struct gl_program *prog)
179601e04c3fSmrg{
179701e04c3fSmrg   unsigned i;
179801e04c3fSmrg
179901e04c3fSmrg   if (likely(!prog->sh.HasBoundBindlessSampler))
180001e04c3fSmrg      return;
1801af69d88dSmrg
180201e04c3fSmrg   for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
180301e04c3fSmrg      struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[i];
1804af69d88dSmrg
180501e04c3fSmrg      if (sampler->bound)
180601e04c3fSmrg         return;
180701e04c3fSmrg   }
180801e04c3fSmrg   prog->sh.HasBoundBindlessSampler = false;
1809af69d88dSmrg}
1810af69d88dSmrg
181101e04c3fSmrgstatic void
181201e04c3fSmrgupdate_bound_bindless_image_flag(struct gl_program *prog)
181301e04c3fSmrg{
181401e04c3fSmrg   unsigned i;
181501e04c3fSmrg
181601e04c3fSmrg   if (likely(!prog->sh.HasBoundBindlessImage))
181701e04c3fSmrg      return;
181801e04c3fSmrg
181901e04c3fSmrg   for (i = 0; i < prog->sh.NumBindlessImages; i++) {
182001e04c3fSmrg      struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
182101e04c3fSmrg
182201e04c3fSmrg      if (image->bound)
182301e04c3fSmrg         return;
182401e04c3fSmrg   }
182501e04c3fSmrg   prog->sh.HasBoundBindlessImage = false;
182601e04c3fSmrg}
1827af69d88dSmrg
1828af69d88dSmrg/**
182901e04c3fSmrg * Called via glUniformHandleui64*ARB() functions.
1830af69d88dSmrg */
183101e04c3fSmrgextern "C" void
183201e04c3fSmrg_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
183301e04c3fSmrg                     struct gl_context *ctx, struct gl_shader_program *shProg)
1834af69d88dSmrg{
183501e04c3fSmrg   unsigned offset;
183601e04c3fSmrg   struct gl_uniform_storage *uni;
1837af69d88dSmrg
183801e04c3fSmrg   if (_mesa_is_no_error_enabled(ctx)) {
183901e04c3fSmrg      /* From Section 7.6 (UNIFORM VARIABLES) of the OpenGL 4.5 spec:
184001e04c3fSmrg       *
184101e04c3fSmrg       *   "If the value of location is -1, the Uniform* commands will
184201e04c3fSmrg       *   silently ignore the data passed in, and the current uniform values
184301e04c3fSmrg       *   will not be changed.
184401e04c3fSmrg       */
184501e04c3fSmrg      if (location == -1)
184601e04c3fSmrg         return;
1847af69d88dSmrg
184801e04c3fSmrg      uni = shProg->UniformRemapTable[location];
18497ec681f3Smrg      if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
18507ec681f3Smrg         return;
185101e04c3fSmrg
185201e04c3fSmrg      /* The array index specified by the uniform location is just the
185301e04c3fSmrg       * uniform location minus the base location of of the uniform.
185401e04c3fSmrg       */
185501e04c3fSmrg      assert(uni->array_elements > 0 || location == (int)uni->remap_location);
185601e04c3fSmrg      offset = location - uni->remap_location;
1857af69d88dSmrg   } else {
185801e04c3fSmrg      uni = validate_uniform_parameters(location, count, &offset,
185901e04c3fSmrg                                        ctx, shProg, "glUniformHandleui64*ARB");
186001e04c3fSmrg      if (!uni)
186101e04c3fSmrg         return;
186201e04c3fSmrg
186301e04c3fSmrg      if (!uni->is_bindless) {
186401e04c3fSmrg         /* From section "Errors" of the ARB_bindless_texture spec:
186501e04c3fSmrg          *
186601e04c3fSmrg          * "The error INVALID_OPERATION is generated by
186701e04c3fSmrg          *  UniformHandleui64{v}ARB if the sampler or image uniform being
186801e04c3fSmrg          *  updated has the "bound_sampler" or "bound_image" layout qualifier."
186901e04c3fSmrg          *
187001e04c3fSmrg          * From section 4.4.6 of the ARB_bindless_texture spec:
187101e04c3fSmrg          *
187201e04c3fSmrg          * "In the absence of these qualifiers, sampler and image uniforms are
187301e04c3fSmrg          *  considered "bound". Additionally, if GL_ARB_bindless_texture is
187401e04c3fSmrg          *  not enabled, these uniforms are considered "bound"."
187501e04c3fSmrg          */
187601e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
187701e04c3fSmrg                     "glUniformHandleui64*ARB(non-bindless sampler/image uniform)");
187801e04c3fSmrg         return;
187901e04c3fSmrg      }
1880af69d88dSmrg   }
1881af69d88dSmrg
188201e04c3fSmrg   const unsigned components = uni->type->vector_elements;
188301e04c3fSmrg   const int size_mul = 2;
1884af69d88dSmrg
188501e04c3fSmrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
188601e04c3fSmrg      log_uniform(values, GLSL_TYPE_UINT64, components, 1, count,
188701e04c3fSmrg                  false, shProg, location, uni);
188801e04c3fSmrg   }
1889af69d88dSmrg
189001e04c3fSmrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
189101e04c3fSmrg    *
189201e04c3fSmrg    *     "When loading N elements starting at an arbitrary position k in a
189301e04c3fSmrg    *     uniform declared as an array, elements k through k + N - 1 in the
189401e04c3fSmrg    *     array will be replaced with the new values. Values for any array
189501e04c3fSmrg    *     element that exceeds the highest array element index used, as
189601e04c3fSmrg    *     reported by GetActiveUniform, will be ignored by the GL."
189701e04c3fSmrg    *
189801e04c3fSmrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
189901e04c3fSmrg    * will have already generated an error.
1900af69d88dSmrg    */
190101e04c3fSmrg   if (uni->array_elements != 0) {
190201e04c3fSmrg      count = MIN2(count, (int) (uni->array_elements - offset));
190301e04c3fSmrg   }
1904af69d88dSmrg
1905af69d88dSmrg
190601e04c3fSmrg   /* Store the data in the "actual type" backing storage for the uniform.
1907af69d88dSmrg    */
190801e04c3fSmrg   if (ctx->Const.PackedDriverUniformStorage) {
19097ec681f3Smrg      bool flushed = false;
19107ec681f3Smrg
191101e04c3fSmrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
19127ec681f3Smrg         void *storage = (gl_constant_value *)
191301e04c3fSmrg            uni->driver_storage[s].data + (size_mul * offset * components);
19147ec681f3Smrg         unsigned size = sizeof(uni->storage[0]) * components * count * size_mul;
19157ec681f3Smrg
19167ec681f3Smrg         if (!memcmp(storage, values, size))
19177ec681f3Smrg            continue;
19187ec681f3Smrg
19197ec681f3Smrg         if (!flushed) {
19207ec681f3Smrg            _mesa_flush_vertices_for_uniforms(ctx, uni);
19217ec681f3Smrg            flushed = true;
19227ec681f3Smrg         }
19237ec681f3Smrg         memcpy(storage, values, size);
192401e04c3fSmrg      }
19257ec681f3Smrg      if (!flushed)
19267ec681f3Smrg         return;
192701e04c3fSmrg   } else {
19287ec681f3Smrg      void *storage = &uni->storage[size_mul * components * offset];
19297ec681f3Smrg      unsigned size = sizeof(uni->storage[0]) * components * count * size_mul;
19307ec681f3Smrg
19317ec681f3Smrg      if (!memcmp(storage, values, size))
19327ec681f3Smrg         return;
193301e04c3fSmrg
19347ec681f3Smrg      _mesa_flush_vertices_for_uniforms(ctx, uni);
19357ec681f3Smrg      memcpy(storage, values, size);
193601e04c3fSmrg      _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
1937af69d88dSmrg   }
1938af69d88dSmrg
193901e04c3fSmrg   if (uni->type->is_sampler()) {
194001e04c3fSmrg      /* Mark this bindless sampler as not bound to a texture unit because
194101e04c3fSmrg       * it refers to a texture handle.
194201e04c3fSmrg       */
194301e04c3fSmrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
194401e04c3fSmrg         struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
1945af69d88dSmrg
194601e04c3fSmrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
194701e04c3fSmrg         if (!uni->opaque[i].active)
194801e04c3fSmrg            continue;
1949af69d88dSmrg
195001e04c3fSmrg         for (int j = 0; j < count; j++) {
195101e04c3fSmrg            unsigned unit = uni->opaque[i].index + offset + j;
195201e04c3fSmrg            struct gl_bindless_sampler *sampler =
195301e04c3fSmrg               &sh->Program->sh.BindlessSamplers[unit];
1954af69d88dSmrg
195501e04c3fSmrg            sampler->bound = false;
195601e04c3fSmrg         }
1957af69d88dSmrg
195801e04c3fSmrg         update_bound_bindless_sampler_flag(sh->Program);
195901e04c3fSmrg      }
196001e04c3fSmrg   }
1961af69d88dSmrg
196201e04c3fSmrg   if (uni->type->is_image()) {
196301e04c3fSmrg      /* Mark this bindless image as not bound to an image unit because it
196401e04c3fSmrg       * refers to a texture handle.
196501e04c3fSmrg       */
196601e04c3fSmrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
196701e04c3fSmrg         struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
196801e04c3fSmrg
196901e04c3fSmrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
197001e04c3fSmrg         if (!uni->opaque[i].active)
197101e04c3fSmrg            continue;
197201e04c3fSmrg
197301e04c3fSmrg         for (int j = 0; j < count; j++) {
197401e04c3fSmrg            unsigned unit = uni->opaque[i].index + offset + j;
197501e04c3fSmrg            struct gl_bindless_image *image =
197601e04c3fSmrg               &sh->Program->sh.BindlessImages[unit];
197701e04c3fSmrg
197801e04c3fSmrg            image->bound = false;
197901e04c3fSmrg         }
198001e04c3fSmrg
198101e04c3fSmrg         update_bound_bindless_image_flag(sh->Program);
1982af69d88dSmrg      }
1983af69d88dSmrg   }
198401e04c3fSmrg}
1985af69d88dSmrg
198601e04c3fSmrgextern "C" bool
198701e04c3fSmrg_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
198801e04c3fSmrg				 char *errMsg, size_t errMsgLength)
198901e04c3fSmrg{
199001e04c3fSmrg   /* Shader does not have samplers. */
199101e04c3fSmrg   if (shProg->data->NumUniformStorage == 0)
199201e04c3fSmrg      return true;
199301e04c3fSmrg
199401e04c3fSmrg   if (!shProg->SamplersValidated) {
19957ec681f3Smrg      snprintf(errMsg, errMsgLength,
199601e04c3fSmrg                     "active samplers with a different type "
199701e04c3fSmrg                     "refer to the same texture image unit");
199801e04c3fSmrg      return false;
199901e04c3fSmrg   }
2000af69d88dSmrg   return true;
2001af69d88dSmrg}
2002af69d88dSmrg
2003af69d88dSmrgextern "C" bool
2004af69d88dSmrg_mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline)
2005af69d88dSmrg{
2006af69d88dSmrg   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
2007af69d88dSmrg    * OpenGL 4.1 spec says:
2008af69d88dSmrg    *
2009af69d88dSmrg    *     "[INVALID_OPERATION] is generated by any command that transfers
2010af69d88dSmrg    *     vertices to the GL if:
2011af69d88dSmrg    *
2012af69d88dSmrg    *         ...
2013af69d88dSmrg    *
2014af69d88dSmrg    *         - Any two active samplers in the current program object are of
2015af69d88dSmrg    *           different types, but refer to the same texture image unit.
2016af69d88dSmrg    *
2017af69d88dSmrg    *         - The number of active samplers in the program exceeds the
2018af69d88dSmrg    *           maximum number of texture image units allowed."
2019af69d88dSmrg    */
202001e04c3fSmrg
202101e04c3fSmrg   GLbitfield mask;
202201e04c3fSmrg   GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
2023af69d88dSmrg   unsigned active_samplers = 0;
202401e04c3fSmrg   const struct gl_program **prog =
202501e04c3fSmrg      (const struct gl_program **) pipeline->CurrentProgram;
202601e04c3fSmrg
2027af69d88dSmrg
202801e04c3fSmrg   memset(TexturesUsed, 0, sizeof(TexturesUsed));
2029af69d88dSmrg
2030af69d88dSmrg   for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
203101e04c3fSmrg      if (!prog[idx])
2032af69d88dSmrg         continue;
2033af69d88dSmrg
203401e04c3fSmrg      mask = prog[idx]->SamplersUsed;
203501e04c3fSmrg      while (mask) {
203601e04c3fSmrg         const int s = u_bit_scan(&mask);
203701e04c3fSmrg         GLuint unit = prog[idx]->SamplerUnits[s];
203801e04c3fSmrg         GLuint tgt = prog[idx]->sh.SamplerTargets[s];
2039af69d88dSmrg
204001e04c3fSmrg         /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
204101e04c3fSmrg          * great job of eliminating unused uniforms currently so for now
204201e04c3fSmrg          * don't throw an error if two sampler types both point to 0.
204301e04c3fSmrg          */
204401e04c3fSmrg         if (unit == 0)
2045af69d88dSmrg            continue;
2046af69d88dSmrg
204701e04c3fSmrg         if (TexturesUsed[unit] & ~(1 << tgt)) {
204801e04c3fSmrg            pipeline->InfoLog =
204901e04c3fSmrg               ralloc_asprintf(pipeline,
205001e04c3fSmrg                     "Program %d: "
205101e04c3fSmrg                     "Texture unit %d is accessed with 2 different types",
205201e04c3fSmrg                     prog[idx]->Id, unit);
205301e04c3fSmrg            return false;
2054af69d88dSmrg         }
205501e04c3fSmrg
205601e04c3fSmrg         TexturesUsed[unit] |= (1 << tgt);
2057af69d88dSmrg      }
205801e04c3fSmrg
205901e04c3fSmrg      active_samplers += prog[idx]->info.num_textures;
2060af69d88dSmrg   }
2061af69d88dSmrg
2062af69d88dSmrg   if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {
2063af69d88dSmrg      pipeline->InfoLog =
2064af69d88dSmrg         ralloc_asprintf(pipeline,
2065af69d88dSmrg                         "the number of active samplers %d exceed the "
2066af69d88dSmrg                         "maximum %d",
2067af69d88dSmrg                         active_samplers, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
2068af69d88dSmrg      return false;
2069af69d88dSmrg   }
2070af69d88dSmrg
2071af69d88dSmrg   return true;
2072af69d88dSmrg}
2073