radeonsi: remove VS epilog code, compile VS with PrimID export on demand
[mesa.git] / src / gallium / drivers / radeonsi / si_state_shaders.c
index 6cacbc7a33aace00c1a5056a03bc63cb7c6c30a8..2150eb9896c9fc6c447da0e4babf093f807f27f0 100644 (file)
@@ -324,10 +324,10 @@ void si_destroy_shader_cache(struct si_screen *sscreen)
 /* SHADER STATES */
 
 static void si_set_tesseval_regs(struct si_screen *sscreen,
-                                struct si_shader *shader,
+                                struct si_shader_selector *tes,
                                 struct si_pm4_state *pm4)
 {
-       struct tgsi_shader_info *info = &shader->selector->info;
+       struct tgsi_shader_info *info = &tes->info;
        unsigned tes_prim_mode = info->properties[TGSI_PROPERTY_TES_PRIM_MODE];
        unsigned tes_spacing = info->properties[TGSI_PROPERTY_TES_SPACING];
        bool tes_vertex_order_cw = info->properties[TGSI_PROPERTY_TES_VERTEX_ORDER_CW];
@@ -401,26 +401,29 @@ static void si_set_tesseval_regs(struct si_screen *sscreen,
  *     VS as ES | ES -> GS -> VS             | 30
  *    TES as VS | LS -> HS -> VS             | 14 or 30
  *    TES as ES | LS -> HS -> ES -> GS -> VS | 14 or 30
+ *
+ * If "shader" is NULL, it's assumed it's not LS or GS copy shader.
  */
 static void polaris_set_vgt_vertex_reuse(struct si_screen *sscreen,
+                                        struct si_shader_selector *sel,
                                         struct si_shader *shader,
                                         struct si_pm4_state *pm4)
 {
-       unsigned type = shader->selector->type;
+       unsigned type = sel->type;
 
        if (sscreen->b.family < CHIP_POLARIS10)
                return;
 
        /* VS as VS, or VS as ES: */
        if ((type == PIPE_SHADER_VERTEX &&
-            !shader->key.as_ls &&
-            !shader->is_gs_copy_shader) ||
+            (!shader ||
+             (!shader->key.as_ls && !shader->is_gs_copy_shader))) ||
            /* TES as VS, or TES as ES: */
            type == PIPE_SHADER_TESS_EVAL) {
                unsigned vtx_reuse_depth = 30;
 
                if (type == PIPE_SHADER_TESS_EVAL &&
-                   shader->selector->info.properties[TGSI_PROPERTY_TES_SPACING] ==
+                   sel->info.properties[TGSI_PROPERTY_TES_SPACING] ==
                    PIPE_TESS_SPACING_FRACTIONAL_ODD)
                        vtx_reuse_depth = 14;
 
@@ -455,8 +458,10 @@ static void si_shader_ls(struct si_screen *sscreen, struct si_shader *shader)
        si_pm4_add_bo(pm4, shader->bo, RADEON_USAGE_READ, RADEON_PRIO_SHADER_BINARY);
 
        /* We need at least 2 components for LS.
-        * VGPR0-3: (VertexID, RelAutoindex, ???, InstanceID). */
-       vgpr_comp_cnt = shader->info.uses_instanceid ? 3 : 1;
+        * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID).
+        * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
+        */
+       vgpr_comp_cnt = shader->info.uses_instanceid ? 2 : 1;
 
        si_pm4_set_reg(pm4, R_00B520_SPI_SHADER_PGM_LO_LS, va >> 8);
        si_pm4_set_reg(pm4, R_00B524_SPI_SHADER_PGM_HI_LS, va >> 40);
@@ -488,8 +493,15 @@ static void si_shader_hs(struct si_screen *sscreen, struct si_shader *shader)
                si_pm4_set_reg(pm4, R_00B414_SPI_SHADER_PGM_HI_LS, va >> 40);
 
                /* We need at least 2 components for LS.
-                * VGPR0-3: (VertexID, RelAutoindex, ???, InstanceID). */
-               ls_vgpr_comp_cnt = shader->info.uses_instanceid ? 3 : 1;
+                * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID).
+                * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
+                */
+               ls_vgpr_comp_cnt = shader->info.uses_instanceid ? 2 : 1;
+
+               if (shader->config.scratch_bytes_per_wave) {
+                       fprintf(stderr, "HS: scratch buffer unsupported");
+                       abort();
+               }
 
                shader->config.rsrc2 =
                        S_00B42C_USER_SGPR(GFX9_TCS_NUM_USER_SGPR) |
@@ -536,10 +548,11 @@ static void si_shader_es(struct si_screen *sscreen, struct si_shader *shader)
        si_pm4_add_bo(pm4, shader->bo, RADEON_USAGE_READ, RADEON_PRIO_SHADER_BINARY);
 
        if (shader->selector->type == PIPE_SHADER_VERTEX) {
-               vgpr_comp_cnt = shader->info.uses_instanceid ? 3 : 0;
+               /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */
+               vgpr_comp_cnt = shader->info.uses_instanceid ? 1 : 0;
                num_user_sgprs = SI_VS_NUM_USER_SGPR;
        } else if (shader->selector->type == PIPE_SHADER_TESS_EVAL) {
-               vgpr_comp_cnt = 3; /* all components are needed for TES */
+               vgpr_comp_cnt = shader->selector->info.uses_primid ? 3 : 2;
                num_user_sgprs = SI_TES_NUM_USER_SGPR;
        } else
                unreachable("invalid shader selector type");
@@ -562,9 +575,9 @@ static void si_shader_es(struct si_screen *sscreen, struct si_shader *shader)
                       S_00B32C_SCRATCH_EN(shader->config.scratch_bytes_per_wave > 0));
 
        if (shader->selector->type == PIPE_SHADER_TESS_EVAL)
