glsl: use is_sampler() anywhere it's possible
[mesa.git] / src / mesa / main / uniform_query.cpp
index 766a465cb11dd46bbd742e0699067bcbf721f48a..4d06313565f63cb8b0fd37796a382c1cd89c2525 100644 (file)
  */
 
 #include <stdlib.h>
+#include <inttypes.h>  /* for PRIx64 macro */
 
 #include "main/core.h"
 #include "main/context.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
 #include "main/uniforms.h"
-#include "glsl/ir.h"
-#include "glsl/ir_uniform.h"
-#include "glsl/glsl_parser_extras.h"
-#include "glsl/program.h"
-#include "program/hash_table.h"
+#include "compiler/glsl/ir.h"
+#include "compiler/glsl/ir_uniform.h"
+#include "compiler/glsl/glsl_parser_extras.h"
+#include "compiler/glsl/program.h"
+#include "util/bitscan.h"
 
 
 extern "C" void GLAPIENTRY
@@ -156,11 +157,11 @@ _mesa_GetActiveUniformsiv(GLuint program,
 }
 
 static struct gl_uniform_storage *
-validate_uniform_parameters(struct gl_context *ctx,
-                           struct gl_shader_program *shProg,
-                           GLint location, GLsizei count,
-                           unsigned *array_index,
-                           const char *caller)
+validate_uniform_parameters(GLint location, GLsizei count,
+                            unsigned *array_index,
+                            struct gl_context *ctx,
+                            struct gl_shader_program *shProg,
+                            const char *caller)
 {
    if (shProg == NULL) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
@@ -179,10 +180,10 @@ validate_uniform_parameters(struct gl_context *ctx,
 
    /* Check that the given location is in bounds of uniform remap table.
     * Unlinked programs will have NumUniformRemapTable == 0, so we can take
-    * the shProg->LinkStatus check out of the main path.
+    * the shProg->data->LinkStatus check out of the main path.
     */
    if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
-      if (!shProg->LinkStatus)
+      if (!shProg->data->LinkStatus)
          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
                      caller);
       else
@@ -193,7 +194,7 @@ validate_uniform_parameters(struct gl_context *ctx,
    }
 
    if (location == -1) {
-      if (!shProg->LinkStatus)
+      if (!shProg->data->LinkStatus)
          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
                      caller);
 
@@ -284,8 +285,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
    unsigned offset;
 
    struct gl_uniform_storage *const uni =
-      validate_uniform_parameters(ctx, shProg, location, 1,
-                                  &offset, "glGetUniform");
+      validate_uniform_parameters(location, 1, &offset,
+                                  ctx, shProg, "glGetUniform");
    if (uni == NULL) {
       /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
        * spec says:
@@ -322,8 +323,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
    {
       unsigned elements = (uni->type->is_sampler())
         ? 1 : uni->type->components();
-      const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1;
-      const int rmul = returnType == GLSL_TYPE_DOUBLE ? 2 : 1;
+      const int dmul = uni->type->is_64bit() ? 2 : 1;
+      const int rmul = glsl_base_type_is_64bit(returnType) ? 2 : 1;
 
       /* Calculate the source base address *BEFORE* modifying elements to
        * account for the size of the user's buffer.
@@ -332,7 +333,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
         &uni->storage[offset * elements * dmul];
 
       assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
-             returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE);
+             returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE ||
+             returnType == GLSL_TYPE_UINT64 || returnType == GLSL_TYPE_INT64);
 
       /* doubles have a different size than the other 3 types */
       unsigned bytes = sizeof(src[0]) * elements * rmul;
@@ -353,8 +355,12 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
              &&
              (uni->type->base_type == GLSL_TYPE_INT
               || uni->type->base_type == GLSL_TYPE_UINT
-               || uni->type->base_type == GLSL_TYPE_SAMPLER
-               || uni->type->base_type == GLSL_TYPE_IMAGE))) {
+               || uni->type->is_sampler()
+               || uni->type->is_image()))
+          || ((returnType == GLSL_TYPE_UINT64 ||
+               returnType == GLSL_TYPE_INT64 ) &&
+              (uni->type->base_type == GLSL_TYPE_UINT64 ||
+               uni->type->base_type == GLSL_TYPE_INT64))) {
         memcpy(paramsOut, src, bytes);
       } else {
         union gl_constant_value *const dst =
@@ -381,9 +387,24 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
               case GLSL_TYPE_BOOL:
                  dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
                  break;
-              case GLSL_TYPE_DOUBLE:
-                 dst[didx].f = *(double *)&src[sidx].f;
+               case GLSL_TYPE_DOUBLE: {
+                  double tmp;
+                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+                  dst[didx].f = tmp;
                  break;
+               }
+               case GLSL_TYPE_UINT64: {
+                  uint64_t tmp;
+                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+                  dst[didx].f = tmp;
+                  break;
+               }
+               case GLSL_TYPE_INT64: {
+                  uint64_t tmp;
+                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+                  dst[didx].f = tmp;
+                  break;
+               }
               default:
                  assert(!"Should not get here.");
                  break;
@@ -391,20 +412,44 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
               break;
            case GLSL_TYPE_DOUBLE:
               switch (uni->type->base_type) {
-              case GLSL_TYPE_UINT:
-                 *(double *)&dst[didx].f = (double) src[sidx].u;
+               case GLSL_TYPE_UINT: {
+                  double tmp = src[sidx].u;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
                  break;
+               }
               case GLSL_TYPE_INT:
               case GLSL_TYPE_SAMPLER:
-              case GLSL_TYPE_IMAGE:
-                 *(double *)&dst[didx].f = (double) src[sidx].i;
+               case GLSL_TYPE_IMAGE: {
+                  double tmp = src[sidx].i;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
                  break;
-              case GLSL_TYPE_BOOL:
-                 *(double *)&dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
+               }
+               case GLSL_TYPE_BOOL: {
+                  double tmp = src[sidx].i ? 1.0 : 0.0;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
                  break;
-              case GLSL_TYPE_FLOAT:
-                 *(double *)&dst[didx].f = (double) src[sidx].f;
+               }
+               case GLSL_TYPE_FLOAT: {
+                  double tmp = src[sidx].f;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
                  break;
+               }
+               case GLSL_TYPE_UINT64: {
+                  uint64_t tmpu;
+                  double tmp;
+                  memcpy(&tmpu, &src[sidx].u, sizeof(tmpu));
+                  tmp = tmpu;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+                  break;
+               }
+               case GLSL_TYPE_INT64: {
+                  int64_t tmpi;
+                  double tmp;
+                  memcpy(&tmpi, &src[sidx].i, sizeof(tmpi));
+                  tmp = tmpi;
+                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+                  break;
+               }
               default:
                  assert(!"Should not get here.");
                  break;
@@ -436,15 +481,59 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
               case GLSL_TYPE_BOOL:
                  dst[didx].i = src[sidx].i ? 1 : 0;
                  break;
-              case GLSL_TYPE_DOUBLE:
-                 dst[didx].i = IROUNDD(*(double *)&src[sidx].f);
+               case GLSL_TYPE_DOUBLE: {
+                  double tmp;
+                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+                  dst[didx].i = IROUNDD(tmp);
                  break;
+               }
+               case GLSL_TYPE_UINT64: {
+                  uint64_t tmp;
+                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+                  dst[didx].i = tmp;
+                  break;
+               }
+               case GLSL_TYPE_INT64: {
+                  int64_t tmp;
+                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+                  dst[didx].i = tmp;
+                  break;
+               }
               default:
                  assert(!"Should not get here.");
                  break;
               }
               break;
-
+            case GLSL_TYPE_INT64:
+            case GLSL_TYPE_UINT64:
+               switch (uni->type->base_type) {
+               case GLSL_TYPE_UINT: {
+                  uint64_t tmp = src[sidx].u;
+                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+                  break;
+               }
+               case GLSL_TYPE_INT:
+               case GLSL_TYPE_SAMPLER:
+               case GLSL_TYPE_IMAGE: {
+                  int64_t tmp = src[sidx].i;
+                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+                  break;
+               }
+               case GLSL_TYPE_BOOL: {
+                  int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
+                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+                  break;
+               }
+               case GLSL_TYPE_FLOAT: {
+                  int64_t tmp = src[sidx].f;
+                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+                  break;
+               }
+               default:
+                  assert(!"Should not get here.");
+                  break;
+               }
+               break;
            default:
               assert(!"Should not get here.");
               break;
@@ -482,12 +571,27 @@ log_uniform(const void *values, enum glsl_base_type basicType,
       case GLSL_TYPE_INT:
         printf("%d ", v[i].i);
         break;
+      case GLSL_TYPE_UINT64: {
+         uint64_t tmp;
+         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
+         printf("%" PRIu64 " ", tmp);
+         break;
+      }
+      case GLSL_TYPE_INT64: {
+         int64_t tmp;
+         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
+         printf("%" PRId64 " ", tmp);
+         break;
+      }
       case GLSL_TYPE_FLOAT:
         printf("%g ", v[i].f);
         break;
-      case GLSL_TYPE_DOUBLE:
-         printf("%g ", *(double* )&v[i * 2].f);
+      case GLSL_TYPE_DOUBLE: {
+         double tmp;
+         memcpy(&tmp, &v[i * 2].f, sizeof(tmp));
+         printf("%g ", tmp);
          break;
+      }
       default:
         assert(!"Should not get here.");
         break;
@@ -548,7 +652,7 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
     */
    const unsigned components = MAX2(1, uni->type->vector_elements);
    const unsigned vectors = MAX2(1, uni->type->matrix_columns);
-   const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1;
+   const int dmul = uni->type->is_64bit() ? 2 : 1;
 
    /* Store the data in the driver's requested type in the driver's storage
     * areas.
@@ -577,14 +681,31 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
         unsigned j;
         unsigned v;
 
-        for (j = 0; j < count; j++) {
-           for (v = 0; v < vectors; v++) {
-              memcpy(dst, src, src_vector_byte_stride);
-              src += src_vector_byte_stride;
-              dst += store->vector_stride;
+        if (src_vector_byte_stride == store->vector_stride) {
+           if (extra_stride) {
+              for (j = 0; j < count; j++) {
+                 memcpy(dst, src, src_vector_byte_stride * vectors);
+                 src += src_vector_byte_stride * vectors;
+                 dst += store->vector_stride * vectors;
+
+                 dst += extra_stride;
+              }
+           } else {
+              /* Unigine Heaven benchmark gets here */
+              memcpy(dst, src, src_vector_byte_stride * vectors * count);
+              src += src_vector_byte_stride * vectors * count;
+              dst += store->vector_stride * vectors * count;
            }
+        } else {
+           for (j = 0; j < count; j++) {
+              for (v = 0; v < vectors; v++) {
+                 memcpy(dst, src, src_vector_byte_stride);
+                 src += src_vector_byte_stride;
+                 dst += store->vector_stride;
+              }
 
-           dst += extra_stride;
+              dst += extra_stride;
+           }
         }
         break;
       }
@@ -633,6 +754,10 @@ glsl_type_name(enum glsl_base_type type)
       return "float";
    case GLSL_TYPE_DOUBLE:
       return "double";
+   case GLSL_TYPE_UINT64:
+      return "uint64";
+   case GLSL_TYPE_INT64:
+      return "int64";
    case GLSL_TYPE_BOOL:
       return "bool";
    case GLSL_TYPE_SAMPLER:
@@ -661,18 +786,16 @@ glsl_type_name(enum glsl_base_type type)
  * Called via glUniform*() functions.
  */
 extern "C" void
-_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
-             GLint location, GLsizei count,
-              const GLvoid *values,
-              enum glsl_base_type basicType,
-              unsigned src_components)
+_mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
+              struct gl_context *ctx, struct gl_shader_program *shProg,
+              enum glsl_base_type basicType, unsigned src_components)
 {
    unsigned offset;
-   int size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
+   int size_mul = glsl_base_type_is_64bit(basicType) ? 2 : 1;
 
    struct gl_uniform_storage *const uni =
-      validate_uniform_parameters(ctx, shProg, location, count,
-                                  &offset, "glUniform");
+      validate_uniform_parameters(location, count, &offset,
+                                  ctx, shProg, "glUniform");
    if (uni == NULL)
       return;
 
@@ -815,8 +938,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
       }
    }
 
