From: Nicolai Hähnle <nicolai.haeh...@amd.com>

The copy shader only depends on the selector. This change avoids creating
separate code paths for monolithic vs. non-monolithic geometry shaders.
---
 src/gallium/drivers/radeonsi/si_pipe.h          |  2 +-
 src/gallium/drivers/radeonsi/si_shader.c        | 18 ++++--------------
 src/gallium/drivers/radeonsi/si_shader.h        |  9 ++++++++-
 src/gallium/drivers/radeonsi/si_state_shaders.c | 22 ++++++++++++++++++----
 4 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_pipe.h 
b/src/gallium/drivers/radeonsi/si_pipe.h
index 0240a3c..e7617bc 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -443,21 +443,21 @@ static inline struct tgsi_shader_info 
*si_get_vs_info(struct si_context *sctx)
                return &sctx->tes_shader.cso->info;
        else if (sctx->vs_shader.cso)
                return &sctx->vs_shader.cso->info;
        else
                return NULL;
 }
 
 static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
 {
        if (sctx->gs_shader.current)
-               return sctx->gs_shader.current->gs_copy_shader;
+               return sctx->gs_shader.cso->gs_copy_shader;
        else if (sctx->tes_shader.current)
                return sctx->tes_shader.current;
        else
                return sctx->vs_shader.current;
 }
 
 static inline bool si_vs_exports_prim_id(struct si_shader *shader)
 {
        if (shader->selector->type == PIPE_SHADER_VERTEX)
                return shader->key.vs.epilog.export_prim_id;
diff --git a/src/gallium/drivers/radeonsi/si_shader.c 
b/src/gallium/drivers/radeonsi/si_shader.c
index e755399..38f65f3 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -5944,21 +5944,21 @@ static const char *si_get_shader_name(struct si_shader 
*shader,
                else
                        return "Vertex Shader as VS";
        case PIPE_SHADER_TESS_CTRL:
                return "Tessellation Control Shader";
        case PIPE_SHADER_TESS_EVAL:
                if (shader->key.tes.as_es)
                        return "Tessellation Evaluation Shader as ES";
                else
                        return "Tessellation Evaluation Shader as VS";
        case PIPE_SHADER_GEOMETRY:
-               if (shader->gs_copy_shader == NULL)
+               if (shader->is_gs_copy_shader)
                        return "GS Copy Shader as VS";
                else
                        return "Geometry Shader";
        case PIPE_SHADER_FRAGMENT:
                return "Pixel Shader";
        case PIPE_SHADER_COMPUTE:
                return "Compute Shader";
        default:
                return "Unknown Shader";
        }
@@ -6073,21 +6073,21 @@ int si_compile_llvm(struct si_screen *sscreen,
 
 static void si_llvm_build_ret(struct si_shader_context *ctx, LLVMValueRef ret)
 {
        if (LLVMGetTypeKind(LLVMTypeOf(ret)) == LLVMVoidTypeKind)
                LLVMBuildRetVoid(ctx->gallivm.builder);
        else
                LLVMBuildRet(ctx->gallivm.builder, ret);
 }
 
 /* Generate code for the hardware VS shader stage to go with a geometry shader 
*/
-static struct si_shader *
+struct si_shader *
 si_generate_gs_copy_shader(struct si_screen *sscreen,
                           LLVMTargetMachineRef tm,
                           struct si_shader_selector *gs_selector,
                           struct pipe_debug_callback *debug)
 {
        struct si_shader_context ctx;
        struct si_shader *shader;
        struct gallivm_state *gallivm = &ctx.gallivm;
        struct lp_build_tgsi_context *bld_base = &ctx.soa.bld_base;
        struct lp_build_context *uint = &bld_base->uint_bld;
@@ -6096,20 +6096,22 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
        LLVMValueRef args[9];
        int i, r;
 
        outputs = MALLOC(gsinfo->num_outputs * sizeof(outputs[0]));
 
        shader = CALLOC_STRUCT(si_shader);
        if (!shader)
                return NULL;
 
        shader->selector = gs_selector;
+       shader->is_gs_copy_shader = true;
+
        si_init_shader_ctx(&ctx, sscreen, shader, tm);
        ctx.type = PIPE_SHADER_VERTEX;
        ctx.is_gs_copy_shader = true;
 
        create_meta_data(&ctx);
        create_function(&ctx);
        preload_ring_buffers(&ctx);
 
        args[0] = ctx.gsvs_ring[0];
        args[1] = lp_build_mul_imm(uint,
@@ -7143,27 +7145,20 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                        shader->info.num_input_vgprs += 1;
                }
                if (G_0286CC_ANCILLARY_ENA(shader->config.spi_ps_input_addr))
                        shader->info.num_input_vgprs += 1;
                if 
(G_0286CC_SAMPLE_COVERAGE_ENA(shader->config.spi_ps_input_addr))
                        shader->info.num_input_vgprs += 1;
                if (G_0286CC_POS_FIXED_PT_ENA(shader->config.spi_ps_input_addr))
                        shader->info.num_input_vgprs += 1;
        }
 
-       if (ctx.type == PIPE_SHADER_GEOMETRY) {
-               shader->gs_copy_shader =
-                       si_generate_gs_copy_shader(sscreen, tm, 
shader->selector, debug);
-               if (!shader->gs_copy_shader)
-                       return -1;
-       }
-
        return 0;
 }
 
 /**
  * Create, compile and return a shader part (prolog or epilog).
  *
  * \param sscreen      screen
  * \param list         list of shader parts of the same category
  * \param type         shader type
  * \param key          shader part key
@@ -8091,25 +8086,20 @@ int si_shader_create(struct si_screen *sscreen, 
LLVMTargetMachineRef tm,
        if (r) {
                fprintf(stderr, "LLVM failed to upload shader\n");
                return r;
        }
 
        return 0;
 }
 
 void si_shader_destroy(struct si_shader *shader)
 {
-       if (shader->gs_copy_shader) {
-               si_shader_destroy(shader->gs_copy_shader);
-               FREE(shader->gs_copy_shader);
-       }
-
        if (shader->scratch_bo)
                r600_resource_reference(&shader->scratch_bo, NULL);
 
        r600_resource_reference(&shader->bo, NULL);
 
        if (!shader->is_binary_shared)
                radeon_shader_binary_clean(&shader->binary);
 
        free(shader->shader_log);
 }
diff --git a/src/gallium/drivers/radeonsi/si_shader.h 
b/src/gallium/drivers/radeonsi/si_shader.h
index 6c7a05f..91f9cbf 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -250,20 +250,22 @@ struct si_shader_selector {
 
        pipe_mutex              mutex;
        struct si_shader        *first_variant; /* immutable after the first 
variant */
        struct si_shader        *last_variant; /* mutable */
 
        /* The compiled TGSI shader expecting a prolog and/or epilog (not
         * uploaded to a buffer).
         */
        struct si_shader        *main_shader_part;
 
+       struct si_shader        *gs_copy_shader;
+
        struct tgsi_token       *tokens;
        struct pipe_stream_output_info  so;
        struct tgsi_shader_info         info;
 
        /* PIPE_SHADER_[VERTEX|FRAGMENT|...] */
        unsigned        type;
 
        /* GS parameters. */
        unsigned        esgs_itemsize;
        unsigned        gs_input_verts_per_prim;
@@ -437,26 +439,26 @@ struct si_shader_info {
        ubyte                   nr_param_exports;
 };
 
 struct si_shader {
        struct si_shader_selector       *selector;
        struct si_shader                *next_variant;
 
        struct si_shader_part           *prolog;
        struct si_shader_part           *epilog;
 
-       struct si_shader                *gs_copy_shader;
        struct si_pm4_state             *pm4;
        struct r600_resource            *bo;
        struct r600_resource            *scratch_bo;
        union si_shader_key             key;
        bool                            is_binary_shared;
+       bool                            is_gs_copy_shader;
 
        /* The following data is all that's needed for binary shaders. */
        struct radeon_shader_binary     binary;
        struct si_shader_config         config;
        struct si_shader_info           info;
 
        /* Shader key + LLVM IR + disassembly + statistics.
         * Generated for debug contexts only.
         */
        char                            *shader_log;
@@ -464,20 +466,25 @@ struct si_shader {
 };
 
 struct si_shader_part {
        struct si_shader_part *next;
        union si_shader_part_key key;
        struct radeon_shader_binary binary;
        struct si_shader_config config;
 };
 
 /* si_shader.c */
+struct si_shader *
+si_generate_gs_copy_shader(struct si_screen *sscreen,
+                          LLVMTargetMachineRef tm,
+                          struct si_shader_selector *gs_selector,
+                          struct pipe_debug_callback *debug);
 int si_compile_tgsi_shader(struct si_screen *sscreen,
                           LLVMTargetMachineRef tm,
                           struct si_shader *shader,
                           bool is_monolithic,
                           struct pipe_debug_callback *debug);
 int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
                     struct si_shader *shader,
                     struct pipe_debug_callback *debug);
 int si_compile_llvm(struct si_screen *sscreen,
                    struct radeon_shader_binary *binary,
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c 
b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 537c673..bd217f3 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -825,21 +825,20 @@ static void si_shader_init_pm4_state(struct si_screen 
*sscreen,
                si_shader_hs(shader);
                break;
        case PIPE_SHADER_TESS_EVAL:
                if (shader->key.tes.as_es)
                        si_shader_es(sscreen, shader);
                else
                        si_shader_vs(sscreen, shader, NULL);
                break;
        case PIPE_SHADER_GEOMETRY:
                si_shader_gs(shader);
-               si_shader_vs(sscreen, shader->gs_copy_shader, shader->selector);
                break;
        case PIPE_SHADER_FRAGMENT:
                si_shader_ps(shader);
                break;
        default:
                assert(0);
        }
 }
 
 static unsigned si_get_alpha_test_func(struct si_context *sctx)
@@ -1225,20 +1224,31 @@ void si_init_shader_selector_async(void *job, int 
thread_index)
                                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,
                                              false, sel->is_debug_context))
                        fprintf(stderr, "radeonsi: can't create a monolithic 
shader\n");
        }
