radeonsi: make the GS copy shader owned by the GS selector
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Mon, 31 Oct 2016 20:10:37 +0000 (21:10 +0100)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 3 Nov 2016 09:07:50 +0000 (10:07 +0100)
The copy shader only depends on the selector. This change avoids creating
separate code paths for monolithic vs. non-monolithic geometry shaders.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index 0240a3c191decf74f3cc9565a1c9ce2082e956d1..e7617bc4975bb1d023b4ec44373dbf6da68268ae 100644 (file)
@@ -450,7 +450,7 @@ static inline struct tgsi_shader_info *si_get_vs_info(struct si_context *sctx)
 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
index e7553991fe5a9e04d97a4a4caedb21ed5ceef2e0..38f65f3b770c01e97ff0a291a2397b906df66cf9 100644 (file)
@@ -5951,7 +5951,7 @@ static const char *si_get_shader_name(struct si_shader *shader,
                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";
@@ -6080,7 +6080,7 @@ static void si_llvm_build_ret(struct si_shader_context *ctx, LLVMValueRef 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,
@@ -6103,6 +6103,8 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
                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;
@@ -7150,13 +7152,6 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                        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;
 }
 
@@ -8098,11 +8093,6 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
 
 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);
 
index 6c7a05f01bf63a90f5abc62a72d71f22afe9704d..91f9cbffd8e4974237c71f5a98e867cbb3410b05 100644 (file)
@@ -257,6 +257,8 @@ struct si_shader_selector {
         */
        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;
@@ -444,12 +446,12 @@ struct si_shader {
        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;
@@ -471,6 +473,11 @@ struct si_shader_part {
 };
 
 /* 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,
index ebe7a75a2f8e2a359a9724b78fce1de2beece077..4c647cbbf0226f4149b914d2d538a0625ee6e40c 100644 (file)
@@ -836,7 +836,6 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen,
                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);
@@ -1236,6 +1235,17 @@ void si_init_shader_selector_async(void *job, int thread_index)
                                              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,
@@ -1518,8 +1528,10 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
                                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);
@@ -1559,6 +1571,8 @@ 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->gs_copy_shader)
+               si_delete_shader(sctx, sel->gs_copy_shader);
 
        util_queue_fence_destroy(&sel->ready);
        pipe_mutex_destroy(sel->mutex);
@@ -2215,7 +2229,7 @@ bool si_update_shaders(struct si_context *sctx)
                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))