Mesa (glsl2): glsl_type: Add get_record_instance method

Ian Romanick idr at kemper.freedesktop.org
Tue Jun 29 11:54:42 PDT 2010


Module: Mesa
Branch: glsl2
Commit: 49e3577b91f44013746f7a3db411e7041b7d899e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=49e3577b91f44013746f7a3db411e7041b7d899e

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Mon Jun 28 11:54:57 2010 -0700

glsl_type: Add get_record_instance method

---

 src/glsl/ast_to_hir.cpp |    4 +-
 src/glsl/glsl_types.cpp |   72 +++++++++++++++++++++++++++++++++++++++++++++++
 src/glsl/glsl_types.h   |   12 ++++++++
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 54a8e9e..664e468 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2383,7 +2383,6 @@ ir_rvalue *
 ast_struct_specifier::hir(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
-   void *ctx = talloc_parent(state);
    unsigned decl_count = 0;
 
    /* Make an initial pass over the list of structure fields to determine how
@@ -2446,7 +2445,8 @@ ast_struct_specifier::hir(exec_list *instructions,
       name = this->name;
    }
 
-   glsl_type *t = new(ctx) glsl_type(fields, decl_count, name);
+   const glsl_type *t =
+      glsl_type::get_record_instance(fields, decl_count, name);
 
    YYLTYPE loc = this->get_location();
    if (!state->symbols->add_type(name, t)) {
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 158659c..672a7f7 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -32,6 +32,7 @@ extern "C" {
 }
 
 hash_table *glsl_type::array_types = NULL;
+hash_table *glsl_type::record_types = NULL;
 
 glsl_type::glsl_type(GLenum gl_type,
 		     unsigned base_type, unsigned vector_elements,
@@ -384,6 +385,77 @@ glsl_type::get_array_instance(void *ctx, const glsl_type *base,
 }
 
 
+int
+glsl_type::record_key_compare(const void *a, const void *b)
+{
+   const glsl_type *const key1 = (glsl_type *) a;
+   const glsl_type *const key2 = (glsl_type *) b;
+
+   /* Return zero is the types match (there is zero difference) or non-zero
+    * otherwise.
+    */
+   if (strcmp(key1->name, key2->name) != 0)
+      return 1;
+
+   if (key1->length != key2->length)
+      return 1;
+
+   for (unsigned i = 0; i < key1->length; i++)
+      /* FINISHME: Is the name of the structure field also significant? */
+      if (key1->fields.structure[i].type != key2->fields.structure[i].type)
+	 return 1;
+
+   return 0;
+}
+
+
+unsigned
+glsl_type::record_key_hash(const void *a)
+{
+   const glsl_type *const key = (glsl_type *) a;
+   char hash_key[128];
+   unsigned size = 0;
+
+   size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
+
+   for (unsigned i = 0; i < key->length; i++) {
+      if (size >= sizeof(hash_key))
+	 break;
+
+      size += snprintf(& hash_key[size], sizeof(hash_key) - size,
+		       "%p", key->fields.structure[i].type);
+   }
+
+   return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_record_instance(const glsl_struct_field *fields,
+			       unsigned num_fields,
+			       const char *name)
+{
+   const glsl_type key(fields, num_fields, name);
+
+   if (record_types == NULL) {
+      record_types = hash_table_ctor(64, record_key_hash, record_key_compare);
+   }
+
+   const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key);
+   if (t == NULL) {
+      t = new(NULL) glsl_type(fields, num_fields, name);
+
+      hash_table_insert(record_types, (void *) t, t);
+   }
+
+   assert(t->base_type == GLSL_TYPE_STRUCT);
+   assert(t->length == num_fields);
+   assert(strcmp(t->name, name) == 0);
+
+   return t;
+}
+
+
 const glsl_type *
 glsl_type::field_type(const char *name) const
 {
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index e1bfd34..a1c9fae 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -206,6 +206,12 @@ struct glsl_type {
 					      unsigned elements);
 
    /**
+    * Get the instance of a record type
+    */
+   static const glsl_type *get_record_instance(const glsl_struct_field *fields,
+					       unsigned num_fields,
+					       const char *name);
+   /**
     * Generate the constructor for this type and add it to the symbol table
     */
    class ir_function *generate_constructor(class glsl_symbol_table *) const;
@@ -407,6 +413,12 @@ private:
    static int array_key_compare(const void *a, const void *b);
    static unsigned array_key_hash(const void *key);
 
+   /** Hash table containing the known record types. */
+   static struct hash_table *record_types;
+
+   static int record_key_compare(const void *a, const void *b);
+   static unsigned record_key_hash(const void *key);
+
    /**
     * \name Pointers to various type singletons
     */



More information about the mesa-commit mailing list