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

Tapani Pälli tapani.palli at intel.com
Wed Jan 29 01:24:57 PST 2014


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 <tapani.palli at intel.com>
---
 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:
     */
    virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -2040,6 +2077,8 @@ public:
     */
    virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
 
+   virtual void serialize_data(memory_writer &mem);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -2102,6 +2141,8 @@ public:
       return this;
    }
 
+   virtual void serialize_data(memory_writer &mem);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -2207,6 +2248,8 @@ public:
       ir_type = ir_type_emit_vertex;
    }
 
+   virtual void serialize_data(memory_writer &mem);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -2231,6 +2274,8 @@ public:
       ir_type = ir_type_end_primitive;
    }
 
+   virtual void serialize_data(memory_writer &mem);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
diff --git a/src/glsl/ir_serialize.cpp b/src/glsl/ir_serialize.cpp
new file mode 100644
index 0000000..087ee97
--- /dev/null
+++ b/src/glsl/ir_serialize.cpp
@@ -0,0 +1,407 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2013 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.
+ */
+
+#include "ir_serialize.h"
+
+
+/**
+ * Wraps serialization of an ir instruction, writes ir_type
+ * and length of each instruction package as a header for it
+ */
+void
+ir_instruction::serialize(memory_writer &mem)
+{
+   uint32_t data_len = 0;
+   uint8_t ir_type = this->ir_type;
+   mem.write_uint8_t(ir_type);
+
+   unsigned start_pos = mem.position();
+   mem.write_uint32_t(data_len);
+
+   this->serialize_data(mem);
+
+   data_len = mem.position() - start_pos - sizeof(data_len);
+   mem.overwrite(&data_len, sizeof(data_len), start_pos);
+}
+
+
+/**
+ * Wraps rvalue serialization, rvalue has its type or
+ * ir_type_unset written before it to indicate if value is NULL
+ */
+static void
+serialize_rvalue(ir_rvalue *val, memory_writer &mem)
+{
+   uint8_t ir_type = val ? val->ir_type : ir_type_unset;
+   mem.write_uint8_t(ir_type);
+
+   if (val)
+      val->serialize(mem);
+}
+
+
+/**
+ * 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);
+}
+
+
+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;
+   }
+
+   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);
+
+   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;
+
+   /* 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";
+   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);
+}
+
+
+void
+ir_assignment::serialize_data(memory_writer &mem)
+{
+   uint8_t assignment_mask = write_mask;
+   mem.write_uint8_t(assignment_mask);
+
+   serialize_rvalue(lhs, mem);
+   serialize_rvalue(condition, mem);
+   serialize_rvalue(rhs, mem);
+}
+
+
+void
+ir_call::serialize_data(memory_writer &mem)
+{
+   mem.write_string(callee_name());
+
+   uint8_t list_len = 0;
+   uint8_t uses_builtin = use_builtin;
+
+   serialize_rvalue(return_deref, mem);
+
+   /* call parameter list */
+   foreach_list(node, &this->actual_parameters)
+      list_len++;
+
+   mem.write_uint8_t(list_len);
+
+   foreach_list(node, &this->actual_parameters)
+      serialize_rvalue((ir_rvalue*)node, mem);
+
+   mem.write_uint8_t(uses_builtin);
+}
+
+
+void
+ir_constant::serialize_data(memory_writer &mem)
+{
+   serialize_glsl_type(type, mem);
+
+   mem.write(&value, sizeof(ir_constant_data));
+
+   if (array_elements) {
+      for (unsigned i = 0; i < type->length; i++)
+         array_elements[i]->serialize(mem);
+   }
+
+   /* struct constant, dump components exec_list */
+   if (!components.is_empty())
+      serialize_list(&components, mem);
+}
+
+
+void
+ir_dereference_array::serialize_data(memory_writer &mem)
+{
+   serialize_rvalue(array, mem);
+   serialize_rvalue(array_index, mem);
+}
+
+
+void
+ir_dereference_record::serialize_data(memory_writer &mem)
+{
+   mem.write_string(field);
+   serialize_rvalue(record, mem);
+}
+
+
+
+/**
+ * address of the variable is used as unique identifier for it
+ */
+void
+ir_dereference_variable::serialize_data(memory_writer &mem)
+{
+   mem.write_int64_t((int64_t) (intptr_t) var);
+}
+
+
+void
+ir_discard::serialize_data(memory_writer &mem)
+{
+   serialize_rvalue(condition, mem);
+}
+
+
+void
+ir_expression::serialize_data(memory_writer &mem)
+{
+   uint32_t num_operands = get_num_operands();
+   uint32_t exp_operation = operation;
+
+   serialize_glsl_type(type, mem);
+
+   mem.write_uint32_t(exp_operation);
+   mem.write_uint32_t(num_operands);
+
+   for (unsigned i = 0; i < num_operands; i++)
+      serialize_rvalue(operands[i], mem);
+}
+
+
+void
+ir_function::serialize_data(memory_writer &mem)
+{
+   mem.write_string(name);
+   serialize_list(&signatures, mem);
+}
+
+
+void
+ir_function_signature::serialize_data(memory_writer &mem)
+{
+   uint8_t builtin_func = is_builtin();
+   mem.write_uint8_t(builtin_func);
+
+   /* dump the return type of function */
+   serialize_glsl_type(return_type, mem);
+
+   /* function parameters */
+   serialize_list(&parameters, mem);
+
+   /* function body */
+   serialize_list(&body, mem);
+}
+
+
+void
+ir_if::serialize_data(memory_writer &mem)
+{
+   serialize_rvalue(condition, mem);
+   serialize_list(&then_instructions, mem);
+   serialize_list(&else_instructions, mem);
+}
+
+
+void
+ir_loop::serialize_data(memory_writer &mem)
+{
+   serialize_list(&body_instructions, mem);
+}
+
+
+void
+ir_loop_jump::serialize_data(memory_writer &mem)
+{
+   uint8_t jump_mode = mode;
+   mem.write_uint8_t(jump_mode);
+}
+
+
+void
+ir_return::serialize_data(memory_writer &mem)
+{
+   serialize_rvalue(value, mem);
+}
+
+
+void
+ir_swizzle::serialize_data(memory_writer &mem)
+{
+   mem.write(&mask, sizeof(ir_swizzle_mask));
+   serialize_rvalue(val, mem);
+}
+
+
+void
+ir_texture::serialize_data(memory_writer &mem)
+{
+   mem.write_int32_t((int32_t)op);
+
+   serialize_glsl_type(type, mem);
+
+   /* sampler */
+   mem.write_uint8_t((uint8_t)sampler->ir_type);
+
+   sampler->serialize(mem);
+
+   serialize_rvalue(coordinate, mem);
+   serialize_rvalue(projector, mem);
+   serialize_rvalue(shadow_comparitor, mem);
+   serialize_rvalue(offset, mem);
+
+   /* lod_info structure */
+   serialize_rvalue(lod_info.lod, mem);
+   serialize_rvalue(lod_info.bias, mem);
+   serialize_rvalue(lod_info.sample_index, mem);
+   serialize_rvalue(lod_info.component, mem);
+   serialize_rvalue(lod_info.grad.dPdx, mem);
+   serialize_rvalue(lod_info.grad.dPdy, mem);
+}
+
+
+void
+ir_emit_vertex::serialize_data(memory_writer &mem)
+{
+   /* no data */
+}
+
+
+void
+ir_end_primitive::serialize_data(memory_writer &mem)
+{
+   /* no data */
+}
+
+
+void
+ir_rvalue::serialize_data(memory_writer &mem)
+{
+   assert(0 && "unreachable");
+}
diff --git a/src/glsl/ir_serialize.h b/src/glsl/ir_serialize.h
new file mode 100644
index 0000000..d6c4741
--- /dev/null
+++ b/src/glsl/ir_serialize.h
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2013 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.
+ */
+
+#pragma once
+#ifndef IR_SERIALIZE_H
+#define IR_SERIALIZE_H
+
+#include "ir.h"
+#include "memory_writer.h"
+#include "main/hash_table.h"
+
+void
+serialize_list(exec_list *list, memory_writer &mem);
+
+#endif /* IR_SERIALIZE_H */
-- 
1.8.5.3



More information about the mesa-dev mailing list