These utility functions can be used to (de)serialize gl_shader and gl_shader_program structures. This makes it possible to implement a shader compiler cache for individual shaders and functionality required by OES_get_program_binary and ARB_get_program_binary extensions.
Signed-off-by: Tapani Pälli <tapani.pa...@intel.com> --- src/glsl/Makefile.sources | 1 + src/glsl/shader_cache.cpp | 734 ++++++++++++++++++++++++++++++++++++++++++++++ src/glsl/shader_cache.h | 58 ++++ 3 files changed, 793 insertions(+) create mode 100644 src/glsl/shader_cache.cpp create mode 100644 src/glsl/shader_cache.h diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 3c49a58..f4a6eb2 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -103,6 +103,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ $(GLSL_SRCDIR)/opt_vectorize.cpp \ $(GLSL_SRCDIR)/s_expression.cpp \ + $(GLSL_SRCDIR)/shader_cache.cpp \ $(GLSL_SRCDIR)/strtod.c # glsl_compiler diff --git a/src/glsl/shader_cache.cpp b/src/glsl/shader_cache.cpp new file mode 100644 index 0000000..c0675ff --- /dev/null +++ b/src/glsl/shader_cache.cpp @@ -0,0 +1,734 @@ +/* -*- 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 "main/shaderobj.h" +#include "main/uniforms.h" +#include "main/macros.h" +#include "program/hash_table.h" +#include "program/prog_parameter.h" +#include "ir_serialize.h" +#include "ir_deserializer.h" +#include "shader_cache_magic.h" + + +static void +write_header(gl_shader *shader, memory_writer &blob) +{ + 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_uint32_t(shader->Version); + blob.write_uint32_t(shader->Type); + blob.write_uint8_t(shader->IsES); +} + + +/* 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); +} + + +static void +serialize_shader_postlink_data(struct gl_shader *shader, memory_writer &blob) +{ + blob.write_uint32_t(shader->num_samplers); + blob.write_uint32_t(shader->active_samplers); + blob.write_uint32_t(shader->shadow_samplers); + blob.write_uint32_t(shader->num_uniform_components); + blob.write_uint32_t(shader->num_combined_uniform_components); + blob.write_uint8_t((uint8_t)shader->uses_builtin_functions); + + /* ARB_get_program_binary supports geometry shaders */ + blob.write(&shader->Geom, sizeof(shader->Geom)); + + for (unsigned i = 0; i < MAX_SAMPLERS; i++) + blob.write_uint8_t(shader->SamplerUnits[i]); + + for (unsigned i = 0; i < MAX_SAMPLERS; i++) + blob.write_int32_t((int32_t)shader->SamplerTargets[i]); +} + + +/** + * 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); + + write_header(shader, blob); + + /* misc required post-link data */ + serialize_shader_postlink_data(shader, blob); + + /* 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_string(uni->name); + + /* note, type is not serialized, it is resolved during parsing */ + + uint8_t initialized = uni->initialized; + uint8_t row_major = uni->row_major; + + blob.write_uint32_t(uni->array_elements); + blob.write_uint8_t(initialized); + blob.write_int32_t(uni->block_index); + blob.write_int32_t(uni->offset); + blob.write_int32_t(uni->matrix_stride); + blob.write_uint8_t(row_major); + blob.write_int32_t(uni->atomic_buffer_index); + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + uint8_t active = uni->sampler[i].active; + blob.write_uint8_t(uni->sampler[i].index); + blob.write_uint8_t(active); + } + + /* 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()); + + CACHE_DEBUG("%s: size %ld\n", __func__, + size * sizeof(union gl_constant_value)); + + blob.write_uint32_t(size); +} + + +static void +serialize_transform_feedback_info(struct gl_transform_feedback_info *info, + memory_writer &blob) +{ + blob.write(info, sizeof(struct gl_transform_feedback_info)); + + blob.write(info->Outputs, + info->NumOutputs * sizeof(gl_transform_feedback_output)); + + for (int i = 0; i < info->NumVarying; i++) { + blob.write(&info->Varyings[i], + sizeof(gl_transform_feedback_varying_info)); + blob.write_string(info->Varyings[i].Name); + } +} + + +/** + * Validation header for the gl_shader_program, this data is used to verify + * that binary program is usable for the Mesa in use. It is intended to catch + * changes in some of the important structures and enums that would it hard + * or impossible to use the binary data. + */ +static const uint32_t validation_data[] = { + ir_type_max, + GLSL_TYPE_ERROR, + sizeof(gl_shader), + sizeof(gl_program), + sizeof(gl_shader_program), + sizeof(gl_uniform_storage), + sizeof(gl_program_parameter_list), + 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 validation_data_items sizeof(validation_data)/sizeof(uint32_t) + + +/** + * Serialize gl_shader_program structure + */ +extern "C" char * +mesa_program_serialize(struct gl_shader_program *prog, size_t *size, + const char *mesa_sha) +{ + memory_writer blob; + + blob.write(&validation_data, sizeof(validation_data)); + + blob.write_uint32_t(prog->Type); + blob.write_uint8_t(prog->LinkStatus); + blob.write_uint32_t(prog->Version); + blob.write_uint8_t(prog->IsES); + blob.write_uint32_t(prog->NumUserUniformStorage); + blob.write_uint32_t(prog->UniformLocationBaseScale); + blob.write_uint32_t(prog->LastClipDistanceArraySize); + blob.write_uint8_t(prog->FragDepthLayout); + + /* 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); + + /* post-link transform feedback information */ + serialize_transform_feedback_info(&prog->LinkedTransformFeedback, blob); + + blob.write(&prog->Geom, sizeof(prog->Geom)); + blob.write(&prog->Vert, sizeof(prog->Vert)); + + /* 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; + + char *data = mesa_shader_serialize(prog->_LinkedShaders[i], &sha_size); + + if (!data) { + CACHE_DEBUG("error serializing data for index %d\n", i); + 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); +} + + +/** + * gl_program contains post-link data populated by the driver + */ +static bool +deserialize_gl_program(struct gl_shader *shader, memory_map &map) +{ + map.read(shader->Program, sizeof(struct gl_program)); + shader->Program->String = (GLubyte*) map.read_string(); + + shader->Program->Parameters = _mesa_new_parameter_list(); + + if (!shader->Program->Parameters) + return false; + + shader->Program->Parameters->NumParameters = 0; + shader->Program->Parameters->Size = 0; + shader->Program->Parameters->StateFlags = 0; + + if (map.errors()) + return false; + + return true; +} + + +/** + * Reads in header part of the shader blob, header contains misc data + * for the gl_shader structure and also validation data + */ +static bool +read_header(struct gl_shader *shader, memory_map &map) +{ + char *cache_magic_id = map.read_string(); + char *cache_vendor = map.read_string(); + char *cache_renderer = map.read_string(); + + shader->Version = map.read_uint32_t(); + shader->Type = map.read_uint32_t(); + shader->IsES = map.read_uint8_t(); + + CACHE_DEBUG("%s: version %d, type 0x%x, %s (mesa %s)\n[%s %s]\n", + __func__, shader->Version, shader->Type, + (shader->IsES) ? "glsl es" : "desktop glsl", + cache_magic_id, cache_vendor, cache_renderer); + + const char *magic = mesa_get_shader_cache_magic(); + + GET_CURRENT_CONTEXT(ctx); + + const char *mesa_vendor = + (const char *) ctx->Driver.GetString(ctx, GL_VENDOR); + const char *mesa_renderer = + (const char *) ctx->Driver.GetString(ctx, GL_RENDERER); + + /* check if cache was created with another driver */ + if ((strcmp(mesa_vendor, cache_vendor)) || + (strcmp(mesa_renderer, cache_renderer))) + return false; + + /* check against different version of mesa */ + if (strcmp(cache_magic_id, magic)) + return false; + + return true; +} + + +static bool +deserialize_shader_postlink_data(struct gl_shader *shader, memory_map &map) +{ + shader->num_samplers = map.read_uint32_t(); + shader->active_samplers = map.read_uint32_t(); + shader->shadow_samplers = map.read_uint32_t(); + shader->num_uniform_components = map.read_uint32_t(); + shader->num_combined_uniform_components = map.read_uint32_t(); + shader->uses_builtin_functions = map.read_uint8_t(); + + map.read(&shader->Geom, sizeof(shader->Geom)); + + for (unsigned i = 0; i < MAX_SAMPLERS; i++) + shader->SamplerUnits[i] = map.read_uint8_t(); + + for (unsigned i = 0; i < MAX_SAMPLERS; i++) + shader->SamplerTargets[i] = (gl_texture_index) map.read_int32_t(); + + /* return success */ + return !map.errors(); +} + + +static bool +read_hash_table(struct string_to_uint_map *hash, memory_map *map) +{ + if (map->errors()) + return false; + + uint32_t size = map->read_uint32_t(); + + for (unsigned i = 0; i < size; i++) { + + char *key = map->read_string(); + uint32_t value = map->read_uint32_t(); + + /* put() adds +1 bias on the value (see hash_table.h), this + * is taken care here when reading + */ + hash->put(value-1, key); + + /* break out in case of read errors */ + if (map->errors()) + return false; + } + return true; +} + + +static void +read_uniform_storage(void *mem_ctx, gl_uniform_storage *uni, memory_map &map) +{ + char *name = map.read_string(); + uni->name = strdup(name); + + /* resolved later */ + uni->type = NULL; + + uni->array_elements = map.read_uint32_t(); + uni->initialized = map.read_uint8_t(); + uni->block_index = map.read_int32_t(); + uni->offset = map.read_int32_t(); + uni->matrix_stride = map.read_int32_t(); + uni->row_major = map.read_uint8_t(); + uni->atomic_buffer_index = map.read_int32_t(); + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + uni->sampler[i].index = map.read_uint8_t(); + uni->sampler[i].active = map.read_uint8_t(); + } + + uint32_t size = map.read_uint32_t(); + + CACHE_DEBUG("read uniform storage size %ld\n", + size * sizeof(union gl_constant_value)); + + uni->storage = + rzalloc_array(mem_ctx, union gl_constant_value, size); + + /* initialize to zero for now, initializers will be propagated later */ + memset(uni->storage, 0, size * sizeof(union gl_constant_value)); + + /* driver uniform storage gets generated and propagated later */ + uni->driver_storage = NULL; + uni->num_driver_storage = 0; +} + + +static ir_variable * +search_var(struct exec_list *list, const char *name) +{ + foreach_list_safe(node, list) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (var && strcmp(name, var->name) == 0) + return var; + } + return NULL; +} + + +/** + * Resolve glsl_types for uniform_storage + */ +static void +resolve_uniform_types(struct gl_shader_program *prog, + struct gl_shader *sha) +{ + /* for each storage, find corresponding uniform from the shader */ + for (unsigned i = 0; i < prog->NumUserUniformStorage; i++) { + ir_variable *var = search_var(sha->ir, prog->UniformStorage[i].name); + + if (var) { + /* for arrays, uniform storage type contains the element type */ + if (var->type->is_array()) + prog->UniformStorage[i].type = var->type->element_type(); + else + prog->UniformStorage[i].type = var->type; + } + } +} + + +/* read and serialize a gl_shader */ +static gl_shader * +read_shader(void *mem_ctx, memory_map &map, ir_deserializer &s) +{ + struct gl_shader *shader = NULL; + struct gl_program *prog = NULL; + gl_shader_stage stage; + GET_CURRENT_CONTEXT(ctx); + memory_map wrapper; + + uint32_t shader_size = map.read_uint32_t(); + uint32_t start = map.position(); + uint32_t type = map.read_uint32_t(); + + /* verify that type is supported */ + switch (type) { + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + case GL_GEOMETRY_SHADER: + break; + default: + goto error_deserialize; + } + + shader = ctx->Driver.NewShader(NULL, 0, type); + + if (!shader) + return NULL; + + shader->Source = NULL; + shader->Label = NULL; + shader->InfoLog = ralloc_strdup(mem_ctx, ""); + shader->ir = NULL; + + if (!read_header(shader, map)) + goto error_deserialize; + + /* verify that type from header matches */ + if (shader->Type != type) + goto error_deserialize; + + /* misc post-link data */ + if (!deserialize_shader_postlink_data(shader, map)) + goto error_deserialize; + + stage = _mesa_shader_enum_to_shader_stage(shader->Type); + + prog = + ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(stage), + shader->Name); + + if (!prog) + goto error_deserialize; + + _mesa_reference_program(ctx, &shader->Program, prog); + + if (!deserialize_gl_program(shader, map)) + goto error_deserialize; + + /* decrement what we have already read */ + shader_size -= map.position() - start; + + /* read existing memory_map with another memory_map */ + wrapper.map(map, shader_size); + + if (!s.deserialize(mem_ctx, shader, + &wrapper, shader_size)) + goto error_deserialize; + + do_set_program_inouts(shader->ir, shader->Program, shader->Stage); + + return shader; + +error_deserialize: + + if (shader) + ctx->Driver.DeleteShader(ctx, shader); + + return NULL; +} + + +/** + * Deserialize gl_shader structure + */ +extern "C" struct gl_shader * +mesa_shader_deserialize(void *mem_ctx, void *blob, size_t size) +{ + memory_map map; + ir_deserializer s; + map.map(blob, size); + return read_shader(mem_ctx, map, s); +} + + +static int +validate_binary_program(struct gl_shader_program *prog, memory_map &map) +{ + uint32_t data[validation_data_items]; + map.read(&data, sizeof(validation_data)); + return memcmp(&data, validation_data, sizeof(validation_data)); +} + + +static void +deserialize_transform_feedback_info(struct gl_shader_program *prog, + memory_map &map) +{ + map.read(&prog->LinkedTransformFeedback, + sizeof(gl_transform_feedback_info)); + + unsigned num_outputs = prog->LinkedTransformFeedback.NumOutputs; + GLint num_varying = prog->LinkedTransformFeedback.NumVarying; + + prog->LinkedTransformFeedback.Outputs = + rzalloc_array(prog, struct gl_transform_feedback_output, + num_outputs); + + map.read(prog->LinkedTransformFeedback.Outputs, + num_outputs * sizeof(gl_transform_feedback_output)); + + prog->LinkedTransformFeedback.Varyings = + rzalloc_array(prog, struct gl_transform_feedback_varying_info, + num_varying); + for (int i = 0; i < num_varying; i++) { + map.read(&prog->LinkedTransformFeedback.Varyings[i], + sizeof(gl_transform_feedback_varying_info)); + prog->LinkedTransformFeedback.Varyings[i].Name = map.read_string(); + } +} + + +/** + * Deserialize gl_shader_program structure + */ +extern "C" int +mesa_program_deserialize(struct gl_shader_program *prog, + const GLvoid *blob, size_t size) +{ + memory_map map; + map.map((const void*)blob, size); + + if(validate_binary_program(prog, map)) + return -1; + + prog->Type = map.read_uint32_t(); + prog->LinkStatus = map.read_uint8_t(); + prog->Version = map.read_uint32_t(); + prog->IsES = map.read_uint8_t(); + prog->NumUserUniformStorage = map.read_uint32_t(); + prog->UniformLocationBaseScale = map.read_uint32_t(); + prog->LastClipDistanceArraySize = map.read_uint32_t(); + prog->FragDepthLayout = (gl_frag_depth_layout) map.read_uint8_t(); + + prog->UniformStorage = NULL; + prog->Label = NULL; + + prog->UniformHash = new string_to_uint_map; + + /* these already allocated by _mesa_init_shader_program */ + read_hash_table(prog->AttributeBindings, &map); + read_hash_table(prog->FragDataBindings, &map); + read_hash_table(prog->FragDataIndexBindings, &map); + + read_hash_table(prog->UniformHash, &map); + + if (map.errors()) + return -1; + + deserialize_transform_feedback_info(prog, map); + + map.read(&prog->Geom, sizeof(prog->Geom)); + map.read(&prog->Vert, sizeof(prog->Vert)); + + /* uniform storage */ + prog->UniformStorage = rzalloc_array(prog, struct gl_uniform_storage, + prog->NumUserUniformStorage); + + for (unsigned i = 0; i < prog->NumUserUniformStorage; i++) + read_uniform_storage(prog, &prog->UniformStorage[i], map); + + GET_CURRENT_CONTEXT(ctx); + + /* how many linked shaders does the binary contain */ + uint8_t shader_amount = map.read_uint8_t(); + + /* use same deserializer to have same type_hash across shader stages */ + ir_deserializer s; + + /* init list, cache can contain only some shader types */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) + prog->_LinkedShaders[i] = NULL; + + /* read _LinkedShaders */ + for (unsigned i = 0; i < shader_amount; i++) { + uint32_t index = map.read_uint32_t(); + + struct gl_shader *sha = read_shader(prog, map, s); + + /* note, for 'automatic cache' in case of failure we would + * need to fallback to compiling/linking the shaders in the + * prog->Shaders list + */ + if (!sha) { + CACHE_DEBUG("failed to read shader (index %d)\n", index); + return -1; + } + + resolve_uniform_types(prog, sha); + + _mesa_reference_shader(ctx, &prog->_LinkedShaders[index], sha); + CACHE_DEBUG("%s: read a linked shader, index %d (%p)\n", + __func__, index, sha); + } + + /* set default values for uniforms that have initializer */ + link_set_uniform_initializers(prog); + +#if 0 + /* for debugging */ + ctx->Driver.LinkShader(ctx, prog); +#endif + + return 0; +} diff --git a/src/glsl/shader_cache.h b/src/glsl/shader_cache.h new file mode 100644 index 0000000..b65660d --- /dev/null +++ b/src/glsl/shader_cache.h @@ -0,0 +1,58 @@ +/* -*- 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 + +/* cache specific debug output */ +#ifdef SHADER_CACHE_DEBUG +#define CACHE_DEBUG(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else +#define CACHE_DEBUG(fmt, ...) do {} while (0) +#endif + +/* C API for the cache */ +#ifdef __cplusplus +extern "C" { +#endif + +char * +mesa_shader_serialize(struct gl_shader *shader, size_t *size); + +struct gl_shader * +mesa_shader_deserialize(void *mem_ctx, void *blob, size_t size); + +char * +mesa_program_serialize(struct gl_shader_program *prog, size_t *size); + +int +mesa_program_deserialize(struct gl_shader_program *prog, + const GLvoid *blob, size_t size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SHADER_CACHE_H */ -- 1.8.5.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev