From abf0c46dc162c61ecc01c78d01d09ae14c9ac8c4 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Thu, 22 Sep 2022 21:57:46 +0200 Subject: [PATCH] Add Nouveau multithreading fix backport (rhbz#2123274) --- mesa.spec | 4 + nouveau-multithreading-fixes.patch | 6151 ++++++++++++++++++++++++++++ 2 files changed, 6155 insertions(+) create mode 100644 nouveau-multithreading-fixes.patch diff --git a/mesa.spec b/mesa.spec index ceed6db..7e85ed8 100644 --- a/mesa.spec +++ b/mesa.spec @@ -75,6 +75,10 @@ Patch0006: 0004-Revert-nouveau-no-modifier-the-invalid-modifier.patch Patch0007: 0005-Revert-nouveau-Use-DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEA.patch Patch0008: 0006-Revert-nouveau-Stash-supported-sector-layout-in-scre.patch +# Patches from Karol Herbst to fix Nouveau multithreading: +# https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10752 +Patch0009: nouveau-multithreading-fixes.patch + BuildRequires: meson >= 0.45 BuildRequires: gcc BuildRequires: gcc-c++ diff --git a/nouveau-multithreading-fixes.patch b/nouveau-multithreading-fixes.patch new file mode 100644 index 0000000..3bb00c6 --- /dev/null +++ b/nouveau-multithreading-fixes.patch @@ -0,0 +1,6151 @@ +From 03891efe6d84ccedfab025173b587bc59b487026 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 7 May 2021 14:48:42 +0200 +Subject: [PATCH 01/17] nouveau/buffer: simplify uses of nouveau_fence_work + +nouveau_fence_work already checks the state, so we can just call it +directly. + +Strictly speaking, this isn't functional equivalent, but practically it +doesn't matter when we get the callback called. + +Main reason for doing this is, that this makes locking way easier as we +can simply lock within nouveau_fence_* functions and callers don't have to +take locks themselves. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_buffer.c | 8 ++------ + src/gallium/drivers/nouveau/nv50/nv50_miptree.c | 6 +----- + 2 files changed, 3 insertions(+), 11 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c +index 284525086d0..78f8a9cb5d8 100644 +--- a/src/gallium/drivers/nouveau/nouveau_buffer.c ++++ b/src/gallium/drivers/nouveau/nouveau_buffer.c +@@ -91,12 +91,8 @@ nouveau_buffer_release_gpu_storage(struct nv04_resource *buf) + { + assert(!(buf->status & NOUVEAU_BUFFER_STATUS_USER_PTR)); + +- if (buf->fence && buf->fence->state < NOUVEAU_FENCE_STATE_FLUSHED) { +- nouveau_fence_work(buf->fence, nouveau_fence_unref_bo, buf->bo); +- buf->bo = NULL; +- } else { +- nouveau_bo_ref(NULL, &buf->bo); +- } ++ nouveau_fence_work(buf->fence, nouveau_fence_unref_bo, buf->bo); ++ buf->bo = NULL; + + if (buf->mm) + release_allocation(&buf->mm, buf->fence); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c +index 8f45d9e659f..4554dbf02d4 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c +@@ -163,11 +163,7 @@ nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) + { + struct nv50_miptree *mt = nv50_miptree(pt); + +- if (mt->base.fence && mt->base.fence->state < NOUVEAU_FENCE_STATE_FLUSHED) +- nouveau_fence_work(mt->base.fence, nouveau_fence_unref_bo, mt->base.bo); +- else +- nouveau_bo_ref(NULL, &mt->base.bo); +- ++ nouveau_fence_work(mt->base.fence, nouveau_fence_unref_bo, mt->base.bo); + nouveau_fence_ref(NULL, &mt->base.fence); + nouveau_fence_ref(NULL, &mt->base.fence_wr); + +-- +2.37.3 + + +From 7d1872d683a62000dd5e878f14bb3e31c1a49a05 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 7 May 2021 15:01:18 +0200 +Subject: [PATCH 02/17] nouveau/fence: rework nouveau_fence_emit so we can call + it on emitted fences + +Signed-off-by: Karol Herbst +Reviewed-by: Emma Anholt +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_fence.c | 10 ++++------ + src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c | 4 ++-- + 2 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c +index 117bce3b5c8..a0789739fa3 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.c ++++ b/src/gallium/drivers/nouveau/nouveau_fence.c +@@ -60,7 +60,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; + +- assert(fence->state == NOUVEAU_FENCE_STATE_AVAILABLE); ++ assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); ++ if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED) ++ return; + + /* set this now, so that if fence.emit triggers a flush we don't recurse */ + fence->state = NOUVEAU_FENCE_STATE_EMITTING; +@@ -190,11 +192,7 @@ nouveau_fence_kick(struct nouveau_fence *fence) + + if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) { + PUSH_SPACE(screen->pushbuf, 8); +- /* The space allocation might trigger a flush, which could emit the +- * current fence. So check again. +- */ +- if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) +- nouveau_fence_emit(fence); ++ nouveau_fence_emit(fence); + } + + if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index d2c011fc1da..e1738508798 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -420,7 +420,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0, + /* If the fence guarding this query has not been emitted, that makes a lot + * of the following logic more complicated. + */ +- if (hq->is64bit && hq->fence->state < NOUVEAU_FENCE_STATE_EMITTED) ++ if (hq->is64bit) + nouveau_fence_emit(hq->fence); + + /* We either need to compute a 32- or 64-bit difference between 2 values, +@@ -642,7 +642,7 @@ nvc0_hw_query_fifo_wait(struct nvc0_context *nvc0, struct nvc0_query *q) + unsigned offset = hq->offset; + + /* ensure the query's fence has been emitted */ +- if (hq->is64bit && hq->fence->state < NOUVEAU_FENCE_STATE_EMITTED) ++ if (hq->is64bit) + nouveau_fence_emit(hq->fence); + + PUSH_SPACE(push, 5); +-- +2.37.3 + + +From 05bfbdba563e3436100d7bf1cb7e360f7c7632b4 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Thu, 10 Jun 2021 16:16:24 +0200 +Subject: [PATCH 03/17] nouveau: move nouveau_context initialization to common + code + +Signed-off-by: Karol Herbst +Reviewed-by: Emma Anholt +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_context.h | 2 +- + src/gallium/drivers/nouveau/nouveau_screen.c | 6 +++++- + src/gallium/drivers/nouveau/nv30/nv30_context.c | 14 +++----------- + src/gallium/drivers/nouveau/nv50/nv50_context.c | 5 +---- + src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 6 +----- + 5 files changed, 11 insertions(+), 22 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h +index 3d4af8d765c..e7941b45ec5 100644 +--- a/src/gallium/drivers/nouveau/nouveau_context.h ++++ b/src/gallium/drivers/nouveau/nouveau_context.h +@@ -66,7 +66,7 @@ void + nouveau_context_init_vdec(struct nouveau_context *); + + void +-nouveau_context_init(struct nouveau_context *); ++nouveau_context_init(struct nouveau_context *, struct nouveau_screen *); + + void + nouveau_scratch_runout_release(struct nouveau_context *); +diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c +index 7312a5b1f98..ac69b9d3968 100644 +--- a/src/gallium/drivers/nouveau/nouveau_screen.c ++++ b/src/gallium/drivers/nouveau/nouveau_screen.c +@@ -393,7 +393,11 @@ nouveau_set_debug_callback(struct pipe_context *pipe, + } + + void +-nouveau_context_init(struct nouveau_context *context) ++nouveau_context_init(struct nouveau_context *context, struct nouveau_screen *screen) + { + context->pipe.set_debug_callback = nouveau_set_debug_callback; ++ ++ context->screen = screen; ++ context->client = screen->client; ++ context->pushbuf = screen->pushbuf; + } +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c +index 83c3c6fd82d..4ce28864b8d 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c +@@ -191,7 +191,6 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + { + struct nv30_screen *screen = nv30_screen(pscreen); + struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context); +- struct nouveau_pushbuf *push; + struct pipe_context *pipe; + int ret; + +@@ -199,7 +198,6 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + return NULL; + + nv30->screen = screen; +- nv30->base.screen = &screen->base; + nv30->base.copy_data = nv30_transfer_copy_data; + + pipe = &nv30->base.pipe; +@@ -208,6 +206,9 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + pipe->destroy = nv30_context_destroy; + pipe->flush = nv30_context_flush; + ++ nouveau_context_init(&nv30->base, &screen->base); ++ nv30->base.pushbuf->kick_notify = nv30_context_kick_notify; ++ + nv30->base.pipe.stream_uploader = u_upload_create_default(&nv30->base.pipe); + if (!nv30->base.pipe.stream_uploader) { + nv30_context_destroy(pipe); +@@ -215,14 +216,6 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + } + nv30->base.pipe.const_uploader = nv30->base.pipe.stream_uploader; + +- /*XXX: *cough* per-context client */ +- nv30->base.client = screen->base.client; +- +- /*XXX: *cough* per-context pushbufs */ +- push = screen->base.pushbuf; +- nv30->base.pushbuf = push; +- push->kick_notify = nv30_context_kick_notify; +- + nv30->base.invalidate_resource_storage = nv30_invalidate_resource_storage; + + ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx); +@@ -244,7 +237,6 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (debug_get_bool_option("NV30_SWTNL", false)) + nv30->draw_flags |= NV30_NEW_SWTNL; + +- nouveau_context_init(&nv30->base); + nv30->sample_mask = 0xffff; + nv30_vbo_init(pipe); + nv30_query_init(pipe); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index c6ba3d4df9c..6b7b6889d38 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -313,8 +313,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (!nv50_blitctx_create(nv50)) + goto out_err; + +- nv50->base.pushbuf = screen->base.pushbuf; +- nv50->base.client = screen->base.client; ++ nouveau_context_init(&nv50->base, &screen->base); + + ret = nouveau_bufctx_new(nv50->base.client, 2, &nv50->bufctx); + if (!ret) +@@ -326,7 +325,6 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (ret) + goto out_err; + +- nv50->base.screen = &screen->base; + nv50->base.copy_data = nv50_m2mf_copy_linear; + nv50->base.push_data = nv50_sifc_linear_u8; + nv50->base.push_cb = nv50_cb_push; +@@ -361,7 +359,6 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + } + nv50->base.pushbuf->kick_notify = nv50_default_kick_notify; + +- nouveau_context_init(&nv50->base); + nv50_init_query_functions(nv50); + nv50_init_surface_functions(nv50); + nv50_init_state_functions(nv50); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +index 546c92361c2..c21c5e130b8 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +@@ -425,8 +425,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (!nvc0_blitctx_create(nvc0)) + goto out_err; + +- nvc0->base.pushbuf = screen->base.pushbuf; +- nvc0->base.client = screen->base.client; ++ nouveau_context_init(&nvc0->base, &screen->base); + + ret = nouveau_bufctx_new(nvc0->base.client, 2, &nvc0->bufctx); + if (!ret) +@@ -439,8 +438,6 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + goto out_err; + + nvc0->screen = screen; +- nvc0->base.screen = &screen->base; +- + pipe->screen = pscreen; + pipe->priv = priv; + pipe->stream_uploader = u_upload_create_default(pipe); +@@ -464,7 +461,6 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + pipe->emit_string_marker = nvc0_emit_string_marker; + pipe->get_device_reset_status = nvc0_get_device_reset_status; + +- nouveau_context_init(&nvc0->base); + nvc0_init_query_functions(nvc0); + nvc0_init_surface_functions(nvc0); + nvc0_init_state_functions(nvc0); +-- +2.37.3 + + +From bc4f80ef83e333b203ba37bff63474091dc6b6de Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 25 Jun 2021 22:44:26 +0200 +Subject: [PATCH 04/17] nouveau: wrap nouveau_bo_map + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_buffer.c | 22 +++++++++---------- + src/gallium/drivers/nouveau/nouveau_video.c | 6 ++--- + .../drivers/nouveau/nouveau_vp3_video.c | 4 +++- + src/gallium/drivers/nouveau/nouveau_winsys.h | 7 ++++++ + .../drivers/nouveau/nv30/nv30_miptree.c | 2 +- + .../drivers/nouveau/nv30/nv30_screen.c | 2 +- + .../drivers/nouveau/nv30/nv30_transfer.c | 4 ++-- + .../drivers/nouveau/nv50/nv50_compute.c | 2 +- + .../drivers/nouveau/nv50/nv50_query_hw.c | 2 +- + .../drivers/nouveau/nv50/nv50_screen.c | 2 +- + .../drivers/nouveau/nv50/nv50_transfer.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv84_video.c | 11 +++++----- + src/gallium/drivers/nouveau/nv50/nv98_video.c | 2 +- + .../drivers/nouveau/nv50/nv98_video_bsp.c | 3 ++- + .../drivers/nouveau/nv50/nv98_video_vp.c | 3 ++- + .../drivers/nouveau/nvc0/nvc0_query_hw.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_screen.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_transfer.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_video.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_video_bsp.c | 8 ++++--- + .../drivers/nouveau/nvc0/nvc0_video_vp.c | 3 ++- + .../drivers/nouveau/nvc0/nve4_compute.c | 2 +- + 22 files changed, 56 insertions(+), 41 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c +index 78f8a9cb5d8..e566541a579 100644 +--- a/src/gallium/drivers/nouveau/nouveau_buffer.c ++++ b/src/gallium/drivers/nouveau/nouveau_buffer.c +@@ -168,7 +168,7 @@ nouveau_transfer_staging(struct nouveau_context *nv, + nouveau_mm_allocate(nv->screen->mm_GART, size, &tx->bo, &tx->offset); + if (tx->bo) { + tx->offset += adj; +- if (!nouveau_bo_map(tx->bo, 0, NULL)) ++ if (!BO_MAP(nv->screen, tx->bo, 0, NULL)) + tx->map = (uint8_t *)tx->bo->map + tx->offset; + } + } +@@ -471,9 +471,9 @@ nouveau_buffer_transfer_map(struct pipe_context *pipe, + * wait on the whole slab and instead use the logic below to return a + * reasonable buffer for that case. + */ +- ret = nouveau_bo_map(buf->bo, +- buf->mm ? 0 : nouveau_screen_transfer_flags(usage), +- nv->client); ++ ret = BO_MAP(nv->screen, buf->bo, ++ buf->mm ? 0 : nouveau_screen_transfer_flags(usage), ++ nv->client); + if (ret) { + FREE(tx); + return NULL; +@@ -639,10 +639,10 @@ nouveau_resource_map_offset(struct nouveau_context *nv, + unsigned rw; + rw = (flags & NOUVEAU_BO_WR) ? PIPE_MAP_WRITE : PIPE_MAP_READ; + nouveau_buffer_sync(nv, res, rw); +- if (nouveau_bo_map(res->bo, 0, NULL)) ++ if (BO_MAP(nv->screen, res->bo, 0, NULL)) + return NULL; + } else { +- if (nouveau_bo_map(res->bo, flags, nv->client)) ++ if (BO_MAP(nv->screen, res->bo, flags, nv->client)) + return NULL; + } + return (uint8_t *)res->bo->map + res->offset + offset; +@@ -798,7 +798,7 @@ nouveau_buffer_data_fetch(struct nouveau_context *nv, struct nv04_resource *buf, + { + if (!nouveau_buffer_malloc(buf)) + return false; +- if (nouveau_bo_map(bo, NOUVEAU_BO_RD, nv->client)) ++ if (BO_MAP(nv->screen, bo, NOUVEAU_BO_RD, nv->client)) + return false; + memcpy(buf->data, (uint8_t *)bo->map + offset, size); + return true; +@@ -823,7 +823,7 @@ nouveau_buffer_migrate(struct nouveau_context *nv, + if (new_domain == NOUVEAU_BO_GART && old_domain == 0) { + if (!nouveau_buffer_allocate(screen, buf, new_domain)) + return false; +- ret = nouveau_bo_map(buf->bo, 0, nv->client); ++ ret = BO_MAP(nv->screen, buf->bo, 0, nv->client); + if (ret) + return ret; + memcpy((uint8_t *)buf->bo->map + buf->offset, buf->data, size); +@@ -893,7 +893,7 @@ nouveau_user_buffer_upload(struct nouveau_context *nv, + if (!nouveau_buffer_reallocate(screen, buf, NOUVEAU_BO_GART)) + return false; + +- ret = nouveau_bo_map(buf->bo, 0, nv->client); ++ ret = BO_MAP(nv->screen, buf->bo, 0, nv->client); + if (ret) + return false; + memcpy((uint8_t *)buf->bo->map + buf->offset + base, buf->data + base, size); +@@ -989,7 +989,7 @@ nouveau_scratch_runout(struct nouveau_context *nv, unsigned size) + + ret = nouveau_scratch_bo_alloc(nv, &nv->scratch.runout->bo[n], size); + if (!ret) { +- ret = nouveau_bo_map(nv->scratch.runout->bo[n], 0, NULL); ++ ret = BO_MAP(nv->screen, nv->scratch.runout->bo[n], 0, NULL); + if (ret) + nouveau_bo_ref(NULL, &nv->scratch.runout->bo[--nv->scratch.runout->nr]); + } +@@ -1027,7 +1027,7 @@ nouveau_scratch_next(struct nouveau_context *nv, unsigned size) + nv->scratch.offset = 0; + nv->scratch.end = nv->scratch.bo_size; + +- ret = nouveau_bo_map(bo, NOUVEAU_BO_WR, nv->client); ++ ret = BO_MAP(nv->screen, bo, NOUVEAU_BO_WR, nv->client); + if (!ret) + nv->scratch.map = bo->map; + return !ret; +diff --git a/src/gallium/drivers/nouveau/nouveau_video.c b/src/gallium/drivers/nouveau/nouveau_video.c +index 5c94686625f..787129b376e 100644 +--- a/src/gallium/drivers/nouveau/nouveau_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_video.c +@@ -37,12 +37,12 @@ nouveau_vpe_init(struct nouveau_decoder *dec) { + int ret; + if (dec->cmds) + return 0; +- ret = nouveau_bo_map(dec->cmd_bo, NOUVEAU_BO_RDWR, dec->client); ++ ret = BO_MAP(dec->screen, dec->cmd_bo, NOUVEAU_BO_RDWR, dec->client); + if (ret) { + debug_printf("Mapping cmd bo: %s\n", strerror(-ret)); + return ret; + } +- ret = nouveau_bo_map(dec->data_bo, NOUVEAU_BO_RDWR, dec->client); ++ ret = BO_MAP(dec->screen, dec->data_bo, NOUVEAU_BO_RDWR, dec->client); + if (ret) { + debug_printf("Mapping data bo: %s\n", strerror(-ret)); + return ret; +@@ -582,7 +582,7 @@ nouveau_create_decoder(struct pipe_context *context, + 0, 4096, NULL, &dec->fence_bo); + if (ret) + goto fail; +- nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, NULL); ++ BO_MAP(screen, dec->fence_bo, NOUVEAU_BO_RDWR, NULL); + dec->fence_map = dec->fence_bo->map; + dec->fence_map[0] = 0; + #endif +diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c +index 3b59fd0a513..b3d93a69195 100644 +--- a/src/gallium/drivers/nouveau/nouveau_vp3_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c +@@ -27,6 +27,7 @@ + + #include + ++#include "nouveau_winsys.h" + #include "nouveau_screen.h" + #include "nouveau_context.h" + #include "nouveau_vp3_video.h" +@@ -284,13 +285,14 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, + char path[PATH_MAX]; + ssize_t r; + uint32_t *end, endval; ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + + if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac) + vp4_getpath(profile, path); + else + vp3_getpath(profile, path); + +- if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client)) ++ if (BO_MAP(screen, dec->fw_bo, NOUVEAU_BO_WR, dec->client)) + return 1; + + fd = open(path, O_RDONLY | O_CLOEXEC); +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index 94116cccfae..a5fbf7fb8a3 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -9,6 +9,8 @@ + #include "drm-uapi/drm.h" + #include + ++#include "nouveau_screen.h" ++ + #ifndef NV04_PFIFO_MAX_PACKET_LEN + #define NV04_PFIFO_MAX_PACKET_LEN 2047 + #endif +@@ -66,6 +68,11 @@ PUSH_KICK(struct nouveau_pushbuf *push) + nouveau_pushbuf_kick(push, push->channel); + } + ++static inline int ++BO_MAP(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) ++{ ++ return nouveau_bo_map(bo, access, client); ++} + + #define NOUVEAU_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0) + #define NOUVEAU_RESOURCE_FLAG_DRV_PRIV (PIPE_RESOURCE_FLAG_DRV_PRIV << 1) +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +index 5d1f16b28c9..ebbe3746717 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +@@ -359,7 +359,7 @@ nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, + if (usage & PIPE_MAP_WRITE) + access |= NOUVEAU_BO_WR; + +- ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client); ++ ret = BO_MAP(nv30->base.screen, tx->tmp.bo, access, nv30->base.client); + if (ret) { + pipe_resource_reference(&tx->base.resource, NULL); + FREE(tx); +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +index 615dd23bbd5..b0a08a207d5 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +@@ -732,7 +732,7 @@ nv30_screen_create(struct nouveau_device *dev) + + ret = nouveau_bo_wrap(screen->base.device, fifo->notify, &screen->notify); + if (ret == 0) +- ret = nouveau_bo_map(screen->notify, 0, screen->base.client); ++ ret = BO_MAP(&screen->base, screen->notify, 0, screen->base.client); + if (ret) + FAIL_SCREEN_INIT("error mapping notifier memory: %d\n", ret); + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +index a79fd1f4545..1a5151acb89 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +@@ -635,8 +635,8 @@ nv30_transfer_rect_cpu(XFER_ARGS) + char *srcmap, *dstmap; + int x, y; + +- nouveau_bo_map(src->bo, NOUVEAU_BO_RD, nv30->base.client); +- nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, nv30->base.client); ++ BO_MAP(nv30->base.screen, src->bo, NOUVEAU_BO_RD, nv30->base.client); ++ BO_MAP(nv30->base.screen, dst->bo, NOUVEAU_BO_WR, nv30->base.client); + srcmap = src->bo->map + src->offset; + dstmap = dst->bo->map + dst->offset; + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +index 2e728f51662..d75aa0a9cd3 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +@@ -540,7 +540,7 @@ nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) + mm = nouveau_mm_allocate(screen->base.mm_GART, size, &bo, &offset); + assert(mm); + +- nouveau_bo_map(bo, 0, nv50->base.client); ++ BO_MAP(&screen->base, bo, 0, nv50->base.client); + memcpy(bo->map + offset, input, size); + + nouveau_bufctx_refn(nv50->bufctx, 0, bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +index ff7f521df68..4d959426148 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +@@ -63,7 +63,7 @@ nv50_hw_query_allocate(struct nv50_context *nv50, struct nv50_query *q, + return false; + hq->offset = hq->base_offset; + +- ret = nouveau_bo_map(hq->bo, 0, nv50->base.client); ++ ret = BO_MAP(&screen->base, hq->bo, 0, nv50->base.client); + if (ret) { + nv50_hw_query_allocate(nv50, q, 0); + return false; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +index e54f0919390..eaa2e84e6ad 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +@@ -1070,7 +1070,7 @@ nv50_screen_create(struct nouveau_device *dev) + goto fail; + } + +- nouveau_bo_map(screen->fence.bo, 0, NULL); ++ BO_MAP(&screen->base, screen->fence.bo, 0, NULL); + screen->fence.map = screen->fence.bo->map; + screen->base.fence.emit = nv50_screen_fence_emit; + screen->base.fence.update = nv50_screen_fence_update; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +index 3ebd5e46809..d84a6763a46 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +@@ -453,7 +453,7 @@ nv50_miptree_transfer_map(struct pipe_context *pctx, + if (usage & PIPE_MAP_WRITE) + flags |= NOUVEAU_BO_WR; + +- ret = nouveau_bo_map(tx->rect[1].bo, flags, nv50->base.client); ++ ret = BO_MAP(nv50->base.screen, tx->rect[1].bo, flags, nv50->base.client); + if (ret) { + nouveau_bo_ref(NULL, &tx->rect[1].bo); + FREE(tx); +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video.c b/src/gallium/drivers/nouveau/nv50/nv84_video.c +index 01ca0479b47..7e6aa8fffb3 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video.c +@@ -69,6 +69,7 @@ nv84_load_firmwares(struct nouveau_device *dev, struct nv84_decoder *dec, + { + int ret, size1, size2 = 0; + struct nouveau_bo *fw; ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + + size1 = filesize(fw1); + if (fw2) +@@ -81,7 +82,7 @@ nv84_load_firmwares(struct nouveau_device *dev, struct nv84_decoder *dec, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, dec->vp_fw2_offset + size2, NULL, &fw); + if (ret) + return NULL; +- ret = nouveau_bo_map(fw, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, fw, NOUVEAU_BO_WR, dec->client); + if (ret) + goto error; + +@@ -406,14 +407,14 @@ nv84_create_decoder(struct pipe_context *context, + NULL, &dec->bitstream); + if (ret) + goto fail; +- ret = nouveau_bo_map(dec->bitstream, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, dec->bitstream, NOUVEAU_BO_WR, dec->client); + if (ret) + goto fail; + ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART, + 0, 0x2000, NULL, &dec->vp_params); + if (ret) + goto fail; +- ret = nouveau_bo_map(dec->vp_params, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, dec->vp_params, NOUVEAU_BO_WR, dec->client); + if (ret) + goto fail; + } +@@ -425,7 +426,7 @@ nv84_create_decoder(struct pipe_context *context, + NULL, &dec->mpeg12_bo); + if (ret) + goto fail; +- ret = nouveau_bo_map(dec->mpeg12_bo, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, dec->mpeg12_bo, NOUVEAU_BO_WR, dec->client); + if (ret) + goto fail; + } +@@ -434,7 +435,7 @@ nv84_create_decoder(struct pipe_context *context, + 0, 0x1000, NULL, &dec->fence); + if (ret) + goto fail; +- ret = nouveau_bo_map(dec->fence, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, dec->fence, NOUVEAU_BO_WR, dec->client); + if (ret) + goto fail; + *(uint32_t *)dec->fence->map = 0; +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video.c b/src/gallium/drivers/nouveau/nv50/nv98_video.c +index efa73294065..bc56aff2665 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video.c +@@ -269,7 +269,7 @@ nv98_create_decoder(struct pipe_context *context, + if (ret) + goto fail; + +- nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); ++ BO_MAP(screen, dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); + dec->fence_map = dec->fence_bo->map; + dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0; + dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +index f77258de850..4c3a6172233 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +@@ -39,6 +39,7 @@ nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + unsigned *vp_caps, unsigned *is_ref, + struct nouveau_vp3_video_buffer *refs[16]) + { ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + struct nouveau_pushbuf *push = dec->pushbuf[0]; + enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile); + uint32_t bsp_addr, comm_addr, inter_addr; +@@ -95,7 +96,7 @@ nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + bo_refs[1].bo = dec->inter_bo[comm_seq & 1] = inter_bo = tmp_bo; + } + +- ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, bsp_bo, NOUVEAU_BO_WR, dec->client); + if (ret) { + debug_printf("map failed: %i %s\n", ret, strerror(-ret)); + return -1; +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +index f1cdf168ed4..68dc3546d8e 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +@@ -44,7 +44,8 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 + + if ((comm->pvp_stage & 0xff) != 0xff) { + unsigned *map; +- int ret = nouveau_bo_map(inter_bo, NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client); ++ int ret = BO_MAP(nouveau_screen(dec->base.context->screen), inter_bo, ++ NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client); + assert(ret >= 0); + map = inter_bo->map; + for (i = 0; i < comm->byte_ofs + slice_size; i += 0x10) { +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index e1738508798..7daf65bb39b 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -55,7 +55,7 @@ nvc0_hw_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q, + return false; + hq->offset = hq->base_offset; + +- ret = nouveau_bo_map(hq->bo, 0, nvc0->base.client); ++ ret = BO_MAP(&screen->base, hq->bo, 0, nvc0->base.client); + if (ret) { + nvc0_hw_query_allocate(nvc0, q, 0); + return false; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +index a04969809c4..59a1d614f86 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -1123,7 +1123,7 @@ nvc0_screen_create(struct nouveau_device *dev) + ret = nouveau_bo_new(dev, flags, 0, 4096, NULL, &screen->fence.bo); + if (ret) + FAIL_SCREEN_INIT("Error allocating fence BO: %d\n", ret); +- nouveau_bo_map(screen->fence.bo, 0, NULL); ++ BO_MAP(&screen->base, screen->fence.bo, 0, NULL); + screen->fence.map = screen->fence.bo->map; + screen->base.fence.emit = nvc0_screen_fence_emit; + screen->base.fence.update = nvc0_screen_fence_update; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +index cb345914510..7ede77333ec 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +@@ -388,7 +388,7 @@ nvc0_miptree_transfer_map(struct pipe_context *pctx, + if (nvc0_mt_transfer_can_map_directly(mt)) { + ret = !nvc0_mt_sync(nvc0, mt, usage); + if (!ret) +- ret = nouveau_bo_map(mt->base.bo, 0, NULL); ++ ret = BO_MAP(nvc0->base.screen, mt->base.bo, 0, NULL); + if (ret && + (usage & PIPE_MAP_DIRECTLY)) + return NULL; +@@ -480,7 +480,7 @@ nvc0_miptree_transfer_map(struct pipe_context *pctx, + if (usage & PIPE_MAP_WRITE) + flags |= NOUVEAU_BO_WR; + +- ret = nouveau_bo_map(tx->rect[1].bo, flags, nvc0->base.client); ++ ret = BO_MAP(nvc0->base.screen, tx->rect[1].bo, flags, nvc0->base.client); + if (ret) { + pipe_resource_reference(&tx->base.resource, NULL); + nouveau_bo_ref(NULL, &tx->rect[1].bo); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +index 77895cdd6fa..60a90174b2c 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +@@ -293,7 +293,7 @@ nvc0_create_decoder(struct pipe_context *context, + if (ret) + goto fail; + +- nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); ++ BO_MAP(screen, dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); + dec->fence_map = dec->fence_bo->map; + dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0; + dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +index ee54596e071..50e67bd81b7 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +@@ -34,10 +34,11 @@ static void dump_comm_bsp(struct comm *comm) + unsigned + nvc0_decoder_bsp_begin(struct nouveau_vp3_decoder *dec, unsigned comm_seq) + { ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; + unsigned ret = 0; + +- ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, bsp_bo, NOUVEAU_BO_WR, dec->client); + if (ret) { + debug_printf("map failed: %i %s\n", ret, strerror(-ret)); + return -1; +@@ -53,6 +54,7 @@ nvc0_decoder_bsp_next(struct nouveau_vp3_decoder *dec, + unsigned comm_seq, unsigned num_buffers, + const void *const *data, const unsigned *num_bytes) + { ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; + struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1]; + uint32_t bsp_size = 0; +@@ -82,7 +84,7 @@ nvc0_decoder_bsp_next(struct nouveau_vp3_decoder *dec, + return -1; + } + +- ret = nouveau_bo_map(tmp_bo, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, tmp_bo, NOUVEAU_BO_WR, dec->client); + if (ret) { + debug_printf("map failed: %i %s\n", ret, strerror(-ret)); + return -1; +@@ -114,7 +116,7 @@ nvc0_decoder_bsp_next(struct nouveau_vp3_decoder *dec, + return -1; + } + +- ret = nouveau_bo_map(tmp_bo, NOUVEAU_BO_WR, dec->client); ++ ret = BO_MAP(screen, tmp_bo, NOUVEAU_BO_WR, dec->client); + if (ret) { + debug_printf("map failed: %i %s\n", ret, strerror(-ret)); + return -1; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +index 3de4ec14867..8ec09df01c6 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +@@ -44,7 +44,8 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 + + if ((comm->pvp_stage & 0xff) != 0xff) { + unsigned *map; +- int ret = nouveau_bo_map(inter_bo, NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client); ++ int ret = BO_MAP(nouveau_screen(dec->base.context->screen), inter_bo, ++ NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client); + assert(ret >= 0); + map = inter_bo->map; + for (i = 0; i < comm->byte_ofs + slice_size; i += 0x10) { +diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +index 03a88b87797..3944dfe23c7 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c ++++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +@@ -1031,7 +1031,7 @@ nve4_compute_trap_info(struct nvc0_context *nvc0) + volatile struct nve4_mp_trap_info *info; + uint8_t *map; + +- ret = nouveau_bo_map(bo, NOUVEAU_BO_RDWR, nvc0->base.client); ++ ret = BO_MAP(&screen->base, bo, NOUVEAU_BO_RDWR, nvc0->base.client); + if (ret) + return; + map = (uint8_t *)bo->map; +-- +2.37.3 + + +From 2095734444387603ef8a6e8d90eef94594b1f07a Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 25 Jun 2021 22:46:10 +0200 +Subject: [PATCH 05/17] nouveau: wrap nouveau_bo_wait + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_buffer.c | 2 +- + src/gallium/drivers/nouveau/nouveau_winsys.h | 6 ++++++ + src/gallium/drivers/nouveau/nv50/nv50_query_hw.c | 7 ++++--- + src/gallium/drivers/nouveau/nv50/nv50_query_hw.h | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_shader_state.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv84_video.c | 3 ++- + src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c | 3 ++- + src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c | 2 +- + 12 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c +index e566541a579..cfaf42d7086 100644 +--- a/src/gallium/drivers/nouveau/nouveau_buffer.c ++++ b/src/gallium/drivers/nouveau/nouveau_buffer.c +@@ -191,7 +191,7 @@ nouveau_transfer_read(struct nouveau_context *nv, struct nouveau_transfer *tx) + nv->copy_data(nv, tx->bo, tx->offset, NOUVEAU_BO_GART, + buf->bo, buf->offset + base, buf->domain, size); + +- if (nouveau_bo_wait(tx->bo, NOUVEAU_BO_RD, nv->client)) ++ if (BO_WAIT(nv->screen, tx->bo, NOUVEAU_BO_RD, nv->client)) + return false; + + if (buf->data) +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index a5fbf7fb8a3..a18bd85ad9f 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -74,6 +74,12 @@ BO_MAP(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, st + return nouveau_bo_map(bo, access, client); + } + ++static inline int ++BO_WAIT(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) ++{ ++ return nouveau_bo_wait(bo, access, client); ++} ++ + #define NOUVEAU_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0) + #define NOUVEAU_RESOURCE_FLAG_DRV_PRIV (PIPE_RESOURCE_FLAG_DRV_PRIV << 1) + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +index 4d959426148..5e079cf3307 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +@@ -294,7 +294,7 @@ nv50_hw_get_query_result(struct nv50_context *nv50, struct nv50_query *q, + } + return false; + } +- if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nv50->base.client)) ++ if (BO_WAIT(&nv50->screen->base, hq->bo, NOUVEAU_BO_RD, nv50->base.client)) + return false; + } + hq->state = NV50_HW_QUERY_STATE_READY; +@@ -447,14 +447,15 @@ nv50_hw_get_driver_query_info(struct nv50_screen *screen, unsigned id, + } + + void +-nv50_hw_query_pushbuf_submit(struct nouveau_pushbuf *push, uint16_t method, ++nv50_hw_query_pushbuf_submit(struct nv50_context *nv50, uint16_t method, + struct nv50_query *q, unsigned result_offset) + { ++ struct nouveau_pushbuf *push = nv50->base.pushbuf; + struct nv50_hw_query *hq = nv50_hw_query(q); + + nv50_hw_query_update(q); + if (hq->state != NV50_HW_QUERY_STATE_READY) +- nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, push->client); ++ BO_WAIT(&nv50->screen->base, hq->bo, NOUVEAU_BO_RD, push->client); + hq->state = NV50_HW_QUERY_STATE_READY; + + BEGIN_NV04(push, SUBC_3D(method), 1); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h +index 4a351510f72..ad2f7ec0f73 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h +@@ -52,7 +52,7 @@ nv50_hw_get_driver_query_info(struct nv50_screen *, unsigned, + bool + nv50_hw_query_allocate(struct nv50_context *, struct nv50_query *, int); + void +-nv50_hw_query_pushbuf_submit(struct nouveau_pushbuf *, uint16_t, ++nv50_hw_query_pushbuf_submit(struct nv50_context *, uint16_t, + struct nv50_query *, unsigned); + void + nv84_hw_query_fifo_wait(struct nouveau_pushbuf *, struct nv50_query *); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c +index de3d8fd950e..a6c92bbbd1e 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c +@@ -321,7 +321,7 @@ nv50_hw_sm_query_read_data(uint32_t count[32][4], + if (hq->data[b + 4] != hq->sequence) { + if (!wait) + return false; +- if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nv50->base.client)) ++ if (BO_WAIT(&nv50->screen->base, hq->bo, NOUVEAU_BO_RD, nv50->base.client)) + return false; + } + count[p][c] = hq->data[b + hsq->ctr[c]]; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +index 5a3b911bfe1..3d17953ed37 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +@@ -717,7 +717,7 @@ nv50_stream_output_validate(struct nv50_context *nv50) + PUSH_DATA(push, targ->pipe.buffer_size); + if (!targ->clean) { + assert(targ->pq); +- nv50_hw_query_pushbuf_submit(push, NVA0_3D_STRMOUT_OFFSET(i), ++ nv50_hw_query_pushbuf_submit(nv50, NVA0_3D_STRMOUT_OFFSET(i), + nv50_query(targ->pq), 0x4); + } else { + BEGIN_NV04(push, NVA0_3D(STRMOUT_OFFSET(i)), 1); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 600434f767d..2d1879ed72f 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -737,7 +737,7 @@ nva0_draw_stream_output(struct nv50_context *nv50, + PUSH_DATA (push, 0); + BEGIN_NV04(push, NVA0_3D(DRAW_TFB_STRIDE), 1); + PUSH_DATA (push, so->stride); +- nv50_hw_query_pushbuf_submit(push, NVA0_3D_DRAW_TFB_BYTES, ++ nv50_hw_query_pushbuf_submit(nv50, NVA0_3D_DRAW_TFB_BYTES, + nv50_query(so->pq), 0x4); + BEGIN_NV04(push, NV50_3D(VERTEX_END_GL), 1); + PUSH_DATA (push, 0); +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video.c b/src/gallium/drivers/nouveau/nv50/nv84_video.c +index 7e6aa8fffb3..c5e04bb7dfb 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video.c +@@ -184,11 +184,12 @@ nv84_decoder_begin_frame_mpeg12(struct pipe_video_codec *decoder, + struct pipe_video_buffer *target, + struct pipe_picture_desc *picture) + { ++ struct nouveau_screen *screen = nouveau_screen(decoder->context->screen); + struct nv84_decoder *dec = (struct nv84_decoder *)decoder; + struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; + int i; + +- nouveau_bo_wait(dec->mpeg12_bo, NOUVEAU_BO_RDWR, dec->client); ++ BO_WAIT(screen, dec->mpeg12_bo, NOUVEAU_BO_RDWR, dec->client); + dec->mpeg12_mb_info = dec->mpeg12_bo->map + 0x100; + dec->mpeg12_data = dec->mpeg12_bo->map + 0x100 + + align(0x20 * mb(dec->base.width) * mb(dec->base.height), 0x100); +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c b/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c +index 38eca1771c5..4bd96105bbb 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c +@@ -89,6 +89,7 @@ nv84_decoder_bsp(struct nv84_decoder *dec, + const unsigned *num_bytes, + struct nv84_video_buffer *dest) + { ++ struct nouveau_screen *screen = nouveau_screen(dec->base.context->screen); + struct iparm params; + uint32_t more_params[0x44 / 4] = {0}; + unsigned total_bytes = 0; +@@ -103,7 +104,7 @@ nv84_decoder_bsp(struct nv84_decoder *dec, + { dec->fence, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM }, + }; + +- nouveau_bo_wait(dec->fence, NOUVEAU_BO_RDWR, dec->client); ++ BO_WAIT(screen, dec->fence, NOUVEAU_BO_RDWR, dec->client); + + STATIC_ASSERT(sizeof(struct iparm) == 0x530); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index 7daf65bb39b..d5e0fd6d1c1 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -330,7 +330,7 @@ nvc0_hw_get_query_result(struct nvc0_context *nvc0, struct nvc0_query *q, + } + return false; + } +- if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) ++ if (BO_WAIT(&nvc0->screen->base, hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) + return false; + NOUVEAU_DRV_STAT(&nvc0->screen->base, query_sync_count, 1); + } +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c +index 4cc564217db..4146ad1bc76 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c +@@ -2636,7 +2636,7 @@ nvc0_hw_sm_query_read_data(uint32_t count[32][8], + if (hq->data[b + 8] != hq->sequence) { + if (!wait) + return false; +- if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) ++ if (BO_WAIT(&nvc0->screen->base, hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) + return false; + } + count[p][c] = hq->data[b + hsq->ctr[c]] * (1 << c); +@@ -2664,7 +2664,7 @@ nve4_hw_sm_query_read_data(uint32_t count[32][8], + if (hq->data[b + 20 + d] != hq->sequence) { + if (!wait) + return false; +- if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) ++ if (BO_WAIT(&nvc0->screen->base, hq->bo, NOUVEAU_BO_RD, nvc0->base.client)) + return false; + } + if (hsq->ctr[c] & ~0x3) +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +index 7ede77333ec..1e57d889289 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +@@ -362,7 +362,7 @@ nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage) + if (!mt->base.mm) { + uint32_t access = (usage & PIPE_MAP_WRITE) ? + NOUVEAU_BO_WR : NOUVEAU_BO_RD; +- return !nouveau_bo_wait(mt->base.bo, access, nvc0->base.client); ++ return !BO_WAIT(&nvc0->screen->base, mt->base.bo, access, nvc0->base.client); + } + if (usage & PIPE_MAP_WRITE) + return !mt->base.fence || nouveau_fence_wait(mt->base.fence, &nvc0->base.debug); +-- +2.37.3 + + +From 1f01cae796e8183407cae3444546fcafe38511f9 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Sat, 26 Jun 2021 10:24:45 +0200 +Subject: [PATCH 06/17] nouveau: wrap all nouveau_pushbuf_space calls + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_video.c | 4 ++-- + src/gallium/drivers/nouveau/nouveau_winsys.h | 8 +++++++- + src/gallium/drivers/nouveau/nv30/nv30_clear.c | 4 ++-- + src/gallium/drivers/nouveau/nv30/nv30_transfer.c | 10 +++++----- + src/gallium/drivers/nouveau/nv50/nv50_compute.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_surface.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv98_video.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv98_video_vp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_compute.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_video.c | 6 +++--- + src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nve4_compute.c | 6 +++--- + 20 files changed, 43 insertions(+), 37 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_video.c b/src/gallium/drivers/nouveau/nouveau_video.c +index 787129b376e..db594416348 100644 +--- a/src/gallium/drivers/nouveau/nouveau_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_video.c +@@ -73,7 +73,7 @@ nouveau_vpe_fini(struct nouveau_decoder *dec) { + if (!dec->cmds) + return; + +- nouveau_pushbuf_space(push, 16, 2, 0); ++ PUSH_SPACE_EX(push, 16, 2, 0); + nouveau_bufctx_reset(dec->bufctx, NV31_VIDEO_BIND_CMD); + + #define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_CMD, NOUVEAU_BO_RD +@@ -588,7 +588,7 @@ nouveau_create_decoder(struct pipe_context *context, + #endif + + nouveau_pushbuf_bufctx(dec->push, dec->bufctx); +- nouveau_pushbuf_space(push, 32, 4, 0); ++ PUSH_SPACE_EX(push, 32, 4, 0); + + BEGIN_NV04(push, SUBC_MPEG(NV01_SUBCHAN_OBJECT), 1); + PUSH_DATA (push, dec->mpeg->handle); +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index a18bd85ad9f..a8f24b27f0d 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -24,13 +24,19 @@ PUSH_AVAIL(struct nouveau_pushbuf *push) + return push->end - push->cur; + } + ++static inline bool ++PUSH_SPACE_EX(struct nouveau_pushbuf *push, uint32_t size, uint32_t relocs, uint32_t pushes) ++{ ++ return nouveau_pushbuf_space(push, size, relocs, pushes) == 0; ++} ++ + static inline bool + PUSH_SPACE(struct nouveau_pushbuf *push, uint32_t size) + { + /* Provide a buffer so that fences always have room to be emitted */ + size += 8; + if (PUSH_AVAIL(push) < size) +- return nouveau_pushbuf_space(push, size, 0, 0) == 0; ++ return PUSH_SPACE_EX(push, size, 0, 0); + return true; + } + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_clear.c b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +index 1d5727a413d..9798639b88c 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_clear.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +@@ -148,7 +148,7 @@ nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, + + refn.bo = mt->base.bo; + refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; +- if (nouveau_pushbuf_space(push, 32, 1, 0) || ++ if (!PUSH_SPACE_EX(push, 32, 1, 0) || + nouveau_pushbuf_refn (push, &refn, 1)) + return; + +@@ -214,7 +214,7 @@ nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, + + refn.bo = mt->base.bo; + refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; +- if (nouveau_pushbuf_space(push, 32, 1, 0) || ++ if (!PUSH_SPACE_EX(push, 32, 1, 0) || + nouveau_pushbuf_refn (push, &refn, 1)) + return; + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +index 1a5151acb89..aaee998cfb5 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +@@ -155,7 +155,7 @@ nv30_transfer_rect_blit(XFER_ARGS) + u32 texfmt, texswz; + u32 format, stride; + +- if (nouveau_pushbuf_space(push, 512, 8, 0) || ++ if (!PUSH_SPACE_EX(push, 512, 8, 0) || + nouveau_pushbuf_refn (push, refs, ARRAY_SIZE(refs))) + return; + +@@ -431,7 +431,7 @@ nv30_transfer_rect_sifm(XFER_ARGS) + si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR; + } + +- if (nouveau_pushbuf_space(push, 64, 6, 0) || ++ if (!PUSH_SPACE_EX(push, 64, 6, 0) || + nouveau_pushbuf_refn (push, refs, 2)) + return; + +@@ -516,7 +516,7 @@ nv30_transfer_rect_m2mf(XFER_ARGS) + while (h) { + unsigned lines = (h > 2047) ? 2047 : h; + +- if (nouveau_pushbuf_space(push, 32, 2, 0) || ++ if (!PUSH_SPACE_EX(push, 32, 2, 0) || + nouveau_pushbuf_refn (push, refs, 2)) + return; + +@@ -708,7 +708,7 @@ nv30_transfer_copy_data(struct nouveau_context *nv, + lines = (pages > 2047) ? 2047 : pages; + pages -= lines; + +- if (nouveau_pushbuf_space(push, 32, 2, 0) || ++ if (!PUSH_SPACE_EX(push, 32, 2, 0) || + nouveau_pushbuf_refn (push, refs, 2)) + return; + +@@ -732,7 +732,7 @@ nv30_transfer_copy_data(struct nouveau_context *nv, + } + + if (size) { +- if (nouveau_pushbuf_space(push, 32, 2, 0) || ++ if (!PUSH_SPACE_EX(push, 32, 2, 0) || + nouveau_pushbuf_refn (push, refs, 2)) + return; + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +index d75aa0a9cd3..1fdd5a41e61 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +@@ -547,7 +547,7 @@ nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) + nouveau_pushbuf_bufctx(push, nv50->bufctx); + nouveau_pushbuf_validate(push); + +- nouveau_pushbuf_space(push, 0, 0, 1); ++ PUSH_SPACE_EX(push, 0, 0, 1); + + BEGIN_NV04(push, NV50_CP(USER_PARAM(1)), size / 4); + nouveau_pushbuf_data(push, bo, offset, size); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +index f6c8642220a..f457ac46258 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +@@ -295,7 +295,7 @@ nv50_clear_render_target(struct pipe_context *pipe, + PUSH_DATAf(push, color->f[2]); + PUSH_DATAf(push, color->f[3]); + +- if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0)) ++ if (!PUSH_SPACE_EX(push, 64 + sf->depth, 1, 0)) + return; + + PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); +@@ -394,7 +394,7 @@ nv50_clear_depth_stencil(struct pipe_context *pipe, + mode |= NV50_3D_CLEAR_BUFFERS_S; + } + +- if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0)) ++ if (!PUSH_SPACE_EX(push, 64 + sf->depth, 1, 0)) + return; + + PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); +@@ -771,7 +771,7 @@ nv50_clear_buffer(struct pipe_context *pipe, + PUSH_DATA (push, color.ui[2]); + PUSH_DATA (push, color.ui[3]); + +- if (nouveau_pushbuf_space(push, 64, 1, 0)) ++ if (!PUSH_SPACE_EX(push, 64, 1, 0)) + return; + + PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 2d1879ed72f..830c13beeda 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -631,7 +631,7 @@ nv50_draw_elements(struct nv50_context *nv50, bool shorten, + BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1); + PUSH_DATA (push, prim); + +- nouveau_pushbuf_space(push, 16, 0, 1); ++ PUSH_SPACE_EX(push, 16, 0, 1); + PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); + + switch (index_size) { +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video.c b/src/gallium/drivers/nouveau/nv50/nv98_video.c +index bc56aff2665..1a5685c0a3f 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video.c +@@ -275,7 +275,7 @@ nv98_create_decoder(struct pipe_context *context, + dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); + + /* So lets test if the fence is working? */ +- nouveau_pushbuf_space(push[0], 16, 1, 0); ++ PUSH_SPACE_EX(push[0], 16, 1, 0); + PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[0], SUBC_BSP(0x240), 3); + PUSH_DATAh(push[0], dec->fence_bo->offset); +@@ -286,7 +286,7 @@ nv98_create_decoder(struct pipe_context *context, + PUSH_DATA (push[0], 0); + PUSH_KICK (push[0]); + +- nouveau_pushbuf_space(push[1], 16, 1, 0); ++ PUSH_SPACE_EX(push[1], 16, 1, 0); + PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[1], SUBC_VP(0x240), 3); + PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); +@@ -297,7 +297,7 @@ nv98_create_decoder(struct pipe_context *context, + PUSH_DATA (push[1], 0); + PUSH_KICK (push[1]); + +- nouveau_pushbuf_space(push[2], 16, 1, 0); ++ PUSH_SPACE_EX(push[2], 16, 1, 0); + PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[2], SUBC_PPP(0x240), 3); + PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +index 4c3a6172233..7a87ad70064 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +@@ -108,7 +108,7 @@ nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + + nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); + +- nouveau_pushbuf_space(push, 32, num_refs, 0); ++ PUSH_SPACE_EX(push, 32, num_refs, 0); + nouveau_pushbuf_refn(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c +index 3fce65ba55b..a207291a07f 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c +@@ -94,7 +94,7 @@ nv98_decoder_ppp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, struct n + struct nouveau_pushbuf *push = dec->pushbuf[2]; + unsigned ppp_caps = 0x10; + +- nouveau_pushbuf_space(push, 32, 4, 0); ++ PUSH_SPACE_EX(push, 32, 4, 0); + + switch (codec) { + case PIPE_VIDEO_FORMAT_MPEG12: { +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +index 68dc3546d8e..96ed9a6cb1a 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +@@ -112,7 +112,7 @@ nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom)) + nv98_decoder_kick_ref(dec, target); + +- nouveau_pushbuf_space(push, 32 + codec_extra, num_refs, 0); ++ PUSH_SPACE_EX(push, 32 + codec_extra, num_refs, 0); + + nouveau_pushbuf_refn(push, bo_refs, num_refs); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c +index 62ff39172fc..f61f9cd424f 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c +@@ -464,7 +464,7 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + PUSH_DATA (push, (info->block[1] << 16) | info->block[0]); + PUSH_DATA (push, info->block[2]); + +- nouveau_pushbuf_space(push, 32, 2, 1); ++ PUSH_SPACE_EX(push, 32, 2, 1); + PUSH_REFN(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + + if (unlikely(info->indirect)) { +@@ -511,7 +511,7 @@ nvc0_compute_update_indirect_invocations(struct nvc0_context *nvc0, + struct nv04_resource *res = nv04_resource(info->indirect); + uint32_t offset = res->offset + info->indirect_offset; + +- nouveau_pushbuf_space(push, 16, 0, 8); ++ PUSH_SPACE_EX(push, 16, 0, 8); + PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); + BEGIN_1IC0(push, NVC0_3D(MACRO_COMPUTE_COUNTER), 7); + PUSH_DATA(push, 6); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index d5e0fd6d1c1..c2f8344a3d6 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -129,7 +129,7 @@ nvc0_hw_query_write_compute_invocations(struct nvc0_context *nvc0, + { + struct nouveau_pushbuf *push = nvc0->base.pushbuf; + +- nouveau_pushbuf_space(push, 16, 0, 8); ++ PUSH_SPACE_EX(push, 16, 0, 8); + PUSH_REFN(push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + BEGIN_1IC0(push, NVC0_3D(MACRO_COMPUTE_COUNTER_TO_QUERY), 4); + PUSH_DATA (push, nvc0->compute_invocations); +@@ -435,7 +435,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0, + if ((flags & PIPE_QUERY_WAIT) && hq->state != NVC0_HW_QUERY_STATE_READY) + nvc0_hw_query_fifo_wait(nvc0, q); + +- nouveau_pushbuf_space(push, 32, 2, 3); ++ PUSH_SPACE_EX(push, 32, 2, 3); + PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR); + BEGIN_1IC0(push, NVC0_3D(MACRO_QUERY_BUFFER_WRITE), 9); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +index a8203b5c6ce..0bd8a752f15 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +@@ -364,7 +364,7 @@ nvc0_tfb_validate(struct nvc0_context *nvc0) + + if (!targ->clean) + nvc0_hw_query_fifo_wait(nvc0, nvc0_query(targ->pq)); +- nouveau_pushbuf_space(push, 0, 0, 1); ++ PUSH_SPACE_EX(push, 0, 0, 1); + BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5); + PUSH_DATA (push, 1); + PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +index b9118cb099e..fe51ed3ee15 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +@@ -788,7 +788,7 @@ nvc0_draw_stream_output(struct nvc0_context *nvc0, + } + + while (num_instances--) { +- nouveau_pushbuf_space(push, 16, 0, 1); ++ PUSH_SPACE_EX(push, 16, 0, 1); + BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); + PUSH_DATA (push, mode); + BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BASE), 1); +@@ -869,7 +869,7 @@ nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info, + pushes = draws; + } + +- nouveau_pushbuf_space(push, 16, 0, pushes + !!buf_count); ++ PUSH_SPACE_EX(push, 16, 0, pushes + !!buf_count); + PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); + if (buf_count) + PUSH_REFN(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +index 60a90174b2c..3df13e26557 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +@@ -299,7 +299,7 @@ nvc0_create_decoder(struct pipe_context *context, + dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); + + /* So lets test if the fence is working? */ +- nouveau_pushbuf_space(push[0], 16, 1, 0); ++ PUSH_SPACE_EX(push[0], 16, 1, 0); + PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3); + PUSH_DATAh(push[0], dec->fence_bo->offset); +@@ -310,7 +310,7 @@ nvc0_create_decoder(struct pipe_context *context, + PUSH_DATA (push[0], 0); + PUSH_KICK (push[0]); + +- nouveau_pushbuf_space(push[1], 16, 1, 0); ++ PUSH_SPACE_EX(push[1], 16, 1, 0); + PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[1], SUBC_VP(0x240), 3); + PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); +@@ -321,7 +321,7 @@ nvc0_create_decoder(struct pipe_context *context, + PUSH_DATA (push[1], 0); + PUSH_KICK (push[1]); + +- nouveau_pushbuf_space(push[2], 16, 1, 0); ++ PUSH_SPACE_EX(push[2], 16, 1, 0); + PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3); + PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +index 50e67bd81b7..96eb1015374 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +@@ -162,7 +162,7 @@ nvc0_decoder_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + + nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); + +- nouveau_pushbuf_space(push, 32, num_refs, 0); ++ PUSH_SPACE_EX(push, 32, num_refs, 0); + nouveau_pushbuf_refn(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c +index 4f058628e31..d36d172f2d0 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c +@@ -94,7 +94,7 @@ nvc0_decoder_ppp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, struct n + struct nouveau_pushbuf *push = dec->pushbuf[2]; + unsigned ppp_caps = 0x10; + +- nouveau_pushbuf_space(push, 32, 4, 0); ++ PUSH_SPACE_EX(push, 32, 4, 0); + + switch (codec) { + case PIPE_VIDEO_FORMAT_MPEG12: { +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +index 8ec09df01c6..6975783a73c 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +@@ -112,7 +112,7 @@ nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom)) + nvc0_decoder_kick_ref(dec, target); + +- nouveau_pushbuf_space(push, 32 + codec_extra, num_refs, 0); ++ PUSH_SPACE_EX(push, 32 + codec_extra, num_refs, 0); + + nouveau_pushbuf_refn(push, bo_refs, num_refs); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +index 3944dfe23c7..f07bc208377 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c ++++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +@@ -545,7 +545,7 @@ nve4_compute_upload_input(struct nvc0_context *nvc0, + struct nv04_resource *res = nv04_resource(info->indirect); + uint32_t offset = res->offset + info->indirect_offset; + +- nouveau_pushbuf_space(push, 32, 0, 1); ++ PUSH_SPACE_EX(push, 32, 0, 1); + PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); + + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + 8); +@@ -829,7 +829,7 @@ nve4_upload_indirect_desc(struct nouveau_pushbuf *push, + PUSH_DATA (push, length); + PUSH_DATA (push, 1); + +- nouveau_pushbuf_space(push, 32, 0, 1); ++ PUSH_SPACE_EX(push, 32, 0, 1); + PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); + + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + (length / 4)); +@@ -923,7 +923,7 @@ nve4_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + } + + /* upload descriptor and flush */ +- nouveau_pushbuf_space(push, 32, 1, 0); ++ PUSH_SPACE_EX(push, 32, 1, 0); + PUSH_REFN(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + BEGIN_NVC0(push, NVE4_CP(LAUNCH_DESC_ADDRESS), 1); + PUSH_DATA (push, desc_gpuaddr >> 8); +-- +2.37.3 + + +From 72d3fd4243ad851989e3e961565a7fc91d93625f Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Tue, 29 Jun 2021 00:37:39 +0200 +Subject: [PATCH 07/17] nouveau: wrap nouveau_pushbuf_validate + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_video.c | 2 +- + src/gallium/drivers/nouveau/nouveau_winsys.h | 6 ++++++ + .../drivers/nouveau/nv30/nv30_state_validate.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_compute.c | 2 +- + .../drivers/nouveau/nv50/nv50_state_validate.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_surface.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv50_transfer.c | 8 ++++---- + .../drivers/nouveau/nvc0/nvc0_state_validate.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 10 +++++----- + src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c | 12 ++++++------ + .../drivers/nouveau/nvc0/nvc0_vbo_translate.c | 4 ++-- + 11 files changed, 31 insertions(+), 25 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_video.c b/src/gallium/drivers/nouveau/nouveau_video.c +index db594416348..9637f39c8e2 100644 +--- a/src/gallium/drivers/nouveau/nouveau_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_video.c +@@ -88,7 +88,7 @@ nouveau_vpe_fini(struct nouveau_decoder *dec) { + + #undef BCTX_ARGS + +- if (unlikely(nouveau_pushbuf_validate(dec->push))) ++ if (unlikely(PUSH_VAL(dec->push))) + return; + + BEGIN_NV04(push, NV31_MPEG(EXEC), 1); +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index a8f24b27f0d..cefd83a68e5 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -74,6 +74,12 @@ PUSH_KICK(struct nouveau_pushbuf *push) + nouveau_pushbuf_kick(push, push->channel); + } + ++static inline int ++PUSH_VAL(struct nouveau_pushbuf *push) ++{ ++ return nouveau_pushbuf_validate(push); ++} ++ + static inline int + BO_MAP(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) + { +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +index 26c77595c2a..248c399dd89 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +@@ -499,7 +499,7 @@ nv30_state_validate(struct nv30_context *nv30, uint32_t mask, bool hwtnl) + } + + nouveau_pushbuf_bufctx(push, bctx); +- if (nouveau_pushbuf_validate(push)) { ++ if (PUSH_VAL(push)) { + nouveau_pushbuf_bufctx(push, NULL); + return false; + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +index 1fdd5a41e61..cf406089eae 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +@@ -545,7 +545,7 @@ nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) + + nouveau_bufctx_refn(nv50->bufctx, 0, bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + nouveau_pushbuf_bufctx(push, nv50->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + PUSH_SPACE_EX(push, 0, 0, 1); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +index d465cf633cf..02cf0b72e7e 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +@@ -559,7 +559,7 @@ nv50_state_validate(struct nv50_context *nv50, uint32_t mask, + nv50_bufctx_fence(bufctx, false); + } + nouveau_pushbuf_bufctx(nv50->base.pushbuf, bufctx); +- ret = nouveau_pushbuf_validate(nv50->base.pushbuf); ++ ret = PUSH_VAL(nv50->base.pushbuf); + + return !ret; + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +index f457ac46258..84c9bac414d 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +@@ -257,7 +257,7 @@ nv50_resource_copy_region(struct pipe_context *pipe, + BCTX_REFN(nv50->bufctx, 2D, nv04_resource(src), RD); + BCTX_REFN(nv50->bufctx, 2D, nv04_resource(dst), WR); + nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); +- nouveau_pushbuf_validate(nv50->base.pushbuf); ++ PUSH_VAL(nv50->base.pushbuf); + + for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) { + ret = nv50_2d_texture_do_copy(nv50->base.pushbuf, +@@ -653,7 +653,7 @@ nv50_clear_buffer_push(struct pipe_context *pipe, + + nouveau_bufctx_refn(nv50->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nv50->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + offset &= ~0xff; + +@@ -1639,7 +1639,7 @@ nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info) + BCTX_REFN(nv50->bufctx, 2D, &dst->base, WR); + BCTX_REFN(nv50->bufctx, 2D, &src->base, RD); + nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); +- if (nouveau_pushbuf_validate(nv50->base.pushbuf)) ++ if (PUSH_VAL(nv50->base.pushbuf)) + return; + + for (i = 0; i < info->dst.box.depth; ++i) { +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +index d84a6763a46..143d920552f 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +@@ -67,7 +67,7 @@ nv50_2d_transfer_rect(struct nv50_context *nv50, + nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + uint32_t format; + switch (cpp) { +@@ -197,7 +197,7 @@ nv50_m2mf_transfer_rect(struct nv50_context *nv50, + nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + if (nouveau_bo_memtype(src->bo)) { + BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 6); +@@ -284,7 +284,7 @@ nv50_sifc_linear_u8(struct nouveau_context *nv, + + nouveau_bufctx_refn(nv50->bufctx, 0, dst, domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nv50->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + offset &= ~0xff; + +@@ -337,7 +337,7 @@ nv50_m2mf_copy_linear(struct nouveau_context *nv, + nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 1); + PUSH_DATA (push, 1); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +index ab9a4717727..39c518efdef 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +@@ -985,7 +985,7 @@ nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask, + } + + nouveau_pushbuf_bufctx(nvc0->base.pushbuf, bufctx); +- ret = nouveau_pushbuf_validate(nvc0->base.pushbuf); ++ ret = PUSH_VAL(nvc0->base.pushbuf); + + return !ret; + } +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +index a1c568b0e8f..24e2a2963d4 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +@@ -267,7 +267,7 @@ nvc0_resource_copy_region(struct pipe_context *pipe, + BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD); + BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR); + nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx); +- nouveau_pushbuf_validate(nvc0->base.pushbuf); ++ PUSH_VAL(nvc0->base.pushbuf); + + for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) { + ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf, +@@ -379,7 +379,7 @@ nvc0_clear_buffer_push_nvc0(struct pipe_context *pipe, + + nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nvc0->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + unsigned count = (size + 3) / 4; + unsigned data_words = data_size / 4; +@@ -428,7 +428,7 @@ nvc0_clear_buffer_push_nve4(struct pipe_context *pipe, + + nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nvc0->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + unsigned count = (size + 3) / 4; + unsigned data_words = data_size / 4; +@@ -1327,7 +1327,7 @@ nvc0_blit_3d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) + NOUVEAU_BO_GART | NOUVEAU_BO_RD, vtxbuf_bo); + BCTX_REFN_bo(nvc0->bufctx_3d, 3D_TEXT, + NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD, screen->text); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(0)), 4); + PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | stride << +@@ -1549,7 +1549,7 @@ nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) + BCTX_REFN(nvc0->bufctx, 2D, &dst->base, WR); + BCTX_REFN(nvc0->bufctx, 2D, &src->base, RD); + nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx); +- if (nouveau_pushbuf_validate(nvc0->base.pushbuf)) ++ if (PUSH_VAL(nvc0->base.pushbuf)) + return; + + for (i = 0; i < info->dst.box.depth; ++i) { +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +index 1e57d889289..1da61c0370a 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +@@ -32,7 +32,7 @@ nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0, + nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + if (nouveau_bo_memtype(src->bo)) { + BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_IN), 5); +@@ -138,7 +138,7 @@ nve4_m2mf_transfer_rect(struct nvc0_context *nvc0, + nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); + nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + exec = NVE4_COPY_EXEC_SWIZZLE_ENABLE | NVE4_COPY_EXEC_2D_ENABLE | NVE4_COPY_EXEC_FLUSH | NVE4_COPY_EXEC_COPY_MODE_NON_PIPELINED; + +@@ -207,7 +207,7 @@ nvc0_m2mf_push_linear(struct nouveau_context *nv, + + nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nvc0->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + while (count) { + unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); +@@ -249,7 +249,7 @@ nve4_p2mf_push_linear(struct nouveau_context *nv, + + nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, nvc0->bufctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + while (count) { + unsigned nr = MIN2(count, (NV04_PFIFO_MAX_PACKET_LEN - 1)); +@@ -289,7 +289,7 @@ nvc0_m2mf_copy_linear(struct nouveau_context *nv, + nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + while (size) { + unsigned bytes = MIN2(size, 1 << 17); +@@ -327,7 +327,7 @@ nve4_m2mf_copy_linear(struct nouveau_context *nv, + nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); + nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); + nouveau_pushbuf_bufctx(push, bctx); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + BEGIN_NVC0(push, NVE4_COPY(SRC_ADDRESS_HIGH), 4); + PUSH_DATAh(push, src->offset + srcoff); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c +index 30dae5a1265..c7ae3fb3f9b 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c +@@ -239,7 +239,7 @@ nvc0_push_setup_vertex_array(struct nvc0_context *nvc0, const unsigned count) + + BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, NOUVEAU_BO_GART | NOUVEAU_BO_RD, + bo); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + return dest; + } +@@ -731,7 +731,7 @@ nvc0_push_upload_vertex_ids(struct push_context *ctx, + + BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, NOUVEAU_BO_GART | NOUVEAU_BO_RD, + bo); +- nouveau_pushbuf_validate(push); ++ PUSH_VAL(push); + + if (info->index_size) { + if (!draw->index_bias) { +-- +2.37.3 + + +From 6dd4957222774264a06720e869e0c7a3e1063697 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 13 May 2022 17:36:14 +0200 +Subject: [PATCH 08/17] nouveau: wrap nouveau_pushbuf_refn + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_winsys.h | 13 +++++++++++++ + src/gallium/drivers/nouveau/nv30/nv30_clear.c | 10 ++-------- + src/gallium/drivers/nouveau/nv30/nv30_transfer.c | 10 +++++----- + src/gallium/drivers/nouveau/nv30/nv30_winsys.h | 7 ------- + src/gallium/drivers/nouveau/nv50/nv50_query.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_query_hw.c | 4 ++-- + src/gallium/drivers/nouveau/nv50/nv50_surface.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv50_transfer.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv50_winsys.h | 8 -------- + src/gallium/drivers/nouveau/nv50/nv84_video.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv84_video_vp.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv98_video.c | 6 +++--- + src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c | 2 +- + src/gallium/drivers/nouveau/nv50/nv98_video_vp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_compute.c | 6 +++--- + src/gallium/drivers/nouveau/nvc0/nvc0_query.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c | 12 ++++++------ + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 6 +++--- + src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 6 +++--- + src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 4 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_video.c | 6 +++--- + src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h | 8 -------- + src/gallium/drivers/nouveau/nvc0/nve4_compute.c | 6 +++--- + 30 files changed, 67 insertions(+), 83 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index cefd83a68e5..3d83d572615 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -68,6 +68,19 @@ PUSH_DATAf(struct nouveau_pushbuf *push, float f) + PUSH_DATA(push, u.i); + } + ++static inline int ++PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_pushbuf_refn *refs, int nr) ++{ ++ return nouveau_pushbuf_refn(push, refs, nr); ++} ++ ++static inline int ++PUSH_REF1(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags) ++{ ++ struct nouveau_pushbuf_refn ref = { bo, flags }; ++ return PUSH_REFN(push, &ref, 1); ++} ++ + static inline void + PUSH_KICK(struct nouveau_pushbuf *push) + { +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_clear.c b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +index 9798639b88c..2b8ea9700cf 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_clear.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +@@ -129,7 +129,6 @@ nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, + struct nv30_miptree *mt = nv30_miptree(ps->texture); + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct nouveau_object *eng3d = nv30->screen->eng3d; +- struct nouveau_pushbuf_refn refn; + uint32_t rt_format; + + rt_format = nv30_format(pipe->screen, ps->format)->hw; +@@ -146,10 +145,8 @@ nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, + rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; + } + +- refn.bo = mt->base.bo; +- refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; + if (!PUSH_SPACE_EX(push, 32, 1, 0) || +- nouveau_pushbuf_refn (push, &refn, 1)) ++ PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) + return; + + BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); +@@ -190,7 +187,6 @@ nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, + struct nv30_miptree *mt = nv30_miptree(ps->texture); + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct nouveau_object *eng3d = nv30->screen->eng3d; +- struct nouveau_pushbuf_refn refn; + uint32_t rt_format, mode = 0; + + rt_format = nv30_format(pipe->screen, ps->format)->hw; +@@ -212,10 +208,8 @@ nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, + if (buffers & PIPE_CLEAR_STENCIL) + mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; + +- refn.bo = mt->base.bo; +- refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; + if (!PUSH_SPACE_EX(push, 32, 1, 0) || +- nouveau_pushbuf_refn (push, &refn, 1)) ++ PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) + return; + + BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +index aaee998cfb5..c78b896a729 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +@@ -156,7 +156,7 @@ nv30_transfer_rect_blit(XFER_ARGS) + u32 format, stride; + + if (!PUSH_SPACE_EX(push, 512, 8, 0) || +- nouveau_pushbuf_refn (push, refs, ARRAY_SIZE(refs))) ++ PUSH_REFN(push, refs, ARRAY_SIZE(refs))) + return; + + /* various switches depending on cpp of the transfer */ +@@ -432,7 +432,7 @@ nv30_transfer_rect_sifm(XFER_ARGS) + } + + if (!PUSH_SPACE_EX(push, 64, 6, 0) || +- nouveau_pushbuf_refn (push, refs, 2)) ++ PUSH_REFN(push, refs, 2)) + return; + + if (dst->pitch) { +@@ -517,7 +517,7 @@ nv30_transfer_rect_m2mf(XFER_ARGS) + unsigned lines = (h > 2047) ? 2047 : h; + + if (!PUSH_SPACE_EX(push, 32, 2, 0) || +- nouveau_pushbuf_refn (push, refs, 2)) ++ PUSH_REFN(push, refs, 2)) + return; + + BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); +@@ -709,7 +709,7 @@ nv30_transfer_copy_data(struct nouveau_context *nv, + pages -= lines; + + if (!PUSH_SPACE_EX(push, 32, 2, 0) || +- nouveau_pushbuf_refn (push, refs, 2)) ++ PUSH_REFN(push, refs, 2)) + return; + + BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); +@@ -733,7 +733,7 @@ nv30_transfer_copy_data(struct nouveau_context *nv, + + if (size) { + if (!PUSH_SPACE_EX(push, 32, 2, 0) || +- nouveau_pushbuf_refn (push, refs, 2)) ++ PUSH_REFN(push, refs, 2)) + return; + + BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_winsys.h b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h +index 2324b517c44..25897ea9f6b 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_winsys.h ++++ b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h +@@ -39,13 +39,6 @@ PUSH_RESET(struct nouveau_pushbuf *push, int bin) + nouveau_bufctx_reset(bufctx(push), bin); + } + +-static inline void +-PUSH_REFN(struct nouveau_pushbuf *push, int bin, +- struct nouveau_bo *bo, uint32_t access) +-{ +- nouveau_bufctx_refn(bufctx(push), bin, bo, access); +-} +- + static inline void + PUSH_MTHDl(struct nouveau_pushbuf *push, int subc, int mthd, int bin, + struct nouveau_bo *bo, uint32_t offset, uint32_t access) +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query.c b/src/gallium/drivers/nouveau/nv50/nv50_query.c +index 08820b33672..4d012a14047 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query.c +@@ -132,7 +132,7 @@ nv50_render_condition(struct pipe_context *pipe, + PUSH_DATA (push, 0); + } + +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_NV04(push, NV50_3D(COND_ADDRESS_HIGH), 3); + PUSH_DATAh(push, hq->bo->offset + hq->offset); + PUSH_DATA (push, hq->bo->offset + hq->offset); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +index 5e079cf3307..7508470e982 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +@@ -82,7 +82,7 @@ nv50_hw_query_get(struct nouveau_pushbuf *push, struct nv50_query *q, + offset += hq->offset; + + PUSH_SPACE(push, 5); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + BEGIN_NV04(push, NV50_3D(QUERY_ADDRESS_HIGH), 4); + PUSH_DATAh(push, hq->bo->offset + offset); + PUSH_DATA (push, hq->bo->offset + offset); +@@ -471,7 +471,7 @@ nv84_hw_query_fifo_wait(struct nouveau_pushbuf *push, struct nv50_query *q) + assert(!hq->is64bit); + + PUSH_SPACE(push, 5); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_NV04(push, SUBC_3D(NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH), 4); + PUSH_DATAh(push, hq->bo->offset + offset); + PUSH_DATA (push, hq->bo->offset + offset); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +index 84c9bac414d..72f185b224e 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +@@ -298,7 +298,7 @@ nv50_clear_render_target(struct pipe_context *pipe, + if (!PUSH_SPACE_EX(push, 64 + sf->depth, 1, 0)) + return; + +- PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); ++ PUSH_REF1(push, bo, mt->base.domain | NOUVEAU_BO_WR); + + BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); + PUSH_DATA (push, ( width << 16) | dstx); +@@ -397,7 +397,7 @@ nv50_clear_depth_stencil(struct pipe_context *pipe, + if (!PUSH_SPACE_EX(push, 64 + sf->depth, 1, 0)) + return; + +- PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); ++ PUSH_REF1(push, bo, mt->base.domain | NOUVEAU_BO_WR); + + BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); + PUSH_DATA (push, ( width << 16) | dstx); +@@ -774,7 +774,7 @@ nv50_clear_buffer(struct pipe_context *pipe, + if (!PUSH_SPACE_EX(push, 64, 1, 0)) + return; + +- PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR); ++ PUSH_REF1(push, buf->bo, buf->domain | NOUVEAU_BO_WR); + + BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); + PUSH_DATA (push, width << 16); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +index 143d920552f..6438510d028 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +@@ -511,7 +511,7 @@ nv50_cb_bo_push(struct nouveau_context *nv, + unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN); + + PUSH_SPACE(push, nr + 3); +- PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain); ++ PUSH_REF1 (push, bo, NOUVEAU_BO_WR | domain); + BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); + PUSH_DATA (push, (offset << 6) | bufid); + BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 830c13beeda..100c71b8c2d 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -632,7 +632,7 @@ nv50_draw_elements(struct nv50_context *nv50, bool shorten, + PUSH_DATA (push, prim); + + PUSH_SPACE_EX(push, 16, 0, 1); +- PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); ++ PUSH_REF1(push, buf->bo, NOUVEAU_BO_RD | buf->domain); + + switch (index_size) { + case 4: +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_winsys.h b/src/gallium/drivers/nouveau/nv50/nv50_winsys.h +index 7056258d1bf..cda05cedee9 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_winsys.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_winsys.h +@@ -39,14 +39,6 @@ nv50_add_bufctx_resident(struct nouveau_bufctx *bufctx, int bin, + #define BCTX_REFN(bctx, bin, res, acc) \ + nv50_add_bufctx_resident(bctx, NV50_BIND_##bin, res, NOUVEAU_BO_##acc) + +-static inline void +-PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags) +-{ +- struct nouveau_pushbuf_refn ref = { bo, flags }; +- nouveau_pushbuf_refn(push, &ref, 1); +-} +- +- + #define SUBC_3D(m) 3, (m) + #define NV50_3D(n) SUBC_3D(NV50_3D_##n) + #define NV84_3D(n) SUBC_3D(NV84_3D_##n) +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video.c b/src/gallium/drivers/nouveau/nv50/nv84_video.c +index c5e04bb7dfb..41f74a66770 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video.c +@@ -496,7 +496,7 @@ nv84_create_decoder(struct pipe_context *context, + context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false); + + PUSH_SPACE(nv50->base.pushbuf, 5); +- PUSH_REFN(nv50->base.pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); ++ PUSH_REF1(nv50->base.pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); + /* The clear_render_target is done via 3D engine, so use it to write to a + * sempahore to indicate that it's done. + */ +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c b/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c +index 4bd96105bbb..f988d0af212 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c +@@ -201,7 +201,7 @@ nv84_decoder_bsp(struct nv84_decoder *dec, + memcpy(dec->bitstream->map + 0x600, more_params, sizeof(more_params)); + + PUSH_SPACE(push, 5 + 21 + 3 + 2 + 4 + 2); +- nouveau_pushbuf_refn(push, bo_refs, ARRAY_SIZE(bo_refs)); ++ PUSH_REFN(push, bo_refs, ARRAY_SIZE(bo_refs)); + + /* Wait for the fence = 1 */ + BEGIN_NV04(push, SUBC_BSP(0x10), 4); +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video_vp.c b/src/gallium/drivers/nouveau/nv50/nv84_video_vp.c +index 811e0c60f83..a5d4d18fb82 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video_vp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video_vp.c +@@ -141,13 +141,13 @@ nv84_decoder_vp_h264(struct nv84_decoder *dec, + { bo1, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM }, + { bo2, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM }, + }; +- nouveau_pushbuf_refn(push, bo_refs, ARRAY_SIZE(bo_refs)); ++ PUSH_REFN(push, bo_refs, ARRAY_SIZE(bo_refs)); + } + + memcpy(dec->vp_params->map, ¶m1, sizeof(param1)); + memcpy(dec->vp_params->map + 0x400, ¶m2, sizeof(param2)); + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + /* Wait for BSP to have completed */ + BEGIN_NV04(push, SUBC_VP(0x10), 4); +@@ -522,7 +522,7 @@ nv84_decoder_vp_mpeg12(struct nv84_decoder *dec, + + PUSH_SPACE(push, 10 + 3 + 2); + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + BEGIN_NV04(push, SUBC_VP(0x400), 9); + PUSH_DATA (push, 0x543210); /* each nibble possibly a dma index */ +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video.c b/src/gallium/drivers/nouveau/nv50/nv98_video.c +index 1a5685c0a3f..07cb05550b1 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video.c +@@ -276,7 +276,7 @@ nv98_create_decoder(struct pipe_context *context, + + /* So lets test if the fence is working? */ + PUSH_SPACE_EX(push[0], 16, 1, 0); +- PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[0], SUBC_BSP(0x240), 3); + PUSH_DATAh(push[0], dec->fence_bo->offset); + PUSH_DATA (push[0], dec->fence_bo->offset); +@@ -287,7 +287,7 @@ nv98_create_decoder(struct pipe_context *context, + PUSH_KICK (push[0]); + + PUSH_SPACE_EX(push[1], 16, 1, 0); +- PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[1], SUBC_VP(0x240), 3); + PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); + PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10)); +@@ -298,7 +298,7 @@ nv98_create_decoder(struct pipe_context *context, + PUSH_KICK (push[1]); + + PUSH_SPACE_EX(push[2], 16, 1, 0); +- PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NV04(push[2], SUBC_PPP(0x240), 3); + PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); + PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20)); +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +index 7a87ad70064..2e8bf3b8af6 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c +@@ -109,7 +109,7 @@ nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); + + PUSH_SPACE_EX(push, 32, num_refs, 0); +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; + inter_addr = inter_bo->offset >> 8; +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c +index a207291a07f..bbca2f99105 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c +@@ -47,7 +47,7 @@ nv98_decoder_setup_ppp(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video + bo_refs[i].bo = mt->base.bo; + } + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + nouveau_vp3_ycbcr_offsets(dec, &y2, &cbcr, &cbcr2); + + BEGIN_NV04(push, SUBC_PPP(0x700), 10); +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +index 96ed9a6cb1a..33f6f758a41 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +@@ -114,7 +114,7 @@ nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + + PUSH_SPACE_EX(push, 32 + codec_extra, num_refs, 0); + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; + #if NOUVEAU_VP3_DEBUG_FENCE +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c +index f61f9cd424f..24ee9bfff6c 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c +@@ -465,14 +465,14 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + PUSH_DATA (push, info->block[2]); + + PUSH_SPACE_EX(push, 32, 2, 1); +- PUSH_REFN(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); ++ PUSH_REF1(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + + if (unlikely(info->indirect)) { + struct nv04_resource *res = nv04_resource(info->indirect); + uint32_t offset = res->offset + info->indirect_offset; + unsigned macro = NVC0_CP_MACRO_LAUNCH_GRID_INDIRECT; + +- PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); ++ PUSH_REF1(push, res->bo, NOUVEAU_BO_RD | res->domain); + PUSH_DATA(push, NVC0_FIFO_PKHDR_1I(1, macro, 3)); + nouveau_pushbuf_data(push, res->bo, offset, + NVC0_IB_ENTRY_1_NO_PREFETCH | 3 * 4); +@@ -512,7 +512,7 @@ nvc0_compute_update_indirect_invocations(struct nvc0_context *nvc0, + uint32_t offset = res->offset + info->indirect_offset; + + PUSH_SPACE_EX(push, 16, 0, 8); +- PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); ++ PUSH_REF1(push, res->bo, NOUVEAU_BO_RD | res->domain); + BEGIN_1IC0(push, NVC0_3D(MACRO_COMPUTE_COUNTER), 7); + PUSH_DATA(push, 6); + PUSH_DATA(push, info->block[0]); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c +index 0deb667a02e..085f9712d35 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c +@@ -153,7 +153,7 @@ nvc0_render_condition(struct pipe_context *pipe, + nvc0_hw_query_fifo_wait(nvc0, q); + + PUSH_SPACE(push, 10); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_NVC0(push, NVC0_3D(COND_ADDRESS_HIGH), 3); + PUSH_DATAh(push, hq->bo->offset + hq->offset); + PUSH_DATA (push, hq->bo->offset + hq->offset); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index c2f8344a3d6..a18fdf2e5ac 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -74,7 +74,7 @@ nvc0_hw_query_get(struct nouveau_pushbuf *push, struct nvc0_query *q, + offset += hq->offset; + + PUSH_SPACE(push, 5); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + BEGIN_NVC0(push, NVC0_3D(QUERY_ADDRESS_HIGH), 4); + PUSH_DATAh(push, hq->bo->offset + offset); + PUSH_DATA (push, hq->bo->offset + offset); +@@ -130,7 +130,7 @@ nvc0_hw_query_write_compute_invocations(struct nvc0_context *nvc0, + struct nouveau_pushbuf *push = nvc0->base.pushbuf; + + PUSH_SPACE_EX(push, 16, 0, 8); +- PUSH_REFN(push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); ++ PUSH_REF1(push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + BEGIN_1IC0(push, NVC0_3D(MACRO_COMPUTE_COUNTER_TO_QUERY), 4); + PUSH_DATA (push, nvc0->compute_invocations); + PUSH_DATAh(push, nvc0->compute_invocations); +@@ -436,8 +436,8 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0, + nvc0_hw_query_fifo_wait(nvc0, q); + + PUSH_SPACE_EX(push, 32, 2, 3); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); +- PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); ++ PUSH_REF1 (push, buf->bo, buf->domain | NOUVEAU_BO_WR); + BEGIN_1IC0(push, NVC0_3D(MACRO_QUERY_BUFFER_WRITE), 9); + switch (q->type) { + case PIPE_QUERY_OCCLUSION_PREDICATE: +@@ -629,7 +629,7 @@ nvc0_hw_query_pushbuf_submit(struct nouveau_pushbuf *push, + { + struct nvc0_hw_query *hq = nvc0_hw_query(q); + +- PUSH_REFN(push, hq->bo, NOUVEAU_BO_RD | NOUVEAU_BO_GART); ++ PUSH_REF1(push, hq->bo, NOUVEAU_BO_RD | NOUVEAU_BO_GART); + nouveau_pushbuf_data(push, hq->bo, hq->offset + result_offset, 4 | + NVC0_IB_ENTRY_1_NO_PREFETCH); + } +@@ -646,7 +646,7 @@ nvc0_hw_query_fifo_wait(struct nvc0_context *nvc0, struct nvc0_query *q) + nouveau_fence_emit(hq->fence); + + PUSH_SPACE(push, 5); +- PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); ++ PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_NVC0(push, SUBC_3D(NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH), 4); + if (hq->is64bit) { + PUSH_DATAh(push, nvc0->screen->fence.bo->offset); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +index 59a1d614f86..fa9fc82ff5a 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -935,7 +935,7 @@ nvc0_screen_resize_tls_area(struct nvc0_screen *screen, + * segment, as it may have commands that will reference it. + */ + if (screen->tls) +- PUSH_REFN(screen->base.pushbuf, screen->tls, ++ PUSH_REF1(screen->base.pushbuf, screen->tls, + NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RDWR); + nouveau_bo_ref(NULL, &screen->tls); + screen->tls = bo; +@@ -958,7 +958,7 @@ nvc0_screen_resize_text_area(struct nvc0_screen *screen, uint64_t size) + * segment, as it may have commands that will reference it. + */ + if (screen->text) +- PUSH_REFN(push, screen->text, ++ PUSH_REF1(push, screen->text, + NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + nouveau_bo_ref(NULL, &screen->text); + screen->text = bo; +@@ -1321,7 +1321,7 @@ nvc0_screen_create(struct nouveau_device *dev) + if (ret) + FAIL_SCREEN_INIT("Error allocating uniform BO: %d\n", ret); + +- PUSH_REFN (push, screen->uniform_bo, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, screen->uniform_bo, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_WR); + + /* return { 0.0, 0.0, 0.0, 0.0 } for out-of-bounds vtxbuf access */ + BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +index 24e2a2963d4..5f95c709dec 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +@@ -301,7 +301,7 @@ nvc0_clear_render_target(struct pipe_context *pipe, + if (!PUSH_SPACE(push, 32 + sf->depth)) + return; + +- PUSH_REFN (push, res->bo, res->domain | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, res->bo, res->domain | NOUVEAU_BO_WR); + + BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); + PUSH_DATAf(push, color->f[0]); +@@ -571,7 +571,7 @@ nvc0_clear_buffer(struct pipe_context *pipe, + if (!PUSH_SPACE(push, 40)) + return; + +- PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, buf->bo, buf->domain | NOUVEAU_BO_WR); + + BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); + PUSH_DATA (push, color.ui[0]); +@@ -639,7 +639,7 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe, + if (!PUSH_SPACE(push, 32 + sf->depth)) + return; + +- PUSH_REFN (push, mt->base.bo, mt->base.domain | NOUVEAU_BO_WR); ++ PUSH_REF1 (push, mt->base.bo, mt->base.domain | NOUVEAU_BO_WR); + + if (clear_flags & PIPE_CLEAR_DEPTH) { + BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +index 1da61c0370a..c5aab3075df 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +@@ -598,7 +598,7 @@ nvc0_cb_bo_push(struct nouveau_context *nv, + unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN - 1); + + PUSH_SPACE(push, nr + 2); +- PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain); ++ PUSH_REF1 (push, bo, NOUVEAU_BO_WR | domain); + BEGIN_1IC0(push, NVC0_3D(CB_POS), nr + 1); + PUSH_DATA (push, offset); + PUSH_DATAp(push, data, nr); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +index fe51ed3ee15..b9ca992ffcb 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +@@ -870,9 +870,9 @@ nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info, + } + + PUSH_SPACE_EX(push, 16, 0, pushes + !!buf_count); +- PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); ++ PUSH_REF1(push, buf->bo, NOUVEAU_BO_RD | buf->domain); + if (buf_count) +- PUSH_REFN(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); ++ PUSH_REF1(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); + PUSH_DATA(push, + NVC0_FIFO_PKHDR_1I(0, macro, 3 + !!buf_count + draws * size)); + PUSH_DATA(push, nvc0_prim_gl(info->mode)); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +index 3df13e26557..3ffc4204b81 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +@@ -300,7 +300,7 @@ nvc0_create_decoder(struct pipe_context *context, + + /* So lets test if the fence is working? */ + PUSH_SPACE_EX(push[0], 16, 1, 0); +- PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3); + PUSH_DATAh(push[0], dec->fence_bo->offset); + PUSH_DATA (push[0], dec->fence_bo->offset); +@@ -311,7 +311,7 @@ nvc0_create_decoder(struct pipe_context *context, + PUSH_KICK (push[0]); + + PUSH_SPACE_EX(push[1], 16, 1, 0); +- PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[1], SUBC_VP(0x240), 3); + PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); + PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10)); +@@ -322,7 +322,7 @@ nvc0_create_decoder(struct pipe_context *context, + PUSH_KICK (push[1]); + + PUSH_SPACE_EX(push[2], 16, 1, 0); +- PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); ++ PUSH_REF1 (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); + BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3); + PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); + PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20)); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +index 96eb1015374..df0b5286b33 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c +@@ -163,7 +163,7 @@ nvc0_decoder_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); + + PUSH_SPACE_EX(push, 32, num_refs, 0); +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; + inter_addr = inter_bo->offset >> 8; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c +index d36d172f2d0..6e633237023 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c +@@ -47,7 +47,7 @@ nvc0_decoder_setup_ppp(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video + bo_refs[i].bo = mt->base.bo; + } + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + nouveau_vp3_ycbcr_offsets(dec, &y2, &cbcr, &cbcr2); + + BEGIN_NVC0(push, SUBC_PPP(0x700), 10); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +index 6975783a73c..98dc1c937fc 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +@@ -114,7 +114,7 @@ nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, + + PUSH_SPACE_EX(push, 32 + codec_extra, num_refs, 0); + +- nouveau_pushbuf_refn(push, bo_refs, num_refs); ++ PUSH_REFN(push, bo_refs, num_refs); + + bsp_addr = bsp_bo->offset >> 8; + #if NOUVEAU_VP3_DEBUG_FENCE +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h b/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h +index 81110493231..c9f4cf57162 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h +@@ -38,14 +38,6 @@ nvc0_add_resident(struct nouveau_bufctx *bufctx, int bin, + #define BCTX_REFN(bctx, bin, res, acc) \ + nvc0_add_resident(bctx, NVC0_BIND_##bin, res, NOUVEAU_BO_##acc) + +-static inline void +-PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags) +-{ +- struct nouveau_pushbuf_refn ref = { bo, flags }; +- nouveau_pushbuf_refn(push, &ref, 1); +-} +- +- + #define SUBC_3D(m) 0, (m) + #define NVC0_3D(n) SUBC_3D(NVC0_3D_##n) + #define NVE4_3D(n) SUBC_3D(NVE4_3D_##n) +diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +index f07bc208377..dccbce91ef7 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c ++++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c +@@ -546,7 +546,7 @@ nve4_compute_upload_input(struct nvc0_context *nvc0, + uint32_t offset = res->offset + info->indirect_offset; + + PUSH_SPACE_EX(push, 32, 0, 1); +- PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); ++ PUSH_REF1(push, res->bo, NOUVEAU_BO_RD | res->domain); + + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + 8); + PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_LINEAR | (0x20 << 1)); +@@ -830,7 +830,7 @@ nve4_upload_indirect_desc(struct nouveau_pushbuf *push, + PUSH_DATA (push, 1); + + PUSH_SPACE_EX(push, 32, 0, 1); +- PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); ++ PUSH_REF1(push, res->bo, NOUVEAU_BO_RD | res->domain); + + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + (length / 4)); + PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_LINEAR | (0x08 << 1)); +@@ -924,7 +924,7 @@ nve4_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + + /* upload descriptor and flush */ + PUSH_SPACE_EX(push, 32, 1, 0); +- PUSH_REFN(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); ++ PUSH_REF1(push, screen->text, NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + BEGIN_NVC0(push, NVE4_CP(LAUNCH_DESC_ADDRESS), 1); + PUSH_DATA (push, desc_gpuaddr >> 8); + BEGIN_NVC0(push, NVE4_CP(LAUNCH), 1); +-- +2.37.3 + + +From 4728a5ce42d98cd0cdc5d1d535ae73074a62a32b Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Wed, 30 Jun 2021 10:01:29 +0200 +Subject: [PATCH 09/17] nouveau: use PUSH_KICK instead of nouveau_pushbuf_kick + +This makes it easier to insert locking code around libdrm. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nv30/nv30_screen.c | 3 +-- + src/gallium/drivers/nouveau/nv50/nv50_context.c | 2 +- + src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 2 +- + 3 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +index b0a08a207d5..4b92db1e20b 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +@@ -859,8 +859,7 @@ nv30_screen_create(struct nouveau_device *dev) + PUSH_DATA (push, screen->ntfy->handle); + BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1); + PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE); +- +- nouveau_pushbuf_kick(push, push->channel); ++ PUSH_KICK (push); + + nouveau_fence_new(&screen->base, &screen->base.fence.current); + return &screen->base; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index 6b7b6889d38..58629873554 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -194,7 +194,7 @@ nv50_destroy(struct pipe_context *pipe) + u_upload_destroy(nv50->base.pipe.stream_uploader); + + nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL); +- nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel); ++ PUSH_KICK(nv50->base.pushbuf); + + nv50_context_unreference_resources(nv50); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +index c21c5e130b8..ea54c67e4c9 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +@@ -257,7 +257,7 @@ nvc0_destroy(struct pipe_context *pipe) + * Other contexts will always set their bufctx again on action calls. + */ + nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL); +- nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel); ++ PUSH_KICK(nvc0->base.pushbuf); + + nvc0_context_unreference_resources(nvc0); + nvc0_blitctx_destroy(nvc0); +-- +2.37.3 + + +From 3e0c8701fce67a9225db83be8cd53682acc04be0 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Tue, 9 Feb 2021 20:32:15 +0100 +Subject: [PATCH 10/17] nouveau/fence: make the fence struct part of the fence + API + +This makes it easier to implement proper locking of the fence struct as we +can redesign some of the functions to take the list object instead of +fence objects. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_fence.c | 68 ++++++++++--------- + src/gallium/drivers/nouveau/nouveau_fence.h | 12 +++- + src/gallium/drivers/nouveau/nouveau_screen.h | 12 +--- + .../drivers/nouveau/nv30/nv30_screen.c | 2 +- + .../drivers/nouveau/nv50/nv50_screen.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_screen.c | 2 +- + 6 files changed, 54 insertions(+), 44 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c +index a0789739fa3..e3ea148b17d 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.c ++++ b/src/gallium/drivers/nouveau/nouveau_fence.c +@@ -59,6 +59,7 @@ void + nouveau_fence_emit(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; ++ struct nouveau_fence_list *fence_list = &screen->fence; + + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); + if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED) +@@ -69,14 +70,14 @@ nouveau_fence_emit(struct nouveau_fence *fence) + + ++fence->ref; + +- if (screen->fence.tail) +- screen->fence.tail->next = fence; ++ if (fence_list->tail) ++ fence_list->tail->next = fence; + else +- screen->fence.head = fence; ++ fence_list->head = fence; + +- screen->fence.tail = fence; ++ fence_list->tail = fence; + +- screen->fence.emit(&screen->base, &fence->sequence); ++ fence_list->emit(&screen->base, &fence->sequence); + + assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING); + fence->state = NOUVEAU_FENCE_STATE_EMITTED; +@@ -86,19 +87,19 @@ void + nouveau_fence_del(struct nouveau_fence *fence) + { + struct nouveau_fence *it; +- struct nouveau_screen *screen = fence->screen; ++ struct nouveau_fence_list *fence_list = &fence->screen->fence; + + if (fence->state == NOUVEAU_FENCE_STATE_EMITTED || + fence->state == NOUVEAU_FENCE_STATE_FLUSHED) { +- if (fence == screen->fence.head) { +- screen->fence.head = fence->next; +- if (!screen->fence.head) +- screen->fence.tail = NULL; ++ if (fence == fence_list->head) { ++ fence_list->head = fence->next; ++ if (!fence_list->head) ++ fence_list->tail = NULL; + } else { +- for (it = screen->fence.head; it && it->next != fence; it = it->next); ++ for (it = fence_list->head; it && it->next != fence; it = it->next); + it->next = fence->next; +- if (screen->fence.tail == fence) +- screen->fence.tail = it; ++ if (fence_list->tail == fence) ++ fence_list->tail = it; + } + } + +@@ -111,18 +112,18 @@ nouveau_fence_del(struct nouveau_fence *fence) + } + + void +-nouveau_fence_cleanup(struct nouveau_screen *screen) ++nouveau_fence_cleanup(struct nouveau_fence_list *fence_list) + { +- if (screen->fence.current) { ++ if (fence_list->current) { + struct nouveau_fence *current = NULL; + + /* nouveau_fence_wait will create a new current fence, so wait on the + * _current_ one, and remove both. + */ +- nouveau_fence_ref(screen->fence.current, ¤t); ++ nouveau_fence_ref(fence_list->current, ¤t); + nouveau_fence_wait(current, NULL); + nouveau_fence_ref(NULL, ¤t); +- nouveau_fence_ref(NULL, &screen->fence.current); ++ nouveau_fence_ref(NULL, &fence_list->current); + } + } + +@@ -131,7 +132,8 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + { + struct nouveau_fence *fence; + struct nouveau_fence *next = NULL; +- u32 sequence = screen->fence.update(&screen->base); ++ struct nouveau_fence_list *fence_list = &screen->fence; ++ u32 sequence = fence_list->update(&screen->base); + + /* If running under drm-shim, let all fences be signalled so things run to + * completion (avoids a hang at the end of shader-db). +@@ -139,11 +141,11 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + if (unlikely(screen->disable_fences)) + sequence = screen->fence.sequence; + +- if (screen->fence.sequence_ack == sequence) ++ if (fence_list->sequence_ack == sequence) + return; +- screen->fence.sequence_ack = sequence; ++ fence_list->sequence_ack = sequence; + +- for (fence = screen->fence.head; fence; fence = next) { ++ for (fence = fence_list->head; fence; fence = next) { + next = fence->next; + sequence = fence->sequence; + +@@ -152,12 +154,12 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + nouveau_fence_trigger_work(fence); + nouveau_fence_ref(NULL, &fence); + +- if (sequence == screen->fence.sequence_ack) ++ if (sequence == fence_list->sequence_ack) + break; + } +- screen->fence.head = next; ++ fence_list->head = next; + if (!next) +- screen->fence.tail = NULL; ++ fence_list->tail = NULL; + + if (flushed) { + for (fence = next; fence; fence = fence->next) +@@ -186,6 +188,7 @@ static bool + nouveau_fence_kick(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; ++ struct nouveau_fence_list *fence_list = &screen->fence; + + /* wtf, someone is waiting on a fence in flush_notify handler? */ + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); +@@ -199,7 +202,7 @@ nouveau_fence_kick(struct nouveau_fence *fence) + if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel)) + return false; + +- if (fence == screen->fence.current) ++ if (fence == fence_list->current) + nouveau_fence_next(screen); + + nouveau_fence_update(screen, false); +@@ -211,6 +214,7 @@ bool + nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug) + { + struct nouveau_screen *screen = fence->screen; ++ struct nouveau_fence_list *fence_list = &screen->fence; + uint32_t spins = 0; + int64_t start = 0; + +@@ -241,7 +245,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu + + debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n", + fence->sequence, +- screen->fence.sequence_ack, screen->fence.sequence); ++ fence_list->sequence_ack, fence_list->sequence); + + return false; + } +@@ -249,16 +253,18 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu + void + nouveau_fence_next(struct nouveau_screen *screen) + { +- if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING) { +- if (screen->fence.current->ref > 1) +- nouveau_fence_emit(screen->fence.current); ++ struct nouveau_fence_list *fence_list = &screen->fence; ++ ++ if (fence_list->current->state < NOUVEAU_FENCE_STATE_EMITTING) { ++ if (fence_list->current->ref > 1) ++ nouveau_fence_emit(fence_list->current); + else + return; + } + +- nouveau_fence_ref(NULL, &screen->fence.current); ++ nouveau_fence_ref(NULL, &fence_list->current); + +- nouveau_fence_new(screen, &screen->fence.current); ++ nouveau_fence_new(screen, &fence_list->current); + } + + void +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h +index 129939f0167..a9b21624543 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.h ++++ b/src/gallium/drivers/nouveau/nouveau_fence.h +@@ -29,11 +29,21 @@ struct nouveau_fence { + struct list_head work; + }; + ++struct nouveau_fence_list { ++ struct nouveau_fence *head; ++ struct nouveau_fence *tail; ++ struct nouveau_fence *current; ++ uint32_t sequence; ++ uint32_t sequence_ack; ++ void (*emit)(struct pipe_screen *, uint32_t *sequence); ++ uint32_t (*update)(struct pipe_screen *); ++}; ++ + void nouveau_fence_emit(struct nouveau_fence *); + void nouveau_fence_del(struct nouveau_fence *); + + bool nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **); +-void nouveau_fence_cleanup(struct nouveau_screen *); ++void nouveau_fence_cleanup(struct nouveau_fence_list *); + bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); + void nouveau_fence_update(struct nouveau_screen *, bool flushed); + void nouveau_fence_next(struct nouveau_screen *); +diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h +index 470e1336785..100e9b207b2 100644 +--- a/src/gallium/drivers/nouveau/nouveau_screen.h ++++ b/src/gallium/drivers/nouveau/nouveau_screen.h +@@ -6,6 +6,8 @@ + #include "util/u_atomic.h" + #include "util/u_memory.h" + ++#include "nouveau_fence.h" ++ + #ifndef NDEBUG + # define NOUVEAU_ENABLE_DRIVER_STATISTICS + #endif +@@ -44,15 +46,7 @@ struct nouveau_screen { + + uint16_t class_3d; + +- struct { +- struct nouveau_fence *head; +- struct nouveau_fence *tail; +- struct nouveau_fence *current; +- u32 sequence; +- u32 sequence_ack; +- void (*emit)(struct pipe_screen *, u32 *sequence); +- u32 (*update)(struct pipe_screen *); +- } fence; ++ struct nouveau_fence_list fence; + + struct nouveau_mman *mm_VRAM; + struct nouveau_mman *mm_GART; +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +index 4b92db1e20b..3c0cb06d19d 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +@@ -549,7 +549,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base); ++ nouveau_fence_cleanup(&screen->base.fence); + + nouveau_bo_ref(NULL, &screen->notify); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +index eaa2e84e6ad..1a5f7e3da5a 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +@@ -622,7 +622,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base); ++ nouveau_fence_cleanup(&screen->base.fence); + + if (screen->base.pushbuf) + screen->base.pushbuf->user_priv = NULL; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +index fa9fc82ff5a..2a0fef63bca 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -714,7 +714,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base); ++ nouveau_fence_cleanup(&screen->base.fence); + + if (screen->base.pushbuf) + screen->base.pushbuf->user_priv = NULL; +-- +2.37.3 + + +From 890bfefbe5f05f034eb7255de2d196346403f543 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Fri, 7 May 2021 18:16:12 +0200 +Subject: [PATCH 11/17] nv50: remove nouveau_fence_signalled prior + nouveau_fence_wait + +nouveau_fence_wait handles signalled fences just as well. + +Signed-off-by: Karol Herbst +Reviewed-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 100c71b8c2d..8c73423ab49 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -624,7 +624,7 @@ nv50_draw_elements(struct nv50_context *nv50, bool shorten, + * the not-yet-written data. Ideally this wait would only happen on + * pushbuf submit, but it's probably not a big performance difference. + */ +- if (buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)) ++ if (buf->fence_wr) + nouveau_fence_wait(buf->fence_wr, &nv50->base.debug); + + while (instance_count--) { +-- +2.37.3 + + +From 22a5047c67b2b9c019512678e1bf0e17bb33f488 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Sat, 3 Jul 2021 10:01:52 +0200 +Subject: [PATCH 12/17] nv50: remove nv50_bufctx_fence call in vbo_kick_notify + +No idea why it is there. nvc0 doesn't do anything like it and it doesn't +regress any tests. Also removing is easier than handling the fence locking +inside the kick notify handler. + +Signed-off-by: Karol Herbst +Part-of: +--- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 8c73423ab49..b8ea652a727 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -752,8 +752,6 @@ nv50_draw_vbo_kick_notify(struct nouveau_pushbuf *chan) + struct nv50_screen *screen = chan->user_priv; + + nouveau_fence_update(&screen->base, true); +- +- nv50_bufctx_fence(screen->cur_ctx->bufctx_3d, true); + } + + void +-- +2.37.3 + + +From d69d4dc5dd51f7c566905d20cdb1605244daaa34 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Wed, 9 Jun 2021 21:48:17 +0200 +Subject: [PATCH 13/17] nouveau/fence: per context fence + +This doesn't add a fence list per pipe context, it simply makes us track +the current fence per context so we can safely modify the fence object +per thread. + +Signed-off-by: Karol Herbst +Acked-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_buffer.c | 21 ++++++------ + src/gallium/drivers/nouveau/nouveau_context.h | 1 + + src/gallium/drivers/nouveau/nouveau_fence.c | 34 +++++++++---------- + src/gallium/drivers/nouveau/nouveau_fence.h | 8 ++--- + .../drivers/nouveau/nv30/nv30_context.c | 10 +++--- + .../drivers/nouveau/nv30/nv30_miptree.c | 2 +- + .../drivers/nouveau/nv30/nv30_screen.c | 3 -- + .../nouveau/nv30/nv30_state_validate.c | 5 ++- + .../drivers/nouveau/nv50/nv50_compute.c | 4 +-- + .../drivers/nouveau/nv50/nv50_context.c | 18 +++++----- + .../drivers/nouveau/nv50/nv50_context.h | 20 ++++++++++- + .../drivers/nouveau/nv50/nv50_query_hw.c | 4 +-- + .../drivers/nouveau/nv50/nv50_screen.c | 4 --- + .../drivers/nouveau/nv50/nv50_screen.h | 26 -------------- + .../nouveau/nv50/nv50_state_validate.c | 4 +-- + .../drivers/nouveau/nv50/nv50_surface.c | 6 ++-- + .../drivers/nouveau/nv50/nv50_transfer.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_context.c | 16 +++++---- + .../drivers/nouveau/nvc0/nvc0_context.h | 23 +++++++++++++ + .../drivers/nouveau/nvc0/nvc0_query_hw.c | 8 ++--- + .../drivers/nouveau/nvc0/nvc0_screen.c | 4 --- + .../drivers/nouveau/nvc0/nvc0_screen.h | 26 -------------- + .../nouveau/nvc0/nvc0_state_validate.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_surface.c | 12 +++---- + .../drivers/nouveau/nvc0/nvc0_transfer.c | 2 +- + 25 files changed, 124 insertions(+), 141 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c +index cfaf42d7086..c1f5e60b905 100644 +--- a/src/gallium/drivers/nouveau/nouveau_buffer.c ++++ b/src/gallium/drivers/nouveau/nouveau_buffer.c +@@ -229,8 +229,8 @@ nouveau_transfer_write(struct nouveau_context *nv, struct nouveau_transfer *tx, + else + nv->push_data(nv, buf->bo, buf->offset + base, buf->domain, size, data); + +- nouveau_fence_ref(nv->screen->fence.current, &buf->fence); +- nouveau_fence_ref(nv->screen->fence.current, &buf->fence_wr); ++ nouveau_fence_ref(nv->fence, &buf->fence); ++ nouveau_fence_ref(nv->fence, &buf->fence_wr); + } + + /* Does a CPU wait for the buffer's backing data to become reliably accessible +@@ -299,10 +299,9 @@ nouveau_buffer_transfer_del(struct nouveau_context *nv, + { + if (tx->map) { + if (likely(tx->bo)) { +- nouveau_fence_work(nv->screen->fence.current, +- nouveau_fence_unref_bo, tx->bo); ++ nouveau_fence_work(nv->fence, nouveau_fence_unref_bo, tx->bo); + if (tx->mm) +- release_allocation(&tx->mm, nv->screen->fence.current); ++ release_allocation(&tx->mm, nv->fence); + } else { + align_free(tx->map - + (tx->base.box.x & NOUVEAU_MIN_BUFFER_MAP_ALIGN_MASK)); +@@ -597,11 +596,11 @@ nouveau_copy_buffer(struct nouveau_context *nv, + src->bo, src->offset + srcx, src->domain, size); + + dst->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; +- nouveau_fence_ref(nv->screen->fence.current, &dst->fence); +- nouveau_fence_ref(nv->screen->fence.current, &dst->fence_wr); ++ nouveau_fence_ref(nv->fence, &dst->fence); ++ nouveau_fence_ref(nv->fence, &dst->fence_wr); + + src->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; +- nouveau_fence_ref(nv->screen->fence.current, &src->fence); ++ nouveau_fence_ref(nv->fence, &src->fence); + } else { + struct pipe_box src_box; + src_box.x = srcx; +@@ -849,9 +848,9 @@ nouveau_buffer_migrate(struct nouveau_context *nv, + nv->copy_data(nv, buf->bo, buf->offset, new_domain, + bo, offset, old_domain, buf->base.width0); + +- nouveau_fence_work(screen->fence.current, nouveau_fence_unref_bo, bo); ++ nouveau_fence_work(nv->fence, nouveau_fence_unref_bo, bo); + if (mm) +- release_allocation(&mm, screen->fence.current); ++ release_allocation(&mm, nv->fence); + } else + if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) { + struct nouveau_transfer tx; +@@ -960,7 +959,7 @@ nouveau_scratch_runout_release(struct nouveau_context *nv) + if (!nv->scratch.runout) + return; + +- if (!nouveau_fence_work(nv->screen->fence.current, nouveau_scratch_unref_bos, ++ if (!nouveau_fence_work(nv->fence, nouveau_scratch_unref_bos, + nv->scratch.runout)) + return; + +diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h +index e7941b45ec5..e6cd7657913 100644 +--- a/src/gallium/drivers/nouveau/nouveau_context.h ++++ b/src/gallium/drivers/nouveau/nouveau_context.h +@@ -15,6 +15,7 @@ struct nouveau_context { + + struct nouveau_client *client; + struct nouveau_pushbuf *pushbuf; ++ struct nouveau_fence *fence; + struct util_debug_callback debug; + + bool vbo_dirty; +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c +index e3ea148b17d..96b324d89cf 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.c ++++ b/src/gallium/drivers/nouveau/nouveau_fence.c +@@ -21,6 +21,7 @@ + */ + + #include "nouveau_screen.h" ++#include "nouveau_context.h" + #include "nouveau_winsys.h" + #include "nouveau_fence.h" + #include "util/os_time.h" +@@ -30,13 +31,14 @@ + #endif + + bool +-nouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence) ++nouveau_fence_new(struct nouveau_context *nv, struct nouveau_fence **fence) + { + *fence = CALLOC_STRUCT(nouveau_fence); + if (!*fence) + return false; + +- (*fence)->screen = screen; ++ (*fence)->screen = nv->screen; ++ (*fence)->context = nv; + (*fence)->ref = 1; + list_inithead(&(*fence)->work); + +@@ -112,18 +114,18 @@ nouveau_fence_del(struct nouveau_fence *fence) + } + + void +-nouveau_fence_cleanup(struct nouveau_fence_list *fence_list) ++nouveau_fence_cleanup(struct nouveau_context *nv) + { +- if (fence_list->current) { ++ if (nv->fence) { + struct nouveau_fence *current = NULL; + + /* nouveau_fence_wait will create a new current fence, so wait on the + * _current_ one, and remove both. + */ +- nouveau_fence_ref(fence_list->current, ¤t); ++ nouveau_fence_ref(nv->fence, ¤t); + nouveau_fence_wait(current, NULL); + nouveau_fence_ref(NULL, ¤t); +- nouveau_fence_ref(NULL, &fence_list->current); ++ nouveau_fence_ref(NULL, &nv->fence); + } + } + +@@ -188,7 +190,7 @@ static bool + nouveau_fence_kick(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; +- struct nouveau_fence_list *fence_list = &screen->fence; ++ bool current = !fence->sequence; + + /* wtf, someone is waiting on a fence in flush_notify handler? */ + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); +@@ -202,8 +204,8 @@ nouveau_fence_kick(struct nouveau_fence *fence) + if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel)) + return false; + +- if (fence == fence_list->current) +- nouveau_fence_next(screen); ++ if (current) ++ nouveau_fence_next(fence->context); + + nouveau_fence_update(screen, false); + +@@ -251,20 +253,18 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu + } + + void +-nouveau_fence_next(struct nouveau_screen *screen) ++nouveau_fence_next(struct nouveau_context *nv) + { +- struct nouveau_fence_list *fence_list = &screen->fence; +- +- if (fence_list->current->state < NOUVEAU_FENCE_STATE_EMITTING) { +- if (fence_list->current->ref > 1) +- nouveau_fence_emit(fence_list->current); ++ if (nv->fence->state < NOUVEAU_FENCE_STATE_EMITTING) { ++ if (nv->fence->ref > 1) ++ nouveau_fence_emit(nv->fence); + else + return; + } + +- nouveau_fence_ref(NULL, &fence_list->current); ++ nouveau_fence_ref(NULL, &nv->fence); + +- nouveau_fence_new(screen, &fence_list->current); ++ nouveau_fence_new(nv, &nv->fence); + } + + void +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h +index a9b21624543..2ea996521b1 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.h ++++ b/src/gallium/drivers/nouveau/nouveau_fence.h +@@ -22,6 +22,7 @@ struct nouveau_fence_work { + struct nouveau_fence { + struct nouveau_fence *next; + struct nouveau_screen *screen; ++ struct nouveau_context *context; + int state; + int ref; + uint32_t sequence; +@@ -32,7 +33,6 @@ struct nouveau_fence { + struct nouveau_fence_list { + struct nouveau_fence *head; + struct nouveau_fence *tail; +- struct nouveau_fence *current; + uint32_t sequence; + uint32_t sequence_ack; + void (*emit)(struct pipe_screen *, uint32_t *sequence); +@@ -42,11 +42,11 @@ struct nouveau_fence_list { + void nouveau_fence_emit(struct nouveau_fence *); + void nouveau_fence_del(struct nouveau_fence *); + +-bool nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **); +-void nouveau_fence_cleanup(struct nouveau_fence_list *); ++bool nouveau_fence_new(struct nouveau_context *, struct nouveau_fence **); ++void nouveau_fence_cleanup(struct nouveau_context *); + bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); + void nouveau_fence_update(struct nouveau_screen *, bool flushed); +-void nouveau_fence_next(struct nouveau_screen *); ++void nouveau_fence_next(struct nouveau_context *); + bool nouveau_fence_wait(struct nouveau_fence *, struct util_debug_callback *); + bool nouveau_fence_signalled(struct nouveau_fence *); + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c +index 4ce28864b8d..3f25855d045 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c +@@ -45,7 +45,7 @@ nv30_context_kick_notify(struct nouveau_pushbuf *push) + nv30 = container_of(push->user_priv, struct nv30_context, bufctx); + screen = &nv30->screen->base; + +- nouveau_fence_next(screen); ++ nouveau_fence_next(&nv30->base); + nouveau_fence_update(screen, true); + + if (push->bufctx) { +@@ -53,13 +53,13 @@ nv30_context_kick_notify(struct nouveau_pushbuf *push) + LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) { + struct nv04_resource *res = bref->priv; + if (res && res->mm) { +- nouveau_fence_ref(screen->fence.current, &res->fence); ++ nouveau_fence_ref(nv30->base.fence, &res->fence); + + if (bref->flags & NOUVEAU_BO_RD) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + + if (bref->flags & NOUVEAU_BO_WR) { +- nouveau_fence_ref(screen->fence.current, &res->fence_wr); ++ nouveau_fence_ref(nv30->base.fence, &res->fence_wr); + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | + NOUVEAU_BUFFER_STATUS_DIRTY; + } +@@ -76,7 +76,7 @@ nv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence, + struct nouveau_pushbuf *push = nv30->base.pushbuf; + + if (fence) +- nouveau_fence_ref(nv30->screen->base.fence.current, ++ nouveau_fence_ref(nv30->base.fence, + (struct nouveau_fence **)fence); + + PUSH_KICK(push); +@@ -176,6 +176,7 @@ nv30_context_destroy(struct pipe_context *pipe) + if (nv30->screen->cur_ctx == nv30) + nv30->screen->cur_ctx = NULL; + ++ nouveau_fence_cleanup(&nv30->base); + nouveau_context_destroy(&nv30->base); + } + +@@ -257,6 +258,7 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + } + + nouveau_context_init_vdec(&nv30->base); ++ nouveau_fence_new(&nv30->base, &nv30->base.fence); + + return pipe; + } +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +index ebbe3746717..992a5d41d57 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +@@ -393,7 +393,7 @@ nv30_miptree_transfer_unmap(struct pipe_context *pipe, + } + + /* Allow the copies above to finish executing before freeing the source */ +- nouveau_fence_work(nv30->screen->base.fence.current, ++ nouveau_fence_work(nv30->base.fence, + nouveau_fence_unref_bo, tx->tmp.bo); + } else { + nouveau_bo_ref(NULL, &tx->tmp.bo); +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +index 3c0cb06d19d..0ffd726102a 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +@@ -549,8 +549,6 @@ nv30_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base.fence); +- + nouveau_bo_ref(NULL, &screen->notify); + + nouveau_heap_destroy(&screen->query_heap); +@@ -861,6 +859,5 @@ nv30_screen_create(struct nouveau_device *dev) + PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE); + PUSH_KICK (push); + +- nouveau_fence_new(&screen->base, &screen->base.fence.current); + return &screen->base; + } +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +index 248c399dd89..66f19f5906f 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +@@ -463,7 +463,6 @@ nv30_state_context_switch(struct nv30_context *nv30) + bool + nv30_state_validate(struct nv30_context *nv30, uint32_t mask, bool hwtnl) + { +- struct nouveau_screen *screen = &nv30->screen->base; + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct nouveau_bufctx *bctx = nv30->bufctx; + struct nouveau_bufref *bref; +@@ -523,13 +522,13 @@ nv30_state_validate(struct nv30_context *nv30, uint32_t mask, bool hwtnl) + LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) { + struct nv04_resource *res = bref->priv; + if (res && res->mm) { +- nouveau_fence_ref(screen->fence.current, &res->fence); ++ nouveau_fence_ref(nv30->base.fence, &res->fence); + + if (bref->flags & NOUVEAU_BO_RD) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + + if (bref->flags & NOUVEAU_BO_WR) { +- nouveau_fence_ref(screen->fence.current, &res->fence_wr); ++ nouveau_fence_ref(nv30->base.fence, &res->fence_wr); + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + } + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +index cf406089eae..af22fd8fd81 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +@@ -518,7 +518,7 @@ nv50_state_validate_cp(struct nv50_context *nv50, uint32_t mask) + nv50->bufctx_cp); + + if (unlikely(nv50->state.flushed)) +- nv50_bufctx_fence(nv50->bufctx_cp, true); ++ nv50_bufctx_fence(nv50, nv50->bufctx_cp, true); + return ret; + } + +@@ -552,7 +552,7 @@ nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) + BEGIN_NV04(push, NV50_CP(USER_PARAM(1)), size / 4); + nouveau_pushbuf_data(push, bo, offset, size); + +- nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work, mm); ++ nouveau_fence_work(nv50->base.fence, nouveau_mm_free_work, mm); + nouveau_bo_ref(NULL, &bo); + nouveau_bufctx_reset(nv50->bufctx, 0); + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index 58629873554..9fd5f08be4c 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -34,10 +34,9 @@ nv50_flush(struct pipe_context *pipe, + unsigned flags) + { + struct nouveau_context *context = nouveau_context(pipe); +- struct nouveau_screen *screen = context->screen; + + if (fence) +- nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); ++ nouveau_fence_ref(context->fence, (struct nouveau_fence **)fence); + + PUSH_KICK(context->pushbuf); + +@@ -136,12 +135,12 @@ void + nv50_default_kick_notify(struct nouveau_pushbuf *push) + { + struct nv50_screen *screen = push->user_priv; ++ struct nv50_context *context = screen->cur_ctx; + +- if (screen) { +- nouveau_fence_next(&screen->base); ++ if (context) { ++ nouveau_fence_next(&context->base); + nouveau_fence_update(&screen->base, true); +- if (screen->cur_ctx) +- screen->cur_ctx->state.flushed = true; ++ context->state.flushed = true; + } + } + +@@ -200,6 +199,7 @@ nv50_destroy(struct pipe_context *pipe) + + FREE(nv50->blit); + ++ nouveau_fence_cleanup(&nv50->base); + nouveau_context_destroy(&nv50->base); + } + +@@ -414,6 +414,8 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + // zero entry if it's not otherwise set. + nv50->dirty_3d |= NV50_NEW_3D_SAMPLERS; + ++ nouveau_fence_new(&nv50->base, &nv50->base.fence); ++ + return pipe; + + out_err: +@@ -431,7 +433,7 @@ out_err: + } + + void +-nv50_bufctx_fence(struct nouveau_bufctx *bufctx, bool on_flush) ++nv50_bufctx_fence(struct nv50_context *nv50, struct nouveau_bufctx *bufctx, bool on_flush) + { + struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending; + struct nouveau_list *it; +@@ -440,7 +442,7 @@ nv50_bufctx_fence(struct nouveau_bufctx *bufctx, bool on_flush) + struct nouveau_bufref *ref = (struct nouveau_bufref *)it; + struct nv04_resource *res = ref->priv; + if (res) +- nv50_resource_validate(res, (unsigned)ref->priv_data); ++ nv50_resource_validate(nv50, res, (unsigned)ref->priv_data); + } + } + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h +index ed89d54afe4..dd3333a9dd2 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h +@@ -254,10 +254,28 @@ nv50_context_shader_stage(unsigned pipe) + } + } + ++static inline void ++nv50_resource_validate(struct nv50_context *context, struct nv04_resource *res, uint32_t flags) ++{ ++ if (likely(res->bo)) { ++ if (flags & NOUVEAU_BO_WR) ++ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | ++ NOUVEAU_BUFFER_STATUS_DIRTY; ++ if (flags & NOUVEAU_BO_RD) ++ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; ++ ++ if (res->mm) { ++ nouveau_fence_ref(context->base.fence, &res->fence); ++ if (flags & NOUVEAU_BO_WR) ++ nouveau_fence_ref(context->base.fence, &res->fence_wr); ++ } ++ } ++} ++ + /* nv50_context.c */ + struct pipe_context *nv50_create(struct pipe_screen *, void *, unsigned flags); + +-void nv50_bufctx_fence(struct nouveau_bufctx *, bool on_flush); ++void nv50_bufctx_fence(struct nv50_context *, struct nouveau_bufctx *, bool on_flush); + + void nv50_default_kick_notify(struct nouveau_pushbuf *); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +index 7508470e982..ba132245249 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c +@@ -52,7 +52,7 @@ nv50_hw_query_allocate(struct nv50_context *nv50, struct nv50_query *q, + if (hq->state == NV50_HW_QUERY_STATE_READY) + nouveau_mm_free(hq->mm); + else +- nouveau_fence_work(screen->base.fence.current, ++ nouveau_fence_work(nv50->base.fence, + nouveau_mm_free_work, hq->mm); + } + } +@@ -265,7 +265,7 @@ nv50_hw_end_query(struct nv50_context *nv50, struct nv50_query *q) + break; + } + if (hq->is64bit) +- nouveau_fence_ref(nv50->screen->base.fence.current, &hq->fence); ++ nouveau_fence_ref(nv50->base.fence, &hq->fence); + } + + static bool +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +index 1a5f7e3da5a..96607b2ef6a 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +@@ -622,8 +622,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base.fence); +- + if (screen->base.pushbuf) + screen->base.pushbuf->user_priv = NULL; + +@@ -1213,8 +1211,6 @@ nv50_screen_create(struct nouveau_device *dev) + goto fail; + } + +- nouveau_fence_new(&screen->base, &screen->base.fence.current); +- + return &screen->base; + + fail: +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.h b/src/gallium/drivers/nouveau/nv50/nv50_screen.h +index 6584b625328..a374ba46c6f 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.h +@@ -133,32 +133,6 @@ int nv50_screen_tsc_alloc(struct nv50_screen *, void *); + + int nv50_screen_compute_setup(struct nv50_screen *, struct nouveau_pushbuf *); + +-static inline void +-nv50_resource_fence(struct nv04_resource *res, uint32_t flags) +-{ +- struct nv50_screen *screen = nv50_screen(res->base.screen); +- +- if (res->mm) { +- nouveau_fence_ref(screen->base.fence.current, &res->fence); +- if (flags & NOUVEAU_BO_WR) +- nouveau_fence_ref(screen->base.fence.current, &res->fence_wr); +- } +-} +- +-static inline void +-nv50_resource_validate(struct nv04_resource *res, uint32_t flags) +-{ +- if (likely(res->bo)) { +- if (flags & NOUVEAU_BO_WR) +- res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | +- NOUVEAU_BUFFER_STATUS_DIRTY; +- if (flags & NOUVEAU_BO_RD) +- res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; +- +- nv50_resource_fence(res, flags); +- } +-} +- + struct nv50_format { + uint32_t rt; + struct { +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +index 02cf0b72e7e..eec85cf6676 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +@@ -556,7 +556,7 @@ nv50_state_validate(struct nv50_context *nv50, uint32_t mask, + PUSH_DATA (nv50->base.pushbuf, 0); + } + +- nv50_bufctx_fence(bufctx, false); ++ nv50_bufctx_fence(nv50, bufctx, false); + } + nouveau_pushbuf_bufctx(nv50->base.pushbuf, bufctx); + ret = PUSH_VAL(nv50->base.pushbuf); +@@ -575,7 +575,7 @@ nv50_state_validate_3d(struct nv50_context *nv50, uint32_t mask) + + if (unlikely(nv50->state.flushed)) { + nv50->state.flushed = false; +- nv50_bufctx_fence(nv50->bufctx_3d, true); ++ nv50_bufctx_fence(nv50, nv50->bufctx_3d, true); + } + return ret; + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +index 72f185b224e..6f28c97cc73 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +@@ -692,7 +692,7 @@ nv50_clear_buffer_push(struct pipe_context *pipe, + count -= nr; + } + +- nv50_resource_validate(buf, NOUVEAU_BO_WR); ++ nv50_resource_validate(nv50, buf, NOUVEAU_BO_WR); + + nouveau_bufctx_reset(nv50->bufctx, 0); + } +@@ -815,7 +815,7 @@ nv50_clear_buffer(struct pipe_context *pipe, + BEGIN_NV04(push, NV50_3D(COND_MODE), 1); + PUSH_DATA (push, nv50->cond_condmode); + +- nv50_resource_validate(buf, NOUVEAU_BO_WR); ++ nv50_resource_validate(nv50, buf, NOUVEAU_BO_WR); + + if (width * height != elements) { + offset += width * height * data_size; +@@ -1679,7 +1679,7 @@ nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info) + PUSH_DATA (push, srcy >> 32); + } + } +- nv50_bufctx_fence(nv50->bufctx, false); ++ nv50_bufctx_fence(nv50, nv50->bufctx, false); + + nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +index 6438510d028..4c73695a28d 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +@@ -485,7 +485,7 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx, + } + + /* Allow the copies above to finish executing before freeing the source */ +- nouveau_fence_work(nv50->screen->base.fence.current, ++ nouveau_fence_work(nv50->base.fence, + nouveau_fence_unref_bo, tx->rect[1].bo); + } else { + nouveau_bo_ref(NULL, &tx->rect[1].bo); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +index ea54c67e4c9..adc36531b28 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +@@ -81,10 +81,9 @@ nvc0_flush(struct pipe_context *pipe, + unsigned flags) + { + struct nvc0_context *nvc0 = nvc0_context(pipe); +- struct nouveau_screen *screen = &nvc0->screen->base; + + if (fence) +- nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); ++ nouveau_fence_ref(nvc0->base.fence, (struct nouveau_fence **)fence); + + PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */ + +@@ -272,6 +271,7 @@ nvc0_destroy(struct pipe_context *pipe) + free(pos); + } + ++ nouveau_fence_cleanup(&nvc0->base); + nouveau_context_destroy(&nvc0->base); + } + +@@ -279,12 +279,12 @@ void + nvc0_default_kick_notify(struct nouveau_pushbuf *push) + { + struct nvc0_screen *screen = push->user_priv; ++ struct nvc0_context *nvc0 = screen->cur_ctx; + +- if (screen) { +- nouveau_fence_next(&screen->base); ++ if (nvc0) { ++ nouveau_fence_next(&nvc0->base); + nouveau_fence_update(&screen->base, true); +- if (screen->cur_ctx) +- screen->cur_ctx->state.flushed = true; ++ nvc0->state.flushed = true; + NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); + } + } +@@ -549,6 +549,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + nvc0->dirty_cp |= NVC0_NEW_CP_SAMPLERS; + } + ++ nouveau_fence_new(&nvc0->base, &nvc0->base.fence); ++ + return pipe; + + out_err: +@@ -579,7 +581,7 @@ nvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx, + struct nouveau_bufref *ref = (struct nouveau_bufref *)it; + struct nv04_resource *res = ref->priv; + if (res) +- nvc0_resource_validate(res, (unsigned)ref->priv_data); ++ nvc0_resource_validate(nvc0, res, (unsigned)ref->priv_data); + NOUVEAU_DRV_STAT_IFD(count++); + } + NOUVEAU_DRV_STAT(&nvc0->screen->base, resource_validate_count, count); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +index 2d8e2f0b38a..bda081d190f 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +@@ -310,6 +310,29 @@ nvc0_shader_stage(unsigned pipe) + } + } + ++static inline void ++nvc0_resource_fence(struct nvc0_context *nvc0, struct nv04_resource *res, uint32_t flags) ++{ ++ if (res->mm) { ++ nouveau_fence_ref(nvc0->base.fence, &res->fence); ++ if (flags & NOUVEAU_BO_WR) ++ nouveau_fence_ref(nvc0->base.fence, &res->fence_wr); ++ } ++} ++ ++static inline void ++nvc0_resource_validate(struct nvc0_context *nvc0, struct nv04_resource *res, uint32_t flags) ++{ ++ if (likely(res->bo)) { ++ if (flags & NOUVEAU_BO_WR) ++ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | ++ NOUVEAU_BUFFER_STATUS_DIRTY; ++ if (flags & NOUVEAU_BO_RD) ++ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; ++ ++ nvc0_resource_fence(nvc0, res, flags); ++ } ++} + + /* nvc0_context.c */ + struct pipe_context *nvc0_create(struct pipe_screen *, void *, unsigned flags); +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +index a18fdf2e5ac..e4c36a8ee96 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c +@@ -44,7 +44,7 @@ nvc0_hw_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q, + if (hq->state == NVC0_HW_QUERY_STATE_READY) + nouveau_mm_free(hq->mm); + else +- nouveau_fence_work(screen->base.fence.current, ++ nouveau_fence_work(nvc0->base.fence, + nouveau_mm_free_work, hq->mm); + } + } +@@ -301,7 +301,7 @@ nvc0_hw_end_query(struct nvc0_context *nvc0, struct nvc0_query *q) + break; + } + if (hq->is64bit) +- nouveau_fence_ref(nvc0->screen->base.fence.current, &hq->fence); ++ nouveau_fence_ref(nvc0->base.fence, &hq->fence); + } + + static bool +@@ -412,7 +412,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0, + util_range_add(&buf->base, &buf->valid_buffer_range, offset, + offset + (result_type >= PIPE_QUERY_TYPE_I64 ? 8 : 4)); + +- nvc0_resource_validate(buf, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, buf, NOUVEAU_BO_WR); + + return; + } +@@ -511,7 +511,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0, + util_range_add(&buf->base, &buf->valid_buffer_range, offset, + offset + (result_type >= PIPE_QUERY_TYPE_I64 ? 8 : 4)); + +- nvc0_resource_validate(buf, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, buf, NOUVEAU_BO_WR); + } + + static const struct nvc0_query_funcs hw_query_funcs = { +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +index 2a0fef63bca..d61568022bd 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -714,8 +714,6 @@ nvc0_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- nouveau_fence_cleanup(&screen->base.fence); +- + if (screen->base.pushbuf) + screen->base.pushbuf->user_priv = NULL; + +@@ -1572,8 +1570,6 @@ nvc0_screen_create(struct nouveau_device *dev) + if (!nvc0_blitter_create(screen)) + goto fail; + +- nouveau_fence_new(&screen->base, &screen->base.fence.current); +- + return &screen->base; + + fail: +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +index 392980562bd..3a17bbcb3c9 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +@@ -157,32 +157,6 @@ int nvc0_screen_resize_text_area(struct nvc0_screen *, uint64_t); + // 3D Only + void nvc0_screen_bind_cb_3d(struct nvc0_screen *, bool *, int, int, int, uint64_t); + +-static inline void +-nvc0_resource_fence(struct nv04_resource *res, uint32_t flags) +-{ +- struct nvc0_screen *screen = nvc0_screen(res->base.screen); +- +- if (res->mm) { +- nouveau_fence_ref(screen->base.fence.current, &res->fence); +- if (flags & NOUVEAU_BO_WR) +- nouveau_fence_ref(screen->base.fence.current, &res->fence_wr); +- } +-} +- +-static inline void +-nvc0_resource_validate(struct nv04_resource *res, uint32_t flags) +-{ +- if (likely(res->bo)) { +- if (flags & NOUVEAU_BO_WR) +- res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | +- NOUVEAU_BUFFER_STATUS_DIRTY; +- if (flags & NOUVEAU_BO_RD) +- res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; +- +- nvc0_resource_fence(res, flags); +- } +-} +- + struct nvc0_format { + uint32_t rt; + struct { +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +index 39c518efdef..41d357e5848 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +@@ -253,7 +253,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0) + PUSH_DATA(push, 0); + PUSH_DATA(push, 0); + +- nvc0_resource_fence(res, NOUVEAU_BO_WR); ++ nvc0_resource_fence(nvc0, res, NOUVEAU_BO_WR); + + assert(!fb->zsbuf); + } +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +index 5f95c709dec..81b833237f8 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +@@ -348,7 +348,7 @@ nvc0_clear_render_target(struct pipe_context *pipe, + IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), 0); + + /* tiled textures don't have to be fenced, they're not mapped directly */ +- nvc0_resource_fence(res, NOUVEAU_BO_WR); ++ nvc0_resource_fence(nvc0, res, NOUVEAU_BO_WR); + } + + if (!render_condition_enabled) +@@ -410,7 +410,7 @@ nvc0_clear_buffer_push_nvc0(struct pipe_context *pipe, + size -= nr * 4; + } + +- nvc0_resource_validate(buf, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, buf, NOUVEAU_BO_WR); + + nouveau_bufctx_reset(nvc0->bufctx, 0); + } +@@ -457,7 +457,7 @@ nvc0_clear_buffer_push_nve4(struct pipe_context *pipe, + size -= nr * 4; + } + +- nvc0_resource_validate(buf, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, buf, NOUVEAU_BO_WR); + + nouveau_bufctx_reset(nvc0->bufctx, 0); + } +@@ -604,7 +604,7 @@ nvc0_clear_buffer(struct pipe_context *pipe, + + IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode); + +- nvc0_resource_validate(buf, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, buf, NOUVEAU_BO_WR); + + if (width * height != elements) { + offset += width * height * data_size; +@@ -1589,8 +1589,8 @@ nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) + PUSH_DATA (push, srcy >> 32); + } + } +- nvc0_resource_validate(&dst->base, NOUVEAU_BO_WR); +- nvc0_resource_validate(&src->base, NOUVEAU_BO_RD); ++ nvc0_resource_validate(nvc0, &dst->base, NOUVEAU_BO_WR); ++ nvc0_resource_validate(nvc0, &src->base, NOUVEAU_BO_RD); + + nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +index c5aab3075df..7a2531e68e1 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +@@ -521,7 +521,7 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx, + NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_wr, 1); + + /* Allow the copies above to finish executing before freeing the source */ +- nouveau_fence_work(nvc0->screen->base.fence.current, ++ nouveau_fence_work(nvc0->base.fence, + nouveau_fence_unref_bo, tx->rect[1].bo); + } else { + nouveau_bo_ref(NULL, &tx->rect[1].bo); +-- +2.37.3 + + +From 5a7c68d03baea7c9b55d431f1bb149f300e56ee2 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Wed, 11 May 2022 02:32:52 +0200 +Subject: [PATCH 14/17] nouveau: per context client and pushbuf + +Signed-off-by: Karol Herbst +Acked-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_context.h | 6 +- + src/gallium/drivers/nouveau/nouveau_fence.c | 7 +- + src/gallium/drivers/nouveau/nouveau_fence.h | 2 +- + src/gallium/drivers/nouveau/nouveau_screen.c | 69 ++++++++++++++++--- + src/gallium/drivers/nouveau/nouveau_screen.h | 11 +++ + src/gallium/drivers/nouveau/nouveau_video.c | 4 +- + .../drivers/nouveau/nouveau_vp3_video.c | 4 +- + src/gallium/drivers/nouveau/nv30/nv30_clear.c | 1 + + .../drivers/nouveau/nv30/nv30_context.c | 24 +++---- + src/gallium/drivers/nouveau/nv30/nv30_draw.c | 1 + + .../drivers/nouveau/nv30/nv30_fragprog.c | 1 + + .../drivers/nouveau/nv30/nv30_fragtex.c | 1 + + .../drivers/nouveau/nv30/nv30_miptree.c | 1 + + src/gallium/drivers/nouveau/nv30/nv30_push.c | 1 + + src/gallium/drivers/nouveau/nv30/nv30_query.c | 1 + + .../drivers/nouveau/nv30/nv30_screen.c | 8 ++- + .../drivers/nouveau/nv30/nv30_screen.h | 1 - + .../nouveau/nv30/nv30_state_validate.c | 2 +- + .../drivers/nouveau/nv30/nv30_transfer.c | 1 + + src/gallium/drivers/nouveau/nv30/nv30_vbo.c | 2 +- + .../drivers/nouveau/nv30/nv30_vertprog.c | 1 + + .../drivers/nouveau/nv30/nv30_winsys.h | 6 +- + .../drivers/nouveau/nv30/nv40_verttex.c | 1 + + .../drivers/nouveau/nv50/nv50_context.c | 22 +++--- + .../drivers/nouveau/nv50/nv50_context.h | 2 +- + .../drivers/nouveau/nv50/nv50_screen.c | 11 ++- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 10 ++- + src/gallium/drivers/nouveau/nv50/nv84_video.c | 12 ++-- + src/gallium/drivers/nouveau/nv50/nv98_video.c | 4 +- + .../drivers/nouveau/nvc0/nvc0_context.c | 24 +++---- + .../drivers/nouveau/nvc0/nvc0_context.h | 2 +- + .../drivers/nouveau/nvc0/nvc0_program.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_screen.c | 27 +++----- + .../drivers/nouveau/nvc0/nvc0_screen.h | 4 +- + .../nouveau/nvc0/nvc0_state_validate.c | 9 +-- + src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 12 ++-- + src/gallium/drivers/nouveau/nvc0/nvc0_video.c | 4 +- + 37 files changed, 183 insertions(+), 118 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h +index e6cd7657913..b4c88c18e84 100644 +--- a/src/gallium/drivers/nouveau/nouveau_context.h ++++ b/src/gallium/drivers/nouveau/nouveau_context.h +@@ -16,6 +16,7 @@ struct nouveau_context { + struct nouveau_client *client; + struct nouveau_pushbuf *pushbuf; + struct nouveau_fence *fence; ++ void (*kick_notify)(struct nouveau_context *); + struct util_debug_callback debug; + + bool vbo_dirty; +@@ -66,7 +67,7 @@ nouveau_context(struct pipe_context *pipe) + void + nouveau_context_init_vdec(struct nouveau_context *); + +-void ++int MUST_CHECK + nouveau_context_init(struct nouveau_context *, struct nouveau_screen *); + + void +@@ -100,6 +101,9 @@ nouveau_context_destroy(struct nouveau_context *ctx) + if (ctx->scratch.bo[i]) + nouveau_bo_ref(NULL, &ctx->scratch.bo[i]); + ++ nouveau_pushbuf_destroy(&ctx->pushbuf); ++ nouveau_client_del(&ctx->client); ++ + FREE(ctx); + } + +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c +index 96b324d89cf..05808ebd68e 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.c ++++ b/src/gallium/drivers/nouveau/nouveau_fence.c +@@ -79,7 +79,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) + + fence_list->tail = fence; + +- fence_list->emit(&screen->base, &fence->sequence); ++ fence_list->emit(&fence->context->pipe, &fence->sequence); + + assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING); + fence->state = NOUVEAU_FENCE_STATE_EMITTED; +@@ -189,6 +189,7 @@ nouveau_fence_signalled(struct nouveau_fence *fence) + static bool + nouveau_fence_kick(struct nouveau_fence *fence) + { ++ struct nouveau_context *context = fence->context; + struct nouveau_screen *screen = fence->screen; + bool current = !fence->sequence; + +@@ -196,12 +197,12 @@ nouveau_fence_kick(struct nouveau_fence *fence) + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); + + if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) { +- PUSH_SPACE(screen->pushbuf, 8); ++ PUSH_SPACE(context->pushbuf, 8); + nouveau_fence_emit(fence); + } + + if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) +- if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel)) ++ if (nouveau_pushbuf_kick(context->pushbuf, context->pushbuf->channel)) + return false; + + if (current) +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h +index 2ea996521b1..49e74bfc52c 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.h ++++ b/src/gallium/drivers/nouveau/nouveau_fence.h +@@ -35,7 +35,7 @@ struct nouveau_fence_list { + struct nouveau_fence *tail; + uint32_t sequence; + uint32_t sequence_ack; +- void (*emit)(struct pipe_screen *, uint32_t *sequence); ++ void (*emit)(struct pipe_context *, uint32_t *sequence); + uint32_t (*update)(struct pipe_screen *); + }; + +diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c +index ac69b9d3968..37d14bee8fd 100644 +--- a/src/gallium/drivers/nouveau/nouveau_screen.c ++++ b/src/gallium/drivers/nouveau/nouveau_screen.c +@@ -187,6 +187,48 @@ reserve_vma(uintptr_t start, uint64_t reserved_size) + return reserved; + } + ++static void ++nouveau_pushbuf_cb(struct nouveau_pushbuf *push) ++{ ++ struct nouveau_pushbuf_priv *p = (struct nouveau_pushbuf_priv *)push->user_priv; ++ ++ if (p->context) ++ p->context->kick_notify(p->context); ++ else ++ nouveau_fence_update(p->screen, true); ++ ++ NOUVEAU_DRV_STAT(p->screen, pushbuf_count, 1); ++} ++ ++int ++nouveau_pushbuf_create(struct nouveau_screen *screen, struct nouveau_context *context, ++ struct nouveau_client *client, struct nouveau_object *chan, int nr, ++ uint32_t size, bool immediate, struct nouveau_pushbuf **push) ++{ ++ int ret; ++ ret = nouveau_pushbuf_new(client, chan, nr, size, immediate, push); ++ if (ret) ++ return ret; ++ ++ struct nouveau_pushbuf_priv *p = MALLOC_STRUCT(nouveau_pushbuf_priv); ++ if (!p) { ++ nouveau_pushbuf_del(push); ++ return -ENOMEM; ++ } ++ p->screen = screen; ++ p->context = context; ++ (*push)->kick_notify = nouveau_pushbuf_cb; ++ (*push)->user_priv = p; ++ return 0; ++} ++ ++void ++nouveau_pushbuf_destroy(struct nouveau_pushbuf **push) ++{ ++ FREE((*push)->user_priv); ++ nouveau_pushbuf_del(push); ++} ++ + int + nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) + { +@@ -301,9 +343,9 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) + ret = nouveau_client_new(screen->device, &screen->client); + if (ret) + goto err; +- ret = nouveau_pushbuf_new(screen->client, screen->channel, +- 4, 512 * 1024, 1, +- &screen->pushbuf); ++ ret = nouveau_pushbuf_create(screen, NULL, screen->client, screen->channel, ++ 4, 512 * 1024, 1, ++ &screen->pushbuf); + if (ret) + goto err; + +@@ -368,7 +410,7 @@ nouveau_screen_fini(struct nouveau_screen *screen) + nouveau_mm_destroy(screen->mm_GART); + nouveau_mm_destroy(screen->mm_VRAM); + +- nouveau_pushbuf_del(&screen->pushbuf); ++ nouveau_pushbuf_destroy(&screen->pushbuf); + + nouveau_client_del(&screen->client); + nouveau_object_del(&screen->channel); +@@ -392,12 +434,23 @@ nouveau_set_debug_callback(struct pipe_context *pipe, + memset(&context->debug, 0, sizeof(context->debug)); + } + +-void ++int + nouveau_context_init(struct nouveau_context *context, struct nouveau_screen *screen) + { +- context->pipe.set_debug_callback = nouveau_set_debug_callback; ++ int ret; + ++ context->pipe.set_debug_callback = nouveau_set_debug_callback; + context->screen = screen; +- context->client = screen->client; +- context->pushbuf = screen->pushbuf; ++ ++ ret = nouveau_client_new(screen->device, &context->client); ++ if (ret) ++ return ret; ++ ++ ret = nouveau_pushbuf_create(screen, context, context->client, screen->channel, ++ 4, 512 * 1024, 1, ++ &context->pushbuf); ++ if (ret) ++ return ret; ++ ++ return 0; + } +diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h +index 100e9b207b2..eafeeb91b7e 100644 +--- a/src/gallium/drivers/nouveau/nouveau_screen.h ++++ b/src/gallium/drivers/nouveau/nouveau_screen.h +@@ -110,6 +110,11 @@ struct nouveau_screen { + #endif + }; + ++struct nouveau_pushbuf_priv { ++ struct nouveau_screen *screen; ++ struct nouveau_context *context; ++}; ++ + #define NV_VRAM_DOMAIN(screen) ((screen)->vram_domain) + + #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS +@@ -150,4 +155,10 @@ void nouveau_screen_fini(struct nouveau_screen *); + + void nouveau_screen_init_vdec(struct nouveau_screen *); + ++int ++nouveau_pushbuf_create(struct nouveau_screen *, struct nouveau_context *, struct nouveau_client *, ++ struct nouveau_object *chan, int nr, uint32_t size, bool immediate, ++ struct nouveau_pushbuf **); ++void nouveau_pushbuf_destroy(struct nouveau_pushbuf **); ++ + #endif +diff --git a/src/gallium/drivers/nouveau/nouveau_video.c b/src/gallium/drivers/nouveau/nouveau_video.c +index 9637f39c8e2..a5596f980a5 100644 +--- a/src/gallium/drivers/nouveau/nouveau_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_video.c +@@ -486,7 +486,7 @@ nouveau_decoder_destroy(struct pipe_video_codec *decoder) + if (dec->bufctx) + nouveau_bufctx_del(&dec->bufctx); + if (dec->push) +- nouveau_pushbuf_del(&dec->push); ++ nouveau_pushbuf_destroy(&dec->push); + if (dec->client) + nouveau_client_del(&dec->client); + if (dec->chan) +@@ -532,7 +532,7 @@ nouveau_create_decoder(struct pipe_context *context, + ret = nouveau_client_new(screen->device, &dec->client); + if (ret) + goto fail; +- ret = nouveau_pushbuf_new(dec->client, dec->chan, 2, 4096, 1, &dec->push); ++ ret = nouveau_pushbuf_create(screen, nouveau_context(context), dec->client, dec->chan, 2, 4096, 1, &dec->push); + if (ret) + goto fail; + ret = nouveau_bufctx_new(dec->client, NV31_VIDEO_BIND_COUNT, &dec->bufctx); +diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c +index b3d93a69195..02cbe246520 100644 +--- a/src/gallium/drivers/nouveau/nouveau_vp3_video.c ++++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c +@@ -214,11 +214,11 @@ nouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder) + + if (dec->channel[0] != dec->channel[1]) { + for (i = 0; i < 3; ++i) { +- nouveau_pushbuf_del(&dec->pushbuf[i]); ++ nouveau_pushbuf_destroy(&dec->pushbuf[i]); + nouveau_object_del(&dec->channel[i]); + } + } else { +- nouveau_pushbuf_del(dec->pushbuf); ++ nouveau_pushbuf_destroy(dec->pushbuf); + nouveau_object_del(dec->channel); + } + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_clear.c b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +index 2b8ea9700cf..7122858b9d1 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_clear.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_clear.c +@@ -30,6 +30,7 @@ + #include "nv_object.xml.h" + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" ++#include "nv30/nv30_winsys.h" + #include "nv30/nv30_format.h" + + static inline uint32_t +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c +index 3f25855d045..50c5071b266 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c +@@ -33,19 +33,15 @@ + #include "nv30/nv30_context.h" + #include "nv30/nv30_transfer.h" + #include "nv30/nv30_state.h" ++#include "nv30/nv30_winsys.h" + + static void + nv30_context_kick_notify(struct nouveau_pushbuf *push) + { +- struct nouveau_screen *screen; +- struct nv30_context *nv30; ++ struct nouveau_pushbuf_priv *p = push->user_priv; ++ struct nouveau_screen *screen = p->screen; + +- if (!push->user_priv) +- return; +- nv30 = container_of(push->user_priv, struct nv30_context, bufctx); +- screen = &nv30->screen->base; +- +- nouveau_fence_next(&nv30->base); ++ nouveau_fence_next(p->context); + nouveau_fence_update(screen, true); + + if (push->bufctx) { +@@ -53,13 +49,13 @@ nv30_context_kick_notify(struct nouveau_pushbuf *push) + LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) { + struct nv04_resource *res = bref->priv; + if (res && res->mm) { +- nouveau_fence_ref(nv30->base.fence, &res->fence); ++ nouveau_fence_ref(p->context->fence, &res->fence); + + if (bref->flags & NOUVEAU_BO_RD) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + + if (bref->flags & NOUVEAU_BO_WR) { +- nouveau_fence_ref(nv30->base.fence, &res->fence_wr); ++ nouveau_fence_ref(p->context->fence, &res->fence_wr); + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | + NOUVEAU_BUFFER_STATUS_DIRTY; + } +@@ -168,9 +164,6 @@ nv30_context_destroy(struct pipe_context *pipe) + if (nv30->blit_fp) + pipe_resource_reference(&nv30->blit_fp, NULL); + +- if (nv30->screen->base.pushbuf->user_priv == &nv30->bufctx) +- nv30->screen->base.pushbuf->user_priv = NULL; +- + nouveau_bufctx_del(&nv30->bufctx); + + if (nv30->screen->cur_ctx == nv30) +@@ -207,7 +200,10 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + pipe->destroy = nv30_context_destroy; + pipe->flush = nv30_context_flush; + +- nouveau_context_init(&nv30->base, &screen->base); ++ if (nouveau_context_init(&nv30->base, &screen->base)) { ++ nv30_context_destroy(pipe); ++ return NULL; ++ } + nv30->base.pushbuf->kick_notify = nv30_context_kick_notify; + + nv30->base.pipe.stream_uploader = u_upload_create_default(&nv30->base.pipe); +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_draw.c b/src/gallium/drivers/nouveau/nv30/nv30_draw.c +index 0a08bda700d..0aafb506cb4 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_draw.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_draw.c +@@ -33,6 +33,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" + #include "nv30/nv30_format.h" ++#include "nv30/nv30_winsys.h" + + struct nv30_render { + struct vbuf_render base; +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c b/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c +index 55857781f5f..9bc55b60a61 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c +@@ -30,6 +30,7 @@ + #include "nv_object.xml.h" + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" ++#include "nv30/nv30_winsys.h" + #include "nv30/nvfx_shader.h" + + static void +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c b/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c +index 1a06eac4746..a46c4c4f1d9 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c +@@ -29,6 +29,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" + #include "nv30/nv30_format.h" ++#include "nv30/nv30_winsys.h" + + void + nv30_fragtex_validate(struct nv30_context *nv30) +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +index 992a5d41d57..f712134f6cc 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +@@ -33,6 +33,7 @@ + #include "nv30/nv30_context.h" + #include "nv30/nv30_resource.h" + #include "nv30/nv30_transfer.h" ++#include "nv30/nv30_winsys.h" + + static inline unsigned + layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer) +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_push.c b/src/gallium/drivers/nouveau/nv30/nv30_push.c +index 4bd799c39f9..7b762bcb054 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_push.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_push.c +@@ -33,6 +33,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" + #include "nv30/nv30_resource.h" ++#include "nv30/nv30_winsys.h" + + struct push_context { + struct nouveau_pushbuf *push; +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_query.c b/src/gallium/drivers/nouveau/nv30/nv30_query.c +index 1335cb99b12..f15184f232f 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_query.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_query.c +@@ -27,6 +27,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_screen.h" + #include "nv30/nv30_context.h" ++#include "nv30/nv30_winsys.h" + + struct nv30_query_object { + struct list_head list; +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +index 0ffd726102a..4dfcd76e4f1 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c +@@ -39,6 +39,7 @@ + #include "nv30/nv30_context.h" + #include "nv30/nv30_resource.h" + #include "nv30/nv30_format.h" ++#include "nv30/nv30_winsys.h" + + #define RANKINE_0397_CHIPSET 0x00000003 + #define RANKINE_0497_CHIPSET 0x000001e0 +@@ -519,10 +520,11 @@ nv30_screen_get_compiler_options(struct pipe_screen *pscreen, + } + + static void +-nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence) ++nv30_screen_fence_emit(struct pipe_context *pcontext, uint32_t *sequence) + { +- struct nv30_screen *screen = nv30_screen(pscreen); +- struct nouveau_pushbuf *push = screen->base.pushbuf; ++ struct nv30_context *nv30 = nv30_context(pcontext); ++ struct nv30_screen *screen = nv30->screen; ++ struct nouveau_pushbuf *push = nv30->base.pushbuf; + + *sequence = ++screen->base.fence.sequence; + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.h b/src/gallium/drivers/nouveau/nv30/nv30_screen.h +index c61a1ece54b..f0bc3683685 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.h ++++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.h +@@ -9,7 +9,6 @@ + #include "nouveau_screen.h" + #include "nouveau_fence.h" + #include "nouveau_heap.h" +-#include "nv30/nv30_winsys.h" + #include "nv30/nv30_resource.h" + #include "compiler/nir/nir.h" + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +index 66f19f5906f..8de11ab67d0 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c +@@ -31,6 +31,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" + #include "nv30/nv30_format.h" ++#include "nv30/nv30_winsys.h" + + static void + nv30_validate_fb(struct nv30_context *nv30) +@@ -457,7 +458,6 @@ nv30_state_context_switch(struct nv30_context *nv30) + nv30->dirty &= ~NV30_NEW_ZSA; + + nv30->screen->cur_ctx = nv30; +- nv30->base.pushbuf->user_priv = &nv30->bufctx; + } + + bool +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +index c78b896a729..c5f5866af6b 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c +@@ -36,6 +36,7 @@ + + #include "nv30/nv30_context.h" + #include "nv30/nv30_transfer.h" ++#include "nv30/nv30_winsys.h" + + /* Various helper functions to transfer different types of data in a number + * of different ways. +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c +index 3e24e90c735..22e309eb773 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c +@@ -34,6 +34,7 @@ + #include "nv30/nv30-40_3d.xml.h" + #include "nv30/nv30_context.h" + #include "nv30/nv30_format.h" ++#include "nv30/nv30_winsys.h" + + static void + nv30_emit_vtxattr(struct nv30_context *nv30, struct pipe_vertex_buffer *vb, +@@ -586,7 +587,6 @@ nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + if (nv30->vbo_push_hint != !!nv30->vbo_fifo) + nv30->dirty |= NV30_NEW_ARRAYS; + +- push->user_priv = &nv30->bufctx; + if (nv30->vbo_user && !(nv30->dirty & (NV30_NEW_VERTEX | NV30_NEW_ARRAYS))) + nv30_update_user_vbufs(nv30); + +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c +index 3866709c138..53e64a38722 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c +@@ -33,6 +33,7 @@ + #include "nv30/nv30_context.h" + #include "nv30/nvfx_shader.h" + #include "nv30/nv30_state.h" ++#include "nv30/nv30_winsys.h" + + static void + nv30_vertprog_destroy(struct nv30_vertprog *vp) +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_winsys.h b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h +index 25897ea9f6b..a72af87c9b6 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_winsys.h ++++ b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h +@@ -3,7 +3,9 @@ + + #include + #include "nouveau_winsys.h" ++#include "nouveau_context.h" + #include "nouveau_buffer.h" ++#include "nv30_context.h" + + /*XXX: rnn */ + #define NV40_3D_VTXTEX_OFFSET(i) (0x0900 + ((i) * 0x20)) // 401e80 +@@ -29,8 +31,8 @@ PUSH_RELOC(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t offset, + static inline struct nouveau_bufctx * + bufctx(struct nouveau_pushbuf *push) + { +- struct nouveau_bufctx **pctx = push->user_priv; +- return *pctx; ++ struct nouveau_pushbuf_priv *p = push->user_priv; ++ return nv30_context(&p->context->pipe)->bufctx; + } + + static inline void +diff --git a/src/gallium/drivers/nouveau/nv30/nv40_verttex.c b/src/gallium/drivers/nouveau/nv30/nv40_verttex.c +index 578695a22ab..04f428ea6ac 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv40_verttex.c ++++ b/src/gallium/drivers/nouveau/nv30/nv40_verttex.c +@@ -25,6 +25,7 @@ + + #include "util/u_inlines.h" + #include "nv30/nv30_context.h" ++#include "nv30/nv30_winsys.h" + + void + nv40_verttex_validate(struct nv30_context *nv30) +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index 9fd5f08be4c..bbc4131a499 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -132,16 +132,13 @@ nv50_emit_string_marker(struct pipe_context *pipe, const char *str, int len) + } + + void +-nv50_default_kick_notify(struct nouveau_pushbuf *push) ++nv50_default_kick_notify(struct nouveau_context *context) + { +- struct nv50_screen *screen = push->user_priv; +- struct nv50_context *context = screen->cur_ctx; ++ struct nv50_context *nv50 = nv50_context(&context->pipe); + +- if (context) { +- nouveau_fence_next(&context->base); +- nouveau_fence_update(&screen->base, true); +- context->state.flushed = true; +- } ++ nouveau_fence_next(context); ++ nouveau_fence_update(context->screen, true); ++ nv50->state.flushed = true; + } + + static void +@@ -313,7 +310,8 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (!nv50_blitctx_create(nv50)) + goto out_err; + +- nouveau_context_init(&nv50->base, &screen->base); ++ if (nouveau_context_init(&nv50->base, &screen->base)) ++ goto out_err; + + ret = nouveau_bufctx_new(nv50->base.client, 2, &nv50->bufctx); + if (!ret) +@@ -355,9 +353,11 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + */ + nv50->state = screen->save_state; + screen->cur_ctx = nv50; +- nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx); + } +- nv50->base.pushbuf->kick_notify = nv50_default_kick_notify; ++ nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); ++ nv50->base.kick_notify = nv50_default_kick_notify; ++ nv50->base.pushbuf->rsvd_kick = 5; ++ PUSH_SPACE(nv50->base.pushbuf, 8); + + nv50_init_query_functions(nv50); + nv50_init_surface_functions(nv50); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h +index dd3333a9dd2..5173d8d1f44 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h +@@ -277,7 +277,7 @@ struct pipe_context *nv50_create(struct pipe_screen *, void *, unsigned flags); + + void nv50_bufctx_fence(struct nv50_context *, struct nouveau_bufctx *, bool on_flush); + +-void nv50_default_kick_notify(struct nouveau_pushbuf *); ++void nv50_default_kick_notify(struct nouveau_context *); + + /* nv50_draw.c */ + extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +index 96607b2ef6a..79a57e5b5fa 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +@@ -622,9 +622,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- if (screen->base.pushbuf) +- screen->base.pushbuf->user_priv = NULL; +- + if (screen->blitter) + nv50_blitter_destroy(screen); + if (screen->pm.prog) { +@@ -658,10 +655,11 @@ nv50_screen_destroy(struct pipe_screen *pscreen) + } + + static void +-nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence) ++nv50_screen_fence_emit(struct pipe_context *pcontext, u32 *sequence) + { +- struct nv50_screen *screen = nv50_screen(pscreen); +- struct nouveau_pushbuf *push = screen->base.pushbuf; ++ struct nv50_context *nv50 = nv50_context(pcontext); ++ struct nv50_screen *screen = nv50->screen; ++ struct nouveau_pushbuf *push = nv50->base.pushbuf; + + /* we need to do it after possible flush in MARK_RING */ + *sequence = ++screen->base.fence.sequence; +@@ -1027,7 +1025,6 @@ nv50_screen_create(struct nouveau_device *dev) + screen->base.sysmem_bindings |= + PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER; + +- screen->base.pushbuf->user_priv = screen; + screen->base.pushbuf->rsvd_kick = 5; + + chan = screen->base.channel; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index b8ea652a727..f2aebccb235 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -747,11 +747,9 @@ nva0_draw_stream_output(struct nv50_context *nv50, + } + + static void +-nv50_draw_vbo_kick_notify(struct nouveau_pushbuf *chan) ++nv50_draw_vbo_kick_notify(struct nouveau_context *context) + { +- struct nv50_screen *screen = chan->user_priv; +- +- nouveau_fence_update(&screen->base, true); ++ nouveau_fence_update(context->screen, true); + } + + void +@@ -815,7 +813,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + + nv50_state_validate_3d(nv50, ~0); + +- push->kick_notify = nv50_draw_vbo_kick_notify; ++ nv50->base.kick_notify = nv50_draw_vbo_kick_notify; + + for (s = 0; s < NV50_MAX_3D_SHADER_STAGES && !nv50->cb_dirty; ++s) { + if (nv50->constbuf_coherent[s]) +@@ -922,7 +920,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + } + + cleanup: +- push->kick_notify = nv50_default_kick_notify; ++ nv50->base.kick_notify = nv50_default_kick_notify; + + nv50_release_user_vbufs(nv50); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video.c b/src/gallium/drivers/nouveau/nv50/nv84_video.c +index 41f74a66770..f013d57c6f2 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv84_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv84_video.c +@@ -249,11 +249,11 @@ nv84_decoder_destroy(struct pipe_video_codec *decoder) + nouveau_object_del(&dec->vp); + + nouveau_bufctx_del(&dec->bsp_bufctx); +- nouveau_pushbuf_del(&dec->bsp_pushbuf); ++ nouveau_pushbuf_destroy(&dec->bsp_pushbuf); + nouveau_object_del(&dec->bsp_channel); + + nouveau_bufctx_del(&dec->vp_bufctx); +- nouveau_pushbuf_del(&dec->vp_pushbuf); ++ nouveau_pushbuf_destroy(&dec->vp_pushbuf); + nouveau_object_del(&dec->vp_channel); + + nouveau_client_del(&dec->client); +@@ -337,8 +337,8 @@ nv84_create_decoder(struct pipe_context *context, + if (ret) + goto fail; + +- ret = nouveau_pushbuf_new(dec->client, dec->bsp_channel, 4, +- 32 * 1024, true, &dec->bsp_pushbuf); ++ ret = nouveau_pushbuf_create(screen, &nv50->base, dec->client, dec->bsp_channel, ++ 4, 32 * 1024, true, &dec->bsp_pushbuf); + if (ret) + goto fail; + +@@ -352,8 +352,8 @@ nv84_create_decoder(struct pipe_context *context, + &nv04_data, sizeof(nv04_data), &dec->vp_channel); + if (ret) + goto fail; +- ret = nouveau_pushbuf_new(dec->client, dec->vp_channel, 4, +- 32 * 1024, true, &dec->vp_pushbuf); ++ ret = nouveau_pushbuf_create(screen, &nv50->base, dec->client, dec->vp_channel, ++ 4, 32 * 1024, true, &dec->vp_pushbuf); + if (ret) + goto fail; + +diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video.c b/src/gallium/drivers/nouveau/nv50/nv98_video.c +index 07cb05550b1..44e6f26daad 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv98_video.c ++++ b/src/gallium/drivers/nouveau/nv50/nv98_video.c +@@ -120,8 +120,8 @@ nv98_create_decoder(struct pipe_context *context, + &nv04_data, sizeof(nv04_data), &dec->channel[0]); + + if (!ret) +- ret = nouveau_pushbuf_new(nv50->base.client, dec->channel[0], 4, +- 32 * 1024, true, &dec->pushbuf[0]); ++ ret = nouveau_pushbuf_create(screen, &nv50->base, nv50->base.client, dec->channel[0], ++ 4, 32 * 1024, true, &dec->pushbuf[0]); + + for (i = 1; i < 3; ++i) { + dec->channel[i] = dec->channel[0]; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +index adc36531b28..1fd77b1db64 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +@@ -276,17 +276,14 @@ nvc0_destroy(struct pipe_context *pipe) + } + + void +-nvc0_default_kick_notify(struct nouveau_pushbuf *push) ++nvc0_default_kick_notify(struct nouveau_context *context) + { +- struct nvc0_screen *screen = push->user_priv; +- struct nvc0_context *nvc0 = screen->cur_ctx; ++ struct nvc0_context *nvc0 = nvc0_context(&context->pipe); + +- if (nvc0) { +- nouveau_fence_next(&nvc0->base); +- nouveau_fence_update(&screen->base, true); +- nvc0->state.flushed = true; +- NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); +- } ++ nouveau_fence_next(context); ++ nouveau_fence_update(context->screen, true); ++ ++ nvc0->state.flushed = true; + } + + static int +@@ -425,7 +422,10 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (!nvc0_blitctx_create(nvc0)) + goto out_err; + +- nouveau_context_init(&nvc0->base, &screen->base); ++ if (nouveau_context_init(&nvc0->base, &screen->base)) ++ goto out_err; ++ nvc0->base.kick_notify = nvc0_default_kick_notify; ++ nvc0->base.pushbuf->rsvd_kick = 5; + + ret = nouveau_bufctx_new(nvc0->base.client, 2, &nvc0->bufctx); + if (!ret) +@@ -496,9 +496,9 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + if (!screen->cur_ctx) { + nvc0->state = screen->save_state; + screen->cur_ctx = nvc0; +- nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx); + } +- screen->base.pushbuf->kick_notify = nvc0_default_kick_notify; ++ nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx); ++ PUSH_SPACE(nvc0->base.pushbuf, 8); + + /* add permanently resident buffers to bufctxts */ + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +index bda081d190f..6711e950e25 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +@@ -338,7 +338,7 @@ nvc0_resource_validate(struct nvc0_context *nvc0, struct nv04_resource *res, uin + struct pipe_context *nvc0_create(struct pipe_screen *, void *, unsigned flags); + void nvc0_bufctx_fence(struct nvc0_context *, struct nouveau_bufctx *, + bool on_flush); +-void nvc0_default_kick_notify(struct nouveau_pushbuf *); ++void nvc0_default_kick_notify(struct nouveau_context *); + const void *nvc0_get_sample_locations(unsigned); + + /* nvc0_draw.c */ +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +index ff89fb6b461..86dd15520a5 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +@@ -905,7 +905,7 @@ nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog) + IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0); + + if ((screen->text->size << 1) <= (1 << 23)) { +- ret = nvc0_screen_resize_text_area(screen, screen->text->size << 1); ++ ret = nvc0_screen_resize_text_area(screen, nvc0->base.pushbuf, screen->text->size << 1); + if (ret) { + NOUVEAU_ERR("Error allocating TEXT area: %d\n", ret); + return false; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +index d61568022bd..64353bcdf39 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -714,9 +714,6 @@ nvc0_screen_destroy(struct pipe_screen *pscreen) + if (!nouveau_drm_screen_unref(&screen->base)) + return; + +- if (screen->base.pushbuf) +- screen->base.pushbuf->user_priv = NULL; +- + if (screen->blitter) + nvc0_blitter_destroy(screen); + if (screen->pm.prog) { +@@ -858,10 +855,11 @@ nvc0_magic_3d_init(struct nouveau_pushbuf *push, uint16_t obj_class) + } + + static void +-nvc0_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence) ++nvc0_screen_fence_emit(struct pipe_context *pcontext, u32 *sequence) + { +- struct nvc0_screen *screen = nvc0_screen(pscreen); +- struct nouveau_pushbuf *push = screen->base.pushbuf; ++ struct nvc0_context *nvc0 = nvc0_context(pcontext); ++ struct nvc0_screen *screen = nvc0->screen; ++ struct nouveau_pushbuf *push = nvc0->base.pushbuf; + + /* we need to do it after possible flush in MARK_RING */ + *sequence = ++screen->base.fence.sequence; +@@ -941,9 +939,9 @@ nvc0_screen_resize_tls_area(struct nvc0_screen *screen, + } + + int +-nvc0_screen_resize_text_area(struct nvc0_screen *screen, uint64_t size) ++nvc0_screen_resize_text_area(struct nvc0_screen *screen, struct nouveau_pushbuf *push, ++ uint64_t size) + { +- struct nouveau_pushbuf *push = screen->base.pushbuf; + struct nouveau_bo *bo; + int ret; + +@@ -956,7 +954,7 @@ nvc0_screen_resize_text_area(struct nvc0_screen *screen, uint64_t size) + * segment, as it may have commands that will reference it. + */ + if (screen->text) +- PUSH_REF1(push, screen->text, ++ PUSH_REF1(screen->base.pushbuf, screen->text, + NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD); + nouveau_bo_ref(NULL, &screen->text); + screen->text = bo; +@@ -985,13 +983,11 @@ nvc0_screen_resize_text_area(struct nvc0_screen *screen, uint64_t size) + } + + void +-nvc0_screen_bind_cb_3d(struct nvc0_screen *screen, bool *can_serialize, +- int stage, int index, int size, uint64_t addr) ++nvc0_screen_bind_cb_3d(struct nvc0_screen *screen, struct nouveau_pushbuf *push, ++ bool *can_serialize, int stage, int index, int size, uint64_t addr) + { + assert(stage != 5); + +- struct nouveau_pushbuf *push = screen->base.pushbuf; +- + if (screen->base.class_3d >= GM107_3D_CLASS) { + struct nvc0_cb_binding *binding = &screen->cb_bindings[stage][index]; + +@@ -1076,7 +1072,6 @@ nvc0_screen_create(struct nouveau_device *dev) + FAIL_SCREEN_INIT("Base screen init failed: %d\n", ret); + chan = screen->base.channel; + push = screen->base.pushbuf; +- push->user_priv = screen; + push->rsvd_kick = 5; + + /* TODO: could this be higher on Kepler+? how does reclocking vs no +@@ -1309,7 +1304,7 @@ nvc0_screen_create(struct nouveau_device *dev) + + nvc0_magic_3d_init(push, screen->eng3d->oclass); + +- ret = nvc0_screen_resize_text_area(screen, 1 << 19); ++ ret = nvc0_screen_resize_text_area(screen, push, 1 << 19); + if (ret) + FAIL_SCREEN_INIT("Error allocating TEXT area: %d\n", ret); + +@@ -1523,7 +1518,7 @@ nvc0_screen_create(struct nouveau_device *dev) + + /* TIC and TSC entries for each unit (nve4+ only) */ + /* auxiliary constants (6 user clip planes, base instance id) */ +- nvc0_screen_bind_cb_3d(screen, NULL, i, 15, NVC0_CB_AUX_SIZE, ++ nvc0_screen_bind_cb_3d(screen, push, NULL, i, 15, NVC0_CB_AUX_SIZE, + screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i)); + if (screen->eng3d->oclass >= NVE4_3D_CLASS) { + unsigned j; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +index 3a17bbcb3c9..3af38b59503 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +@@ -152,10 +152,10 @@ int nvc0_screen_tsc_alloc(struct nvc0_screen *, void *); + int nve4_screen_compute_setup(struct nvc0_screen *, struct nouveau_pushbuf *); + int nvc0_screen_compute_setup(struct nvc0_screen *, struct nouveau_pushbuf *); + +-int nvc0_screen_resize_text_area(struct nvc0_screen *, uint64_t); ++int nvc0_screen_resize_text_area(struct nvc0_screen *, struct nouveau_pushbuf *, uint64_t); + + // 3D Only +-void nvc0_screen_bind_cb_3d(struct nvc0_screen *, bool *, int, int, int, uint64_t); ++void nvc0_screen_bind_cb_3d(struct nvc0_screen *, struct nouveau_pushbuf *, bool *, int, int, int, uint64_t); + + struct nvc0_format { + uint32_t rt; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +index 41d357e5848..3fb69b51208 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +@@ -577,6 +577,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) + unsigned s; + + bool can_serialize = true; ++ struct nouveau_pushbuf *push = nvc0->base.pushbuf; + + for (s = 0; s < 5; ++s) { + while (nvc0->constbuf_dirty[s]) { +@@ -593,7 +594,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) + if (!nvc0->state.uniform_buffer_bound[s]) { + nvc0->state.uniform_buffer_bound[s] = true; + +- nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i, ++ nvc0_screen_bind_cb_3d(nvc0->screen, push, &can_serialize, s, i, + NVC0_MAX_CONSTBUF_SIZE, bo->offset + base); + } + nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base), +@@ -604,7 +605,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) + struct nv04_resource *res = + nv04_resource(nvc0->constbuf[s][i].u.buf); + if (res) { +- nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i, ++ nvc0_screen_bind_cb_3d(nvc0->screen, push, &can_serialize, s, i, + nvc0->constbuf[s][i].size, + res->address + nvc0->constbuf[s][i].offset); + +@@ -616,7 +617,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) + if (i == 0) + nvc0->state.uniform_buffer_bound[s] = false; + } else if (i != 0) { +- nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i, -1, 0); ++ nvc0_screen_bind_cb_3d(nvc0->screen, push, &can_serialize, s, i, -1, 0); + } + } + } +@@ -717,7 +718,7 @@ nvc0_validate_driverconst(struct nvc0_context *nvc0) + int i; + + for (i = 0; i < 5; ++i) +- nvc0_screen_bind_cb_3d(screen, NULL, i, 15, NVC0_CB_AUX_SIZE, ++ nvc0_screen_bind_cb_3d(screen, nvc0->base.pushbuf, NULL, i, 15, NVC0_CB_AUX_SIZE, + screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i)); + + nvc0->dirty_cp |= NVC0_NEW_CP_DRIVERCONST; +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +index b9ca992ffcb..8f11296f812 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +@@ -557,13 +557,9 @@ nvc0_prim_gl(unsigned prim) + } + + static void +-nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push) ++nvc0_draw_vbo_kick_notify(struct nouveau_context *context) + { +- struct nvc0_screen *screen = push->user_priv; +- +- nouveau_fence_update(&screen->base, true); +- +- NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); ++ nouveau_fence_update(context->screen, true); + } + + static void +@@ -1047,7 +1043,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + nvc0->seamless_cube_map ? NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP : 0); + } + +- push->kick_notify = nvc0_draw_vbo_kick_notify; ++ nvc0->base.kick_notify = nvc0_draw_vbo_kick_notify; + + for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) { + if (nvc0->constbuf_coherent[s]) +@@ -1131,7 +1127,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + } + + cleanup: +- push->kick_notify = nvc0_default_kick_notify; ++ nvc0->base.kick_notify = nvc0_default_kick_notify; + + nvc0_release_user_vbufs(nvc0); + +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +index 3ffc4204b81..d2aed4a7030 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_video.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video.c +@@ -161,8 +161,8 @@ nvc0_create_decoder(struct pipe_context *context, + data, size, &dec->channel[i]); + + if (!ret) +- ret = nouveau_pushbuf_new(nvc0->base.client, dec->channel[i], 4, +- 32 * 1024, true, &dec->pushbuf[i]); ++ ret = nouveau_pushbuf_create(screen, &nvc0->base, nvc0->base.client, dec->channel[i], ++ 4, 32 * 1024, true, &dec->pushbuf[i]); + if (ret) + break; + } +-- +2.37.3 + + +From 8dc30c20a41f886c28f56552c7eb6a8d04a342f9 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Wed, 30 Jun 2021 10:26:35 +0200 +Subject: [PATCH 15/17] nouveau: make fencing race free + +Signed-off-by: Karol Herbst +Acked-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nouveau_fence.c | 145 ++++++++++++++---- + src/gallium/drivers/nouveau/nouveau_fence.h | 37 +++-- + src/gallium/drivers/nouveau/nouveau_screen.c | 4 +- + src/gallium/drivers/nouveau/nouveau_winsys.h | 33 +++- + .../drivers/nouveau/nv30/nv30_context.c | 8 +- + .../drivers/nouveau/nv50/nv50_context.c | 4 +- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 2 +- + .../drivers/nouveau/nvc0/nvc0_context.c | 4 +- + src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 2 +- + 9 files changed, 179 insertions(+), 60 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c +index 05808ebd68e..4ac3fa4f7b6 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.c ++++ b/src/gallium/drivers/nouveau/nouveau_fence.c +@@ -30,6 +30,9 @@ + #include + #endif + ++static bool ++_nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug); ++ + bool + nouveau_fence_new(struct nouveau_context *nv, struct nouveau_fence **fence) + { +@@ -48,6 +51,8 @@ nouveau_fence_new(struct nouveau_context *nv, struct nouveau_fence **fence) + static void + nouveau_fence_trigger_work(struct nouveau_fence *fence) + { ++ simple_mtx_assert_locked(&fence->screen->fence.lock); ++ + struct nouveau_fence_work *work, *tmp; + + LIST_FOR_EACH_ENTRY_SAFE(work, tmp, &fence->work, list) { +@@ -57,12 +62,14 @@ nouveau_fence_trigger_work(struct nouveau_fence *fence) + } + } + +-void +-nouveau_fence_emit(struct nouveau_fence *fence) ++static void ++_nouveau_fence_emit(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &screen->fence; + ++ simple_mtx_assert_locked(&fence_list->lock); ++ + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); + if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED) + return; +@@ -70,7 +77,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) + /* set this now, so that if fence.emit triggers a flush we don't recurse */ + fence->state = NOUVEAU_FENCE_STATE_EMITTING; + +- ++fence->ref; ++ p_atomic_inc(&fence->ref); + + if (fence_list->tail) + fence_list->tail->next = fence; +@@ -85,12 +92,14 @@ nouveau_fence_emit(struct nouveau_fence *fence) + fence->state = NOUVEAU_FENCE_STATE_EMITTED; + } + +-void ++static void + nouveau_fence_del(struct nouveau_fence *fence) + { + struct nouveau_fence *it; + struct nouveau_fence_list *fence_list = &fence->screen->fence; + ++ simple_mtx_assert_locked(&fence_list->lock); ++ + if (fence->state == NOUVEAU_FENCE_STATE_EMITTED || + fence->state == NOUVEAU_FENCE_STATE_FLUSHED) { + if (fence == fence_list->head) { +@@ -117,26 +126,31 @@ void + nouveau_fence_cleanup(struct nouveau_context *nv) + { + if (nv->fence) { ++ struct nouveau_fence_list *fence_list = &nv->screen->fence; + struct nouveau_fence *current = NULL; + + /* nouveau_fence_wait will create a new current fence, so wait on the + * _current_ one, and remove both. + */ +- nouveau_fence_ref(nv->fence, ¤t); +- nouveau_fence_wait(current, NULL); +- nouveau_fence_ref(NULL, ¤t); +- nouveau_fence_ref(NULL, &nv->fence); ++ simple_mtx_lock(&fence_list->lock); ++ _nouveau_fence_ref(nv->fence, ¤t); ++ _nouveau_fence_wait(current, NULL); ++ _nouveau_fence_ref(NULL, ¤t); ++ _nouveau_fence_ref(NULL, &nv->fence); ++ simple_mtx_unlock(&fence_list->lock); + } + } + + void +-nouveau_fence_update(struct nouveau_screen *screen, bool flushed) ++_nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + { + struct nouveau_fence *fence; + struct nouveau_fence *next = NULL; + struct nouveau_fence_list *fence_list = &screen->fence; + u32 sequence = fence_list->update(&screen->base); + ++ simple_mtx_assert_locked(&fence_list->lock); ++ + /* If running under drm-shim, let all fences be signalled so things run to + * completion (avoids a hang at the end of shader-db). + */ +@@ -154,7 +168,7 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + fence->state = NOUVEAU_FENCE_STATE_SIGNALLED; + + nouveau_fence_trigger_work(fence); +- nouveau_fence_ref(NULL, &fence); ++ _nouveau_fence_ref(NULL, &fence); + + if (sequence == fence_list->sequence_ack) + break; +@@ -172,16 +186,18 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) + + #define NOUVEAU_FENCE_MAX_SPINS (1 << 31) + +-bool +-nouveau_fence_signalled(struct nouveau_fence *fence) ++static bool ++_nouveau_fence_signalled(struct nouveau_fence *fence) + { + struct nouveau_screen *screen = fence->screen; + ++ simple_mtx_assert_locked(&screen->fence.lock); ++ + if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) + return true; + + if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED) +- nouveau_fence_update(screen, false); ++ _nouveau_fence_update(screen, false); + + return fence->state == NOUVEAU_FENCE_STATE_SIGNALLED; + } +@@ -191,36 +207,43 @@ nouveau_fence_kick(struct nouveau_fence *fence) + { + struct nouveau_context *context = fence->context; + struct nouveau_screen *screen = fence->screen; ++ struct nouveau_fence_list *fence_list = &screen->fence; + bool current = !fence->sequence; + ++ simple_mtx_assert_locked(&fence_list->lock); ++ + /* wtf, someone is waiting on a fence in flush_notify handler? */ + assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); + + if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) { +- PUSH_SPACE(context->pushbuf, 8); +- nouveau_fence_emit(fence); ++ if (PUSH_AVAIL(context->pushbuf) < 16) ++ nouveau_pushbuf_space(context->pushbuf, 16, 0, 0); ++ _nouveau_fence_emit(fence); + } + +- if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) ++ if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) { + if (nouveau_pushbuf_kick(context->pushbuf, context->pushbuf->channel)) + return false; ++ } + + if (current) +- nouveau_fence_next(fence->context); ++ _nouveau_fence_next(fence->context); + +- nouveau_fence_update(screen, false); ++ _nouveau_fence_update(screen, false); + + return true; + } + +-bool +-nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug) ++static bool ++_nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug) + { + struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &screen->fence; + uint32_t spins = 0; + int64_t start = 0; + ++ simple_mtx_assert_locked(&fence_list->lock); ++ + if (debug && debug->debug_message) + start = os_time_get_nano(); + +@@ -243,7 +266,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu + sched_yield(); + #endif + +- nouveau_fence_update(screen, false); ++ _nouveau_fence_update(screen, false); + } while (spins < NOUVEAU_FENCE_MAX_SPINS); + + debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n", +@@ -254,16 +277,20 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu + } + + void +-nouveau_fence_next(struct nouveau_context *nv) ++_nouveau_fence_next(struct nouveau_context *nv) + { ++ struct nouveau_fence_list *fence_list = &nv->screen->fence; ++ ++ simple_mtx_assert_locked(&fence_list->lock); ++ + if (nv->fence->state < NOUVEAU_FENCE_STATE_EMITTING) { +- if (nv->fence->ref > 1) +- nouveau_fence_emit(nv->fence); ++ if (p_atomic_read(&nv->fence->ref) > 1) ++ _nouveau_fence_emit(nv->fence); + else + return; + } + +- nouveau_fence_ref(NULL, &nv->fence); ++ _nouveau_fence_ref(NULL, &nv->fence); + + nouveau_fence_new(nv, &nv->fence); + } +@@ -281,6 +308,7 @@ nouveau_fence_work(struct nouveau_fence *fence, + void (*func)(void *), void *data) + { + struct nouveau_fence_work *work; ++ struct nouveau_screen *screen; + + if (!fence || fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) { + func(data); +@@ -292,9 +320,72 @@ nouveau_fence_work(struct nouveau_fence *fence, + return false; + work->func = func; + work->data = data; ++ ++ /* the fence might get deleted by fence_kick */ ++ screen = fence->screen; ++ ++ simple_mtx_lock(&screen->fence.lock); + list_add(&work->list, &fence->work); +- p_atomic_inc(&fence->work_count); +- if (fence->work_count > 64) ++ if (++fence->work_count > 64) + nouveau_fence_kick(fence); ++ simple_mtx_unlock(&screen->fence.lock); + return true; + } ++ ++void ++_nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref) ++{ ++ if (fence) ++ p_atomic_inc(&fence->ref); ++ ++ if (*ref) { ++ simple_mtx_assert_locked(&(*ref)->screen->fence.lock); ++ if (p_atomic_dec_zero(&(*ref)->ref)) ++ nouveau_fence_del(*ref); ++ } ++ ++ *ref = fence; ++} ++ ++void ++nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref) ++{ ++ struct nouveau_fence_list *fence_list = NULL; ++ if (ref && *ref) ++ fence_list = &(*ref)->screen->fence; ++ ++ if (fence_list) ++ simple_mtx_lock(&fence_list->lock); ++ ++ _nouveau_fence_ref(fence, ref); ++ ++ if (fence_list) ++ simple_mtx_unlock(&fence_list->lock); ++} ++ ++bool ++nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug) ++{ ++ struct nouveau_fence_list *fence_list = &fence->screen->fence; ++ simple_mtx_lock(&fence_list->lock); ++ bool res = _nouveau_fence_wait(fence, debug); ++ simple_mtx_unlock(&fence_list->lock); ++ return res; ++} ++ ++void ++nouveau_fence_emit(struct nouveau_fence *fence) ++{ ++ simple_mtx_lock(&fence->screen->fence.lock); ++ _nouveau_fence_emit(fence); ++ simple_mtx_unlock(&fence->screen->fence.lock); ++} ++ ++bool ++nouveau_fence_signalled(struct nouveau_fence *fence) ++{ ++ simple_mtx_lock(&fence->screen->fence.lock); ++ bool ret = _nouveau_fence_signalled(fence); ++ simple_mtx_unlock(&fence->screen->fence.lock); ++ return ret; ++} +diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h +index 49e74bfc52c..444598b3eb1 100644 +--- a/src/gallium/drivers/nouveau/nouveau_fence.h ++++ b/src/gallium/drivers/nouveau/nouveau_fence.h +@@ -4,6 +4,7 @@ + + #include "util/u_inlines.h" + #include "util/list.h" ++#include "util/simple_mtx.h" + + #define NOUVEAU_FENCE_STATE_AVAILABLE 0 + #define NOUVEAU_FENCE_STATE_EMITTING 1 +@@ -35,13 +36,29 @@ struct nouveau_fence_list { + struct nouveau_fence *tail; + uint32_t sequence; + uint32_t sequence_ack; ++ simple_mtx_t lock; + void (*emit)(struct pipe_context *, uint32_t *sequence); + uint32_t (*update)(struct pipe_screen *); + }; + +-void nouveau_fence_emit(struct nouveau_fence *); +-void nouveau_fence_del(struct nouveau_fence *); ++static inline void ++nouveau_fence_list_init(struct nouveau_fence_list *fence_list) ++{ ++ simple_mtx_init(&fence_list->lock, mtx_plain); ++} ++ ++static inline void ++nouveau_fence_list_destroy(struct nouveau_fence_list *fence_list) ++{ ++ simple_mtx_destroy(&fence_list->lock); ++} ++ ++/* unlocked versions, use with care */ ++void _nouveau_fence_update(struct nouveau_screen *, bool flushed); ++void _nouveau_fence_next(struct nouveau_context *); ++void _nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **); + ++void nouveau_fence_emit(struct nouveau_fence *); + bool nouveau_fence_new(struct nouveau_context *, struct nouveau_fence **); + void nouveau_fence_cleanup(struct nouveau_context *); + bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); +@@ -49,24 +66,10 @@ void nouveau_fence_update(struct nouveau_screen *, bool flushed); + void nouveau_fence_next(struct nouveau_context *); + bool nouveau_fence_wait(struct nouveau_fence *, struct util_debug_callback *); + bool nouveau_fence_signalled(struct nouveau_fence *); ++void nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **); + + void nouveau_fence_unref_bo(void *data); /* generic unref bo callback */ + +- +-static inline void +-nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref) +-{ +- if (fence) +- ++fence->ref; +- +- if (*ref) { +- if (--(*ref)->ref == 0) +- nouveau_fence_del(*ref); +- } +- +- *ref = fence; +-} +- + static inline struct nouveau_fence * + nouveau_fence(struct pipe_fence_handle *fence) + { +diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c +index 37d14bee8fd..5f4b9c8cad4 100644 +--- a/src/gallium/drivers/nouveau/nouveau_screen.c ++++ b/src/gallium/drivers/nouveau/nouveau_screen.c +@@ -195,7 +195,7 @@ nouveau_pushbuf_cb(struct nouveau_pushbuf *push) + if (p->context) + p->context->kick_notify(p->context); + else +- nouveau_fence_update(p->screen, true); ++ _nouveau_fence_update(p->screen, true); + + NOUVEAU_DRV_STAT(p->screen, pushbuf_count, 1); + } +@@ -384,6 +384,7 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) + PIPE_BIND_COMMAND_ARGS_BUFFER; + + memset(&mm_config, 0, sizeof(mm_config)); ++ nouveau_fence_list_init(&screen->fence); + + screen->mm_GART = nouveau_mm_create(dev, + NOUVEAU_BO_GART | NOUVEAU_BO_MAP, +@@ -420,6 +421,7 @@ nouveau_screen_fini(struct nouveau_screen *screen) + close(fd); + + disk_cache_destroy(screen->disk_shader_cache); ++ nouveau_fence_list_destroy(&screen->fence); + } + + static void +diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h +index 3d83d572615..1b6652f6952 100644 +--- a/src/gallium/drivers/nouveau/nouveau_winsys.h ++++ b/src/gallium/drivers/nouveau/nouveau_winsys.h +@@ -27,7 +27,11 @@ PUSH_AVAIL(struct nouveau_pushbuf *push) + static inline bool + PUSH_SPACE_EX(struct nouveau_pushbuf *push, uint32_t size, uint32_t relocs, uint32_t pushes) + { +- return nouveau_pushbuf_space(push, size, relocs, pushes) == 0; ++ struct nouveau_pushbuf_priv *ppush = push->user_priv; ++ simple_mtx_lock(&ppush->screen->fence.lock); ++ bool res = nouveau_pushbuf_space(push, size, relocs, pushes) == 0; ++ simple_mtx_unlock(&ppush->screen->fence.lock); ++ return res; + } + + static inline bool +@@ -71,7 +75,11 @@ PUSH_DATAf(struct nouveau_pushbuf *push, float f) + static inline int + PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_pushbuf_refn *refs, int nr) + { +- return nouveau_pushbuf_refn(push, refs, nr); ++ struct nouveau_pushbuf_priv *ppush = push->user_priv; ++ simple_mtx_lock(&ppush->screen->fence.lock); ++ int ret = nouveau_pushbuf_refn(push, refs, nr); ++ simple_mtx_unlock(&ppush->screen->fence.lock); ++ return ret; + } + + static inline int +@@ -84,25 +92,40 @@ PUSH_REF1(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags) + static inline void + PUSH_KICK(struct nouveau_pushbuf *push) + { ++ struct nouveau_pushbuf_priv *ppush = push->user_priv; ++ simple_mtx_lock(&ppush->screen->fence.lock); + nouveau_pushbuf_kick(push, push->channel); ++ simple_mtx_unlock(&ppush->screen->fence.lock); + } + + static inline int + PUSH_VAL(struct nouveau_pushbuf *push) + { +- return nouveau_pushbuf_validate(push); ++ struct nouveau_pushbuf_priv *ppush = push->user_priv; ++ simple_mtx_lock(&ppush->screen->fence.lock); ++ int res = nouveau_pushbuf_validate(push); ++ simple_mtx_unlock(&ppush->screen->fence.lock); ++ return res; + } + + static inline int + BO_MAP(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) + { +- return nouveau_bo_map(bo, access, client); ++ int res; ++ simple_mtx_lock(&screen->fence.lock); ++ res = nouveau_bo_map(bo, access, client); ++ simple_mtx_unlock(&screen->fence.lock); ++ return res; + } + + static inline int + BO_WAIT(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) + { +- return nouveau_bo_wait(bo, access, client); ++ int res; ++ simple_mtx_lock(&screen->fence.lock); ++ res = nouveau_bo_wait(bo, access, client); ++ simple_mtx_unlock(&screen->fence.lock); ++ return res; + } + + #define NOUVEAU_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0) +diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c +index 50c5071b266..7ce9f33a165 100644 +--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c ++++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c +@@ -41,21 +41,21 @@ nv30_context_kick_notify(struct nouveau_pushbuf *push) + struct nouveau_pushbuf_priv *p = push->user_priv; + struct nouveau_screen *screen = p->screen; + +- nouveau_fence_next(p->context); +- nouveau_fence_update(screen, true); ++ _nouveau_fence_next(p->context); ++ _nouveau_fence_update(screen, true); + + if (push->bufctx) { + struct nouveau_bufref *bref; + LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) { + struct nv04_resource *res = bref->priv; + if (res && res->mm) { +- nouveau_fence_ref(p->context->fence, &res->fence); ++ _nouveau_fence_ref(p->context->fence, &res->fence); + + if (bref->flags & NOUVEAU_BO_RD) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + + if (bref->flags & NOUVEAU_BO_WR) { +- nouveau_fence_ref(p->context->fence, &res->fence_wr); ++ _nouveau_fence_ref(p->context->fence, &res->fence_wr); + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | + NOUVEAU_BUFFER_STATUS_DIRTY; + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index bbc4131a499..977ce2e27e7 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -136,8 +136,8 @@ nv50_default_kick_notify(struct nouveau_context *context) + { + struct nv50_context *nv50 = nv50_context(&context->pipe); + +- nouveau_fence_next(context); +- nouveau_fence_update(context->screen, true); ++ _nouveau_fence_next(context); ++ _nouveau_fence_update(context->screen, true); + nv50->state.flushed = true; + } + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index f2aebccb235..2a49539b0cd 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -749,7 +749,7 @@ nva0_draw_stream_output(struct nv50_context *nv50, + static void + nv50_draw_vbo_kick_notify(struct nouveau_context *context) + { +- nouveau_fence_update(context->screen, true); ++ _nouveau_fence_update(context->screen, true); + } + + void +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +index 1fd77b1db64..1c90ba17853 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +@@ -280,8 +280,8 @@ nvc0_default_kick_notify(struct nouveau_context *context) + { + struct nvc0_context *nvc0 = nvc0_context(&context->pipe); + +- nouveau_fence_next(context); +- nouveau_fence_update(context->screen, true); ++ _nouveau_fence_next(context); ++ _nouveau_fence_update(context->screen, true); + + nvc0->state.flushed = true; + } +diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +index 8f11296f812..d55792c44e8 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +@@ -559,7 +559,7 @@ nvc0_prim_gl(unsigned prim) + static void + nvc0_draw_vbo_kick_notify(struct nouveau_context *context) + { +- nouveau_fence_update(context->screen, true); ++ _nouveau_fence_update(context->screen, true); + } + + static void +-- +2.37.3 + + +From 468eb784519eee1cdfde1ff2e447c6685f844d31 Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Thu, 17 Jun 2021 18:56:24 +0200 +Subject: [PATCH 16/17] 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 +Acked-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nvc0/nvc0_compute.c | 7 ++++++- + src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 5 +++++ + src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 6 +++++- + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 3 +++ + src/gallium/drivers/nouveau/nvc0/nvc0_screen.h | 1 + + .../drivers/nouveau/nvc0/nvc0_shader_state.c | 3 +++ + src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 3 +++ + .../drivers/nouveau/nvc0/nvc0_state_validate.c | 3 +++ + src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 16 ++++++++++++++-- + src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 6 ++++++ + src/gallium/drivers/nouveau/nvc0/nve4_compute.c | 7 ++++++- + 11 files changed, 55 insertions(+), 5 deletions(-) + +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 64353bcdf39..07bb622db08 100644 +--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c ++++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +@@ -741,6 +741,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); + } +@@ -1067,6 +1068,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 13c4fc6a27b..d7283b344a2 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"); +-- +2.37.3 + + +From e90b5ca67ed1824e4b5825564a9ab3a90016da1f Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Sun, 15 May 2022 19:20:40 +0200 +Subject: [PATCH 17/17] nv50: race free state tracking + +Signed-off-by: Karol Herbst +Acked-by: M Henning +Part-of: +--- + src/gallium/drivers/nouveau/nv50/nv50_compute.c | 7 ++++++- + src/gallium/drivers/nouveau/nv50/nv50_context.c | 5 +++++ + src/gallium/drivers/nouveau/nv50/nv50_program.c | 6 +++++- + src/gallium/drivers/nouveau/nv50/nv50_screen.c | 2 ++ + src/gallium/drivers/nouveau/nv50/nv50_screen.h | 1 + + .../drivers/nouveau/nv50/nv50_shader_state.c | 1 + + src/gallium/drivers/nouveau/nv50/nv50_state.c | 5 ++++- + .../drivers/nouveau/nv50/nv50_state_validate.c | 3 +++ + src/gallium/drivers/nouveau/nv50/nv50_surface.c | 13 +++++++++++-- + src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 4 ++++ + 10 files changed, 42 insertions(+), 5 deletions(-) + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +index af22fd8fd81..1213effd53d 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c +@@ -567,10 +567,11 @@ nv50_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + struct nv50_program *cp = nv50->compprog; + bool ret; + ++ simple_mtx_lock(&nv50->screen->state_lock); + ret = !nv50_state_validate_cp(nv50, ~0); + if (ret) { + NOUVEAU_ERR("Failed to launch grid !\n"); +- return; ++ goto out; + } + + nv50_compute_upload_input(nv50, info->input); +@@ -622,4 +623,8 @@ nv50_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) + + nv50->compute_invocations += info->block[0] * info->block[1] * info->block[2] * + grid[0] * grid[1] * grid[2]; ++ ++out: ++ PUSH_KICK(push); ++ simple_mtx_unlock(&nv50->screen->state_lock); + } +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c +index 977ce2e27e7..056aa0f0087 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c +@@ -180,11 +180,13 @@ nv50_destroy(struct pipe_context *pipe) + { + struct nv50_context *nv50 = nv50_context(pipe); + ++ simple_mtx_lock(&nv50->screen->state_lock); + if (nv50->screen->cur_ctx == nv50) { + nv50->screen->cur_ctx = NULL; + /* Save off the state in case another context gets created */ + nv50->screen->save_state = nv50->state; + } ++ simple_mtx_unlock(&nv50->screen->state_lock); + + if (nv50->base.pipe.stream_uploader) + u_upload_destroy(nv50->base.pipe.stream_uploader); +@@ -347,6 +349,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + pipe->get_sample_position = nv50_context_get_sample_position; + pipe->emit_string_marker = nv50_emit_string_marker; + ++ simple_mtx_lock(&screen->state_lock); + if (!screen->cur_ctx) { + /* Restore the last context's state here, normally handled during + * context switch +@@ -354,6 +357,8 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) + nv50->state = screen->save_state; + screen->cur_ctx = nv50; + } ++ simple_mtx_unlock(&screen->state_lock); ++ + nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); + nv50->base.kick_notify = nv50_default_kick_notify; + nv50->base.pushbuf->rsvd_kick = 5; +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c +index a81b176fccf..903145dca98 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c +@@ -486,6 +486,7 @@ nv50_program_upload_code(struct nv50_context *nv50, struct nv50_program *prog) + return false; + } + ++ simple_mtx_assert_locked(&nv50->screen->state_lock); + ret = nouveau_heap_alloc(heap, size, prog, &prog->mem); + if (ret) { + /* Out of space: evict everything to compactify the code segment, hoping +@@ -545,8 +546,11 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) + const struct pipe_shader_state pipe = p->pipe; + const ubyte type = p->type; + +- if (p->mem) ++ if (p->mem) { ++ if (nv50) ++ simple_mtx_assert_locked(&nv50->screen->state_lock); + nouveau_heap_free(&p->mem); ++ } + + FREE(p->code); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +index 79a57e5b5fa..eb2e71a28f8 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c +@@ -650,6 +650,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen) + nouveau_object_del(&screen->sync); + + nouveau_screen_fini(&screen->base); ++ simple_mtx_destroy(&screen->state_lock); + + FREE(screen); + } +@@ -1011,6 +1012,7 @@ nv50_screen_create(struct nouveau_device *dev) + pscreen = &screen->base.base; + pscreen->destroy = nv50_screen_destroy; + ++ simple_mtx_init(&screen->state_lock, mtx_plain); + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + NOUVEAU_ERR("nouveau_screen_init failed: %d\n", ret); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.h b/src/gallium/drivers/nouveau/nv50/nv50_screen.h +index a374ba46c6f..72a6fc851fe 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.h ++++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.h +@@ -62,6 +62,7 @@ struct nv50_screen { + + struct nv50_context *cur_ctx; + struct nv50_graph_state save_state; ++ simple_mtx_t state_lock; + + int num_occlusion_queries_active; + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +index 3d17953ed37..be9f25209ef 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +@@ -128,6 +128,7 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog) + if (prog->mem) + return true; + ++ simple_mtx_assert_locked(&nv50->screen->state_lock); + return nv50_program_upload_code(nv50, prog); + } + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c +index 3ad9e41fdbb..bb7d78712b8 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_state.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c +@@ -774,9 +774,12 @@ nv50_sp_state_create(struct pipe_context *pipe, + static void + nv50_sp_state_delete(struct pipe_context *pipe, void *hwcso) + { ++ struct nv50_context *nv50 = nv50_context(pipe); + struct nv50_program *prog = (struct nv50_program *)hwcso; + +- nv50_program_destroy(nv50_context(pipe), prog); ++ simple_mtx_lock(&nv50->screen->state_lock); ++ nv50_program_destroy(nv50, prog); ++ simple_mtx_unlock(&nv50->screen->state_lock); + + if (prog->pipe.type == PIPE_SHADER_IR_TGSI) + FREE((void *)prog->pipe.tokens); +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +index eec85cf6676..daba9f730c6 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +@@ -450,6 +450,7 @@ nv50_switch_pipe_context(struct nv50_context *ctx_to) + { + struct nv50_context *ctx_from = ctx_to->screen->cur_ctx; + ++ simple_mtx_assert_locked(&ctx_to->screen->state_lock); + if (ctx_from) + ctx_to->state = ctx_from->state; + else +@@ -536,6 +537,8 @@ nv50_state_validate(struct nv50_context *nv50, uint32_t mask, + int ret; + unsigned i; + ++ simple_mtx_assert_locked(&nv50->screen->state_lock); ++ + if (nv50->screen->cur_ctx != nv50) + nv50_switch_pipe_context(nv50); + +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +index 6f28c97cc73..983a67200ff 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c +@@ -534,9 +534,11 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scisso + unsigned i, j, k; + uint32_t mode = 0; + ++ simple_mtx_lock(&nv50->screen->state_lock); ++ + /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */ + if (!nv50_state_validate_3d(nv50, NV50_NEW_3D_FRAMEBUFFER)) +- return; ++ goto out; + + if (scissor_state) { + uint32_t minx = scissor_state->minx; +@@ -544,7 +546,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scisso + uint32_t miny = scissor_state->miny; + uint32_t maxy = MIN2(fb->height, scissor_state->maxy); + if (maxx <= minx || maxy <= miny) +- return; ++ goto out; + + BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); + PUSH_DATA (push, minx | (maxx - minx) << 16); +@@ -622,6 +624,10 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scisso + PUSH_DATA (push, fb->width << 16); + PUSH_DATA (push, fb->height << 16); + } ++ ++out: ++ PUSH_KICK(push); ++ simple_mtx_unlock(&nv50->screen->state_lock); + } + + static void +@@ -1773,6 +1779,7 @@ nv50_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) + info->src.box.height != -info->dst.box.height)) + eng3d = true; + ++ simple_mtx_lock(&nv50->screen->state_lock); + if (nv50->screen->num_occlusion_queries_active) { + BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1); + PUSH_DATA (push, 0); +@@ -1787,6 +1794,8 @@ nv50_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) + BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1); + PUSH_DATA (push, 1); + } ++ PUSH_KICK(push); ++ simple_mtx_unlock(&nv50->screen->state_lock); + } + + static void +diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +index 2a49539b0cd..24070085634 100644 +--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c ++++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +@@ -811,6 +811,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + if (unlikely(nv50->num_so_targets && !nv50->gmtyprog)) + nv50->state.prim_size = nv50_pipe_prim_to_prim_size[info->mode]; + ++ simple_mtx_lock(&nv50->screen->state_lock); + nv50_state_validate_3d(nv50, ~0); + + nv50->base.kick_notify = nv50_draw_vbo_kick_notify; +@@ -920,6 +921,9 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + } + + cleanup: ++ PUSH_KICK(push); ++ simple_mtx_unlock(&nv50->screen->state_lock); ++ + nv50->base.kick_notify = nv50_default_kick_notify; + + nv50_release_user_vbufs(nv50); +-- +2.37.3 +