nvc0: make state handling race free

I am not entirely convinced that contexts can't mess up the state of other
contexts, but with this we at least turn down the amount of races on the
CPU side.

If we hit bugs later we can always look into it then and figure out what
to fix how.

I think we might need a better solution for it in the future as state
tracking might need to become more involved, but for now this should be
good enough.

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Acked-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10752>
This commit is contained in:
Karol Herbst
2021-06-17 18:56:24 +02:00
committed by Marge Bot
parent f2af3a9cae
commit df0a4d02f2
11 changed files with 55 additions and 5 deletions
@@ -428,10 +428,11 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
struct nvc0_program *cp = nvc0->compprog;
int ret;
simple_mtx_lock(&screen->state_lock);
ret = !nvc0_state_validate_cp(nvc0, ~0);
if (ret) {
NOUVEAU_ERR("Failed to launch grid !\n");
return;
goto out;
}
nvc0_compute_upload_input(nvc0, info);
@@ -502,6 +503,10 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
nvc0->images_dirty[5] |= nvc0->images_valid[5];
nvc0_update_compute_invocations_counter(nvc0, info);
out:
PUSH_KICK(push);
simple_mtx_unlock(&screen->state_lock);
}
static void
@@ -243,11 +243,13 @@ nvc0_destroy(struct pipe_context *pipe)
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
simple_mtx_lock(&nvc0->screen->state_lock);
if (nvc0->screen->cur_ctx == nvc0) {
nvc0->screen->cur_ctx = NULL;
nvc0->screen->save_state = nvc0->state;
nvc0->screen->save_state.tfb = NULL;
}
simple_mtx_unlock(&nvc0->screen->state_lock);
if (nvc0->base.pipe.stream_uploader)
u_upload_destroy(nvc0->base.pipe.stream_uploader);
@@ -493,10 +495,13 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
/* now that there are no more opportunities for errors, set the current
* context if there isn't already one.
*/
simple_mtx_lock(&screen->state_lock);
if (!screen->cur_ctx) {
nvc0->state = screen->save_state;
screen->cur_ctx = nvc0;
}
simple_mtx_unlock(&screen->state_lock);
nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
PUSH_SPACE(nvc0->base.pushbuf, 8);
@@ -884,6 +884,7 @@ nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog)
size += TU102_SHADER_HEADER_SIZE;
}
simple_mtx_assert_locked(&nvc0->screen->state_lock);
ret = nvc0_program_alloc_code(nvc0, prog);
if (ret) {
struct nouveau_heap *heap = screen->text_heap;
@@ -990,8 +991,11 @@ nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog)
const struct pipe_shader_state pipe = prog->pipe;
const ubyte type = prog->type;
if (prog->mem)
if (prog->mem) {
if (nvc0)
simple_mtx_assert_locked(&nvc0->screen->state_lock);
nouveau_heap_free(&prog->mem);
}
FREE(prog->code); /* may be 0 for hardcoded shaders */
FREE(prog->relocs);
FREE(prog->fixups);
@@ -742,6 +742,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
nouveau_object_del(&screen->nvsw);
nouveau_screen_fini(&screen->base);
simple_mtx_destroy(&screen->state_lock);
FREE(screen);
}
@@ -1068,6 +1069,8 @@ nvc0_screen_create(struct nouveau_device *dev)
pscreen = &screen->base.base;
pscreen->destroy = nvc0_screen_destroy;
simple_mtx_init(&screen->state_lock, mtx_plain);
ret = nouveau_screen_init(&screen->base, dev);
if (ret)
FAIL_SCREEN_INIT("Base screen init failed: %d\n", ret);
@@ -71,6 +71,7 @@ struct nvc0_screen {
struct nvc0_context *cur_ctx;
struct nvc0_graph_state save_state;
simple_mtx_t state_lock;
int num_occlusion_queries_active;
@@ -71,6 +71,7 @@ nvc0_program_sp_start_id(struct nvc0_context *nvc0, int stage,
{
struct nouveau_pushbuf *push = nvc0->base.pushbuf;
simple_mtx_assert_locked(&nvc0->screen->state_lock);
if (nvc0->screen->eng3d->oclass < GV100_3D_CLASS) {
BEGIN_NVC0(push, NVC0_3D(SP_START_ID(stage)), 1);
PUSH_DATA (push, prog->code_base);
@@ -338,6 +339,8 @@ nvc0_tfb_validate(struct nvc0_context *nvc0)
}
}
}
simple_mtx_assert_locked(&nvc0->screen->state_lock);
nvc0->state.tfb = tfb;
if (!(nvc0->dirty_3d & NVC0_NEW_3D_TFB_TARGETS))
@@ -635,9 +635,12 @@ nvc0_sp_state_create(struct pipe_context *pipe,
static void
nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso)
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
struct nvc0_program *prog = (struct nvc0_program *)hwcso;
simple_mtx_lock(&nvc0->screen->state_lock);
nvc0_program_destroy(nvc0_context(pipe), prog);
simple_mtx_unlock(&nvc0->screen->state_lock);
if (prog->pipe.type == PIPE_SHADER_IR_TGSI)
FREE((void *)prog->pipe.tokens);
@@ -872,6 +872,7 @@ nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx;
unsigned s;
simple_mtx_assert_locked(&ctx_to->screen->state_lock);
if (ctx_from)
ctx_to->state = ctx_from->state;
else
@@ -968,6 +969,8 @@ nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask,
int ret;
unsigned i;
simple_mtx_assert_locked(&nvc0->screen->state_lock);
if (nvc0->screen->cur_ctx != nvc0)
nvc0_switch_pipe_context(nvc0);
@@ -700,9 +700,11 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers,
unsigned i, j, k;
uint32_t mode = 0;
simple_mtx_lock(&nvc0->screen->state_lock);
/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
if (!nvc0_state_validate_3d(nvc0, NVC0_NEW_3D_FRAMEBUFFER))
return;
goto out;
if (scissor_state) {
uint32_t minx = scissor_state->minx;
@@ -710,7 +712,7 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers,
uint32_t miny = scissor_state->miny;
uint32_t maxy = MIN2(fb->height, scissor_state->maxy);
if (maxx <= minx || maxy <= miny)
return;
goto out;
BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
PUSH_DATA (push, minx | (maxx - minx) << 16);
@@ -781,6 +783,10 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers,
PUSH_DATA (push, fb->width << 16);
PUSH_DATA (push, fb->height << 16);
}
out:
PUSH_KICK(push);
simple_mtx_unlock(&nvc0->screen->state_lock);
}
static void
@@ -789,8 +795,11 @@ gm200_evaluate_depth_buffer(struct pipe_context *pipe)
struct nvc0_context *nvc0 = nvc0_context(pipe);
struct nouveau_pushbuf *push = nvc0->base.pushbuf;
simple_mtx_lock(&nvc0->screen->state_lock);
nvc0_state_validate_3d(nvc0, NVC0_NEW_3D_FRAMEBUFFER);
IMMED_NVC0(push, SUBC_3D(0x11fc), 1);
PUSH_KICK(push);
simple_mtx_unlock(&nvc0->screen->state_lock);
}
@@ -1684,6 +1693,7 @@ nvc0_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
if (info->num_window_rectangles > 0 || info->window_rectangle_include)
eng3d = true;
simple_mtx_lock(&nvc0->screen->state_lock);
if (nvc0->screen->num_occlusion_queries_active)
IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 0);
@@ -1694,6 +1704,8 @@ nvc0_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
if (nvc0->screen->num_occlusion_queries_active)
IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 1);
PUSH_KICK(push);
simple_mtx_unlock(&nvc0->screen->state_lock);
NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_blit_count, 1);
}
@@ -462,6 +462,7 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
if (update_vertex) {
const unsigned n = MAX2(vertex->num_elements, nvc0->state.num_vtxelts);
simple_mtx_assert_locked(&nvc0->screen->state_lock);
nvc0->state.constant_vbos = const_vbos;
nvc0->state.constant_elts = 0;
nvc0->state.num_vtxelts = vertex->num_elements;
@@ -1020,6 +1021,8 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
BCTX_REFN_bo(nvc0->bufctx_3d, 3D_TEXT, vram_domain | NOUVEAU_BO_RD,
screen->text);
simple_mtx_lock(&nvc0->screen->state_lock);
nvc0_state_validate_3d(nvc0, ~0);
if (nvc0->vertprog->vp.need_draw_parameters && (!indirect || indirect->count_from_stream_output)) {
@@ -1127,6 +1130,9 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
}
cleanup:
PUSH_KICK(push);
simple_mtx_unlock(&nvc0->screen->state_lock);
nvc0->base.kick_notify = nvc0_default_kick_notify;
nvc0_release_user_vbufs(nvc0);
@@ -867,9 +867,10 @@ nve4_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
resident->flags);
}
simple_mtx_lock(&screen->state_lock);
ret = !nve4_state_validate_cp(nvc0, ~0);
if (ret)
goto out;
goto out_unlock;
if (nvc0->screen->compute->oclass >= GV100_COMPUTE_CLASS)
gv100_compute_setup_launch_desc(nvc0, desc, info);
@@ -934,6 +935,10 @@ nve4_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
nvc0_update_compute_invocations_counter(nvc0, info);
out_unlock:
PUSH_KICK(push);
simple_mtx_unlock(&screen->state_lock);
out:
if (ret)
NOUVEAU_ERR("Failed to launch grid !\n");