[Mesa-dev] [PATCHv3 16/16] i965: enable threaded precompile
Chia-I Wu
olvaffe at gmail.com
Tue Aug 19 23:40:37 PDT 2014
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 <olv at lunarg.com>
Acked-by: Ian Romanick <ian.d.romanick at 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
More information about the mesa-dev
mailing list