These utility functions for serialization can be utilized by binary shader cache and ARB_get_program_binary extension.
Signed-off-by: Tapani Pälli <tapani.pa...@intel.com> --- src/glsl/Makefile.sources | 1 + src/glsl/shader_cache.h | 86 +++++++++++++++ src/glsl/shader_serialize.cpp | 240 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 src/glsl/shader_cache.h create mode 100644 src/glsl/shader_serialize.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 06e0ae5..f6a86f2 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -104,6 +104,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ $(GLSL_SRCDIR)/opt_vectorize.cpp \ $(GLSL_SRCDIR)/s_expression.cpp \ + $(GLSL_SRCDIR)/shader_serialize.cpp \ $(GLSL_SRCDIR)/strtod.c # glsl_compiler diff --git a/src/glsl/shader_cache.h b/src/glsl/shader_cache.h new file mode 100644 index 0000000..2f75e83 --- /dev/null +++ b/src/glsl/shader_cache.h @@ -0,0 +1,86 @@ +/* -*- 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 SHADER_CACHE_H +#define SHADER_CACHE_H + +#include "main/shaderobj.h" +#include "main/uniforms.h" +#include "main/macros.h" +#include "program/hash_table.h" +#include "ir.h" + +#ifdef __cplusplus +#include "shader_cache_magic.h" +const uint32_t cache_validation_data[] = { + ir_type_max, + GLSL_TYPE_ERROR, + sizeof(long), + sizeof(gl_shader), + sizeof(gl_program), + sizeof(gl_shader_program), + sizeof(gl_uniform_storage), + sizeof(gl_program_parameter_list), + sizeof(gl_program_parameter), + sizeof(ir_variable), + sizeof(ir_assignment), + sizeof(ir_call), + sizeof(ir_constant), + sizeof(ir_dereference_array), + sizeof(ir_dereference_record), + sizeof(ir_dereference_variable), + sizeof(ir_discard), + sizeof(ir_expression), + sizeof(ir_function), + sizeof(ir_function_signature), + sizeof(ir_if), + sizeof(ir_loop), + sizeof(ir_loop_jump), + sizeof(ir_return), + sizeof(ir_swizzle), + sizeof(ir_texture), + sizeof(ir_emit_vertex), + sizeof(ir_end_primitive) +}; +#define num_cache_validation_data_items\ + sizeof(cache_validation_data)/sizeof(uint32_t) +#endif + +/* C API for the cache */ +#ifdef __cplusplus +extern "C" { +#endif + +char * +mesa_shader_serialize(struct gl_shader *shader, size_t *size); + +char * +mesa_program_serialize(struct gl_shader_program *prog, size_t *size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SHADER_CACHE_H */ diff --git a/src/glsl/shader_serialize.cpp b/src/glsl/shader_serialize.cpp new file mode 100644 index 0000000..842bc3a --- /dev/null +++ b/src/glsl/shader_serialize.cpp @@ -0,0 +1,240 @@ +/* -*- 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 "shader_cache.h" +#include "ir_serialize.h" + + +static void +serialize_program_parameters(struct gl_program_parameter_list *list, + memory_writer &blob) +{ + for (unsigned i = 0; i < list->NumParameters; i++) { + blob.write_string(list->Parameters[i].Name); + blob.write(&list->Parameters[i], sizeof(struct gl_program_parameter)); + blob.write(list->ParameterValues, 4 * sizeof(gl_constant_value)); + } + blob.write_uint32_t(list->StateFlags); +} + + +/* gl_program contains post-link data populated by the driver */ +static void +serialize_gl_program(struct gl_shader *shader, memory_writer &blob) +{ + blob.write(shader->Program, sizeof(struct gl_program)); + blob.write_string((const char *)shader->Program->String); + + uint8_t num_parameters = _mesa_num_parameters(shader->Program->Parameters); + blob.write_uint8_t(num_parameters); + + if (num_parameters > 0) + serialize_program_parameters(shader->Program->Parameters, blob); +} + + +/** + * Serializes gl_shader structure, writes shader header + * information and exec_list of instructions + */ +extern "C" char * +mesa_shader_serialize(struct gl_shader *shader, size_t *size) +{ + *size = 0; + + memory_writer blob; + + int32_t start_pos = blob.position(); + uint32_t shader_data_len = 0; + uint32_t shader_type = shader->Type; + + blob.write_uint32_t(shader_data_len); + blob.write_uint32_t(shader_type); + + blob.write(shader, sizeof(struct gl_shader)); + + /* gl_program structure */ + serialize_gl_program(shader, blob); + + /* dump all shader instructions */ + serialize_list(shader->ir, blob); + + shader_data_len = blob.position() - + start_pos - sizeof(shader_data_len); + blob.overwrite(&shader_data_len, sizeof(shader_data_len), start_pos); + + return blob.release_memory(size); +} + + +/** + * helper structure for hash serialization, hash size is + * counted to item_count during serialization + */ +struct hash_serialize_data +{ + hash_serialize_data(void *memory_writer) : + writer(memory_writer), + item_count(0) { } + + void *writer; + uint32_t item_count; +}; + + +static void +serialize_hash(const void *key, void *data, void *closure) +{ + hash_serialize_data *s_data = (hash_serialize_data *) closure; + memory_writer *blob = (memory_writer *) s_data->writer; + + uint32_t value = ((intptr_t)data); + + blob->write_string((char *)key); + blob->write_uint32_t(value); + + s_data->item_count++; +} + + +static void +serialize_hash_table(struct string_to_uint_map *map, memory_writer *blob) +{ + struct hash_serialize_data data(blob); + int32_t pos = blob->position(); + blob->write_uint32_t(data.item_count); + + map->iterate(serialize_hash, &data); + + blob->overwrite(&data.item_count, sizeof(data.item_count), pos); +} + + +static void +serialize_uniform_storage(gl_uniform_storage *uni, memory_writer &blob) +{ + blob.write(uni, sizeof(gl_uniform_storage)); + blob.write_string(uni->name); + + /* note, type is not serialized, it is resolved during parsing */ + + /* how many elements (1 if not array) * how many components in the type */ + const unsigned elements = MAX2(1, uni->array_elements); + uint32_t size = elements * MAX2(1, uni->type->components()); + + blob.write_uint32_t(size); +} + + +/** + * Features not currently supported by the cache. + */ +static bool +supported_by_cache(struct gl_shader_program *prog) +{ + /* No geometry shader support. */ + if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY]) + return false; + + /* No uniform block support. */ + if (prog->NumUniformBlocks > 0) + return false; + + /* No transform feedback support. */ + if (prog->LinkedTransformFeedback.NumVarying > 0) + return false; + + return true; +} + + +/** + * Serialize gl_shader_program structure + */ +extern "C" char * +mesa_program_serialize(struct gl_shader_program *prog, size_t *size) +{ + if (!supported_by_cache(prog)) + return NULL; + + memory_writer blob; + blob.write(&cache_validation_data, sizeof(cache_validation_data)); + + GET_CURRENT_CONTEXT(ctx); + + blob.write_string(mesa_get_shader_cache_magic()); + blob.write_string((const char *)ctx->Driver.GetString(ctx, GL_VENDOR)); + blob.write_string((const char *)ctx->Driver.GetString(ctx, GL_RENDERER)); + + blob.write(prog, sizeof(gl_shader_program)); + + /* hash tables */ + serialize_hash_table(prog->AttributeBindings, &blob); + serialize_hash_table(prog->FragDataBindings, &blob); + serialize_hash_table(prog->FragDataIndexBindings, &blob); + serialize_hash_table(prog->UniformHash, &blob); + + /* uniform storage */ + if (prog->UniformStorage) { + for (unsigned i = 0; i < prog->NumUserUniformStorage; i++) + serialize_uniform_storage(&prog->UniformStorage[i], blob); + } + + uint8_t shader_amount = 0; + unsigned shader_amount_pos = blob.position(); + blob.write_uint8_t(shader_amount); + + /* _LinkedShaders IR */ + for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { + size_t sha_size = 0; + + if (!prog->_LinkedShaders[i]) + continue; + + /* Set used GLSL version and IsES flag from gl_shader_program, + * this is required when deserializing the data. + */ + prog->_LinkedShaders[i]->Version = prog->Version; + prog->_LinkedShaders[i]->IsES = prog->IsES; + + char *data = mesa_shader_serialize(prog->_LinkedShaders[i], &sha_size); + + if (!data) + return NULL; + + shader_amount++; + + /* index in _LinkedShaders list + shader blob */ + if (data) { + blob.write_uint32_t(i); + blob.write(data, sha_size); + free(data); + } + } + + blob.overwrite(&shader_amount, sizeof(shader_amount), shader_amount_pos); + + *size = blob.position(); + return blob.release_memory(size); +} -- 1.8.3.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev