Submitted By: Douglas R. Reno Date: 2022-02-11 Initial Package Version: 21.3.6 Upstream Status: Merge Request (Partial), Self Origin: Upstream MR (#10752) with modifications Description: Fixes several multi-threading related issues in the Nouveau driver in Mesa. These issues can lead to kernel panics and application crashes, and also cause KDE Plasma in Wayland mode to instantly crash the system once launched on a NVC0 or later card (NV50 is unaffected). My changes include additional PUSH commands to fix timing issues, which will be picked up upstream shortly. Tested with KDE Plasma/Wayland, GNOME, VLC, MPlayer, Minecraft, Discord, Zoom, XINE, and Kdenlive. diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_buffer.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_buffer.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_buffer.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_buffer.c 2022-02-11 16:51:08.220134863 -0600 @@ -91,12 +91,8 @@ nouveau_buffer_release_gpu_storage(struc { 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); @@ -172,7 +168,7 @@ nouveau_transfer_staging(struct nouveau_ 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; } } @@ -195,7 +191,7 @@ nouveau_transfer_read(struct nouveau_con 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) @@ -233,8 +229,8 @@ nouveau_transfer_write(struct nouveau_co 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 @@ -303,10 +299,9 @@ nouveau_buffer_transfer_del(struct nouve { 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)); @@ -475,9 +470,9 @@ nouveau_buffer_transfer_map(struct 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; @@ -601,11 +596,11 @@ nouveau_copy_buffer(struct nouveau_conte 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; @@ -643,10 +638,10 @@ nouveau_resource_map_offset(struct nouve 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; @@ -802,7 +797,7 @@ nouveau_buffer_data_fetch(struct nouveau { 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; @@ -827,7 +822,7 @@ nouveau_buffer_migrate(struct nouveau_co 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); @@ -853,9 +848,9 @@ nouveau_buffer_migrate(struct nouveau_co 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; @@ -897,7 +892,7 @@ nouveau_user_buffer_upload(struct nouvea 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); @@ -964,7 +959,7 @@ nouveau_scratch_runout_release(struct no 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; @@ -993,7 +988,7 @@ nouveau_scratch_runout(struct nouveau_co 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]); } @@ -1031,7 +1026,7 @@ nouveau_scratch_next(struct nouveau_cont 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_context.h mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_context.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_context.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_context.h 2022-02-11 16:51:52.682577582 -0600 @@ -15,6 +15,7 @@ struct nouveau_context { struct nouveau_client *client; struct nouveau_pushbuf *pushbuf; + struct nouveau_fence *fence; struct pipe_debug_callback debug; bool vbo_dirty; @@ -66,7 +67,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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_fence.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_fence.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_fence.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_fence.c 2022-02-11 17:03:39.714131948 -0600 @@ -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); @@ -59,22 +61,25 @@ 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_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; ++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; @@ -84,19 +89,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; } } @@ -109,18 +114,19 @@ nouveau_fence_del(struct nouveau_fence * } void -nouveau_fence_cleanup(struct nouveau_screen *screen) +nouveau_fence_cleanup(struct nouveau_context *nv) { - if (screen->fence.current) { + struct nouveau_fence_list *fence_list = &nv->screen->fence; + 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(screen->fence.current, ¤t); + nouveau_fence_ref(nv->fence, ¤t); nouveau_fence_wait(current, NULL); nouveau_fence_ref(NULL, ¤t); - nouveau_fence_ref(NULL, &screen->fence.current); + nouveau_fence_ref(NULL, &nv->fence); } } @@ -129,13 +135,14 @@ nouveau_fence_update(struct nouveau_scre { 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 (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; @@ -144,12 +151,12 @@ nouveau_fence_update(struct nouveau_scre 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) @@ -178,25 +185,23 @@ 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); 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) if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel)) return false; - if (fence == screen->fence.current) - nouveau_fence_next(screen); + if (current) + nouveau_fence_next(fence->context); nouveau_fence_update(screen, false); @@ -207,6 +212,7 @@ bool nouveau_fence_wait(struct nouveau_fence *fence, struct pipe_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; @@ -237,24 +243,26 @@ nouveau_fence_wait(struct nouveau_fence 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; } void -nouveau_fence_next(struct nouveau_screen *screen) +nouveau_fence_next(struct nouveau_context *nv) { - 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 = &nv->screen->fence; + + if (nv->fence->state < NOUVEAU_FENCE_STATE_EMITTING) { + if (nv->fence->ref > 1) + nouveau_fence_emit(nv->fence); else return; } - nouveau_fence_ref(NULL, &screen->fence.current); + nouveau_fence_ref(NULL, &nv->fence); - nouveau_fence_new(screen, &screen->fence.current); + nouveau_fence_new(nv, &nv->fence); } void diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_fence.h mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_fence.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_fence.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_fence.h 2022-02-11 17:06:52.375811111 -0600 @@ -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; @@ -29,14 +30,23 @@ struct nouveau_fence { struct list_head work; }; +struct nouveau_fence_list { + struct nouveau_fence *head; + struct nouveau_fence *tail; + 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 *); +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 pipe_debug_callback *); bool nouveau_fence_signalled(struct nouveau_fence *); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_mm.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_mm.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_mm.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_mm.c 2022-02-11 17:09:55.188637737 -0600 @@ -1,6 +1,7 @@ #include +#include "util/simple_mtx.h" #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/list.h" @@ -29,6 +30,7 @@ struct mm_bucket { struct list_head used; struct list_head full; int num_free; + simple_mtx_t lock; }; struct nouveau_mman { @@ -124,6 +126,8 @@ mm_slab_new(struct nouveau_mman *cache, int words, ret; const uint32_t size = mm_default_slab_size(chunk_order); + simple_mtx_assert_locked(&bucket->lock); + words = ((size >> chunk_order) + 31) / 32; assert(words); @@ -151,7 +155,7 @@ mm_slab_new(struct nouveau_mman *cache, assert(bucket == mm_bucket_by_order(cache, chunk_order)); list_add(&slab->head, &bucket->free); - cache->allocated += size; + p_atomic_add(&cache->allocated, size); if (nouveau_mesa_debug) debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n", @@ -182,6 +186,11 @@ nouveau_mm_allocate(struct nouveau_mman return NULL; } + alloc = MALLOC_STRUCT(nouveau_mm_allocation); + if (!alloc) + return NULL; + + simple_mtx_lock(&bucket->lock); if (!list_is_empty(&bucket->used)) { slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head); } else { @@ -196,16 +205,13 @@ nouveau_mm_allocate(struct nouveau_mman *offset = mm_slab_alloc(slab) << slab->order; - alloc = MALLOC_STRUCT(nouveau_mm_allocation); - if (!alloc) - return NULL; - nouveau_bo_ref(slab->bo, bo); if (slab->free == 0) { list_del(&slab->head); list_add(&slab->head, &bucket->full); } + simple_mtx_unlock(&bucket->lock); alloc->offset = *offset; alloc->priv = (void *)slab; @@ -229,6 +235,7 @@ nouveau_mm_free(struct nouveau_mm_alloca list_del(&slab->head); list_addtail(&slab->head, &bucket->used); } + simple_mtx_unlock(&bucket->lock); FREE(alloc); } @@ -258,6 +265,7 @@ nouveau_mm_create(struct nouveau_device list_inithead(&cache->bucket[i].free); list_inithead(&cache->bucket[i].used); list_inithead(&cache->bucket[i].full); + simple_mtx_init(&cache->bucket[i].lock, mtx_plain); } return cache; @@ -292,6 +300,7 @@ nouveau_mm_destroy(struct nouveau_mman * nouveau_mm_free_slabs(&cache->bucket[i].free); nouveau_mm_free_slabs(&cache->bucket[i].used); nouveau_mm_free_slabs(&cache->bucket[i].full); + simple_mtx_destroy(&cache->bucket[i].lock); } FREE(cache); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_screen.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_screen.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_screen.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_screen.c 2022-02-11 17:11:30.951045828 -0600 @@ -394,7 +394,11 @@ nouveau_set_debug_callback(struct pipe_c } 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_screen.h mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_screen.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_screen.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_screen.h 2022-02-11 17:12:22.999729379 -0600 @@ -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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_video.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_video.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_video.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_video.c 2022-02-11 17:13:47.703221196 -0600 @@ -37,12 +37,12 @@ nouveau_vpe_init(struct nouveau_decoder 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; @@ -73,7 +73,7 @@ nouveau_vpe_fini(struct nouveau_decoder 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 @@ -88,7 +88,7 @@ nouveau_vpe_fini(struct nouveau_decoder #undef BCTX_ARGS - if (unlikely(nouveau_pushbuf_validate(dec->push))) + if (unlikely(PUSH_VAL(dec->push))) return; BEGIN_NV04(push, NV31_MPEG(EXEC), 1); @@ -582,13 +582,13 @@ nouveau_create_decoder(struct pipe_conte 0, 4096, NULL, &dec->fence_bo); if (ret) goto fail; - nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, NULL); + BO_MAP(dec->fence_bo, NOUVEAU_BO_RDWR, NULL); dec->fence_map = dec->fence_bo->map; dec->fence_map[0] = 0; #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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_vp3_video.c mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_vp3_video.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_vp3_video.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_vp3_video.c 2022-02-11 17:14:38.549919717 -0600 @@ -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 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_winsys.h mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_winsys.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nouveau_winsys.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nouveau_winsys.h 2022-02-11 17:17:15.566002822 -0600 @@ -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 @@ -23,12 +25,18 @@ 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; +} + +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; } @@ -66,6 +74,23 @@ 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) +{ + 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_clear.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_clear.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_clear.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_clear.c 2022-02-11 14:24:23.189190438 -0600 @@ -128,7 +128,7 @@ nv30_clear_render_target(struct pipe_con 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; @@ -193,7 +193,7 @@ nv30_clear_depth_stencil(struct pipe_con 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_context.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_context.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_context.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_context.c 2022-02-11 14:28:00.534301647 -0600 @@ -45,7 +45,7 @@ nv30_context_kick_notify(struct nouveau_ 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_ 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 * 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 if (nv30->screen->cur_ctx == nv30) nv30->screen->cur_ctx = NULL; + nouveau_fence_cleanup(&nv30->base); nouveau_context_destroy(&nv30->base); } @@ -191,7 +192,6 @@ nv30_context_create(struct pipe_screen * { 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 +199,6 @@ nv30_context_create(struct pipe_screen * return NULL; nv30->screen = screen; - nv30->base.screen = &screen->base; nv30->base.copy_data = nv30_transfer_copy_data; pipe = &nv30->base.pipe; @@ -208,6 +207,9 @@ nv30_context_create(struct pipe_screen * 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 +217,6 @@ nv30_context_create(struct pipe_screen * } 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 +238,6 @@ nv30_context_create(struct pipe_screen * 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); @@ -265,6 +258,7 @@ nv30_context_create(struct pipe_screen * } nouveau_context_init_vdec(&nv30->base); + nouveau_fence_new(&nv30->base, &nv30->base.fence); return pipe; } diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_draw.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_draw.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_draw.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_draw.c 2022-02-11 14:28:44.868118544 -0600 @@ -124,7 +124,7 @@ nv30_render_draw_elements(struct vbuf_re { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; - struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; + struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); @@ -280,7 +280,7 @@ nv30_render_validate(struct nv30_context struct nv30_render *r = nv30_render(nv30->draw->render); struct nv30_rasterizer_stateobj *rast = nv30->rast; struct pipe_screen *pscreen = &nv30->screen->base.base; - struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; + struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_vertprog *vp = nv30->vertprog.program; struct vertex_info *vinfo = &r->vertex_info; diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_miptree.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_miptree.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_miptree.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_miptree.c 2022-02-11 14:29:22.740961717 -0600 @@ -359,7 +359,7 @@ nv30_miptree_transfer_map(struct pipe_co 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); @@ -393,7 +393,7 @@ nv30_miptree_transfer_unmap(struct 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_screen.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_screen.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_screen.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_screen.c 2022-02-11 14:30:44.381622525 -0600 @@ -508,8 +508,6 @@ nv30_screen_destroy(struct pipe_screen * if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); - nouveau_bo_ref(NULL, &screen->notify); nouveau_heap_destroy(&screen->query_heap); @@ -684,7 +682,7 @@ nv30_screen_create(struct nouveau_device 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); @@ -811,9 +809,7 @@ nv30_screen_create(struct nouveau_device PUSH_DATA (push, screen->ntfy->handle); BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1); PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE); + PUSH_KICK (push); - nouveau_pushbuf_kick(push, push->channel); - - nouveau_fence_new(&screen->base, &screen->base.fence.current); return &screen->base; } diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c 2022-02-11 14:32:00.766303956 -0600 @@ -463,7 +463,6 @@ nv30_state_context_switch(struct nv30_co 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; @@ -499,7 +498,7 @@ nv30_state_validate(struct nv30_context } nouveau_pushbuf_bufctx(push, bctx); - if (nouveau_pushbuf_validate(push)) { + if (PUSH_VAL(push)) { nouveau_pushbuf_bufctx(push, NULL); return false; } @@ -523,13 +522,13 @@ nv30_state_validate(struct nv30_context 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_transfer.c mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_transfer.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv30/nv30_transfer.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv30/nv30_transfer.c 2022-02-11 14:35:05.786902168 -0600 @@ -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; @@ -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; @@ -708,7 +708,7 @@ nv30_transfer_copy_data(struct nouveau_c 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_c } 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_compute.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_compute.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_compute.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_compute.c 2022-02-11 14:39:27.849132704 -0600 @@ -518,7 +518,7 @@ nv50_state_validate_cp(struct nv50_conte 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; } @@ -526,7 +526,7 @@ static void nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) { struct nv50_screen *screen = nv50->screen; - struct nouveau_pushbuf *push = screen->base.pushbuf; + struct nouveau_pushbuf *push = nv50->base.pushbuf; unsigned size = align(nv50->compprog->parm_size, 0x4); BEGIN_NV04(push, NV50_CP(USER_PARAM_COUNT), 1); @@ -540,19 +540,19 @@ nv50_compute_upload_input(struct nv50_co mm = nouveau_mm_allocate(screen->base.mm_GART, size, &bo, &offset); assert(mm); - nouveau_bo_map(bo, 0, screen->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); nouveau_pushbuf_bufctx(push, nv50->bufctx); - nouveau_pushbuf_validate(push); + PUSH_VAL(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); - 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_context.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_context.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_context.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_context.c 2022-02-11 17:44:52.706228555 -0600 @@ -34,9 +34,10 @@ nv50_flush(struct pipe_context *pipe, unsigned flags) { struct nouveau_screen *screen = nouveau_screen(pipe->screen); + struct nouveau_context *context = nouveau_context(pipe); if (fence) - nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); + nouveau_fence_ref(context->fence, (struct nouveau_fence **)fence); PUSH_KICK(screen->pushbuf); @@ -135,12 +136,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; } } @@ -193,12 +194,13 @@ 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); FREE(nv50->blit); + nouveau_fence_cleanup(&nv50->base); nouveau_context_destroy(&nv50->base); } @@ -312,20 +314,18 @@ nv50_create(struct pipe_screen *pscreen, 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(screen->base.client, 2, &nv50->bufctx); + ret = nouveau_bufctx_new(nv50->base.client, 2, &nv50->bufctx); if (!ret) - ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_3D_COUNT, + ret = nouveau_bufctx_new(nv50->base.client, NV50_BIND_3D_COUNT, &nv50->bufctx_3d); if (!ret) - ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_CP_COUNT, + ret = nouveau_bufctx_new(nv50->base.client, NV50_BIND_CP_COUNT, &nv50->bufctx_cp); 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; @@ -360,7 +360,6 @@ nv50_create(struct pipe_screen *pscreen, } 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); @@ -416,6 +415,8 @@ nv50_create(struct pipe_screen *pscreen, // 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: @@ -433,7 +434,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; @@ -442,7 +443,7 @@ nv50_bufctx_fence(struct nouveau_bufctx 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_context.h mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_context.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_context.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_context.h 2022-02-11 14:48:38.488869249 -0600 @@ -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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_miptree.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_miptree.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_miptree.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_miptree.c 2022-02-11 14:49:23.116575689 -0600 @@ -163,11 +163,7 @@ nv50_miptree_destroy(struct pipe_screen { 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); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c 2022-02-11 14:53:02.848195107 -0600 @@ -52,7 +52,7 @@ nv50_hw_query_allocate(struct nv50_conte 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); } } @@ -63,7 +63,7 @@ nv50_hw_query_allocate(struct nv50_conte return false; hq->offset = hq->base_offset; - ret = nouveau_bo_map(hq->bo, 0, screen->base.client); + ret = BO_MAP(&screen->base, hq->bo, 0, nv50->base.client); if (ret) { nv50_hw_query_allocate(nv50, q, 0); return false; @@ -265,7 +265,7 @@ nv50_hw_end_query(struct nv50_context *n break; } if (hq->is64bit) - nouveau_fence_ref(nv50->screen->base.fence.current, &hq->fence); + nouveau_fence_ref(nv50->base.fence, &hq->fence); } static bool @@ -294,7 +294,7 @@ nv50_hw_get_query_result(struct nv50_con } return false; } - if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nv50->screen->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 nv5 } 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw.h 2022-02-11 14:53:21.749080536 -0600 @@ -52,7 +52,7 @@ nv50_hw_get_driver_query_info(struct nv5 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_query_hw_sm.c 2022-02-11 14:54:28.454680509 -0600 @@ -321,7 +321,7 @@ nv50_hw_sm_query_read_data(uint32_t coun 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_screen.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_screen.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_screen.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_screen.c 2022-02-11 14:55:45.692224889 -0600 @@ -595,8 +595,6 @@ nv50_screen_destroy(struct pipe_screen * if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); - if (screen->base.pushbuf) screen->base.pushbuf->user_priv = NULL; @@ -1074,7 +1072,7 @@ nv50_screen_create(struct nouveau_device 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; @@ -1217,8 +1215,6 @@ nv50_screen_create(struct nouveau_device goto fail; } - nouveau_fence_new(&screen->base, &screen->base.fence.current); - return &screen->base; fail: diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_screen.h mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_screen.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_screen.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_screen.h 2022-02-11 14:56:32.391952891 -0600 @@ -133,32 +133,6 @@ int nv50_screen_tsc_alloc(struct nv50_sc 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c 2022-02-11 14:56:59.654795192 -0600 @@ -717,7 +717,7 @@ nv50_stream_output_validate(struct 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c 2022-02-11 14:58:09.012397327 -0600 @@ -556,10 +556,10 @@ nv50_state_validate(struct nv50_context 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 = nouveau_pushbuf_validate(nv50->base.pushbuf); + ret = PUSH_VAL(nv50->base.pushbuf); return !ret; } @@ -575,7 +575,7 @@ nv50_state_validate_3d(struct nv50_conte 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_surface.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_surface.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_surface.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_surface.c 2022-02-11 18:05:39.993075211 -0600 @@ -257,7 +257,7 @@ nv50_resource_copy_region(struct pipe_co 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, @@ -295,7 +295,7 @@ nv50_clear_render_target(struct pipe_con 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_con 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); @@ -653,7 +653,7 @@ nv50_clear_buffer_push(struct pipe_conte 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; @@ -692,7 +692,7 @@ nv50_clear_buffer_push(struct pipe_conte count -= nr; } - nv50_resource_validate(buf, NOUVEAU_BO_WR); + nv50_resource_validate(nv50, buf, NOUVEAU_BO_WR); nouveau_bufctx_reset(nv50->bufctx, 0); } @@ -771,7 +771,7 @@ nv50_clear_buffer(struct pipe_context *p 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); @@ -815,7 +815,7 @@ nv50_clear_buffer(struct pipe_context *p 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; @@ -1639,7 +1639,7 @@ nv50_blit_eng2d(struct nv50_context *nv5 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) { @@ -1679,7 +1679,7 @@ nv50_blit_eng2d(struct nv50_context *nv5 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_transfer.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_transfer.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_transfer.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_transfer.c 2022-02-11 15:02:10.331043100 -0600 @@ -67,7 +67,7 @@ nv50_2d_transfer_rect(struct nv50_contex 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_cont 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_conte 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_con 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); @@ -375,7 +375,6 @@ nv50_miptree_transfer_map(struct pipe_co const struct pipe_box *box, struct pipe_transfer **ptransfer) { - struct nv50_screen *screen = nv50_screen(pctx->screen); struct nv50_context *nv50 = nv50_context(pctx); struct nouveau_device *dev = nv50->screen->base.device; const struct nv50_miptree *mt = nv50_miptree(res); @@ -454,7 +453,7 @@ nv50_miptree_transfer_map(struct pipe_co if (usage & PIPE_MAP_WRITE) flags |= NOUVEAU_BO_WR; - ret = nouveau_bo_map(tx->rect[1].bo, flags, screen->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); @@ -486,7 +485,7 @@ nv50_miptree_transfer_unmap(struct pipe_ } /* 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_vbo.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_vbo.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv50_vbo.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv50_vbo.c 2022-02-11 15:03:36.446568575 -0600 @@ -624,14 +624,14 @@ nv50_draw_elements(struct nv50_context * * 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--) { 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) { @@ -737,7 +737,7 @@ nva0_draw_stream_output(struct nv50_cont 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); @@ -752,8 +752,6 @@ nv50_draw_vbo_kick_notify(struct nouveau struct nv50_screen *screen = chan->user_priv; nouveau_fence_update(&screen->base, true); - - nv50_bufctx_fence(screen->cur_ctx->bufctx_3d, true); } void diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv84_video_bsp.c 2022-02-11 15:09:14.426111024 -0600 @@ -89,6 +89,7 @@ nv84_decoder_bsp(struct nv84_decoder *de 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 *de { 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv84_video.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv84_video.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv84_video.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv84_video.c 2022-02-11 15:08:27.115135546 -0600 @@ -69,6 +69,7 @@ nv84_load_firmwares(struct nouveau_devic { 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_devic 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; @@ -183,11 +184,12 @@ nv84_decoder_begin_frame_mpeg12(struct p 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); @@ -406,14 +408,14 @@ nv84_create_decoder(struct pipe_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 +427,7 @@ nv84_create_decoder(struct pipe_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 +436,7 @@ nv84_create_decoder(struct pipe_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; @@ -493,17 +495,17 @@ nv84_create_decoder(struct pipe_context surf.offset = dec->vpring->size - 0x1000; context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false); - PUSH_SPACE(screen->pushbuf, 5); - PUSH_REFN(screen->pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); + PUSH_SPACE(nv50->base.pushbuf, 5); + PUSH_REFN(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. */ - BEGIN_NV04(screen->pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4); - PUSH_DATAh(screen->pushbuf, dec->fence->offset); - PUSH_DATA (screen->pushbuf, dec->fence->offset); - PUSH_DATA (screen->pushbuf, 1); - PUSH_DATA (screen->pushbuf, 0xf010); - PUSH_KICK (screen->pushbuf); + BEGIN_NV04(nv50->base.pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4); + PUSH_DATAh(nv50->base.pushbuf, dec->fence->offset); + PUSH_DATA (nv50->base.pushbuf, dec->fence->offset); + PUSH_DATA (nv50->base.pushbuf, 1); + PUSH_DATA (nv50->base.pushbuf, 0xf010); + PUSH_KICK (nv50->base.pushbuf); PUSH_SPACE(bsp_push, 2 + 12 + 2 + 4 + 3); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_bsp.c 2022-02-11 15:12:36.619828402 -0600 @@ -39,6 +39,7 @@ nv98_decoder_bsp(struct nouveau_vp3_deco 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_deco 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; @@ -107,7 +108,7 @@ nv98_decoder_bsp(struct nouveau_vp3_deco 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video.c 2022-02-11 15:11:41.428930690 -0600 @@ -85,7 +85,8 @@ struct pipe_video_codec * nv98_create_decoder(struct pipe_context *context, const struct pipe_video_codec *templ) { - struct nouveau_screen *screen = &((struct nv50_context *)context)->screen->base; + struct nv50_context *nv50 = nv50_context(context); + struct nouveau_screen *screen = &nv50->screen->base; struct nouveau_vp3_decoder *dec; struct nouveau_pushbuf **push; struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202}; @@ -106,7 +107,7 @@ nv98_create_decoder(struct pipe_context dec = CALLOC_STRUCT(nouveau_vp3_decoder); if (!dec) return NULL; - dec->client = screen->client; + dec->client = nv50->base.client; dec->base = *templ; nouveau_vp3_decoder_init_common(&dec->base); @@ -119,7 +120,7 @@ nv98_create_decoder(struct pipe_context &nv04_data, sizeof(nv04_data), &dec->channel[0]); if (!ret) - ret = nouveau_pushbuf_new(screen->client, dec->channel[0], 4, + ret = nouveau_pushbuf_new(nv50->base.client, dec->channel[0], 4, 32 * 1024, true, &dec->pushbuf[0]); for (i = 1; i < 3; ++i) { @@ -268,13 +269,13 @@ nv98_create_decoder(struct pipe_context if (ret) goto fail; - nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); + BO_MAP(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))); /* 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); @@ -285,7 +286,7 @@ nv98_create_decoder(struct pipe_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)); @@ -296,7 +297,7 @@ nv98_create_decoder(struct pipe_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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_ppp.c 2022-02-11 15:12:49.083803035 -0600 @@ -94,7 +94,7 @@ nv98_decoder_ppp(struct nouveau_vp3_deco 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c 2022-02-11 15:13:28.216718331 -0600 @@ -44,7 +44,7 @@ static void dump_comm_vp(struct nouveau_ 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(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) { @@ -111,7 +111,7 @@ nv98_decoder_vp(struct nouveau_vp3_decod 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c 2022-02-11 15:16:25.426251672 -0600 @@ -428,10 +428,11 @@ nvc0_launch_grid(struct pipe_context *pi 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); @@ -464,7 +465,7 @@ nvc0_launch_grid(struct pipe_context *pi 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)) { @@ -502,6 +503,9 @@ nvc0_launch_grid(struct pipe_context *pi nvc0->images_dirty[5] |= nvc0->images_valid[5]; nvc0_update_compute_invocations_counter(nvc0, info); + +out: + simple_mtx_unlock(&screen->state_lock); } static void @@ -511,7 +515,7 @@ nvc0_compute_update_indirect_invocations 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_context.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_context.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_context.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_context.c 2022-02-11 18:08:12.440206042 -0600 @@ -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 */ @@ -257,7 +256,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); @@ -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); } } @@ -425,22 +425,19 @@ nvc0_create(struct pipe_screen *pscreen, 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(screen->base.client, 2, &nvc0->bufctx); + ret = nouveau_bufctx_new(nvc0->base.client, 2, &nvc0->bufctx); if (!ret) - ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_3D_COUNT, + ret = nouveau_bufctx_new(nvc0->base.client, NVC0_BIND_3D_COUNT, &nvc0->bufctx_3d); if (!ret) - ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_CP_COUNT, + ret = nouveau_bufctx_new(nvc0->base.client, NVC0_BIND_CP_COUNT, &nvc0->bufctx_cp); if (ret) 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, 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); @@ -553,6 +549,8 @@ nvc0_create(struct pipe_screen *pscreen, nvc0->dirty_cp |= NVC0_NEW_CP_SAMPLERS; } + nouveau_fence_new(&nvc0->base, &nvc0->base.fence); + return pipe; out_err: @@ -583,7 +581,7 @@ nvc0_bufctx_fence(struct nvc0_context *n 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_context.h mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_context.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_context.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_context.h 2022-02-11 15:23:13.508824215 -0600 @@ -311,6 +311,30 @@ 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); void nvc0_bufctx_fence(struct nvc0_context *, struct nouveau_bufctx *, diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_program.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_program.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_program.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_program.c 2022-02-11 15:25:32.848266636 -0600 @@ -884,6 +884,7 @@ nvc0_program_upload(struct nvc0_context 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 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c 2022-02-11 15:30:18.641058844 -0600 @@ -44,7 +44,7 @@ nvc0_hw_query_allocate(struct nvc0_conte 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); } } @@ -55,7 +55,7 @@ nvc0_hw_query_allocate(struct nvc0_conte return false; hq->offset = hq->base_offset; - ret = nouveau_bo_map(hq->bo, 0, screen->base.client); + ret = BO_MAP(&screen->base, hq->bo, 0, nvc0->base.client); if (ret) { nvc0_hw_query_allocate(nvc0, q, 0); return false; @@ -129,7 +129,7 @@ nvc0_hw_query_write_compute_invocations( { 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); @@ -301,7 +301,7 @@ nvc0_hw_end_query(struct nvc0_context *n break; } if (hq->is64bit) - nouveau_fence_ref(nvc0->screen->base.fence.current, &hq->fence); + nouveau_fence_ref(nvc0->base.fence, &hq->fence); } static bool @@ -319,7 +319,7 @@ nvc0_hw_get_query_result(struct nvc0_con return hq->funcs->get_query_result(nvc0, hq, wait, result); if (hq->state != NVC0_HW_QUERY_STATE_READY) - nvc0_hw_query_update(nvc0->screen->base.client, q); + nvc0_hw_query_update(nvc0->base.client, q); if (hq->state != NVC0_HW_QUERY_STATE_READY) { if (!wait) { @@ -330,7 +330,7 @@ nvc0_hw_get_query_result(struct nvc0_con } return false; } - if (nouveau_bo_wait(hq->bo, NOUVEAU_BO_RD, nvc0->screen->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); } @@ -403,7 +403,7 @@ nvc0_hw_get_query_result_resource(struct if (index == -1) { /* TODO: Use a macro to write the availability of the query */ if (hq->state != NVC0_HW_QUERY_STATE_READY) - nvc0_hw_query_update(nvc0->screen->base.client, q); + nvc0_hw_query_update(nvc0->base.client, q); uint32_t ready[2] = {hq->state == NVC0_HW_QUERY_STATE_READY}; nvc0->base.push_cb(&nvc0->base, buf, offset, result_type >= PIPE_QUERY_TYPE_I64 ? 2 : 1, @@ -412,7 +412,7 @@ nvc0_hw_get_query_result_resource(struct 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; } @@ -420,7 +420,7 @@ nvc0_hw_get_query_result_resource(struct /* 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, @@ -430,12 +430,12 @@ nvc0_hw_get_query_result_resource(struct * outputs the difference (no need to worry about 64-bit clamping). */ if (hq->state != NVC0_HW_QUERY_STATE_READY) - nvc0_hw_query_update(nvc0->screen->base.client, q); + nvc0_hw_query_update(nvc0->base.client, q); if (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); @@ -511,7 +511,7 @@ nvc0_hw_get_query_result_resource(struct 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 = { @@ -642,7 +642,7 @@ nvc0_hw_query_fifo_wait(struct nvc0_cont 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); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw_sm.c 2022-02-11 15:31:39.237707036 -0600 @@ -2636,7 +2636,7 @@ nvc0_hw_sm_query_read_data(uint32_t coun 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 coun 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c 2022-02-11 16:20:30.965275088 -0600 @@ -701,8 +701,6 @@ nvc0_screen_destroy(struct pipe_screen * if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); - if (screen->base.pushbuf) screen->base.pushbuf->user_priv = NULL; @@ -733,6 +731,7 @@ nvc0_screen_destroy(struct pipe_screen * nouveau_object_del(&screen->nvsw); nouveau_screen_fini(&screen->base); + simple_mtx_destroy(&screen->state_lock); FREE(screen); } @@ -1058,6 +1057,8 @@ nvc0_screen_create(struct nouveau_device return NULL; 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) @@ -1109,7 +1110,7 @@ nvc0_screen_create(struct nouveau_device 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; @@ -1558,8 +1559,6 @@ nvc0_screen_create(struct nouveau_device if (!nvc0_blitter_create(screen)) goto fail; - nouveau_fence_new(&screen->base, &screen->base.fence.current); - return &screen->base; fail: diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h 2022-02-11 16:21:46.650277251 -0600 @@ -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; @@ -157,32 +158,6 @@ int nvc0_screen_resize_text_area(struct // 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c 2022-02-11 16:24:08.657161261 -0600 @@ -71,6 +71,7 @@ nvc0_program_sp_start_id(struct nvc0_con { 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 *n } } } + + simple_mtx_assert_locked(&nvc0->screen->state_lock); nvc0->state.tfb = tfb; if (!(nvc0->dirty_3d & NVC0_NEW_3D_TFB_TARGETS)) @@ -364,7 +367,7 @@ nvc0_tfb_validate(struct nvc0_context *n 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_state.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_state.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_state.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_state.c 2022-02-11 16:25:08.106073895 -0600 @@ -635,9 +635,12 @@ nvc0_sp_state_create(struct pipe_context 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c 2022-02-11 16:26:48.061884623 -0600 @@ -253,7 +253,7 @@ nvc0_validate_fb(struct nvc0_context *nv 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); } @@ -871,6 +871,7 @@ nvc0_switch_pipe_context(struct nvc0_con 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 @@ -967,6 +968,8 @@ nvc0_state_validate(struct nvc0_context int ret; unsigned i; + simple_mtx_assert_locked(&nvc0->screen->state_lock); + if (nvc0->screen->cur_ctx != nvc0) nvc0_switch_pipe_context(nvc0); @@ -985,7 +988,7 @@ nvc0_state_validate(struct nvc0_context } nouveau_pushbuf_bufctx(nvc0->base.pushbuf, bufctx); - ret = nouveau_pushbuf_validate(nvc0->base.pushbuf); + ret = PUSH_VAL(nvc0->base.pushbuf); return !ret; } diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c 2022-02-11 16:33:12.692802344 -0600 @@ -267,7 +267,7 @@ nvc0_resource_copy_region(struct pipe_co 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, @@ -348,7 +348,7 @@ nvc0_clear_render_target(struct pipe_con 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) @@ -379,7 +379,7 @@ nvc0_clear_buffer_push_nvc0(struct 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; @@ -410,7 +410,7 @@ nvc0_clear_buffer_push_nvc0(struct 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); } @@ -428,7 +428,7 @@ nvc0_clear_buffer_push_nve4(struct 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; @@ -457,7 +457,7 @@ nvc0_clear_buffer_push_nve4(struct 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 *p 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; @@ -700,9 +700,11 @@ nvc0_clear(struct pipe_context *pipe, un 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, un 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,9 @@ nvc0_clear(struct pipe_context *pipe, un PUSH_DATA (push, fb->width << 16); PUSH_DATA (push, fb->height << 16); } + +out: + simple_mtx_unlock(&nvc0->screen->state_lock); } static void @@ -789,8 +794,10 @@ gm200_evaluate_depth_buffer(struct 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); + simple_mtx_unlock(&nvc0->screen->state_lock); } @@ -1327,7 +1334,7 @@ nvc0_blit_3d(struct nvc0_context *nvc0, 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 +1556,7 @@ nvc0_blit_eng2d(struct nvc0_context *nvc 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) { @@ -1589,8 +1596,8 @@ nvc0_blit_eng2d(struct nvc0_context *nvc 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); @@ -1684,6 +1691,7 @@ nvc0_blit(struct pipe_context *pipe, con 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 +1702,7 @@ nvc0_blit(struct pipe_context *pipe, con if (nvc0->screen->num_occlusion_queries_active) IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 1); + simple_mtx_unlock(&nvc0->screen->state_lock); NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_blit_count, 1); } diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c 2022-02-11 16:36:06.082194000 -0600 @@ -32,7 +32,7 @@ nvc0_m2mf_transfer_rect(struct nvc0_cont 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_cont 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_con 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_con 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_con 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_con 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); @@ -362,7 +362,7 @@ nvc0_mt_sync(struct nvc0_context *nvc0, 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); @@ -388,7 +388,7 @@ nvc0_miptree_transfer_map(struct pipe_co 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_co if (usage & PIPE_MAP_WRITE) flags |= NOUVEAU_BO_WR; - ret = nouveau_bo_map(tx->rect[1].bo, flags, nvc0->screen->base.client); + ret = BO_MAP(nvc0->base.screen, tx->rect[1].bo, flags, nvc0->screen->base.client); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); nouveau_bo_ref(NULL, &tx->rect[1].bo); @@ -521,7 +521,7 @@ nvc0_miptree_transfer_unmap(struct pipe_ 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); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c 2022-02-11 16:37:55.523785563 -0600 @@ -462,6 +462,7 @@ nvc0_vertex_arrays_validate(struct 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; @@ -788,7 +789,7 @@ nvc0_draw_stream_output(struct nvc0_cont } 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 +870,7 @@ nvc0_draw_indirect(struct nvc0_context * 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); @@ -1024,6 +1025,8 @@ nvc0_draw_vbo(struct pipe_context *pipe, 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)) { @@ -1131,6 +1134,8 @@ nvc0_draw_vbo(struct pipe_context *pipe, } cleanup: + simple_mtx_unlock(&nvc0->screen->state_lock); + push->kick_notify = nvc0_default_kick_notify; nvc0_release_user_vbufs(nvc0); diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c 2022-02-11 16:38:16.159706821 -0600 @@ -239,7 +239,7 @@ nvc0_push_setup_vertex_array(struct nvc0 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_ 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) { diff -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_bsp.c 2022-02-11 16:42:26.561716987 -0600 @@ -34,10 +34,11 @@ static void dump_comm_bsp(struct comm *c 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 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 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 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; @@ -160,7 +162,7 @@ nvc0_decoder_bsp_end(struct nouveau_vp3_ 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video.c 2022-02-11 18:09:21.787821149 -0600 @@ -91,7 +91,8 @@ struct pipe_video_codec * nvc0_create_decoder(struct pipe_context *context, const struct pipe_video_codec *templ) { - struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base; + struct nvc0_context *nvc0 = nvc0_context(context); + struct nouveau_screen *screen = &nvc0->screen->base; struct nouveau_vp3_decoder *dec; struct nouveau_pushbuf **push; union nouveau_bo_config cfg; @@ -116,7 +117,7 @@ nvc0_create_decoder(struct pipe_context dec = CALLOC_STRUCT(nouveau_vp3_decoder); if (!dec) return NULL; - dec->client = screen->client; + dec->client = nvc0->base.client; dec->base = *templ; nouveau_vp3_decoder_init_common(&dec->base); @@ -160,7 +161,7 @@ nvc0_create_decoder(struct pipe_context data, size, &dec->channel[i]); if (!ret) - ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4, + ret = nouveau_pushbuf_new(nvc0->base.client, dec->channel[i], 4, 32 * 1024, true, &dec->pushbuf[i]); if (ret) break; @@ -292,13 +293,13 @@ nvc0_create_decoder(struct pipe_context if (ret) goto fail; - nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); + BO_MAP(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))); /* 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); @@ -309,7 +310,7 @@ nvc0_create_decoder(struct pipe_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)); @@ -320,7 +321,7 @@ nvc0_create_decoder(struct pipe_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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_ppp.c 2022-02-11 16:42:38.048670313 -0600 @@ -94,7 +94,7 @@ nvc0_decoder_ppp(struct nouveau_vp3_deco 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c 2022-02-11 16:43:16.978511453 -0600 @@ -44,7 +44,7 @@ static void dump_comm_vp(struct nouveau_ 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(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) { @@ -111,7 +111,7 @@ nvc0_decoder_vp(struct nouveau_vp3_decod 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 -Naurp mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nve4_compute.c mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nve4_compute.c --- mesa-21.3.6.orig/src/gallium/drivers/nouveau/nvc0/nve4_compute.c 2022-02-09 14:10:39.000000000 -0600 +++ mesa-21.3.6/src/gallium/drivers/nouveau/nvc0/nve4_compute.c 2022-02-11 16:44:39.346172201 -0600 @@ -545,7 +545,7 @@ nve4_compute_upload_input(struct nvc0_co 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 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)); @@ -867,9 +867,10 @@ nve4_launch_grid(struct pipe_context *pi 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); @@ -923,7 +924,7 @@ nve4_launch_grid(struct pipe_context *pi } /* 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); @@ -934,6 +935,9 @@ nve4_launch_grid(struct pipe_context *pi nvc0_update_compute_invocations_counter(nvc0, info); +out_unlock: + simple_mtx_unlock(&screen->state_lock); + out: if (ret) NOUVEAU_ERR("Failed to launch grid !\n"); @@ -1031,7 +1035,7 @@ nve4_compute_trap_info(struct nvc0_conte volatile struct nve4_mp_trap_info *info; uint8_t *map; - ret = nouveau_bo_map(bo, NOUVEAU_BO_RDWR, nvc0->base.client); + ret = BO_MAP(bo, NOUVEAU_BO_RDWR, nvc0->base.client); if (ret) return; map = (uint8_t *)bo->map;