summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.h7
-rw-r--r--src/gallium/drivers/radeonsi/si_state.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_state_shaders.c182
3 files changed, 110 insertions, 80 deletions
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index 14ef4e74994..be75a354279 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -233,6 +233,13 @@ struct si_shader;
* binaries for one TGSI program. This can be shared by multiple contexts.
*/
struct si_shader_selector {
+ struct si_screen *screen;
+
+ /* Should only be used by si_init_shader_selector_async
+ * if thread_index == -1 (non-threaded). */
+ LLVMTargetMachineRef tm;
+ struct pipe_debug_callback debug;
+
pipe_mutex mutex;
struct si_shader *first_variant; /* immutable after the first variant */
struct si_shader *last_variant; /* mutable */
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 05654bbb2e4..f5cc3008c44 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -338,6 +338,7 @@ bool si_update_shaders(struct si_context *sctx);
void si_init_shader_functions(struct si_context *sctx);
bool si_init_shader_cache(struct si_screen *sscreen);
void si_destroy_shader_cache(struct si_screen *sscreen);
+void si_init_shader_selector_async(void *job, int thread_index);
/* si_state_draw.c */
void si_emit_cache_flush(struct si_context *sctx, struct r600_atom *atom);
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 766ef2c6549..a2453c23c7f 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -981,11 +981,12 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
}
/* Select the hw shader variant depending on the current state. */
-static int si_shader_select_with_key(struct pipe_context *ctx,
+static int si_shader_select_with_key(struct si_screen *sscreen,
struct si_shader_ctx_state *state,
- union si_shader_key *key)
+ union si_shader_key *key,
+ LLVMTargetMachineRef tm,
+ struct pipe_debug_callback *debug)
{
- struct si_context *sctx = (struct si_context *)ctx;
struct si_shader_selector *sel = state->cso;
struct si_shader *current = state->current;
struct si_shader *iter, *shader = NULL;
@@ -1020,7 +1021,7 @@ static int si_shader_select_with_key(struct pipe_context *ctx,
shader->selector = sel;
shader->key = *key;
- r = si_shader_create(sctx->screen, sctx->tm, shader, &sctx->b.debug);
+ r = si_shader_create(sscreen, tm, shader, debug);
if (unlikely(r)) {
R600_ERR("Failed to build shader variant (type=%u) %d\n",
sel->type, r);
@@ -1028,7 +1029,7 @@ static int si_shader_select_with_key(struct pipe_context *ctx,
pipe_mutex_unlock(sel->mutex);
return r;
}
- si_shader_init_pm4_state(sctx->screen, shader);
+ si_shader_init_pm4_state(sscreen, shader);
if (!sel->last_variant) {
sel->first_variant = shader;
@@ -1045,10 +1046,12 @@ static int si_shader_select_with_key(struct pipe_context *ctx,
static int si_shader_select(struct pipe_context *ctx,
struct si_shader_ctx_state *state)
{
+ struct si_context *sctx = (struct si_context *)ctx;
union si_shader_key key;
si_shader_selector_key(ctx, state->cso, &key);
- return si_shader_select_with_key(ctx, state, &key);
+ return si_shader_select_with_key(sctx->screen, state, &key,
+ sctx->tm, &sctx->b.debug);
}
static void si_parse_next_shader_property(const struct tgsi_shader_info *info,
@@ -1076,6 +1079,94 @@ static void si_parse_next_shader_property(const struct tgsi_shader_info *info,
}
}
+/**
+ * Compile the main shader part or the monolithic shader as part of
+ * si_shader_selector initialization. Since it can be done asynchronously,
+ * there is no way to report compile failures to applications.
+ */
+void si_init_shader_selector_async(void *job, int thread_index)
+{
+ struct si_shader_selector *sel = (struct si_shader_selector *)job;
+ struct si_screen *sscreen = sel->screen;
+ LLVMTargetMachineRef tm = sel->tm;
+ struct pipe_debug_callback *debug = &sel->debug;
+ unsigned i;
+
+ /* Compile the main shader part for use with a prolog and/or epilog.
+ * If this fails, the driver will try to compile a monolithic shader
+ * on demand.
+ */
+ if (sel->type != PIPE_SHADER_GEOMETRY &&
+ !sscreen->use_monolithic_shaders) {
+ struct si_shader *shader = CALLOC_STRUCT(si_shader);
+ void *tgsi_binary;
+
+ if (!shader) {
+ fprintf(stderr, "radeonsi: can't allocate a main shader part\n");
+ return;
+ }
+
+ shader->selector = sel;
+ si_parse_next_shader_property(&sel->info, &shader->key);
+
+ tgsi_binary = si_get_tgsi_binary(sel);
+
+ /* Try to load the shader from the shader cache. */
+ pipe_mutex_lock(sscreen->shader_cache_mutex);
+
+ if (tgsi_binary &&
+ si_shader_cache_load_shader(sscreen, tgsi_binary, shader)) {
+ FREE(tgsi_binary);
+ } else {
+ /* Compile the shader if it hasn't been loaded from the cache. */
+ if (si_compile_tgsi_shader(sscreen, tm, shader, false,
+ debug) != 0) {
+ FREE(shader);
+ FREE(tgsi_binary);
+ pipe_mutex_unlock(sscreen->shader_cache_mutex);
+ fprintf(stderr, "radeonsi: can't compile a main shader part\n");
+ return;
+ }
+
+ if (tgsi_binary &&
+ !si_shader_cache_insert_shader(sscreen, tgsi_binary, shader))
+ FREE(tgsi_binary);
+ }
+ pipe_mutex_unlock(sscreen->shader_cache_mutex);
+
+ sel->main_shader_part = shader;
+ }
+
+ /* Pre-compilation. */
+ if (sel->type == PIPE_SHADER_GEOMETRY ||
+ sscreen->b.debug_flags & DBG_PRECOMPILE) {
+ struct si_shader_ctx_state state = {sel};
+ union si_shader_key key;
+
+ memset(&key, 0, sizeof(key));
+ si_parse_next_shader_property(&sel->info, &key);
+
+ /* Set reasonable defaults, so that the shader key doesn't
+ * cause any code to be eliminated.
+ */
+ switch (sel->type) {
+ case PIPE_SHADER_TESS_CTRL:
+ key.tcs.epilog.prim_mode = PIPE_PRIM_TRIANGLES;
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ key.ps.epilog.alpha_func = PIPE_FUNC_ALWAYS;
+ for (i = 0; i < 8; i++)
+ if (sel->info.colors_written & (1 << i))
+ key.ps.epilog.spi_shader_col_format |=
+ V_028710_SPI_SHADER_FP16_ABGR << (i * 4);
+ break;
+ }
+
+ if (si_shader_select_with_key(sscreen, &state, &key, tm, debug))
+ fprintf(stderr, "radeonsi: can't create a monolithic shader\n");
+ }
+}
+
static void *si_create_shader_selector(struct pipe_context *ctx,
const struct pipe_shader_state *state)
{
@@ -1087,6 +1178,9 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
if (!sel)
return NULL;
+ sel->screen = sscreen;
+ sel->tm = sctx->tm;
+ sel->debug = sctx->b.debug;
sel->tokens = tgsi_dup_tokens(state->tokens);
if (!sel->tokens) {
FREE(sel);
@@ -1199,83 +1293,11 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
if (sel->info.writes_memory)
sel->db_shader_control |= S_02880C_EXEC_ON_HIER_FAIL(1) |
S_02880C_EXEC_ON_NOOP(1);
+ pipe_mutex_init(sel->mutex);
- /* Compile the main shader part for use with a prolog and/or epilog. */
- if (sel->type != PIPE_SHADER_GEOMETRY &&
- !sscreen->use_monolithic_shaders) {
- struct si_shader *shader = CALLOC_STRUCT(si_shader);
- void *tgsi_binary;
-
- if (!shader)
- goto error;
-
- shader->selector = sel;
- si_parse_next_shader_property(&sel->info, &shader->key);
-
- tgsi_binary = si_get_tgsi_binary(sel);
-
- /* Try to load the shader from the shader cache. */
- pipe_mutex_lock(sscreen->shader_cache_mutex);
-
- if (tgsi_binary &&
- si_shader_cache_load_shader(sscreen, tgsi_binary, shader)) {
- FREE(tgsi_binary);
- } else {
- /* Compile the shader if it hasn't been loaded from the cache. */
- if (si_compile_tgsi_shader(sscreen, sctx->tm, shader, false,
- &sctx->b.debug) != 0) {
- FREE(shader);
- FREE(tgsi_binary);
- pipe_mutex_unlock(sscreen->shader_cache_mutex);
- goto error;
- }
-
- if (tgsi_binary &&
- !si_shader_cache_insert_shader(sscreen, tgsi_binary, shader))
- FREE(tgsi_binary);
- }
- pipe_mutex_unlock(sscreen->shader_cache_mutex);
-
- sel->main_shader_part = shader;
- }
-
- /* Pre-compilation. */
- if (sel->type == PIPE_SHADER_GEOMETRY ||
- sscreen->b.debug_flags & DBG_PRECOMPILE) {
- struct si_shader_ctx_state state = {sel};
- union si_shader_key key;
-
- memset(&key, 0, sizeof(key));
- si_parse_next_shader_property(&sel->info, &key);
-
- /* Set reasonable defaults, so that the shader key doesn't
- * cause any code to be eliminated.
- */
- switch (sel->type) {
- case PIPE_SHADER_TESS_CTRL:
- key.tcs.epilog.prim_mode = PIPE_PRIM_TRIANGLES;
- break;
- case PIPE_SHADER_FRAGMENT:
- key.ps.epilog.alpha_func = PIPE_FUNC_ALWAYS;
- for (i = 0; i < 8; i++)
- if (sel->info.colors_written & (1 << i))
- key.ps.epilog.spi_shader_col_format |=
- V_028710_SPI_SHADER_FP16_ABGR << (i * 4);
- break;
- }
-
- if (si_shader_select_with_key(ctx, &state, &key))
- goto error;
- }
+ si_init_shader_selector_async(sel, -1);
- pipe_mutex_init(sel->mutex);
return sel;
-
-error:
- fprintf(stderr, "radeonsi: can't create a shader\n");
- tgsi_free_tokens(sel->tokens);
- FREE(sel);
- return NULL;
}
static void si_bind_vs_shader(struct pipe_context *ctx, void *state)