util: move string_to_uint_map to glsl
authorEmil Velikov <emil.velikov@collabora.com>
Sat, 26 Aug 2017 01:37:11 +0000 (02:37 +0100)
committerEmil Velikov <emil.l.velikov@gmail.com>
Tue, 29 Aug 2017 12:40:44 +0000 (13:40 +0100)
The functionality is used by glsl and mesa. With the latter already
depending on the former.

With this in place the src/util/ static library libmesautil.la no longer
has a C++ dependency. Thus objects which use it (like libEGL) don't need
the C++ link.

Cc: "17.2" <mesa-stable@lists.freedesktop.org>
Fixes: 02cc35937277 ("egl/wayland: Use linux-dmabuf interface for buffers")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101851
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Suggested-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Tested-by: Mike Lothian <mike@fireburn.co.uk>
Tested-by: James Harvey <lothmordor@gmail.com>
17 files changed:
src/compiler/Makefile.sources
src/compiler/glsl/link_uniform_initializers.cpp
src/compiler/glsl/link_uniforms.cpp
src/compiler/glsl/linker.cpp
src/compiler/glsl/shader_cache.cpp
src/compiler/glsl/standalone.cpp
src/compiler/glsl/string_to_uint_map.cpp [new file with mode: 0644]
src/compiler/glsl/string_to_uint_map.h [new file with mode: 0644]
src/compiler/glsl/tests/set_uniform_initializer_tests.cpp
src/mesa/main/shader_query.cpp
src/mesa/main/shaderobj.c
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_nir.cpp
src/mesa/state_tracker/st_glsl_to_nir.cpp.orig [new file with mode: 0644]
src/util/Makefile.sources
src/util/string_to_uint_map.cpp [deleted file]
src/util/string_to_uint_map.h [deleted file]

index a56a7103515b31f6212de13d024d2af24dc65633..0153df2d812c2398497581fe1a5baf0f156954e8 100644 (file)
@@ -140,7 +140,9 @@ LIBGLSL_FILES = \
        glsl/program.h \
        glsl/propagate_invariance.cpp \
        glsl/s_expression.cpp \
-       glsl/s_expression.h
+       glsl/s_expression.h \
+       glsl/string_to_uint_map.cpp \
+       glsl/string_to_uint_map.h
 
 LIBGLSL_SHADER_CACHE_FILES = \
        glsl/shader_cache.cpp \
index 4ca1a0fe0c4a1a35a8cb43d88591c7873849c249..01754cd3daf4eee28b26f412a56b37a364ffc36e 100644 (file)
@@ -25,7 +25,7 @@
 #include "ir.h"
 #include "linker.h"
 #include "ir_uniform.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 
 /* These functions are put in a "private" namespace instead of being marked
  * static so that the unit tests can access them.  See
index f7ee17ef02171a6b4951cfefa2b16513963d6a20..7d141549f55ad6f23fb8382b6104cf423909c930 100644 (file)
@@ -27,7 +27,7 @@
 #include "ir_uniform.h"
 #include "glsl_symbol_table.h"
 #include "program.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 #include "ir_array_refcount.h"
 
 /**
index 131518b15fcd54c05fd748d40b094c2dfd98102a..5c3f1d12bbcdd97f37d90375bad342b0e2e9513a 100644 (file)
@@ -75,7 +75,7 @@
 #include "program/program.h"
 #include "util/mesa-sha1.h"
 #include "util/set.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 #include "linker.h"
 #include "link_varyings.h"
 #include "ir_optimization.h"
index a6e998218421edd334c84f9a600059ac6ec05e87..c9109aa222b090c2b211ff5e640742180b080426 100644 (file)
@@ -59,7 +59,7 @@
 #include "program.h"
 #include "shader_cache.h"
 #include "util/mesa-sha1.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 
 extern "C" {
 #include "main/enums.h"
index 7e5c06d20541ebeff1e1f5c87db80f8539ee406a..2f74813182f3683a516bb492443bae0d0e58da32 100644 (file)
@@ -36,7 +36,7 @@
 #include "loop_analysis.h"
 #include "standalone_scaffolding.h"
 #include "standalone.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 #include "util/set.h"
 #include "linker.h"
 #include "glsl_parser_extras.h"
diff --git a/src/compiler/glsl/string_to_uint_map.cpp b/src/compiler/glsl/string_to_uint_map.cpp
new file mode 100644 (file)
index 0000000..35fb76b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file string_to_uint_map.cpp
+ * \brief Dumb wrapprs so that C code can create and destroy maps.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include "string_to_uint_map.h"
+
+extern "C" struct string_to_uint_map *
+string_to_uint_map_ctor()
+{
+   return new string_to_uint_map;
+}
+
+extern "C" void
+string_to_uint_map_dtor(struct string_to_uint_map *map)
+{
+   delete map;
+}
diff --git a/src/compiler/glsl/string_to_uint_map.h b/src/compiler/glsl/string_to_uint_map.h
new file mode 100644 (file)
index 0000000..e0533ec
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef STRING_TO_UINT_MAP_H
+#define STRING_TO_UINT_MAP_H
+
+#include <string.h>
+#include <limits.h>
+#include "util/hash_table.h"
+
+struct string_to_uint_map;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct string_to_uint_map *
+string_to_uint_map_ctor();
+
+void
+string_to_uint_map_dtor(struct string_to_uint_map *);
+
+
+#ifdef __cplusplus
+}
+
+struct string_map_iterate_wrapper_closure {
+   void (*callback)(const char *key, unsigned value, void *closure);
+   void *closure;
+};
+
+/**
+ * Map from a string (name) to an unsigned integer value
+ *
+ * \note
+ * Because of the way this class interacts with the \c hash_table
+ * implementation, values of \c UINT_MAX cannot be stored in the map.
+ */
+struct string_to_uint_map {
+public:
+   string_to_uint_map()
+   {
+      this->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+                                         _mesa_key_string_equal);
+   }
+
+   ~string_to_uint_map()
+   {
+      hash_table_call_foreach(this->ht, delete_key, NULL);
+      _mesa_hash_table_destroy(this->ht, NULL);
+   }
+
+   /**
+    * Remove all mappings from this map.
+    */
+   void clear()
+   {
+      hash_table_call_foreach(this->ht, delete_key, NULL);
+      _mesa_hash_table_clear(this->ht, NULL);
+   }
+
+   /**
+    * Runs a passed callback for the hash
+    */
+   void iterate(void (*func)(const char *, unsigned, void *), void *closure)
+   {
+      struct string_map_iterate_wrapper_closure *wrapper;
+
+      wrapper = (struct string_map_iterate_wrapper_closure *)
+         malloc(sizeof(struct string_map_iterate_wrapper_closure));
+      if (wrapper == NULL)
+         return;
+
+      wrapper->callback = func;
+      wrapper->closure = closure;
+
+      hash_table_call_foreach(this->ht, subtract_one_wrapper, wrapper);
+      free(wrapper);
+   }
+
+   /**
+    * Get the value associated with a particular key
+    *
+    * \return
+    * If \c key is found in the map, \c true is returned.  Otherwise \c false
+    * is returned.
+    *
+    * \note
+    * If \c key is not found in the table, \c value is not modified.
+    */
+   bool get(unsigned &value, const char *key)
+   {
+      hash_entry *entry = _mesa_hash_table_search(this->ht,
+                                                  (const void *) key);
+
+      if (!entry)
+         return false;
+
+      const intptr_t v = (intptr_t) entry->data;
+      value = (unsigned)(v - 1);
+      return true;
+   }
+
+   void put(unsigned value, const char *key)
+   {
+      /* The low-level hash table structure returns NULL if key is not in the
+       * hash table.  However, users of this map might want to store zero as a
+       * valid value in the table.  Bias the value by +1 so that a
+       * user-specified zero is stored as 1.  This enables ::get to tell the
+       * difference between a user-specified zero (returned as 1 by
+       * _mesa_hash_table_search) and the key not in the table (returned as 0 by
+       * _mesa_hash_table_search).
+       *
+       * The net effect is that we can't store UINT_MAX in the table.  This is
+       * because UINT_MAX+1 = 0.
+       */
+      assert(value != UINT_MAX);
+      char *dup_key = strdup(key);
+
+      struct hash_entry *entry = _mesa_hash_table_search(this->ht, dup_key);
+      if (entry) {
+         entry->data = (void *) (intptr_t) (value + 1);
+      } else {
+         _mesa_hash_table_insert(this->ht, dup_key,
+                                 (void *) (intptr_t) (value + 1));
+      }
+
+      if (entry)
+         free(dup_key);
+   }
+
+private:
+   static void delete_key(const void *key, void *data, void *closure)
+   {
+      (void) data;
+      (void) closure;
+
+      free((char *)key);
+   }
+
+   static void subtract_one_wrapper(const void *key, void *data, void *closure)
+   {
+      struct string_map_iterate_wrapper_closure *wrapper =
+         (struct string_map_iterate_wrapper_closure *) closure;
+      unsigned value = (intptr_t) data;
+
+      value -= 1;
+
+      wrapper->callback((const char *) key, value, wrapper->closure);
+   }
+
+   struct hash_table *ht;
+};
+
+#endif /* __cplusplus */
+#endif /* STRING_TO_UINT_MAP_H */
index d30abc320b361b440337b068b00e4970e122169f..94a6d270ec43f342f333780f6308d7da49837c48 100644 (file)
@@ -25,7 +25,7 @@
 #include "main/mtypes.h"
 #include "main/macros.h"
 #include "util/ralloc.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
 #include "uniform_initializer_utils.h"
 
 namespace linker {
index f2bdcaab1212d48c6047c57c7a9629b97a238e24..64e68b4a26d96f9225dc94cc63b33391ebec2258 100644 (file)
@@ -37,7 +37,7 @@
 #include "compiler/glsl/glsl_symbol_table.h"
 #include "compiler/glsl/ir.h"
 #include "compiler/glsl/program.h"
-#include "util/string_to_uint_map.h"
+#include "compiler/glsl/string_to_uint_map.h"
 
 
 static GLint
index 8a5fa5e2dfcfa56d835592d755a0edd4e3a6718f..b9d1079a35abab68fbb776627dcbe057d46249c9 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 
+#include "compiler/glsl/string_to_uint_map.h"
 #include "main/glheader.h"
 #include "main/context.h"
 #include "main/hash.h"
@@ -40,7 +41,6 @@
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "util/ralloc.h"
-#include "util/string_to_uint_map.h"
 #include "util/u_atomic.h"
 
 /**********************************************************************/
index 78f244987839b4cdc2e48d4735bc601d1d7a635d..11207dd82892ffae8590fdfc330a48361e3fbfc3 100644 (file)
 #include "compiler/glsl/linker.h"
 #include "compiler/glsl/program.h"
 #include "compiler/glsl/shader_cache.h"
+#include "compiler/glsl/string_to_uint_map.h"
 #include "program/prog_instruction.h"
 #include "program/prog_optimize.h"
 #include "program/prog_print.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
-#include "util/string_to_uint_map.h"
 
 
 static int swizzle_for_size(int size);
index 38d6c7068c2435fa955a59ec1bf0ed44c700c68c..06a8ee8c612b93a9667a160a92eda08cb9071a1d 100644 (file)
@@ -35,7 +35,6 @@
 #include "main/errors.h"
 #include "main/shaderapi.h"
 #include "main/uniforms.h"
-#include "util/string_to_uint_map.h"
 
 #include "st_context.h"
 #include "st_program.h"
@@ -44,6 +43,7 @@
 #include "compiler/glsl_types.h"
 #include "compiler/glsl/glsl_to_nir.h"
 #include "compiler/glsl/ir.h"
+#include "compiler/glsl/string_to_uint_map.h"
 
 
 static int
diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp.orig b/src/mesa/state_tracker/st_glsl_to_nir.cpp.orig
new file mode 100644 (file)
index 0000000..38d6c70
--- /dev/null
@@ -0,0 +1,479 @@
+/*
+ * Copyright © 2015 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "st_nir.h"
+
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+
+#include "program/program.h"
+#include "program/prog_statevars.h"
+#include "program/prog_parameter.h"
+#include "program/ir_to_mesa.h"
+#include "main/mtypes.h"
+#include "main/errors.h"
+#include "main/shaderapi.h"
+#include "main/uniforms.h"
+#include "util/string_to_uint_map.h"
+
+#include "st_context.h"
+#include "st_program.h"
+
+#include "compiler/nir/nir.h"
+#include "compiler/glsl_types.h"
+#include "compiler/glsl/glsl_to_nir.h"
+#include "compiler/glsl/ir.h"
+
+
+static int
+type_size(const struct glsl_type *type)
+{
+   return type->count_attribute_slots(false);
+}
+
+/* Depending on PIPE_CAP_TGSI_TEXCOORD (st->needs_texcoord_semantic) we
+ * may need to fix up varying slots so the glsl->nir path is aligned
+ * with the anything->tgsi->nir path.
+ */
+static void
+st_nir_fixup_varying_slots(struct st_context *st, struct exec_list *var_list)
+{
+   if (st->needs_texcoord_semantic)
+      return;
+
+   nir_foreach_variable(var, var_list) {
+      if (var->data.location >= VARYING_SLOT_VAR0) {
+         var->data.location += 9;
+      } else if ((var->data.location >= VARYING_SLOT_TEX0) &&
+               (var->data.location <= VARYING_SLOT_TEX7)) {
+         var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
+      }
+   }
+}
+
+/* input location assignment for VS inputs must be handled specially, so
+ * that it is aligned w/ st's vbo state.
+ * (This isn't the case with, for ex, FS inputs, which only need to agree
+ * on varying-slot w/ the VS outputs)
+ */
+static void
+st_nir_assign_vs_in_locations(struct gl_program *prog, nir_shader *nir)
+{
+   unsigned attr, num_inputs = 0;
+   unsigned input_to_index[VERT_ATTRIB_MAX] = {0};
+
+   /* TODO de-duplicate w/ similar code in st_translate_vertex_program()? */
+   for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+      if ((prog->info.inputs_read & BITFIELD64_BIT(attr)) != 0) {
+         input_to_index[attr] = num_inputs;
+         num_inputs++;
+         if ((prog->info.double_inputs_read & BITFIELD64_BIT(attr)) != 0) {
+            /* add placeholder for second part of a double attribute */
+            num_inputs++;
+         }
+      } else {
+         input_to_index[attr] = ~0;
+      }
+   }
+
+   /* bit of a hack, mirroring st_translate_vertex_program */
+   input_to_index[VERT_ATTRIB_EDGEFLAG] = num_inputs;
+
+   nir->num_inputs = 0;
+   nir_foreach_variable_safe(var, &nir->inputs) {
+      attr = var->data.location;
+      assert(attr < ARRAY_SIZE(input_to_index));
+
+      if (input_to_index[attr] != ~0u) {
+         var->data.driver_location = input_to_index[attr];
+         nir->num_inputs++;
+      } else {
+         /* Move unused input variables to the globals list (with no
+          * initialization), to avoid confusing drivers looking through the
+          * inputs array and expecting to find inputs with a driver_location
+          * set.
+          */
+         exec_node_remove(&var->node);
+         var->data.mode = nir_var_global;
+         exec_list_push_tail(&nir->globals, &var->node);
+      }
+   }
+}
+
+static int
+st_nir_lookup_parameter_index(const struct gl_program_parameter_list *params,
+                              const char *name)
+{
+   int loc = _mesa_lookup_parameter_index(params, name);
+
+   /* is there a better way to do this?  If we have something like:
+    *
+    *    struct S {
+    *           float f;
+    *           vec4 v;
+    *    };
+    *    uniform S color;
+    *
+    * Then what we get in prog->Parameters looks like:
+    *
+    *    0: Name=color.f, Type=6, DataType=1406, Size=1
+    *    1: Name=color.v, Type=6, DataType=8b52, Size=4
+    *
+    * So the name doesn't match up and _mesa_lookup_parameter_index()
+    * fails.  In this case just find the first matching "color.*"..
+    *
+    * Note for arrays you could end up w/ color[n].f, for example.
+    *
+    * glsl_to_tgsi works slightly differently in this regard.  It is
+    * emitting something more low level, so it just translates the
+    * params list 1:1 to CONST[] regs.  Going from GLSL IR to TGSI,
+    * it just calculates the additional offset of struct field members
+    * in glsl_to_tgsi_visitor::visit(ir_dereference_record *ir) or
+    * glsl_to_tgsi_visitor::visit(ir_dereference_array *ir).  It never
+    * needs to work backwards to get base var loc from the param-list
+    * which already has them separated out.
+    */
+   if (loc < 0) {
+      int namelen = strlen(name);
+      for (unsigned i = 0; i < params->NumParameters; i++) {
+         struct gl_program_parameter *p = &params->Parameters[i];
+         if ((strncmp(p->Name, name, namelen) == 0) &&
+             ((p->Name[namelen] == '.') || (p->Name[namelen] == '['))) {
+            loc = i;
+            break;
+         }
+      }
+   }
+
+   return loc;
+}
+
+static void
+st_nir_assign_uniform_locations(struct gl_program *prog,
+                                struct gl_shader_program *shader_program,
+                                struct exec_list *uniform_list, unsigned *size)
+{
+   int max = 0;
+   int shaderidx = 0;
+
+   nir_foreach_variable(uniform, uniform_list) {
+      int loc;
+
+      /*
+       * UBO's have their own address spaces, so don't count them towards the
+       * number of global uniforms
+       */
+      if ((uniform->data.mode == nir_var_uniform || uniform->data.mode == nir_var_shader_storage) &&
+          uniform->interface_type != NULL)
+         continue;
+
+      if (uniform->type->is_sampler()) {
+         unsigned val = 0;
+         bool found = shader_program->UniformHash->get(val, uniform->name);
+         loc = shaderidx++;
+         assert(found);
+         (void) found; /* silence unused var warning */
+         /* this ensure that nir_lower_samplers looks at the correct
+          * shader_program->UniformStorage[location]:
+          */
+         uniform->data.location = val;
+      } else if (strncmp(uniform->name, "gl_", 3) == 0) {
+         const gl_state_index *const stateTokens = (gl_state_index *)uniform->state_slots[0].tokens;
+         /* This state reference has already been setup by ir_to_mesa, but we'll
+          * get the same index back here.
+          */
+         loc = _mesa_add_state_reference(prog->Parameters, stateTokens);
+      } else {
+         loc = st_nir_lookup_parameter_index(prog->Parameters, uniform->name);
+      }
+
+      uniform->data.driver_location = loc;
+
+      max = MAX2(max, loc + type_size(uniform->type));
+   }
+   *size = max;
+}
+
+extern "C" {
+
+/* First half of converting glsl_to_nir.. this leaves things in a pre-
+ * nir_lower_io state, so that shader variants can more easily insert/
+ * replace variables, etc.
+ */
+nir_shader *
+st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
+               struct gl_shader_program *shader_program,
+               gl_shader_stage stage)
+{
+   struct pipe_screen *pscreen = st->pipe->screen;
+   enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage);
+   const nir_shader_compiler_options *options;
+   nir_shader *nir;
+
+   assert(pscreen->get_compiler_options);   /* drivers using NIR must implement this */
+
+   options = (const nir_shader_compiler_options *)
+      pscreen->get_compiler_options(pscreen, PIPE_SHADER_IR_NIR, ptarget);
+   assert(options);
+
+   if (prog->nir)
+      return prog->nir;
+
+   nir = glsl_to_nir(shader_program, stage, options);
+
+   NIR_PASS_V(nir, nir_lower_io_to_temporaries,
+         nir_shader_get_entrypoint(nir),
+         true, true);
+   NIR_PASS_V(nir, nir_lower_global_vars_to_local);
+   NIR_PASS_V(nir, nir_split_var_copies);
+   NIR_PASS_V(nir, nir_lower_var_copies);
+   NIR_PASS_V(nir, st_nir_lower_builtin);
+   NIR_PASS_V(nir, nir_lower_atomics, shader_program);
+
+   /* fragment shaders may need : */
+   if (stage == MESA_SHADER_FRAGMENT) {
+      static const gl_state_index wposTransformState[STATE_LENGTH] = {
+         STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
+      };
+      nir_lower_wpos_ytransform_options wpos_options = { { 0 } };
+      struct pipe_screen *pscreen = st->pipe->screen;
+
+      memcpy(wpos_options.state_tokens, wposTransformState,
+             sizeof(wpos_options.state_tokens));
+      wpos_options.fs_coord_origin_upper_left =
+         pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT);
+      wpos_options.fs_coord_origin_lower_left =
+         pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
+      wpos_options.fs_coord_pixel_center_integer =
+         pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
+      wpos_options.fs_coord_pixel_center_half_integer =
+         pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER);
+
+      if (nir_lower_wpos_ytransform(nir, &wpos_options)) {
+         nir_validate_shader(nir);
+         _mesa_add_state_reference(prog->Parameters, wposTransformState);
+      }
+   }
+
+   if (st->ctx->_Shader->Flags & GLSL_DUMP) {
+      _mesa_log("\n");
+      _mesa_log("NIR IR for linked %s program %d:\n",
+             _mesa_shader_stage_to_string(stage),
+             shader_program->Name);
+      nir_print_shader(nir, _mesa_get_log_file());
+      _mesa_log("\n\n");
+   }
+
+   prog->nir = nir;
+
+   return nir;
+}
+
+/* TODO any better helper somewhere to sort a list? */
+
+static void
+insert_sorted(struct exec_list *var_list, nir_variable *new_var)
+{
+   nir_foreach_variable(var, var_list) {
+      if (var->data.location > new_var->data.location) {
+         exec_node_insert_node_before(&var->node, &new_var->node);
+         return;
+      }
+   }
+   exec_list_push_tail(var_list, &new_var->node);
+}
+
+static void
+sort_varyings(struct exec_list *var_list)
+{
+   struct exec_list new_list;
+   exec_list_make_empty(&new_list);
+   nir_foreach_variable_safe(var, var_list) {
+      exec_node_remove(&var->node);
+      insert_sorted(&new_list, var);
+   }
+   exec_list_move_nodes_to(&new_list, var_list);
+}
+
+/* Second half of preparing nir from glsl, which happens after shader
+ * variant lowering.
+ */
+void
+st_finalize_nir(struct st_context *st, struct gl_program *prog, nir_shader *nir)
+{
+   struct pipe_screen *screen = st->pipe->screen;
+
+   NIR_PASS_V(nir, nir_split_var_copies);
+   NIR_PASS_V(nir, nir_lower_var_copies);
+   NIR_PASS_V(nir, nir_lower_io_types);
+
+   if (nir->stage == MESA_SHADER_VERTEX) {
+      /* Needs special handling so drvloc matches the vbo state: */
+      st_nir_assign_vs_in_locations(prog, nir);
+      /* Re-lower global vars, to deal with any dead VS inputs. */
+      NIR_PASS_V(nir, nir_lower_global_vars_to_local);
+
+      sort_varyings(&nir->outputs);
+      nir_assign_var_locations(&nir->outputs,
+                               &nir->num_outputs,
+                               type_size);
+      st_nir_fixup_varying_slots(st, &nir->outputs);
+   } else if (nir->stage == MESA_SHADER_FRAGMENT) {
+      sort_varyings(&nir->inputs);
+      nir_assign_var_locations(&nir->inputs,
+                               &nir->num_inputs,
+                               type_size);
+      st_nir_fixup_varying_slots(st, &nir->inputs);
+      nir_assign_var_locations(&nir->outputs,
+                               &nir->num_outputs,
+                               type_size);
+   } else if (nir->stage == MESA_SHADER_COMPUTE) {
+       /* TODO? */
+   } else {
+      unreachable("invalid shader type for tgsi bypass\n");
+   }
+
+   struct gl_shader_program *shader_program;
+   switch (nir->stage) {
+   case MESA_SHADER_VERTEX:
+      shader_program = ((struct st_vertex_program *)prog)->shader_program;
+      break;
+   case MESA_SHADER_FRAGMENT:
+      shader_program = ((struct st_fragment_program *)prog)->shader_program;
+      break;
+   case MESA_SHADER_COMPUTE:
+      shader_program = ((struct st_compute_program *)prog)->shader_program;
+      break;
+   default:
+      assert(!"should not be reached");
+      return;
+   }
+
+   NIR_PASS_V(nir, nir_lower_atomics_to_ssbo,
+         st->ctx->Const.Program[nir->stage].MaxAtomicBuffers);
+
+   st_nir_assign_uniform_locations(prog, shader_program,
+                                   &nir->uniforms, &nir->num_uniforms);
+
+   NIR_PASS_V(nir, nir_lower_system_values);
+
+   if (screen->get_param(screen, PIPE_CAP_NIR_SAMPLERS_AS_DEREF))
+      NIR_PASS_V(nir, nir_lower_samplers_as_deref, shader_program);
+   else
+      NIR_PASS_V(nir, nir_lower_samplers, shader_program);
+}
+
+struct gl_program *
+st_nir_get_mesa_program(struct gl_context *ctx,
+                        struct gl_shader_program *shader_program,
+                        struct gl_linked_shader *shader)
+{
+   struct gl_program *prog;
+
+   validate_ir_tree(shader->ir);
+
+   prog = shader->Program;
+
+   prog->Parameters = _mesa_new_parameter_list();
+
+   do_set_program_inouts(shader->ir, prog, shader->Stage);
+
+   _mesa_copy_linked_program_data(shader_program, shader);
+   _mesa_generate_parameters_list_for_uniforms(ctx, shader_program, shader,
+                                               prog->Parameters);
+
+   /* Make a pass over the IR to add state references for any built-in
+    * uniforms that are used.  This has to be done now (during linking).
+    * Code generation doesn't happen until the first time this shader is
+    * used for rendering.  Waiting until then to generate the parameters is
+    * too late.  At that point, the values for the built-in uniforms won't
+    * get sent to the shader.
+    */
+   foreach_in_list(ir_instruction, node, shader->ir) {
+      ir_variable *var = node->as_variable();
+
+      if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
+          (strncmp(var->name, "gl_", 3) != 0))
+         continue;
+
+      const ir_state_slot *const slots = var->get_state_slots();
+      assert(slots != NULL);
+
+      for (unsigned int i = 0; i < var->get_num_state_slots(); i++) {
+         _mesa_add_state_reference(prog->Parameters,
+                                   (gl_state_index *) slots[i].tokens);
+      }
+   }
+
+   if (ctx->_Shader->Flags & GLSL_DUMP) {
+      _mesa_log("\n");
+      _mesa_log("GLSL IR for linked %s program %d:\n",
+             _mesa_shader_stage_to_string(shader->Stage),
+             shader_program->Name);
+      _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
+      _mesa_log("\n\n");
+   }
+
+   prog->ShadowSamplers = shader->shadow_samplers;
+   prog->ExternalSamplersUsed = gl_external_samplers(prog);
+   _mesa_update_shader_textures_used(shader_program, prog);
+
+   /* Avoid reallocation of the program parameter list, because the uniform
+    * storage is only associated with the original parameter list.
+    * This should be enough for Bitmap and DrawPixels constants.
+    */
+   _mesa_reserve_parameter_storage(prog->Parameters, 8);
+
+   /* This has to be done last.  Any operation the can cause
+    * prog->ParameterValues to get reallocated (e.g., anything that adds a
+    * program constant) has to happen before creating this linkage.
+    */
+   _mesa_associate_uniform_storage(ctx, shader_program, prog, true);
+
+   struct st_vertex_program *stvp;
+   struct st_fragment_program *stfp;
+   struct st_compute_program *stcp;
+
+   switch (shader->Stage) {
+   case MESA_SHADER_VERTEX:
+      stvp = (struct st_vertex_program *)prog;
+      stvp->shader_program = shader_program;
+      break;
+   case MESA_SHADER_FRAGMENT:
+      stfp = (struct st_fragment_program *)prog;
+      stfp->shader_program = shader_program;
+      break;
+   case MESA_SHADER_COMPUTE:
+      stcp = (struct st_compute_program *)prog;
+      stcp->shader_program = shader_program;
+      break;
+   default:
+      assert(!"should not be reached");
+      return NULL;
+   }
+
+   return prog;
+}
+
+} /* extern "C" */
index 3315285f05e975238841e85f194e7dc6bfb9b097..4ed4e39f039c27d9f2c2e8a6ae8cab6236408538 100644 (file)
@@ -37,8 +37,6 @@ MESA_UTIL_FILES := \
        simple_list.h \
        slab.c \
        slab.h \
