Re: [Mesa-dev] [PATCH 02/10] glsl: serialize methods for IR instructions

2014-02-04 Thread Paul Berry
On 29 January 2014 01:24, Tapani Pälli  wrote:

> +
> +
> +/**
> + * Serialization of exec_list, writes length of the list +
> + * calls serialize_data for each instruction
> + */
> +void
> +serialize_list(exec_list *list, memory_writer &mem)
> +{
> +   uint32_t list_len = 0;
> +   foreach_list(node, list)
> +  list_len++;
> +
> +   mem.write_uint32_t(list_len);
> +
> +   foreach_list(node, list)
> +  ((ir_instruction *)node)->serialize(mem);
>

Nit pick: we could avoid having to walk the list twice by using
mem.overwrite() to write out the length once we've written all the list
elements.  A similar comment applies to ir_call::serialize_data().


> +}
> +
> +
> +static void
> +serialize_glsl_type(const glsl_type *type, memory_writer &mem)
> +{
> +   uint32_t data_len = 0;
> +
> +   mem.write_string(type->name);
> +
> +   unsigned start_pos = mem.position();
> +   mem.write_uint32_t(data_len);
> +
> +   uint32_t type_hash;
> +
> +   /**
> +* notify reader if a user defined type exists already
> +* (has been serialized before)
> +*/
> +   uint8_t user_type_exists = 0;
> +
> +   /* serialize only user defined types */
> +   switch (type->base_type) {
> +   case GLSL_TYPE_ARRAY:
> +   case GLSL_TYPE_STRUCT:
> +   case GLSL_TYPE_INTERFACE:
> +  break;
> +   default:
> +  goto glsl_type_serilization_epilogue;
> +   }
> +
>

With the changes I recommended in the last patch, I believe we can replace
everything from here...


> +   type_hash = _mesa_hash_data(type, sizeof(glsl_type));
>
+
> +   /* check if this type has been written before */
> +   if (mem.data_was_written((void *)type, type_hash))
> +  user_type_exists = 1;
> +   else
> +  mem.mark_data_written((void *)type, type_hash);
>

...to here with:

   user_type_exists = mem.make_unique_id(type, &type_hash);

Although I'd recommend renaming type_hash to type_id so that there's no
confusion about the fact that it's a unique ID and not a hash (hashes
aren't guaranteed to be unique).


> +
> +   mem.write_uint8_t(user_type_exists);
> +   mem.write_uint32_t(type_hash);
> +
> +   /* no need to write again ... */
> +   if (user_type_exists)
> +  goto glsl_type_serilization_epilogue;
>

Nit pick: how about instead of the goto, just do:

if (!user_type_exists) {
   /* glsl type data */
   mem.write_uint32_t((uint32_t) type->length);
   ...
}

data_len = mem.position() - start_pos - sizeof(data_len);
...



> +
> +   /* glsl type data */
> +   mem.write_uint32_t((uint32_t)type->length);
> +   mem.write_uint8_t((uint8_t)type->base_type);
> +   mem.write_uint8_t((uint8_t)type->interface_packing);
> +
> +   if (type->base_type == GLSL_TYPE_ARRAY)
> +  serialize_glsl_type(type->element_type(), mem);
> +   else if (type->base_type == GLSL_TYPE_STRUCT ||
> +  type->base_type == GLSL_TYPE_INTERFACE) {
> +  glsl_struct_field *field = type->fields.structure;
> +  for (unsigned k = 0; k < type->length; k++, field++) {
> + mem.write_string(field->name);
> + serialize_glsl_type(field->type, mem);
> + mem.write_uint8_t((uint8_t)field->row_major);
> + mem.write_int32_t(field->location);
> + mem.write_uint8_t((uint8_t)field->interpolation);
> + mem.write_uint8_t((uint8_t)field->centroid);
> +  }
> +   }
> +
> +glsl_type_serilization_epilogue:
> +
> +   data_len = mem.position() - start_pos - sizeof(data_len);
> +   mem.overwrite(&data_len, sizeof(data_len), start_pos);
> +}
> +
> +
> +void
> +ir_variable::serialize_data(memory_writer &mem)
> +{
> +   /* name can be NULL, see ir_print_visitor for explanation */
> +   const char *non_null_name = name ? name : "parameter";
>

Since mem.write_string handles NULL strings, can we get rid of this?


> +   int64_t unique_id = (int64_t) (intptr_t) this;
> +   uint8_t mode = data.mode;
> +   uint8_t has_constant_value = constant_value ? 1 : 0;
> +   uint8_t has_constant_initializer = constant_initializer ? 1 : 0;
> +
> +   serialize_glsl_type(type, mem);
> +
> +   mem.write_string(non_null_name);
> +   mem.write_int64_t(unique_id);
> +   mem.write_uint8_t(mode);
> +
> +   mem.write(&data, sizeof(data));
> +
> +   mem.write_uint32_t(num_state_slots);
> +   mem.write_uint8_t(has_constant_value);
> +   mem.write_uint8_t(has_constant_initializer);
> +
> +   for (unsigned i = 0; i < num_state_slots; i++) {
> +  mem.write_int32_t(state_slots[i].swizzle);
> +  for (unsigned j = 0; j < 5; j++) {
> + mem.write_int32_t(state_slots[i].tokens[j]);
> +  }
> +   }
> +
> +   if (constant_value)
> +  constant_value->serialize(mem);
> +
> +   if (constant_initializer)
> +  constant_initializer->serialize(mem);
> +
> +   uint8_t has_interface_type = get_interface_type() ? 1 : 0;
> +
> +   mem.write_uint8_t(has_interface_type);
> +   if (has_interface_type)
> +  serialize_glsl_type(get_interface_type(), mem);
> +}
>

