diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c index 24ee9bfff6c..b2b00f4ba98 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c @@ -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 diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c index 1c90ba17853..f718d0d8fec 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c index 86dd15520a5..36d0f7017c7 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index e6aac565bd2..909e983ed00 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h index 3af38b59503..8bce90ae3af 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h @@ -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; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c index 0bd8a752f15..b0715c7bfff 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c @@ -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)) diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c index 08d2336589f..2f4a9c117d2 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c index 3fb69b51208..6726b94587e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c index 81b833237f8..2e7de275252 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c @@ -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); } diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c index d55792c44e8..75c5080fa77 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c index dccbce91ef7..23d157fd4bf 100644 --- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c @@ -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");