-   uni->initialized = true;
-
    _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
 
    /* If the uniform is a sampler, do the extra magic necessary to propagate
@@ -825,44 +946,28 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
    if (uni->type->is_sampler()) {
       bool flushed = false;
       for (int i = 0; i < MESA_SHADER_STAGES; i++) {
-        struct gl_shader *const sh = shProg->_LinkedShaders[i];
+        struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
 
-        /* If the shader stage doesn't use the sampler uniform, skip this.
-         */
-        if (sh == NULL || !uni->opaque[i].active)
+        /* If the shader stage doesn't use the sampler uniform, skip this. */
+        if (!uni->opaque[i].active)
            continue;
 
+         bool changed = false;
          for (int j = 0; j < count; j++) {
-            sh->SamplerUnits[uni->opaque[i].index + offset + j] =
-               ((unsigned *) values)[j];
+            unsigned unit = uni->opaque[i].index + offset + j;
+            if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
+               sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
+               changed = true;
+            }
          }
 
-        struct gl_program *const prog = sh->Program;
-
-        assert(sizeof(prog->SamplerUnits) == sizeof(sh->SamplerUnits));
-
-        /* Determine if any of the samplers used by this shader stage have
-         * been modified.
-         */
-        bool changed = false;
-        for (unsigned j = 0; j < ARRAY_SIZE(prog->SamplerUnits); j++) {
-           if ((sh->active_samplers & (1U << j)) != 0
-               && (prog->SamplerUnits[j] != sh->SamplerUnits[j])) {
-              changed = true;
-              break;
-           }
-        }
-
         if (changed) {
            if (!flushed) {
               FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
               flushed = true;
            }
 
-           memcpy(prog->SamplerUnits,
-                  sh->SamplerUnits,
-                  sizeof(sh->SamplerUnits));
-
+            struct gl_program *const prog = sh->Program;
            _mesa_update_shader_textures_used(shProg, prog);
             if (ctx->Driver.SamplerUniformChange)
               ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
@@ -876,10 +981,10 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
    if (uni->type->is_image()) {
       for (int i = 0; i < MESA_SHADER_STAGES; i++) {
         if (uni->opaque[i].active) {
-            struct gl_shader *sh = shProg->_LinkedShaders[i];
+            struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
 
             for (int j = 0; j < count; j++)
-               sh->ImageUnits[uni->opaque[i].index + offset + j] =
+               sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
                   ((GLint *) values)[j];
          }
       }
@@ -893,20 +998,15 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
  * Note: cols=2, rows=4  ==>  array[2] of vec4
  */
 extern "C" void
-_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
-                    GLuint cols, GLuint rows,
-                     GLint location, GLsizei count,
-                     GLboolean transpose,
-                     const GLvoid *values, enum glsl_base_type basicType)
+_mesa_uniform_matrix(GLint location, GLsizei count,
+                     GLboolean transpose, const void *values,
+                     struct gl_context *ctx, struct gl_shader_program *shProg,
+                     GLuint cols, GLuint rows, enum glsl_base_type basicType)
 {
    unsigned offset;
-   unsigned vectors;
-   unsigned components;
-   unsigned elements;
-   int size_mul;
    struct gl_uniform_storage *const uni =
-      validate_uniform_parameters(ctx, shProg, location, count,
-                                  &offset, "glUniformMatrix");
+      validate_uniform_parameters(location, count, &offset,
+                                  ctx, shProg, "glUniformMatrix");
    if (uni == NULL)
       return;
 
@@ -917,11 +1017,11 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
    }
 
    assert(basicType == GLSL_TYPE_FLOAT || basicType == GLSL_TYPE_DOUBLE);
-   size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
+   const unsigned size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
 
    assert(!uni->type->is_sampler());
-   vectors = uni->type->matrix_columns;
-   components = uni->type->vector_elements;
+   const unsigned vectors = uni->type->matrix_columns;
+   const unsigned components = uni->type->vector_elements;
 
    /* Verify that the types are compatible.  This is greatly simplified for
     * matrices because they can only have a float base type.
@@ -992,10 +1092,10 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
 
    /* Store the data in the "actual type" backing storage for the uniform.
     */
-   elements = components * vectors;
+   const unsigned elements = components * vectors;
 
    if (!transpose) {
-      memcpy(&uni->storage[elements * offset], values,
+      memcpy(&uni->storage[size_mul * elements * offset], values,
             sizeof(uni->storage[0]) * elements * count * size_mul);
    } else if (basicType == GLSL_TYPE_FLOAT) {
       /* Copy and transpose the matrix.
@@ -1030,8 +1130,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
       }
    }
 
-   uni->initialized = true;
-
    _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
 }
 
@@ -1041,7 +1139,7 @@ _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
                                 char *errMsg, size_t errMsgLength)
 {
    /* Shader does not have samplers. */
-   if (shProg->NumUniformStorage == 0)
+   if (shProg->data->NumUniformStorage == 0)
       return true;
 
    if (!shProg->SamplersValidated) {
@@ -1070,58 +1168,46 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline)
     *         - The number of active samplers in the program exceeds the
     *           maximum number of texture image units allowed."
     */
+
+   GLbitfield mask;
+   GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
    unsigned active_samplers = 0;
-   const struct gl_shader_program **shProg =
-      (const struct gl_shader_program **) pipeline->CurrentProgram;
+   const struct gl_program **prog =
+      (const struct gl_program **) pipeline->CurrentProgram;
+
 
-   const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-   memset(unit_types, 0, sizeof(unit_types));
+   memset(TexturesUsed, 0, sizeof(TexturesUsed));
 
    for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
-      if (!shProg[idx])
+      if (!prog[idx])
          continue;
 
-      for (unsigned i = 0; i < shProg[idx]->NumUniformStorage; i++) {
-         const struct gl_uniform_storage *const storage =
-            &shProg[idx]->UniformStorage[i];
-
-         if (!storage->type->is_sampler())
+      mask = prog[idx]->SamplersUsed;
+      while (mask) {
+         const int s = u_bit_scan(&mask);
+         GLuint unit = prog[idx]->SamplerUnits[s];
+         GLuint tgt = prog[idx]->sh.SamplerTargets[s];
+
+         /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
+          * great job of eliminating unused uniforms currently so for now
+          * don't throw an error if two sampler types both point to 0.
+          */
+         if (unit == 0)
             continue;
 
-         active_samplers++;
-
-         const unsigned count = MAX2(1, storage->array_elements);
-         for (unsigned j = 0; j < count; j++) {
-            const unsigned unit = storage->storage[j].i;
-
-            /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
-             * great job of eliminating unused uniforms currently so for now
-             * don't throw an error if two sampler types both point to 0.
-             */
-            if (unit == 0)
-               continue;
-
-            /* The types of the samplers associated with a particular texture
-             * unit must be an exact match.  Page 74 (page 89 of the PDF) of
-             * the OpenGL 3.3 core spec says:
-             *
-             *     "It is not allowed to have variables of different sampler
-             *     types pointing to the same texture image unit within a
-             *     program object."
-             */
-            if (unit_types[unit] == NULL) {
-               unit_types[unit] = storage->type;
-            } else if (unit_types[unit] != storage->type) {
-               pipeline->InfoLog =
-                  ralloc_asprintf(pipeline,
-                                  "Texture unit %d is accessed both as %s "
-                                  "and %s",
-                                  unit, unit_types[unit]->name,
-                                  storage->type->name);
-               return false;
-            }
+         if (TexturesUsed[unit] & ~(1 << tgt)) {
+            pipeline->InfoLog =
+               ralloc_asprintf(pipeline,
+                     "Program %d: "
+                     "Texture unit %d is accessed with 2 different types",
+                     prog[idx]->Id, unit);
+            return false;
          }
+
+         TexturesUsed[unit] |= (1 << tgt);
       }
+
+      active_samplers += prog[idx]->info.num_textures;
    }
 
    if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {