gallium: remove pipe_index_buffer and set_index_buffer
[mesa.git] / src / gallium / drivers / radeonsi / si_state_shaders.c
index 3a9a6f7fcf92ed50b31b96b3fbb3427e4920e3e4..11e3dab2d7d6e30c6cf12331e92fb4b3d515dbdc 100644 (file)
@@ -498,11 +498,6 @@ static void si_shader_hs(struct si_screen *sscreen, struct si_shader *shader)
                 */
                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) |
                        S_00B42C_USER_SGPR_MSB(GFX9_TCS_NUM_USER_SGPR >> 5) |
@@ -816,11 +811,6 @@ static void si_shader_gs(struct si_screen *sscreen, struct si_shader *shader)
 
                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);
@@ -853,7 +843,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 = shader->key.mono.vs_export_prim_id;
+       bool enable_prim_id = shader->key.mono.vs_export_prim_id || shader->selector->info.uses_primid;
 
        pm4 = si_get_shader_pm4_state(shader);
        if (!pm4)
@@ -898,7 +888,7 @@ static void si_shader_vs(struct si_screen *sscreen, struct si_shader *shader,
                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 = shader->selector->info.uses_primid ? 3 : 2;
+               vgpr_comp_cnt = enable_prim_id ? 3 : 2;
                num_user_sgprs = SI_TES_NUM_USER_SGPR;
        } else
                unreachable("invalid shader selector type");
@@ -1991,8 +1981,8 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
        case PIPE_SHADER_TESS_CTRL:
                /* Always reserve space for these. */
                sel->patch_outputs_written |=
-                       (1llu << si_shader_io_get_unique_index(TGSI_SEMANTIC_TESSINNER, 0)) |
-                       (1llu << si_shader_io_get_unique_index(TGSI_SEMANTIC_TESSOUTER, 0));
+                       (1llu << si_shader_io_get_unique_index_patch(TGSI_SEMANTIC_TESSINNER, 0)) |
+                       (1llu << si_shader_io_get_unique_index_patch(TGSI_SEMANTIC_TESSOUTER, 0));
                /* fall through */
        case PIPE_SHADER_VERTEX:
        case PIPE_SHADER_TESS_EVAL:
@@ -2005,7 +1995,7 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
                        case TGSI_SEMANTIC_TESSOUTER:
                        case TGSI_SEMANTIC_PATCH:
                                sel->patch_outputs_written |=
-                                       1llu << si_shader_io_get_unique_index(name, index);
+                                       1llu << si_shader_io_get_unique_index_patch(name, index);
                                break;
 
                        case TGSI_SEMANTIC_GENERIC:
@@ -2148,6 +2138,17 @@ static void si_bind_vs_shader(struct pipe_context *ctx, void *state)
        r600_update_vs_writes_viewport_index(&sctx->b, si_get_vs_info(sctx));
 }
 
+static void si_update_tcs_tes_uses_prim_id(struct si_context *sctx)
+{
+       sctx->ia_multi_vgt_param_key.u.tcs_tes_uses_prim_id =
+               (sctx->tes_shader.cso &&
+                sctx->tes_shader.cso->info.uses_primid) ||
+               (sctx->tcs_shader.cso &&
+                sctx->tcs_shader.cso->info.uses_primid) ||
+               (sctx->ps_shader.cso && !sctx->gs_shader.cso &&
+                sctx->ps_shader.cso->info.uses_primid);
+}
+
 static void si_bind_gs_shader(struct pipe_context *ctx, void *state)
 {
        struct si_context *sctx = (struct si_context *)ctx;
@@ -2164,20 +2165,14 @@ static void si_bind_gs_shader(struct pipe_context *ctx, void *state)
        si_mark_atom_dirty(sctx, &sctx->clip_regs);
        sctx->last_rast_prim = -1; /* reset this so that it gets updated */
 
-       if (enable_changed)
+       if (enable_changed) {
                si_shader_change_notify(sctx);
+               if (sctx->ia_multi_vgt_param_key.u.uses_tess)
+                       si_update_tcs_tes_uses_prim_id(sctx);
+       }
        r600_update_vs_writes_viewport_index(&sctx->b, si_get_vs_info(sctx));
 }
 
-static void si_update_tcs_tes_uses_prim_id(struct si_context *sctx)
-{
-       sctx->ia_multi_vgt_param_key.u.tcs_tes_uses_prim_id =
-               (sctx->tes_shader.cso &&
-                sctx->tes_shader.cso->info.uses_primid) ||
-               (sctx->tcs_shader.cso &&
-                sctx->tcs_shader.cso->info.uses_primid);
-}
-
 static void si_bind_tcs_shader(struct pipe_context *ctx, void *state)
 {
        struct si_context *sctx = (struct si_context *)ctx;
@@ -2232,6 +2227,8 @@ static void si_bind_ps_shader(struct pipe_context *ctx, void *state)
        sctx->ps_shader.cso = sel;
        sctx->ps_shader.current = sel ? sel->first_variant : NULL;
        sctx->do_update_shaders = true;
+       if (sel && sctx->ia_multi_vgt_param_key.u.uses_tess)
+               si_update_tcs_tes_uses_prim_id(sctx);
        si_mark_atom_dirty(sctx, &sctx->cb_render_state);
 }
 
@@ -2586,6 +2583,22 @@ static bool si_update_gs_ring_buffers(struct si_context *sctx)
        return true;
 }
 
+static void si_shader_lock(struct si_shader *shader)
+{
+       mtx_lock(&shader->selector->mutex);
+       if (shader->previous_stage_sel) {
+               assert(shader->previous_stage_sel != shader->selector);
+               mtx_lock(&shader->previous_stage_sel->mutex);
+       }
+}
+
+static void si_shader_unlock(struct si_shader *shader)
+{
+       if (shader->previous_stage_sel)
+               mtx_unlock(&shader->previous_stage_sel->mutex);
+       mtx_unlock(&shader->selector->mutex);
+}
+
 /**
  * @returns 1 if \p sel has been updated to use a new scratch buffer
  *          0 if not
@@ -2604,10 +2617,19 @@ static int si_update_scratch_buffer(struct si_context *sctx,
        if (shader->config.scratch_bytes_per_wave == 0)
                return 0;
 
+       /* Prevent race conditions when updating:
+        * - si_shader::scratch_bo
+        * - si_shader::binary::code
+        * - si_shader::previous_stage::binary::code.
+        */
+       si_shader_lock(shader);
+
        /* This shader is already configured to use the current
         * scratch buffer. */
-       if (shader->scratch_bo == sctx->scratch_buffer)
+       if (shader->scratch_bo == sctx->scratch_buffer) {
+               si_shader_unlock(shader);
                return 0;
+       }
 
        assert(sctx->scratch_buffer);
 
@@ -2618,14 +2640,17 @@ static int si_update_scratch_buffer(struct si_context *sctx,
 
        /* Replace the shader bo with a new bo that has the relocs applied. */
        r = si_shader_binary_upload(sctx->screen, shader);
-       if (r)
+       if (r) {
+               si_shader_unlock(shader);
                return r;
+       }
 
        /* Update the shader state to use the new shader bo. */
        si_shader_init_pm4_state(sctx->screen, shader);
 
        r600_resource_reference(&shader->scratch_bo, sctx->scratch_buffer);
 
+       si_shader_unlock(shader);
        return 1;
 }
 
@@ -2651,6 +2676,60 @@ static unsigned si_get_max_scratch_bytes_per_wave(struct si_context *sctx)
        return bytes;
 }
 
+static bool si_update_scratch_relocs(struct si_context *sctx)
+{
+       int r;
+
+       /* Update the shaders, so that they are using the latest scratch.
+        * The scratch buffer may have been changed since these shaders were
+        * last used, so we still need to try to update them, even if they
+        * require scratch buffers smaller than the current size.
+        */
+       r = si_update_scratch_buffer(sctx, sctx->ps_shader.current);
+       if (r < 0)
+               return false;
+       if (r == 1)
+               si_pm4_bind_state(sctx, ps, sctx->ps_shader.current->pm4);
+
+       r = si_update_scratch_buffer(sctx, sctx->gs_shader.current);
+       if (r < 0)
+               return false;
+       if (r == 1)
+               si_pm4_bind_state(sctx, gs, sctx->gs_shader.current->pm4);
+
+       r = si_update_scratch_buffer(sctx, sctx->tcs_shader.current);
+       if (r < 0)
+               return false;
+       if (r == 1)
+               si_pm4_bind_state(sctx, hs, sctx->tcs_shader.current->pm4);
+
+       /* VS can be bound as LS, ES, or VS. */
+       r = si_update_scratch_buffer(sctx, sctx->vs_shader.current);
+       if (r < 0)
+               return false;
+       if (r == 1) {
+               if (sctx->tes_shader.current)
+                       si_pm4_bind_state(sctx, ls, sctx->vs_shader.current->pm4);
+               else if (sctx->gs_shader.current)
+                       si_pm4_bind_state(sctx, es, sctx->vs_shader.current->pm4);
+               else
+                       si_pm4_bind_state(sctx, vs, sctx->vs_shader.current->pm4);
+       }
+
+       /* TES can be bound as ES or VS. */
+       r = si_update_scratch_buffer(sctx, sctx->tes_shader.current);
+       if (r < 0)
+               return false;
+       if (r == 1) {
+               if (sctx->gs_shader.current)
+                       si_pm4_bind_state(sctx, es, sctx->tes_shader.current->pm4);
+               else
+                       si_pm4_bind_state(sctx, vs, sctx->tes_shader.current->pm4);
+       }
+
+       return true;
+}
+
 static bool si_update_spi_tmpring_size(struct si_context *sctx)
 {
        unsigned current_scratch_buffer_size =
@@ -2660,7 +2739,6 @@ static bool si_update_spi_tmpring_size(struct si_context *sctx)
        unsigned scratch_needed_size = scratch_bytes_per_wave *
                sctx->scratch_waves;
        unsigned spi_tmpring_size;
-       int r;
 
        if (scratch_needed_size > 0) {
                if (scratch_needed_size > current_scratch_buffer_size) {
@@ -2680,52 +2758,8 @@ static bool si_update_spi_tmpring_size(struct si_context *sctx)
                                                       &sctx->scratch_buffer->b.b);
                }
 
-               /* Update the shaders, so they are using the latest scratch.  The
-                * scratch buffer may have been changed since these shaders were
-                * last used, so we still need to try to update them, even if
-                * they require scratch buffers smaller than the current size.
-                */
-               r = si_update_scratch_buffer(sctx, sctx->ps_shader.current);
-               if (r < 0)
-                       return false;
-               if (r == 1)
-                       si_pm4_bind_state(sctx, ps, sctx->ps_shader.current->pm4);
-
-               r = si_update_scratch_buffer(sctx, sctx->gs_shader.current);
-               if (r < 0)
+               if (!si_update_scratch_relocs(sctx))
                        return false;
-               if (r == 1)
-                       si_pm4_bind_state(sctx, gs, sctx->gs_shader.current->pm4);
-
-               r = si_update_scratch_buffer(sctx, sctx->tcs_shader.current);
-               if (r < 0)
-                       return false;
-               if (r == 1)
-                       si_pm4_bind_state(sctx, hs, sctx->tcs_shader.current->pm4);
-
-               /* VS can be bound as LS, ES, or VS. */
-               r = si_update_scratch_buffer(sctx, sctx->vs_shader.current);
-               if (r < 0)
-                       return false;
-               if (r == 1) {
-                       if (sctx->tes_shader.current)
-                               si_pm4_bind_state(sctx, ls, sctx->vs_shader.current->pm4);
-                       else if (sctx->gs_shader.current)
-                               si_pm4_bind_state(sctx, es, sctx->vs_shader.current->pm4);
-                       else
-                               si_pm4_bind_state(sctx, vs, sctx->vs_shader.current->pm4);
-               }
-
-               /* TES can be bound as ES or VS. */
-               r = si_update_scratch_buffer(sctx, sctx->tes_shader.current);
-               if (r < 0)
-                       return false;
-               if (r == 1) {
-                       if (sctx->gs_shader.current)
-                               si_pm4_bind_state(sctx, es, sctx->tes_shader.current->pm4);
-                       else
-                               si_pm4_bind_state(sctx, vs, sctx->tes_shader.current->pm4);
-               }
        }
 
        /* The LLVM shader backend should be reporting aligned scratch_sizes. */