-               si_set_tesseval_regs(sscreen, shader, pm4);
+               si_set_tesseval_regs(sscreen, shader->selector, pm4);
 
-       polaris_set_vgt_vertex_reuse(sscreen, shader, pm4);
+       polaris_set_vgt_vertex_reuse(sscreen, shader->selector, shader, pm4);
 }
 
 /**
@@ -751,9 +764,10 @@ static void si_shader_gs(struct si_screen *sscreen, struct si_shader *shader)
                struct gfx9_gs_info gs_info;
 
                if (es_type == PIPE_SHADER_VERTEX)
-                       es_vgpr_comp_cnt = shader->info.uses_instanceid ? 3 : 0;
+                       /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */
+                       es_vgpr_comp_cnt = shader->info.uses_instanceid ? 1 : 0;
                else if (es_type == PIPE_SHADER_TESS_EVAL)
-                       es_vgpr_comp_cnt = 3; /* all components are needed for TES */
+                       es_vgpr_comp_cnt = shader->key.part.gs.es->info.uses_primid ? 3 : 2;
                else
                        unreachable("invalid shader selector type");
 
@@ -796,6 +810,17 @@ static void si_shader_gs(struct si_screen *sscreen, struct si_shader *shader)
                               S_028A94_MAX_PRIMS_PER_SUBGROUP(gs_info.max_prims_per_subgroup));
                si_pm4_set_reg(pm4, R_028AAC_VGT_ESGS_RING_ITEMSIZE,
                               shader->key.part.gs.es->esgs_itemsize / 4);
+
+               if (es_type == PIPE_SHADER_TESS_EVAL)
+                       si_set_tesseval_regs(sscreen, shader->key.part.gs.es, pm4);
+
+               polaris_set_vgt_vertex_reuse(sscreen, shader->key.part.gs.es,
+                                            NULL, pm4);
+
+               if (shader->config.scratch_bytes_per_wave) {
+                       fprintf(stderr, "GS: scratch buffer unsupported");
+                       abort();
+               }
        } else {
                si_pm4_set_reg(pm4, R_00B220_SPI_SHADER_PGM_LO_GS, va >> 8);
                si_pm4_set_reg(pm4, R_00B224_SPI_SHADER_PGM_HI_GS, va >> 40);
@@ -828,7 +853,7 @@ static void si_shader_vs(struct si_screen *sscreen, struct si_shader *shader,
        unsigned oc_lds_en;
        unsigned window_space =
           shader->selector->info.properties[TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION];
-       bool enable_prim_id = si_vs_exports_prim_id(shader);
+       bool enable_prim_id = shader->key.mono.vs_export_prim_id;
 
        pm4 = si_get_shader_pm4_state(shader);
        if (!pm4)
@@ -857,10 +882,14 @@ static void si_shader_vs(struct si_screen *sscreen, struct si_shader *shader,
                vgpr_comp_cnt = 0; /* only VertexID is needed for GS-COPY. */
                num_user_sgprs = SI_GSCOPY_NUM_USER_SGPR;
        } else if (shader->selector->type == PIPE_SHADER_VERTEX) {
-               vgpr_comp_cnt = shader->info.uses_instanceid ? 3 : (enable_prim_id ? 2 : 0);
+               /* VGPR0-3: (VertexID, InstanceID / StepRate0, PrimID, InstanceID)
+                * If PrimID is disabled. InstanceID / StepRate1 is loaded instead.
+                * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
+                */
+               vgpr_comp_cnt = enable_prim_id ? 2 : (shader->info.uses_instanceid ? 1 : 0);
                num_user_sgprs = SI_VS_NUM_USER_SGPR;
        } else if (shader->selector->type == PIPE_SHADER_TESS_EVAL) {
-               vgpr_comp_cnt = 3; /* all components are needed for TES */
+               vgpr_comp_cnt = shader->selector->info.uses_primid ? 3 : 2;
                num_user_sgprs = SI_TES_NUM_USER_SGPR;
        } else
                unreachable("invalid shader selector type");
@@ -912,9 +941,9 @@ static void si_shader_vs(struct si_screen *sscreen, struct si_shader *shader,
                               S_028818_VPORT_Z_SCALE_ENA(1) | S_028818_VPORT_Z_OFFSET_ENA(1));
 
        if (shader->selector->type == PIPE_SHADER_TESS_EVAL)
-               si_set_tesseval_regs(sscreen, shader, pm4);
+               si_set_tesseval_regs(sscreen, shader->selector, pm4);
 
-       polaris_set_vgt_vertex_reuse(sscreen, shader, pm4);
+       polaris_set_vgt_vertex_reuse(sscreen, shader->selector, shader, pm4);
 }
 
 static unsigned si_get_ps_num_interp(struct si_shader *ps)
@@ -1242,7 +1271,7 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                        si_shader_selector_key_hw_vs(sctx, sel, key);
 
                        if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
-                               key->part.vs.epilog.export_prim_id = 1;
+                               key->mono.vs_export_prim_id = 1;
                }
                break;
        case PIPE_SHADER_TESS_CTRL:
