On 07/09/2014 12:47 AM, Chia-I Wu wrote: > Inherit gl_shader_program and add save/restore functions to save precompile > results in the shader programs. When DeferLinkProgram is set, we will save > the precompile results instead of uploading them immediately because we may be > on a different thread. > > A few other modifications are also needed. brw_shader_program_precompile_key > is introduced and initialized in NofityLinkShader for we cannot inspect the > context during precompiling. > > Signed-off-by: Chia-I Wu <o...@lunarg.com> > --- > src/mesa/drivers/dri/i965/brw_context.c | 4 +- > src/mesa/drivers/dri/i965/brw_fs.cpp | 33 ++++-- > src/mesa/drivers/dri/i965/brw_program.c | 1 + > src/mesa/drivers/dri/i965/brw_shader.cpp | 177 > ++++++++++++++++++++++++++++++- > src/mesa/drivers/dri/i965/brw_shader.h | 44 ++++++++ > src/mesa/drivers/dri/i965/brw_vec4_gs.c | 37 +++++-- > src/mesa/drivers/dri/i965/brw_vs.c | 36 +++++-- > src/mesa/drivers/dri/i965/brw_wm.c | 23 ++-- > src/mesa/drivers/dri/i965/brw_wm.h | 5 +- > 9 files changed, 310 insertions(+), 50 deletions(-) > > diff --git a/src/mesa/drivers/dri/i965/brw_context.c > b/src/mesa/drivers/dri/i965/brw_context.c > index bd13ebf..4a28766 100644 > --- a/src/mesa/drivers/dri/i965/brw_context.c > +++ b/src/mesa/drivers/dri/i965/brw_context.c > @@ -784,8 +784,8 @@ brwCreateContext(gl_api api, > if (INTEL_DEBUG & DEBUG_SHADER_TIME) > brw_init_shader_time(brw); > > - /* brw_shader_precompile is not thread-safe */ > - if (brw->precompile) > + /* brw_shader_precompile is not thread-safe when debug flags are set */ > + if (brw->precompile && (INTEL_DEBUG || brw->perf_debug)) > ctx->Const.DeferLinkProgram = GL_FALSE;
But it is safe now without debug flags? > > _mesa_compute_version(ctx); > diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp > b/src/mesa/drivers/dri/i965/brw_fs.cpp > index a3ad375..61a0dff 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs.cpp > +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp > @@ -3288,6 +3288,8 @@ bool > brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog) > { > struct brw_context *brw = brw_context(ctx); > + const struct brw_shader_program_precompile_key *pre_key = > + brw_shader_program_get_precompile_key(prog); > struct brw_wm_prog_key key; > > if (!prog->_LinkedShaders[MESA_SHADER_FRAGMENT]) > @@ -3329,7 +3331,7 @@ brw_fs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > } > > if (fp->Base.InputsRead & VARYING_BIT_POS) { > - key.drawable_height = ctx->DrawBuffer->Height; > + key.drawable_height = pre_key->fbo_height; > } > > key.nr_color_regions = _mesa_bitcount_64(fp->Base.OutputsWritten & > @@ -3337,7 +3339,7 @@ brw_fs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK))); > > if ((fp->Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { > - key.render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer) || > + key.render_to_fbo = pre_key->is_user_fbo || > key.nr_color_regions > 1; > } > > @@ -3349,13 +3351,28 @@ brw_fs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > > key.program_string_id = bfp->id; > > - uint32_t old_prog_offset = brw->wm.base.prog_offset; > - struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data; > + struct brw_wm_compile c; > > - bool success = do_wm_prog(brw, prog, bfp, &key); > + brw_wm_init_compile(brw, prog, bfp, &key, &c); > + if (!brw_wm_do_compile(brw, &c)) { > + brw_wm_clear_compile(brw, &c); > + return false; > + } > + > + if (brw->ctx.Const.DeferLinkProgram) { > + brw_shader_program_save_wm_compile(prog, &c); > + } > + else { > + uint32_t old_prog_offset = brw->wm.base.prog_offset; > + struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data; > > - brw->wm.base.prog_offset = old_prog_offset; > - brw->wm.prog_data = old_prog_data; > + brw_wm_upload_compile(brw, &c); > > - return success; > + brw->wm.base.prog_offset = old_prog_offset; > + brw->wm.prog_data = old_prog_data; > + } > + > + brw_wm_clear_compile(brw, &c); > + > + return true; > } > diff --git a/src/mesa/drivers/dri/i965/brw_program.c > b/src/mesa/drivers/dri/i965/brw_program.c > index cff1188..2194640 100644 > --- a/src/mesa/drivers/dri/i965/brw_program.c > +++ b/src/mesa/drivers/dri/i965/brw_program.c > @@ -259,6 +259,7 @@ void brwInitFragProgFuncs( struct dd_function_table > *functions ) > functions->NewShader = brw_new_shader; > functions->NewShaderProgram = brw_new_shader_program; > functions->LinkShader = brw_link_shader; > + functions->NotifyLinkShader = brw_notify_link_shader; > } > > void > diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp > b/src/mesa/drivers/dri/i965/brw_shader.cpp > index 318802b..3cf1f15 100644 > --- a/src/mesa/drivers/dri/i965/brw_shader.cpp > +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp > @@ -25,14 +25,52 @@ extern "C" { > #include "main/macros.h" > #include "brw_context.h" > } > +#include "brw_shader.h" > #include "brw_vs.h" > #include "brw_vec4_gs.h" > +#include "brw_vec4_gs_visitor.h" > #include "brw_fs.h" > #include "brw_cfg.h" > #include "glsl/ir_optimization.h" > #include "glsl/glsl_parser_extras.h" > +#include "main/fbobject.h" > #include "main/shaderapi.h" > > +struct brw_shader_program { > + struct gl_shader_program base; > + > + struct brw_shader_program_precompile_key pre_key; > + > + GLbitfield saved; > + > + struct { > + struct brw_vs_prog_key key; > + struct brw_vs_prog_data data; > + const unsigned *program; > + unsigned program_size; > + } vs; > + > + struct { > + struct brw_gs_prog_key key; > + struct brw_gs_prog_data data; > + const unsigned *program; > + unsigned program_size; > + } gs; > + > + struct { > + struct brw_wm_prog_key key; > + struct brw_wm_prog_data data; > + const unsigned *program; > + unsigned program_size; > + } wm; > +}; > + > +static inline struct brw_shader_program * > +brw_shader_program(struct gl_shader_program *prog) > +{ > + return (struct brw_shader_program *) prog; > +} > + > struct gl_shader * > brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type) > { > @@ -52,12 +90,143 @@ brw_new_shader(struct gl_context *ctx, GLuint name, > GLuint type) > struct gl_shader_program * > brw_new_shader_program(struct gl_context *ctx, GLuint name) > { > - struct gl_shader_program *prog = rzalloc(NULL, struct gl_shader_program); > + struct brw_shader_program *prog = rzalloc(NULL, struct > brw_shader_program); > if (prog) { > - prog->Name = name; > - _mesa_init_shader_program(ctx, prog); > + prog->base.Name = name; > + _mesa_init_shader_program(ctx, &prog->base); > } > - return prog; > + return &prog->base; > +} > + > +void > +brw_notify_link_shader(struct gl_context *ctx, > + struct gl_shader_program *shProg) > +{ > + struct brw_context *brw = brw_context(ctx); > + struct brw_shader_program *prog = brw_shader_program(shProg); > + > + if (brw->precompile) { > + prog->pre_key.fbo_height = ctx->DrawBuffer->Height; > + prog->pre_key.is_user_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); > + } > +} > + > +const struct brw_shader_program_precompile_key * > +brw_shader_program_get_precompile_key(struct gl_shader_program *shader_prog) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + return &prog->pre_key; > +} > + > +void > +brw_shader_program_save_vs_compile(struct gl_shader_program *shader_prog, > + const struct brw_vs_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + memcpy(&prog->vs.key, &c->key, sizeof(prog->vs.key)); > + memcpy(&prog->vs.data, &c->prog_data, sizeof(prog->vs.data)); > + prog->vs.program = c->base.program; > + prog->vs.program_size = c->base.program_size; > + ralloc_steal(shader_prog, (void *) c->base.program); > + > + prog->saved |= 1 << BRW_VS_PROG; > +} > + > +void > +brw_shader_program_save_gs_compile(struct gl_shader_program *shader_prog, > + const struct brw_gs_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + memcpy(&prog->gs.key, &c->key, sizeof(prog->gs.key)); > + memcpy(&prog->gs.data, &c->prog_data, sizeof(prog->gs.data)); > + prog->gs.program = c->base.program; > + prog->gs.program_size = c->base.program_size; > + ralloc_steal(shader_prog, (void *) c->base.program); > + > + prog->saved |= 1 << BRW_GS_PROG; > +} > + > +void > +brw_shader_program_save_wm_compile(struct gl_shader_program *shader_prog, > + const struct brw_wm_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + memcpy(&prog->wm.key, c->key, sizeof(prog->wm.key)); > + memcpy(&prog->wm.data, &c->prog_data, sizeof(prog->wm.data)); > + prog->wm.program = c->program; > + prog->wm.program_size = c->program_size; > + ralloc_steal(shader_prog, (void *) c->program); > + > + prog->saved |= 1 << BRW_WM_PROG; > +} > + > +bool > +brw_shader_program_restore_vs_compile(struct gl_shader_program *shader_prog, > + struct brw_vs_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + if (!(prog->saved & (1 << BRW_VS_PROG))) > + return false; > + > + prog->saved &= ~(1 << BRW_VS_PROG); > + > + if (memcmp(&c->key, &prog->vs.key, sizeof(prog->vs.key))) > + return false; > + > + memcpy(&c->prog_data, &prog->vs.data, sizeof(prog->vs.data)); > + c->base.program = prog->vs.program; > + c->base.program_size = prog->vs.program_size; > + ralloc_steal(c->base.mem_ctx, (void *) c->base.program); > + > + return true; > +} > + > +bool > +brw_shader_program_restore_gs_compile(struct gl_shader_program *shader_prog, > + struct brw_gs_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + if (!(prog->saved & (1 << BRW_GS_PROG))) > + return false; > + > + prog->saved &= ~(1 << BRW_GS_PROG); > + > + if (memcmp(&c->key, &prog->gs.key, sizeof(prog->gs.key))) > + return false; > + > + memcpy(&c->prog_data, &prog->gs.data, sizeof(prog->gs.data)); > + c->base.program = prog->gs.program; > + c->base.program_size = prog->gs.program_size; > + ralloc_steal(c->base.mem_ctx, (void *) c->base.program); > + > + return true; > +} > + > +bool > +brw_shader_program_restore_wm_compile(struct gl_shader_program *shader_prog, > + struct brw_wm_compile *c) > +{ > + struct brw_shader_program *prog = brw_shader_program(shader_prog); > + > + if (!(prog->saved & (1 << BRW_WM_PROG))) > + return false; > + > + prog->saved &= ~(1 << BRW_WM_PROG); > + > + if (memcmp(c->key, &prog->wm.key, sizeof(prog->wm.key))) > + return false; > + > + memcpy(&c->prog_data, &prog->wm.data, sizeof(prog->wm.data)); > + c->program = prog->wm.program; > + c->program_size = prog->wm.program_size; > + ralloc_steal(c->mem_ctx, (void *) c->program); > + > + return true; > } > > /** > diff --git a/src/mesa/drivers/dri/i965/brw_shader.h > b/src/mesa/drivers/dri/i965/brw_shader.h > index cfaea9e..ac5a9f9 100644 > --- a/src/mesa/drivers/dri/i965/brw_shader.h > +++ b/src/mesa/drivers/dri/i965/brw_shader.h > @@ -178,3 +178,47 @@ enum brw_reg_type brw_type_for_base_type(const struct > glsl_type *type); > enum brw_conditional_mod brw_conditional_for_comparison(unsigned int op); > uint32_t brw_math_function(enum opcode op); > const char *brw_instruction_name(enum opcode op); > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +struct brw_shader_program_precompile_key { > + unsigned fbo_height; > + bool is_user_fbo; > +}; > + > +struct brw_vs_compile; > +struct brw_gs_compile; > +struct brw_wm_compile; > + > +const struct brw_shader_program_precompile_key * > +brw_shader_program_get_precompile_key(struct gl_shader_program *shader_prog); > + > +void > +brw_shader_program_save_vs_compile(struct gl_shader_program *shader_prog, > + const struct brw_vs_compile *c); > + > +void > +brw_shader_program_save_gs_compile(struct gl_shader_program *shader_prog, > + const struct brw_gs_compile *c); > + > +void > +brw_shader_program_save_wm_compile(struct gl_shader_program *shader_prog, > + const struct brw_wm_compile *c); > + > +bool > +brw_shader_program_restore_vs_compile(struct gl_shader_program *shader_prog, > + struct brw_vs_compile *c); > + > +bool > +brw_shader_program_restore_gs_compile(struct gl_shader_program *shader_prog, > + struct brw_gs_compile *c); > + > +bool > +brw_shader_program_restore_wm_compile(struct gl_shader_program *shader_prog, > + struct brw_wm_compile *c); > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/src/mesa/drivers/dri/i965/brw_vec4_gs.c > b/src/mesa/drivers/dri/i965/brw_vec4_gs.c > index 39ee507..9effca2 100644 > --- a/src/mesa/drivers/dri/i965/brw_vec4_gs.c > +++ b/src/mesa/drivers/dri/i965/brw_vec4_gs.c > @@ -286,9 +286,11 @@ do_gs_prog(struct brw_context *brw, > > brw_gs_init_compile(brw, prog, gp, key, &c); > > - if (!brw_gs_do_compile(brw, &c)) { > - brw_gs_clear_compile(brw, &c); > - return false; > + if (!brw_shader_program_restore_gs_compile(prog, &c)) { > + if (!brw_gs_do_compile(brw, &c)) { > + brw_gs_clear_compile(brw, &c); > + return false; > + } > } > > brw_gs_upload_compile(brw, &c); > @@ -375,9 +377,6 @@ brw_gs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > { > struct brw_context *brw = brw_context(ctx); > struct brw_gs_prog_key key; > - uint32_t old_prog_offset = brw->gs.base.prog_offset; > - struct brw_gs_prog_data *old_prog_data = brw->gs.prog_data; > - bool success; > > if (!prog->_LinkedShaders[MESA_SHADER_GEOMETRY]) > return true; > @@ -395,12 +394,30 @@ brw_gs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > */ > key.input_varyings = gp->Base.InputsRead; > > - success = do_gs_prog(brw, prog, bgp, &key); > + struct brw_gs_compile c; > > - brw->gs.base.prog_offset = old_prog_offset; > - brw->gs.prog_data = old_prog_data; > + brw_gs_init_compile(brw, prog, bgp, &key, &c); > + if (!brw_gs_do_compile(brw, &c)) { > + brw_gs_clear_compile(brw, &c); > + return false; > + } > > - return success; > + if (brw->ctx.Const.DeferLinkProgram) { > + brw_shader_program_save_gs_compile(prog, &c); > + } > + else { > + uint32_t old_prog_offset = brw->gs.base.prog_offset; > + struct brw_gs_prog_data *old_prog_data = brw->gs.prog_data; > + > + brw_gs_upload_compile(brw, &c); > + > + brw->gs.base.prog_offset = old_prog_offset; > + brw->gs.prog_data = old_prog_data; > + } > + > + brw_gs_clear_compile(brw, &c); > + > + return true; > } > > > diff --git a/src/mesa/drivers/dri/i965/brw_vs.c > b/src/mesa/drivers/dri/i965/brw_vs.c > index 22bc473..6910b59 100644 > --- a/src/mesa/drivers/dri/i965/brw_vs.c > +++ b/src/mesa/drivers/dri/i965/brw_vs.c > @@ -339,9 +339,12 @@ do_vs_prog(struct brw_context *brw, > struct brw_vs_compile c; > > brw_vs_init_compile(brw, prog, vp, key, &c); > - if (!brw_vs_do_compile(brw, &c)) { > - brw_vs_clear_compile(brw, &c); > - return false; > + > + if (!prog || !brw_shader_program_restore_vs_compile(prog, &c)) { > + if (!brw_vs_do_compile(brw, &c)) { > + brw_vs_clear_compile(brw, &c); > + return false; > + } > } > > brw_vs_upload_compile(brw, &c); > @@ -555,9 +558,6 @@ brw_vs_precompile(struct gl_context *ctx, struct > gl_shader_program *prog) > { > struct brw_context *brw = brw_context(ctx); > struct brw_vs_prog_key key; > - uint32_t old_prog_offset = brw->vs.base.prog_offset; > - struct brw_vs_prog_data *old_prog_data = brw->vs.prog_data; > - bool success; > > if (!prog->_LinkedShaders[MESA_SHADER_VERTEX]) > return true; > @@ -570,10 +570,26 @@ 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); > + struct brw_vs_compile c; > + > + brw_vs_init_compile(brw, prog, bvp, &key, &c); > + if (!brw_vs_do_compile(brw, &c)) { > + brw_vs_clear_compile(brw, &c); > + return false; > + } > + > + if (brw->ctx.Const.DeferLinkProgram) { > + brw_shader_program_save_vs_compile(prog, &c); > + } > + else { > + uint32_t old_prog_offset = brw->vs.base.prog_offset; > + struct brw_vs_prog_data *old_prog_data = brw->vs.prog_data; > + > + brw_vs_upload_compile(brw, &c); > > - brw->vs.base.prog_offset = old_prog_offset; > - brw->vs.prog_data = old_prog_data; > + brw->vs.base.prog_offset = old_prog_offset; > + brw->vs.prog_data = old_prog_data; > + } > > - return success; > + return true; > } > diff --git a/src/mesa/drivers/dri/i965/brw_wm.c > b/src/mesa/drivers/dri/i965/brw_wm.c > index 6849963..0b8180d 100644 > --- a/src/mesa/drivers/dri/i965/brw_wm.c > +++ b/src/mesa/drivers/dri/i965/brw_wm.c > @@ -30,6 +30,7 @@ > */ > > #include "brw_context.h" > +#include "brw_shader.h" > #include "brw_wm.h" > #include "brw_state.h" > #include "main/enums.h" > @@ -216,22 +217,20 @@ brw_wm_clear_compile(struct brw_context *brw, > ralloc_free(c->mem_ctx); > } > > -/** > - * All Mesa program -> GPU code generation goes through this function. > - * Depending on the instructions used (i.e. flow control instructions) > - * we'll use one of two code generators. > - */ > -bool do_wm_prog(struct brw_context *brw, > - struct gl_shader_program *prog, > - struct brw_fragment_program *fp, > - struct brw_wm_prog_key *key) > +static bool do_wm_prog(struct brw_context *brw, > + struct gl_shader_program *prog, > + struct brw_fragment_program *fp, > + struct brw_wm_prog_key *key) > { > struct brw_wm_compile c; > > brw_wm_init_compile(brw, prog, fp, key, &c); > - if (!brw_wm_do_compile(brw, &c)) { > - brw_wm_clear_compile(brw, &c); > - return false; > + > + if (!prog || !brw_shader_program_restore_wm_compile(prog, &c)) { > + if (!brw_wm_do_compile(brw, &c)) { > + brw_wm_clear_compile(brw, &c); > + return false; > + } > } > > brw_wm_upload_compile(brw, &c); > diff --git a/src/mesa/drivers/dri/i965/brw_wm.h > b/src/mesa/drivers/dri/i965/brw_wm.h > index b1a6e8f..89083fc 100644 > --- a/src/mesa/drivers/dri/i965/brw_wm.h > +++ b/src/mesa/drivers/dri/i965/brw_wm.h > @@ -123,15 +123,12 @@ const unsigned *brw_wm_fs_emit(struct brw_context *brw, > struct gl_shader_program *prog, > unsigned *final_assembly_size); > > +void brw_notify_link_shader(struct gl_context *ctx, struct gl_shader_program > *prog); > GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program > *prog); > struct gl_shader *brw_new_shader(struct gl_context *ctx, GLuint name, GLuint > type); > struct gl_shader_program *brw_new_shader_program(struct gl_context *ctx, > GLuint name); > > bool brw_color_buffer_write_enabled(struct brw_context *brw); > -bool do_wm_prog(struct brw_context *brw, > - struct gl_shader_program *prog, > - struct brw_fragment_program *fp, > - struct brw_wm_prog_key *key); > void brw_wm_debug_recompile(struct brw_context *brw, > struct gl_shader_program *prog, > const struct brw_wm_prog_key *key); > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev