diff options
author | Tapani Pälli <tapani.palli@intel.com> | 2014-04-03 07:54:54 +0300 |
---|---|---|
committer | Tapani Pälli <tapani.palli@intel.com> | 2014-05-05 10:41:57 +0300 |
commit | 614d9e2d3ce7c1343e363c262aefa12713296ff7 (patch) | |
tree | f8ce90366fc7f3c17e3919516ffbcbb0fc326dbc | |
parent | 0d30c775c3f0c071052accd363567b2484159bc8 (diff) |
glsl: serialize methods for IR instructions
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@intel.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
-rw-r--r-- | src/glsl/Makefile.sources | 1 | ||||
-rw-r--r-- | src/glsl/ir.h | 45 | ||||
-rw-r--r-- | src/glsl/ir_serialize.cpp | 402 | ||||
-rw-r--r-- | src/glsl/ir_serialize.h | 36 |
4 files changed, 484 insertions, 0 deletions
diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 5945590a57e..fe93e91692f 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 6c7c60a27d9..57d701acc5f 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 @@ -108,6 +109,10 @@ public: void print(void) const; void fprint(FILE *f) 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, @@ -168,6 +173,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); @@ -382,6 +389,8 @@ public: virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_variable *as_variable() { return this; @@ -791,6 +800,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); @@ -917,6 +928,8 @@ public: virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_function *as_function() { return this; @@ -991,6 +1004,8 @@ public: virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_if *as_if() { return this; @@ -1020,6 +1035,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); @@ -1053,6 +1070,8 @@ public: virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual void accept(ir_visitor *v) @@ -1439,6 +1458,8 @@ public: virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + /** * Attempt to constant-fold the expression * @@ -1524,6 +1545,8 @@ public: virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_call *as_call() @@ -1607,6 +1630,8 @@ public: virtual ir_return *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_return *as_return() { return this; @@ -1651,6 +1676,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); @@ -1691,6 +1718,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); @@ -1761,6 +1790,8 @@ public: virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual void accept(ir_visitor *v) @@ -1862,6 +1893,8 @@ public: virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_swizzle *as_swizzle() @@ -1931,6 +1964,8 @@ public: virtual ir_dereference_variable *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_dereference_variable *as_dereference_variable() @@ -1982,6 +2017,8 @@ public: virtual ir_dereference_array *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_dereference_array *as_dereference_array() @@ -2023,6 +2060,8 @@ public: virtual ir_dereference_record *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_dereference_record *as_dereference_record() @@ -2093,6 +2132,8 @@ public: virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const; + virtual void serialize_data(memory_writer &mem); + virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); virtual ir_constant *as_constant() @@ -2221,6 +2262,8 @@ public: return new(mem_ctx) ir_emit_vertex(); } + virtual void serialize_data(memory_writer &mem); + virtual ir_visitor_status accept(ir_hierarchical_visitor *); }; @@ -2245,6 +2288,8 @@ public: return new(mem_ctx) ir_end_primitive(); } + virtual void serialize_data(memory_writer &mem); + virtual ir_visitor_status accept(ir_hierarchical_visitor *); }; diff --git a/src/glsl/ir_serialize.cpp b/src/glsl/ir_serialize.cpp new file mode 100644 index 00000000000..225b34adfc1 --- /dev/null +++ b/src/glsl/ir_serialize.cpp @@ -0,0 +1,402 @@ +/* -*- 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; + + unsigned start_pos = mem.position(); + mem.write_uint32_t(list_len); + + foreach_list(node, list) { + ((ir_instruction *)node)->serialize(mem); + list_len++; + } + + mem.overwrite(&list_len, sizeof(list_len), start_pos); +} + + +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_id; + + /** + * 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; + } + + user_type_exists = mem.make_unique_id(type, &type_id); + + mem.write_uint8_t(user_type_exists); + mem.write_uint32_t(type_id); + + /* 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(field, sizeof(glsl_struct_field)); + mem.write_string(field->name); + serialize_glsl_type(field->type, mem); + } + } + +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); + + unsigned start_pos = mem.position(); + mem.write_uint8_t(list_len); + + foreach_list(node, &this->actual_parameters) { + serialize_rvalue((ir_rvalue*)node, mem); + list_len++; + } + + mem.overwrite(&list_len, sizeof(list_len), start_pos); + 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(¶meters, 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 00000000000..d6c4741f47e --- /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 */ |