summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c2
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.h16
-rw-r--r--src/gallium/drivers/radeonsi/si_state_shaders.c36
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);