diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader.h | 16 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_shaders.c | 36 |
3 files changed, 49 insertions, 5 deletions
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 1829e3ec118..de427789aae 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -8240,7 +8240,7 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, struct pipe_debug_callback *debug) { struct si_shader_selector *sel = shader->selector; - struct si_shader *mainp = sel->main_shader_part; + struct si_shader *mainp = *si_get_main_shader_part(sel, &shader->key); int r; /* LS, ES, VS are compiled on demand if the main part hasn't been diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index da88df041ca..d4b57c97d59 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -287,6 +287,8 @@ struct si_shader_selector { * uploaded to a buffer). */ struct si_shader *main_shader_part; + struct si_shader *main_shader_part_ls; /* as_ls is set in the key */ + struct si_shader *main_shader_part_es; /* as_es is set in the key */ struct si_shader *gs_copy_shader; @@ -585,4 +587,18 @@ unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil, bool writes_samplemask); const char *si_get_shader_name(struct si_shader *shader, unsigned processor); +/* Inline helpers. */ + +/* Return the pointer to the main shader part's pointer. */ +static inline struct si_shader ** +si_get_main_shader_part(struct si_shader_selector *sel, + struct si_shader_key *key) +{ + if (key->as_ls) + return &sel->main_shader_part_ls; + if (key->as_es) + return &sel->main_shader_part_es; + return &sel->main_shader_part; +} + #endif diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 3630911be76..179176c486e 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -1236,15 +1236,39 @@ again: shader->key = *key; shader->compiler_ctx_state = *compiler_state; + /* 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 = memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0; + if (!*mainp && !is_pure_monolithic) { + struct si_shader *main_part = CALLOC_STRUCT(si_shader); + + if (!main_part) { + FREE(shader); + pipe_mutex_unlock(sel->mutex); + return -ENOMEM; /* skip the draw call */ + } + + 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); + FREE(shader); + pipe_mutex_unlock(sel->mutex); + return -ENOMEM; /* skip the draw call */ + } + *mainp = main_part; + } + /* Monolithic-only shaders don't make a distinction between optimized * and unoptimized. */ shader->is_monolithic = - !sel->main_shader_part || - sel->main_shader_part->key.as_ls != key->as_ls || - sel->main_shader_part->key.as_es != key->as_es || is_pure_monolithic || memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0; @@ -1399,7 +1423,7 @@ void si_init_shader_selector_async(void *job, int thread_index) } } - sel->main_shader_part = shader; + *si_get_main_shader_part(sel, &shader->key) = shader; /* Unset "outputs_written" flags for outputs converted to * DEFAULT_VAL, so that later inter-shader optimizations don't @@ -1869,6 +1893,10 @@ static void si_delete_shader_selector(struct pipe_context *ctx, void *state) if (sel->main_shader_part) si_delete_shader(sctx, sel->main_shader_part); + if (sel->main_shader_part_ls) + si_delete_shader(sctx, sel->main_shader_part_ls); + if (sel->main_shader_part_es) + si_delete_shader(sctx, sel->main_shader_part_es); if (sel->gs_copy_shader) si_delete_shader(sctx, sel->gs_copy_shader); |