+
+       /* The GS copy shader is always pre-compiled. */
+       if (sel->type == PIPE_SHADER_GEOMETRY) {
+               sel->gs_copy_shader = si_generate_gs_copy_shader(sscreen, tm, 
sel, debug);
+               if (!sel->gs_copy_shader) {
+                       fprintf(stderr, "radeonsi: can't create GS copy 
shader\n");
+                       return;
+               }
+
+               si_shader_vs(sscreen, sel->gs_copy_shader, sel);
+       }
 }
 
 static void *si_create_shader_selector(struct pipe_context *ctx,
                                       const struct pipe_shader_state *state)
 {
        struct si_screen *sscreen = (struct si_screen *)ctx->screen;
        struct si_context *sctx = (struct si_context*)ctx;
        struct si_shader_selector *sel = CALLOC_STRUCT(si_shader_selector);
        int i;
 
@@ -1507,22 +1517,24 @@ static void si_delete_shader(struct si_context *sctx, 
struct si_shader *shader)
                case PIPE_SHADER_TESS_CTRL:
                        si_pm4_delete_state(sctx, hs, shader->pm4);
                        break;
                case PIPE_SHADER_TESS_EVAL:
                        if (shader->key.tes.as_es)
                                si_pm4_delete_state(sctx, es, shader->pm4);
                        else
                                si_pm4_delete_state(sctx, vs, shader->pm4);
                        break;
                case PIPE_SHADER_GEOMETRY:
-                       si_pm4_delete_state(sctx, gs, shader->pm4);
-                       si_pm4_delete_state(sctx, vs, 
shader->gs_copy_shader->pm4);
+                       if (shader->is_gs_copy_shader)
+                               si_pm4_delete_state(sctx, vs, shader->pm4);
+                       else
+                               si_pm4_delete_state(sctx, gs, shader->pm4);
                        break;
                case PIPE_SHADER_FRAGMENT:
                        si_pm4_delete_state(sctx, ps, shader->pm4);
                        break;
                }
        }
 
        si_shader_destroy(shader);
        free(shader);
 }
