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> Acked-by: Ian Romanick <ian.d.roman...@intel.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 b02128c..70e61f7 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -839,8 +839,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; _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 5c70f50..393a262 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -3452,6 +3452,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]) @@ -3493,7 +3495,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 & @@ -3501,7 +3503,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; } @@ -3513,13 +3515,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 d782b4f..35fd69a 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 28db29a..29f4a19 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 5980cf0..3cc03f6 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.h +++ b/src/mesa/drivers/dri/i965/brw_shader.h @@ -184,3 +184,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 04407b8..2f043eb 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_gs.c +++ b/src/mesa/drivers/dri/i965/brw_vec4_gs.c @@ -291,9 +291,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); @@ -380,9 +382,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; @@ -400,12 +399,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 8e3dcf4..fb5ec29 100644 --- a/src/mesa/drivers/dri/i965/brw_vs.c +++ b/src/mesa/drivers/dri/i965/brw_vs.c @@ -341,9 +341,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); @@ -557,9 +560,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; @@ -572,10 +572,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 329e82c..a7b6bdc 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" @@ -218,22 +219,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 cd3c290..df94077 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -124,15 +124,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); -- 2.0.0.rc2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev