diff options
author | Marek Olšák <[email protected]> | 2017-04-18 23:49:07 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2017-04-28 21:47:35 +0200 |
commit | 6a9c20fdd58f64c653dea0d45bedbd3c1b06fe97 (patch) | |
tree | 286293bbdfe036acb8926ea702e92a5a9a764bb8 | |
parent | 7df682c291307c730a56b064b8df2cd5c8b1be82 (diff) |
radeonsi/gfx9: make sure the 1st shader's main part exists for merged shaders
Reviewed-by: Nicolai Hähnle <[email protected]>
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_shaders.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 6cacbc7a33a..b7f848fd077 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -1436,6 +1436,36 @@ static void si_build_shader_variant(void *job, int thread_index) si_shader_init_pm4_state(sscreen, shader); } +static const struct si_shader_key zeroed; + +static bool si_check_missing_main_part(struct si_screen *sscreen, + struct si_shader_selector *sel, + struct si_compiler_ctx_state *compiler_state, + struct si_shader_key *key) +{ + struct si_shader **mainp = si_get_main_shader_part(sel, key); + + if (!*mainp) { + struct si_shader *main_part = CALLOC_STRUCT(si_shader); + + if (!main_part) + return false; + + main_part->selector = sel; + main_part->key.as_es = key->as_es; + main_part->key.as_ls = key->as_ls; + + if (si_compile_tgsi_shader(sscreen, compiler_state->tm, + main_part, false, + &compiler_state->debug) != 0) { + FREE(main_part); + return false; + } + *mainp = main_part; + } + return true; +} + /* Select the hw shader variant depending on the current state. */ static int si_shader_select_with_key(struct si_screen *sscreen, struct si_shader_ctx_state *state, @@ -1443,7 +1473,6 @@ static int si_shader_select_with_key(struct si_screen *sscreen, struct si_shader_key *key, int thread_index) { - static const struct si_shader_key zeroed; struct si_shader_selector *sel = state->cso; struct si_shader *current = state->current; struct si_shader *iter, *shader = NULL; @@ -1514,33 +1543,46 @@ again: /* Compile the main shader part if it doesn't exist. This can happen * if the initial guess was wrong. */ - struct si_shader **mainp = si_get_main_shader_part(sel, key); bool is_pure_monolithic = sscreen->use_monolithic_shaders || memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0; - if (!*mainp && !is_pure_monolithic) { - struct si_shader *main_part = CALLOC_STRUCT(si_shader); + if (!is_pure_monolithic) { + bool ok; - if (!main_part) { - FREE(shader); - mtx_unlock(&sel->mutex); - return -ENOMEM; /* skip the draw call */ + /* Make sure the main shader part is present. This is needed + * for shaders that can be compiled as VS, LS, or ES, and only + * one of them is compiled at creation. + * + * For merged shaders, check that the starting shader's main + * part is present. + */ + if (sscreen->b.chip_class >= GFX9 && + (sel->type == PIPE_SHADER_TESS_CTRL || + sel->type == PIPE_SHADER_GEOMETRY)) { + struct si_shader_selector *shader1 = NULL; + struct si_shader_key shader1_key = zeroed; + + if (sel->type == PIPE_SHADER_TESS_CTRL) { + shader1 = key->part.tcs.ls; + shader1_key.as_ls = 1; + } else if (sel->type == PIPE_SHADER_GEOMETRY) { + shader1 = key->part.gs.es; + shader1_key.as_es = 1; + } else + assert(0); + + ok = si_check_missing_main_part(sscreen, shader1, + compiler_state, &shader1_key); + } else { + ok = si_check_missing_main_part(sscreen, sel, + compiler_state, key); } - - main_part->selector = sel; - main_part->key.as_es = key->as_es; - main_part->key.as_ls = key->as_ls; - - if (si_compile_tgsi_shader(sscreen, compiler_state->tm, - main_part, false, - &compiler_state->debug) != 0) { - FREE(main_part); + if (!ok) { FREE(shader); mtx_unlock(&sel->mutex); return -ENOMEM; /* skip the draw call */ } - *mainp = main_part; } /* Monolithic-only shaders don't make a distinction between optimized |