summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTapani Pälli <tapani.palli@intel.com>2014-05-05 11:03:28 +0300
committerTapani Pälli <tapani.palli@intel.com>2014-05-06 15:10:26 +0300
commit30cdb2caead3d9ba6216c8c7ce1399b4e45a4d88 (patch)
tree96239c7defa2fde5d9dbf41c997a2eed89395766
parent4737f44e26fb07fb0ab05006cd5343474129802d (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.cpp23
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.cpp7
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.c87
-rw-r--r--src/mesa/main/mtypes.h19
-rw-r--r--src/mesa/main/shaderobj.c38
-rw-r--r--src/mesa/main/shaderobj.h3
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)