@@ -1267,7 +1296,7 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                        si_shader_selector_key_hw_vs(sctx, sel, key);
 
                        if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
-                               key->part.tes.epilog.export_prim_id = 1;
+                               key->mono.vs_export_prim_id = 1;
                }
                break;
        case PIPE_SHADER_GEOMETRY:
@@ -1279,6 +1308,25 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                                                          key, &key->part.gs.vs_prolog);
                                key->part.gs.es = sctx->vs_shader.cso;
                        }
+
+                       /* Merged ES-GS can have unbalanced wave usage.
+                        *
+                        * ES threads are per-vertex, while GS threads are
+                        * per-primitive. So without any amplification, there
+                        * are fewer GS threads than ES threads, which can result
+                        * in empty (no-op) GS waves. With too much amplification,
+                        * there are more GS threads than ES threads, which
+                        * can result in empty (no-op) ES waves.
+                        *
+                        * Non-monolithic shaders are implemented by setting EXEC
+                        * at the beginning of shader parts, and don't jump to
+                        * the end if EXEC is 0.
+                        *
+                        * Monolithic shaders use conditional blocks, so they can
+                        * jump and skip empty waves of ES or GS. So set this to
+                        * always use optimized variants, which are monolithic.
+                        */
+                       key->opt.prefer_mono = 1;
                }
                key->part.gs.prolog.tri_strip_adj_fix = sctx->gs_tri_strip_adj_fix;
                break;
@@ -1436,6 +1484,49 @@ static void si_build_shader_variant(void *job, int thread_index)
        si_shader_init_pm4_state(sscreen, shader);
 }
 
