diff options
author | Tapani Pälli <tapani.palli@intel.com> | 2014-05-05 11:03:28 +0300 |
---|---|---|
committer | Tapani Pälli <tapani.palli@intel.com> | 2014-05-06 15:10:26 +0300 |
commit | 30cdb2caead3d9ba6216c8c7ce1399b4e45a4d88 (patch) | |
tree | 96239c7defa2fde5d9dbf41c997a2eed89395766 | |
parent | 4737f44e26fb07fb0ab05006cd5343474129802d (diff) |
mesa: binary program driver interface WIPdriver_interface
Patch adds a helper structure to gl_shader_program for drivers to store
binary data required by shader program. This can be used to store final
program assembly as well as other structures required by the backend.
Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
-rw-r--r-- | src/glsl/shader_cache.cpp | 23 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4.cpp | 7 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vs.c | 87 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 19 | ||||
-rw-r--r-- | src/mesa/main/shaderobj.c | 38 | ||||
-rw-r--r-- | src/mesa/main/shaderobj.h | 3 |
6 files changed, 170 insertions, 7 deletions
diff --git a/src/glsl/shader_cache.cpp b/src/glsl/shader_cache.cpp index 5e4b29deaac..976081a6b67 100644 --- a/src/glsl/shader_cache.cpp +++ b/src/glsl/shader_cache.cpp @@ -319,6 +319,15 @@ mesa_program_serialize(struct gl_shader_program *prog, size_t *size, blob.overwrite(&shader_amount, sizeof(shader_amount), shader_amount_pos); + /* BinaryShaders from the driver */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + blob.write_uint8_t((uint8_t)prog->BinarySlotsUsed[i]); + for (unsigned j = 0; j < prog->BinarySlotsUsed[i]; j++) { + blob.write_uint32_t((uint32_t)prog->BinaryShaders[i][j].size); + blob.write(prog->BinaryShaders[i][j].data, prog->BinaryShaders[i][j].size); + } + } + *size = blob.position(); return blob.release_memory(size); } @@ -745,6 +754,20 @@ mesa_program_deserialize(struct gl_shader_program *prog, /* set default values for uniforms that have initializer */ link_set_uniform_initializers(prog); + /* BinaryShaders */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + uint8_t slots = map.read_uint8_t(); + + for (unsigned j = 0; j < slots; j++) { + uint32_t size = map.read_uint32_t(); + void *data = malloc(size); + assert(data); + map.read(data, size); + _mesa_cache_binary_data(prog, i, data, size); + free(data); + } + } + prog->LinkStatus = true; return 0; diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index daff3641119..6f8fcaf0245 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1828,6 +1828,11 @@ brw_vs_emit(struct brw_context *brw, } const unsigned *assembly = NULL; + /* assembly exists already ... */ + if (*final_assembly_size != 0) { + goto skip_asm_generation; + } + if (brw->gen >= 8) { gen8_vec4_generator g(brw, prog, &c->vp->program.Base, &prog_data->base, mem_ctx, INTEL_DEBUG & DEBUG_VS); @@ -1838,6 +1843,8 @@ brw_vs_emit(struct brw_context *brw, assembly = g.generate_assembly(&v.instructions, final_assembly_size); } +skip_asm_generation: + if (unlikely(brw->perf_debug) && shader) { if (shader->compiled_once) { brw_vs_debug_recompile(brw, prog, &c->key); diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c index e0f32b3333f..9ee03284921 100644 --- a/src/mesa/drivers/dri/i965/brw_vs.c +++ b/src/mesa/drivers/dri/i965/brw_vs.c @@ -31,6 +31,7 @@ #include "main/compiler.h" +#include "main/shaderobj.h" #include "brw_context.h" #include "brw_vs.h" #include "brw_util.h" @@ -191,10 +192,12 @@ static bool do_vs_prog(struct brw_context *brw, struct gl_shader_program *prog, struct brw_vertex_program *vp, - struct brw_vs_prog_key *key) + struct brw_vs_prog_key *key, + const GLuint *binary_program, + const GLuint binary_program_size) { - GLuint program_size; - const GLuint *program; + GLuint program_size = 0; + const GLuint *program = NULL; struct brw_vs_compile c; struct brw_vs_prog_data prog_data; struct brw_stage_prog_data *stage_prog_data = &prog_data.base.base; @@ -202,6 +205,11 @@ do_vs_prog(struct brw_context *brw, int i; struct gl_shader *vs = NULL; + if (binary_program) { + program = binary_program; + program_size = binary_program_size; + } + if (prog) vs = prog->_LinkedShaders[MESA_SHADER_VERTEX]; @@ -291,11 +299,15 @@ do_vs_prog(struct brw_context *brw, /* Emit GEN4 code. */ program = brw_vs_emit(brw, prog, &c, &prog_data, mem_ctx, &program_size); - if (program == NULL) { + if (program == NULL && program_size == 0) { ralloc_free(mem_ctx); return false; } + if (program == NULL && program_size != 0) { + program = binary_program; + } + /* Scratch space is used for register spilling */ if (c.base.last_scratch) { perf_debug("Vertex shader triggered register spilling. " @@ -309,6 +321,28 @@ do_vs_prog(struct brw_context *brw, prog_data.base.total_scratch * brw->max_vs_threads); } + + /* cache shader data : program and key + * (later possibly prog_data, params, pull_params ...) + */ + if (prog && prog->BinarySlotsUsed[MESA_SHADER_VERTEX] == 0) { + + /* FIXME - why programs with pull_params do not work? */ + if (stage_prog_data->nr_pull_params == 0) { + +#define CACHE(d, s) \ + _mesa_cache_binary_data(prog, MESA_SHADER_VERTEX, (void *)d, s) + + CACHE(program, program_size); + CACHE(key, sizeof(*key)); + + /* experimental attempt to cache prog_data and params array ... */ + CACHE(&prog_data, sizeof(prog_data)); + for (unsigned i = 0; i < stage_prog_data->nr_params; i++) + CACHE(stage_prog_data->param[i], 4 * sizeof(float)); + } + } + brw_upload_cache(&brw->cache, BRW_VS_PROG, &c.key, sizeof(c.key), program, program_size, @@ -403,7 +437,8 @@ brw_setup_vec4_key_clip_info(struct brw_context *brw, } -static void brw_upload_vs_prog(struct brw_context *brw) +void brw_upload_vs_prog(struct brw_context *brw); +void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_vs_prog_key key; @@ -483,12 +518,50 @@ static void brw_upload_vs_prog(struct brw_context *brw) if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.base.prog_offset, &brw->vs.prog_data)) { + + const GLuint *program = NULL; + GLuint program_size = 0; + struct brw_vs_prog_data prog_data; + + { + struct gl_shader_program *shProg = + ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]; + + /* check if the key matches with loaded binary cache data */ + if (shProg->BinarySlotsUsed[MESA_SHADER_VERTEX] > 0 && + memcmp(shProg->BinaryShaders[MESA_SHADER_VERTEX][1].data, + &key, sizeof(key)) == 0) { + + program = (GLuint *) + shProg->BinaryShaders[MESA_SHADER_VERTEX][0].data; + program_size = shProg->BinaryShaders[MESA_SHADER_VERTEX][0].size; + + /* TODO - take data below in to use, compare with generated one */ + memcpy(&prog_data, + shProg->BinaryShaders[MESA_SHADER_VERTEX][2].data, + sizeof(struct brw_vs_prog_data)); + + prog_data.base.base.param = + rzalloc_array(NULL, const float *, + prog_data.base.base.nr_params); + int k = 3; /* binary data slot where params start */ + for (int i = 0; i < prog_data.base.base.nr_params; i++, k++) { + prog_data.base.base.param[i] = + (float *) malloc (4 * sizeof(float)); + memcpy(prog_data.base.base.param[i], + shProg->BinaryShaders[MESA_SHADER_VERTEX][k].data, + 4 * sizeof(float)); + } + } + } + bool success = do_vs_prog(brw, ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX], vp, - &key); + &key, program, program_size); (void) success; assert(success); } + brw->vs.base.prog_data = &brw->vs.prog_data->base.base; if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, @@ -539,7 +612,7 @@ brw_vs_precompile(struct gl_context *ctx, struct gl_shader_program *prog) brw_vec4_setup_prog_key_for_precompile(ctx, &key.base, bvp->id, &vp->Base); - success = do_vs_prog(brw, prog, bvp, &key); + success = do_vs_prog(brw, prog, bvp, &key, NULL, 0); brw->vs.base.prog_offset = old_prog_offset; brw->vs.prog_data = old_prog_data; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 917d071a2c8..37ad9d4be80 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2591,6 +2591,17 @@ struct gl_active_atomic_buffer }; /** + * Structure for the drivers to store shader program binary + * (used with GL_ARB_get_program_binary extension) + */ +struct gl_shader_cache_data +{ + void *data; + uint32_t size; +}; +#define MESA_BINARY_SHADER_DATA_SLOTS 512 + +/** * A GLSL program object. * Basically a linked collection of vertex and fragment shaders. */ @@ -2761,6 +2772,14 @@ struct gl_shader_program */ struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES]; + /** + * Per-stage shader binary cache for GL_ARB_get_program_binary, each stage + * can have MESA_BINARY_SHADER_DATA_SLOTS amount of data blobs cached + */ + struct gl_shader_cache_data + BinaryShaders[MESA_SHADER_STAGES][MESA_BINARY_SHADER_DATA_SLOTS]; + unsigned BinarySlotsUsed[MESA_SHADER_STAGES]; + /* True if any of the fragment shaders attached to this program use: * #extension ARB_fragment_coord_conventions: enable */ diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index b0f0bfa915b..0295bbf4a2c 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -252,6 +252,15 @@ _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS; prog->InfoLog = ralloc_strdup(prog, ""); + + /* initialize binary shader cache */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + for (unsigned j = 0; j < MESA_BINARY_SHADER_DATA_SLOTS; j++) { + prog->BinaryShaders[i][j].data = NULL; + prog->BinaryShaders[i][j].size = 0; + } + prog->BinarySlotsUsed[i] = 0; + } } /** @@ -427,6 +436,35 @@ _mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name, } +/** + * Interface for driver to dump binary shader for a shader stage + */ +void +_mesa_cache_binary_data(struct gl_shader_program *shProg, + GLenum stage, void *data, size_t size) +{ + struct gl_shader_cache_data *cache = + &shProg->BinaryShaders[stage][shProg->BinarySlotsUsed[stage]]; + + if (cache->data) + ralloc_free(data); + + cache->data = ralloc_size(shProg, size); + cache->size = size; + + memcpy(cache->data, data, size); + +#if 0 + printf("%s: binary data, slot %d, size %d\n", + __func__, shProg->BinarySlotsUsed[stage], size); +#endif + + shProg->BinarySlotsUsed[stage]++; + + assert(shProg->BinarySlotsUsed[stage] < MESA_BINARY_SHADER_DATA_SLOTS); +} + + void _mesa_init_shader_object_functions(struct dd_function_table *driver) { diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h index fae8be827c5..c536729aae9 100644 --- a/src/mesa/main/shaderobj.h +++ b/src/mesa/main/shaderobj.h @@ -100,6 +100,9 @@ _mesa_init_shader_state(struct gl_context *ctx); extern void _mesa_free_shader_state(struct gl_context *ctx); +extern void +_mesa_cache_binary_data(struct gl_shader_program *shProg, + GLenum stage, void *data, size_t size); static inline gl_shader_stage _mesa_shader_enum_to_shader_stage(GLenum v) |