@@ -1548,20 +1560,22 @@ static void si_delete_shader_selector(struct 
pipe_context *ctx, void *state)
        }
 
        while (p) {
                c = p->next_variant;
                si_delete_shader(sctx, p);
                p = c;
        }
 
        if (sel->main_shader_part)
                si_delete_shader(sctx, sel->main_shader_part);
+       if (sel->gs_copy_shader)
+               si_delete_shader(sctx, sel->gs_copy_shader);
 
        util_queue_fence_destroy(&sel->ready);
        pipe_mutex_destroy(sel->mutex);
        free(sel->tokens);
        free(sel);
 }
 
 static unsigned si_get_ps_input_cntl(struct si_context *sctx,
                                     struct si_shader *vs, unsigned name,
                                     unsigned index, unsigned interpolate)
@@ -2204,21 +2218,21 @@ bool si_update_shaders(struct si_context *sctx)
                si_pm4_bind_state(sctx, vs, sctx->vs_shader.current->pm4);
                si_update_so(sctx, sctx->vs_shader.cso);
        }
 
        /* Update GS. */
        if (sctx->gs_shader.cso) {
                r = si_shader_select(ctx, &sctx->gs_shader);
                if (r)
                        return false;
                si_pm4_bind_state(sctx, gs, sctx->gs_shader.current->pm4);
-               si_pm4_bind_state(sctx, vs, 
sctx->gs_shader.current->gs_copy_shader->pm4);
+               si_pm4_bind_state(sctx, vs, 
sctx->gs_shader.cso->gs_copy_shader->pm4);
                si_update_so(sctx, sctx->gs_shader.cso);
 
                if (!si_update_gs_ring_buffers(sctx))
                        return false;
 
                si_update_gsvs_ring_bindings(sctx);
        } else {
                si_pm4_bind_state(sctx, gs, NULL);
                si_pm4_bind_state(sctx, es, NULL);
        }
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to