-       string_to_uint_map.cpp \
-       string_to_uint_map.h \
        strndup.h \
        strtod.c \
        strtod.h \
diff --git a/src/util/string_to_uint_map.cpp b/src/util/string_to_uint_map.cpp
deleted file mode 100644 (file)
index 35fb76b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file string_to_uint_map.cpp
- * \brief Dumb wrapprs so that C code can create and destroy maps.
- *
- * \author Ian Romanick <ian.d.romanick@intel.com>
- */
-#include "string_to_uint_map.h"
-
-extern "C" struct string_to_uint_map *
-string_to_uint_map_ctor()
-{
-   return new string_to_uint_map;
-}
-
-extern "C" void
-string_to_uint_map_dtor(struct string_to_uint_map *map)
-{
-   delete map;
-}
diff --git a/src/util/string_to_uint_map.h b/src/util/string_to_uint_map.h
deleted file mode 100644 (file)
index e0533ec..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright © 2008 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- */
-
-#ifndef STRING_TO_UINT_MAP_H
-#define STRING_TO_UINT_MAP_H
-
-#include <string.h>
-#include <limits.h>
-#include "util/hash_table.h"
-
-struct string_to_uint_map;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct string_to_uint_map *
-string_to_uint_map_ctor();
-
-void
-string_to_uint_map_dtor(struct string_to_uint_map *);
-
-
-#ifdef __cplusplus
-}
-
-struct string_map_iterate_wrapper_closure {
-   void (*callback)(const char *key, unsigned value, void *closure);
-   void *closure;
-};
-
-/**
- * Map from a string (name) to an unsigned integer value
- *
- * \note
- * Because of the way this class interacts with the \c hash_table
- * implementation, values of \c UINT_MAX cannot be stored in the map.
- */
-struct string_to_uint_map {
-public:
-   string_to_uint_map()
-   {
-      this->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
-                                         _mesa_key_string_equal);
-   }
-
-   ~string_to_uint_map()
-   {
-      hash_table_call_foreach(this->ht, delete_key, NULL);
-      _mesa_hash_table_destroy(this->ht, NULL);
-   }
-
-   /**
-    * Remove all mappings from this map.
-    */
-   void clear()
-   {
-      hash_table_call_foreach(this->ht, delete_key, NULL);
-      _mesa_hash_table_clear(this->ht, NULL);
-   }
-
-   /**
-    * Runs a passed callback for the hash
-    */
-   void iterate(void (*func)(const char *, unsigned, void *), void *closure)
-   {
-      struct string_map_iterate_wrapper_closure *wrapper;
-
-      wrapper = (struct string_map_iterate_wrapper_closure *)
-         malloc(sizeof(struct string_map_iterate_wrapper_closure));
-      if (wrapper == NULL)
-         return;
-
-      wrapper->callback = func;
-      wrapper->closure = closure;
-
-      hash_table_call_foreach(this->ht, subtract_one_wrapper, wrapper);
-      free(wrapper);
-   }
-
-   /**
-    * Get the value associated with a particular key
-    *
-    * \return
-    * If \c key is found in the map, \c true is returned.  Otherwise \c false
-    * is returned.
-    *
-    * \note
-    * If \c key is not found in the table, \c value is not modified.
-    */
-   bool get(unsigned &value, const char *key)
-   {
-      hash_entry *entry = _mesa_hash_table_search(this->ht,
-                                                  (const void *) key);
-
-      if (!entry)
-         return false;
-
-      const intptr_t v = (intptr_t) entry->data;
-      value = (unsigned)(v - 1);
-      return true;
-   }
-
-   void put(unsigned value, const char *key)
-   {
-      /* The low-level hash table structure returns NULL if key is not in the
-       * hash table.  However, users of this map might want to store zero as a
-       * valid value in the table.  Bias the value by +1 so that a
-       * user-specified zero is stored as 1.  This enables ::get to tell the
-       * difference between a user-specified zero (returned as 1 by
-       * _mesa_hash_table_search) and the key not in the table (returned as 0 by
-       * _mesa_hash_table_search).
-       *
-       * The net effect is that we can't store UINT_MAX in the table.  This is
-       * because UINT_MAX+1 = 0.
-       */
-      assert(value != UINT_MAX);
-      char *dup_key = strdup(key);
-
-      struct hash_entry *entry = _mesa_hash_table_search(this->ht, dup_key);
-      if (entry) {
-         entry->data = (void *) (intptr_t) (value + 1);
-      } else {
-         _mesa_hash_table_insert(this->ht, dup_key,
-                                 (void *) (intptr_t) (value + 1));
-      }
-
-      if (entry)
-         free(dup_key);
-   }
-
-private:
-   static void delete_key(const void *key, void *data, void *closure)
-   {
-      (void) data;
-      (void) closure;
-
-      free((char *)key);
-   }
-
-   static void subtract_one_wrapper(const void *key, void *data, void *closure)
-   {
-      struct string_map_iterate_wrapper_closure *wrapper =
-         (struct string_map_iterate_wrapper_closure *) closure;
-      unsigned value = (intptr_t) data;
-
-      value -= 1;
-
-      wrapper->callback((const char *) key, value, wrapper->closure);
-   }
-
-   struct hash_table *ht;
-};
-
-#endif /* __cplusplus */
-#endif /* STRING_TO_UINT_MAP_H */