radeonsi: allow si_shader_select_with_key to return an optimized shader or fail
authorMarek Olšák <marek.olsak@amd.com>
Tue, 12 Feb 2019 19:38:31 +0000 (14:38 -0500)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 16 May 2019 17:10:07 +0000 (13:10 -0400)
If a prim discard compute shader hasn't finished compilation, we don't want
to any shader.

Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Acked-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_state.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index 116fce5b1465e61fe5a29b42dcb37efaa8f7cb4d..15c4ef6d9a1d09242628fd16ba699bec66ef807b 100644 (file)
@@ -41,6 +41,7 @@
 
 struct si_screen;
 struct si_shader;
+struct si_shader_ctx_state;
 struct si_shader_selector;
 struct si_texture;
 struct si_qbo_state;
@@ -576,6 +577,12 @@ void si_schedule_initial_compile(struct si_context *sctx, unsigned processor,
 void si_get_active_slot_masks(const struct tgsi_shader_info *info,
                              uint32_t *const_and_shader_buffers,
                              uint64_t *samplers_and_images);
+int si_shader_select_with_key(struct si_screen *sscreen,
+                             struct si_shader_ctx_state *state,
+                             struct si_compiler_ctx_state *compiler_state,
+                             struct si_shader_key *key,
+                             int thread_index,
+                             bool optimized_or_none);
 
 /* si_state_draw.c */
 void si_emit_cache_flush(struct si_context *sctx);
index 10677f175de2faf7c7be7ddd328c9940233f0425..8ae77fda3f3009fc4346c4d9625235fecd8aa423 100644 (file)
@@ -1794,12 +1794,19 @@ static bool si_check_missing_main_part(struct si_screen *sscreen,
        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,
-                                    struct si_compiler_ctx_state *compiler_state,
-                                    struct si_shader_key *key,
-                                    int thread_index)
+/**
+ * Select a shader variant according to the shader key.
+ *
+ * \param optimized_or_none  If the key describes an optimized shader variant and
+ *                           the compilation isn't finished, don't select any
+ *                           shader and return an error.
+ */
+int si_shader_select_with_key(struct si_screen *sscreen,
+                             struct si_shader_ctx_state *state,
+                             struct si_compiler_ctx_state *compiler_state,
+                             struct si_shader_key *key,
+                             int thread_index,
+                             bool optimized_or_none)
 {
        struct si_shader_selector *sel = state->cso;
        struct si_shader_selector *previous_stage_sel = NULL;
@@ -1815,6 +1822,9 @@ again:
                   memcmp(&current->key, key, sizeof(*key)) == 0)) {
                if (unlikely(!util_queue_fence_is_signalled(&current->ready))) {
                        if (current->is_optimized) {
+                               if (optimized_or_none)
+                                       return -1;
+
                                memset(&key->opt, 0, sizeof(key->opt));
                                goto current_not_ready;
                        }
@@ -1851,6 +1861,8 @@ current_not_ready:
                                 * shader so as not to cause a stall due to compilation.
                                 */
                                if (iter->is_optimized) {
+                                       if (optimized_or_none)
+                                               return -1;
                                        memset(&key->opt, 0, sizeof(key->opt));
                                        goto again;
                                }
@@ -1892,12 +1904,13 @@ current_not_ready:
                        util_queue_fence_wait(&previous_stage_sel->ready);
        }
 
-       /* Compile the main shader part if it doesn't exist. This can happen
-        * if the initial guess was wrong. */
        bool is_pure_monolithic =
                sscreen->use_monolithic_shaders ||
                memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0;
 
+       /* Compile the main shader part if it doesn't exist. This can happen
+        * if the initial guess was wrong.
+        */
        if (!is_pure_monolithic) {
                bool ok;
 
@@ -1954,9 +1967,7 @@ current_not_ready:
                memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
 
        /* If it's an optimized shader, compile it asynchronously. */
-       if (shader->is_optimized &&
-           !is_pure_monolithic &&
-           thread_index < 0) {
+       if (shader->is_optimized && thread_index < 0) {
                /* Compile it asynchronously. */
                util_queue_add_job(&sscreen->shader_compiler_queue_low_priority,
                                   shader, &shader->ready,
@@ -1979,6 +1990,8 @@ current_not_ready:
                if (sscreen->options.sync_compile)
                        util_queue_fence_wait(&shader->ready);
 
+               if (optimized_or_none)
+                       return -1;
                goto again;
        }
 
@@ -2015,7 +2028,7 @@ static int si_shader_select(struct pipe_context *ctx,
 
        si_shader_selector_key(ctx, state->cso, &key);
        return si_shader_select_with_key(sctx->screen, state, compiler_state,
-                                        &key, -1);
+                                        &key, -1, false);
 }
 
 static void si_parse_next_shader_property(const struct tgsi_shader_info *info,