+static const struct si_shader_key zeroed;
+
+static bool si_check_missing_main_part(struct si_screen *sscreen,
+                                      struct si_shader_selector *sel,
+                                      struct si_compiler_ctx_state *compiler_state,
+                                      struct si_shader_key *key)
+{
+       struct si_shader **mainp = si_get_main_shader_part(sel, key);
+
+       if (!*mainp) {
+               struct si_shader *main_part = CALLOC_STRUCT(si_shader);
+
+               if (!main_part)
+                       return false;
+
+               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);
+                       return false;
+               }
+               *mainp = main_part;
+       }
+       return true;
+}
+
+static void si_destroy_shader_selector(struct si_context *sctx,
+                                      struct si_shader_selector *sel);
+
+static void si_shader_selector_reference(struct si_context *sctx,
+                                        struct si_shader_selector **dst,
+                                        struct si_shader_selector *src)
+{
+       if (pipe_reference(&(*dst)->reference, &src->reference))
+               si_destroy_shader_selector(sctx, *dst);
+
+       *dst = src;
+}
+
 /* 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,
@@ -1443,8 +1534,8 @@ static int si_shader_select_with_key(struct si_screen *sscreen,
                                     struct si_shader_key *key,
                                     int thread_index)
 {
-       static const struct si_shader_key zeroed;
        struct si_shader_selector *sel = state->cso;
+       struct si_shader_selector *previous_stage_sel = NULL;
        struct si_shader *current = state->current;
        struct si_shader *iter, *shader = NULL;
 
@@ -1512,37 +1603,63 @@ again:
        shader->key = *key;
        shader->compiler_ctx_state = *compiler_state;
 
+       /* If this is a merged shader, get the first shader's selector. */
+       if (sscreen->b.chip_class >= GFX9) {
+               if (sel->type == PIPE_SHADER_TESS_CTRL)
+                       previous_stage_sel = key->part.tcs.ls;
+               else if (sel->type == PIPE_SHADER_GEOMETRY)
+                       previous_stage_sel = key->part.gs.es;
+       }
+
        /* 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 =
                sscreen->use_monolithic_shaders ||
                memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0;
 
-       if (!*mainp && !is_pure_monolithic) {
-               struct si_shader *main_part = CALLOC_STRUCT(si_shader);
+       if (!is_pure_monolithic) {
+               bool ok;
 
-               if (!main_part) {
-                       FREE(shader);
-                       mtx_unlock(&sel->mutex);
-                       return -ENOMEM; /* skip the draw call */
-               }
+               /* Make sure the main shader part is present. This is needed
+                * for shaders that can be compiled as VS, LS, or ES, and only
+                * one of them is compiled at creation.
+                *
+                * For merged shaders, check that the starting shader's main
+                * part is present.
+                */
+               if (previous_stage_sel) {
+                       struct si_shader_key shader1_key = zeroed;
 
-               main_part->selector = sel;
-               main_part->key.as_es = key->as_es;
-               main_part->key.as_ls = key->as_ls;
+                       if (sel->type == PIPE_SHADER_TESS_CTRL)
+                               shader1_key.as_ls = 1;
+                       else if (sel->type == PIPE_SHADER_GEOMETRY)
+                               shader1_key.as_es = 1;
+                       else
+                               assert(0);
 
-               if (si_compile_tgsi_shader(sscreen, compiler_state->tm,
-                                          main_part, false,
-                                          &compiler_state->debug) != 0) {
-                       FREE(main_part);
+                       ok = si_check_missing_main_part(sscreen,
+                                                       previous_stage_sel,
+                                                       compiler_state, &shader1_key);
+               } else {
+                       ok = si_check_missing_main_part(sscreen, sel,
+                                                       compiler_state, key);
+               }
+               if (!ok) {
                        FREE(shader);
                        mtx_unlock(&sel->mutex);
                        return -ENOMEM; /* skip the draw call */
                }
-               *mainp = main_part;
        }
 
+       /* Keep the reference to the 1st shader of merged shaders, so that
+        * Gallium can't destroy it before we destroy the 2nd shader.
+        *
+        * Set sctx = NULL, because it's unused if we're not releasing
+        * the shader, and we don't have any sctx here.
+        */
+       si_shader_selector_reference(NULL, &shader->previous_stage_sel,
+                                    previous_stage_sel);
+
        /* Monolithic-only shaders don't make a distinction between optimized
         * and unoptimized. */
        shader->is_monolithic =
@@ -1806,6 +1923,7 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
        if (!sel)
                return NULL;
 
+       pipe_reference_init(&sel->reference, 1);
        sel->screen = sscreen;
        sel->compiler_ctx_state.tm = sctx->tm;
        sel->compiler_ctx_state.debug = sctx->b.debug;
@@ -2151,14 +2269,14 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
                }
        }
 
+       si_shader_selector_reference(sctx, &shader->previous_stage_sel, NULL);
        si_shader_destroy(shader);
        free(shader);
 }
 
-static void si_delete_shader_selector(struct pipe_context *ctx, void *state)
+static void si_destroy_shader_selector(struct si_context *sctx,
+                                      struct si_shader_selector *sel)
 {
-       struct si_context *sctx = (struct si_context *)ctx;
-       struct si_shader_selector *sel = (struct si_shader_selector *)state;
        struct si_shader *p = sel->first_variant, *c;
        struct si_shader_ctx_state *current_shader[SI_NUM_SHADERS] = {
                [PIPE_SHADER_VERTEX] = &sctx->vs_shader,
@@ -2196,6 +2314,14 @@ static void si_delete_shader_selector(struct pipe_context *ctx, void *state)
        free(sel);
 }
 
+static void si_delete_shader_selector(struct pipe_context *ctx, void *state)
+{
+       struct si_context *sctx = (struct si_context *)ctx;
+       struct si_shader_selector *sel = (struct si_shader_selector *)state;
+
+       si_shader_selector_reference(sctx, &sel, NULL);
+}
+
 static unsigned si_get_ps_input_cntl(struct si_context *sctx,
                                     struct si_shader *vs, unsigned name,
                                     unsigned index, unsigned interpolate)