Everything's a nit pick except for the suggestion to use make_unique_id().
With that fixed, this patch is

[Mesa-dev] [PATCH 02/10] glsl: serialize methods for IR instructions

2014-01-29 Thread Tapani Pälli
Patch adds a new virtual function for ir_instruction base class which
has to be implemented by each instruction. This data will be used by the
shader binary cache implementation.

Signed-off-by: Tapani Pälli 
---
 src/glsl/Makefile.sources |   1 +
 src/glsl/ir.h |  45 +
 src/glsl/ir_serialize.cpp | 407 ++
 src/glsl/ir_serialize.h   |  36 
 4 files changed, 489 insertions(+)
 create mode 100644 src/glsl/ir_serialize.cpp
 create mode 100644 src/glsl/ir_serialize.h

diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
index e69c1ac..24bb70f 100644
--- a/src/glsl/Makefile.sources
+++ b/src/glsl/Makefile.sources
@@ -45,6 +45,7 @@ LIBGLSL_FILES = \
$(GLSL_SRCDIR)/ir_reader.cpp \
$(GLSL_SRCDIR)/ir_rvalue_visitor.cpp \
$(GLSL_SRCDIR)/ir_set_program_inouts.cpp \
+   $(GLSL_SRCDIR)/ir_serialize.cpp \
$(GLSL_SRCDIR)/ir_validate.cpp \
$(GLSL_SRCDIR)/ir_variable_refcount.cpp \
$(GLSL_SRCDIR)/linker.cpp \
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 19e8383..1e31d70 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -35,6 +35,7 @@
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
 #include "main/mtypes.h"
+#include "memory_writer.h"
 
 #ifdef __cplusplus
 
@@ -107,6 +108,10 @@ public:
/** ir_print_visitor helper for debugging. */
void print(void) const;
 
+   /* serialization */
+   void serialize(memory_writer &mem);
+   virtual void serialize_data(memory_writer &mem) = 0;
+
virtual void accept(ir_visitor *) = 0;
virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
virtual ir_instruction *clone(void *mem_ctx,
@@ -167,6 +172,8 @@ public:
 
virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -379,6 +386,8 @@ public:
   return this;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -769,6 +778,8 @@ public:
ir_function_signature *clone_prototype(void *mem_ctx,
  struct hash_table *ht) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -900,6 +911,8 @@ public:
   return this;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -974,6 +987,8 @@ public:
   return this;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -998,6 +1013,8 @@ public:
 
virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1033,6 +1050,8 @@ public:
 
virtual ir_constant *constant_expression_value(struct hash_table 
*variable_context = NULL);
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1459,6 +1478,8 @@ public:
 */
static ir_expression_operation get_operator(const char *);
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1497,6 +1518,8 @@ public:
   return this;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1583,6 +1606,8 @@ public:
   return value;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1617,6 +1642,8 @@ public:
 
virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1657,6 +1684,8 @@ public:
 
virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1729,6 +1758,8 @@ public:
 
virtual ir_constant *constant_expression_value(struct hash_table 
*variable_context = NULL);
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1840,6 +1871,8 @@ public:
 */
static ir_swizzle *create(ir_rvalue *, const char *, unsigned 
vector_length);
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1943,6 +1976,8 @@ public:
   return this->var;
}
 
+   virtual void serialize_data(memory_writer &mem);
+
virtual void accept(ir_visitor *v)
{
   v->visit(this);
@@ -1992,6 +2027,8 @@ public: