mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 13:48:06 +02:00
nouveau: make sure there's always room to emit a fence
I started seeing a lot of situations on nv30 where fence emission wouldn't fit into the previous buffer (causing assertions). This ensures that whenever checking for space, we always leave a bit of extra room for the fence emission commands. Adjusts the nv30 and nvc0 fence emission logic to bypass the space checking as well. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Cc: mesa-stable@lists.freedesktop.org Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> (cherry picked from commit47d11990b2) Squashed with commit nouveau: avoid emitting new fences unnecessarily Right now we emit on every kick, but this is only necessary if something will ever be able to observe that the fence completed. If there are no refs, leave the fence alone and emit it another day. This also happens to work around an issue for the kick handler -- a kick can be a result of e.g. nouveau_bo_wait or explicit kick, or it can be due to lack of space in the pushbuf. We want the emit to happen in the current batch, so we want there to always be enough space. However an explicit kick could take the reserved space for the implicitly-triggered kick's fence emission if it happened right after. With the new mechanism, hopefully there's no way to cause two fences to be emitted into the same reserved space. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Fixes:47d11990b(nouveau: make sure there's always room to emit a fence) Cc: mesa-stable@lists.freedesktop.org (cherry picked from commit8053c9208f) Squashed with commit nv50,nvc0: don't base decisions on available pushbuf space We still have to push everything out, might as well kick earlier and flip pushbufs when we know we'll need it. This resolves some issues with the new policy of making sure that we always leave a bit of room at the end for fences. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Fixes:47d11990b(nouveau: make sure there's always room to emit a fence) Cc: mesa-stable@lists.freedesktop.org (cherry picked from commit9fe458335f) Squashed with commit nouveau: avoid double-emitting fence The act of ensuring that there is space can cause a flush to happen, which will emit the current screen fence. If that is the fence we're trying to wait on, then it will have been emitted as a result of doing the PUSH_SPACE. Don't attempt to emit it a second time. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Fixes:8053c9208f(nouveau: avoid emitting new fences unnecessarily) Cc: mesa-stable@lists.freedesktop.org (cherry picked from commitbf97f8d467)
This commit is contained in:
parent
b4bfea0094
commit
3f802ebaf8
8 changed files with 32 additions and 41 deletions
|
|
@ -190,8 +190,14 @@ nouveau_fence_wait(struct nouveau_fence *fence)
|
|||
/* 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)
|
||||
nouveau_fence_emit(fence);
|
||||
if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
|
||||
PUSH_SPACE(screen->pushbuf, 8);
|
||||
/* The space allocation might trigger a flush, which could emit the
|
||||
* current fence. So check again.
|
||||
*/
|
||||
if (fence->state < NOUVEAU_FENCE_STATE_EMITTED)
|
||||
nouveau_fence_emit(fence);
|
||||
}
|
||||
|
||||
if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED)
|
||||
if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
|
||||
|
|
@ -224,8 +230,12 @@ nouveau_fence_wait(struct nouveau_fence *fence)
|
|||
void
|
||||
nouveau_fence_next(struct nouveau_screen *screen)
|
||||
{
|
||||
if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING)
|
||||
nouveau_fence_emit(screen->fence.current);
|
||||
if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING) {
|
||||
if (screen->fence.current->ref > 1)
|
||||
nouveau_fence_emit(screen->fence.current);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
nouveau_fence_ref(NULL, &screen->fence.current);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ PUSH_AVAIL(struct nouveau_pushbuf *push)
|
|||
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 true;
|
||||
|
|
|
|||
|
|
@ -345,7 +345,9 @@ nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence)
|
|||
|
||||
*sequence = ++screen->base.fence.sequence;
|
||||
|
||||
BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2);
|
||||
assert(PUSH_AVAIL(push) >= 3);
|
||||
PUSH_DATA (push, NV30_3D_FENCE_OFFSET |
|
||||
(2 /* size */ << 18) | (7 /* subchan */ << 13));
|
||||
PUSH_DATA (push, 0);
|
||||
PUSH_DATA (push, *sequence);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,6 +386,7 @@ nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
|
|||
/* we need to do it after possible flush in MARK_RING */
|
||||
*sequence = ++screen->base.fence.sequence;
|
||||
|
||||
assert(PUSH_AVAIL(push) >= 5);
|
||||
PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4));
|
||||
PUSH_DATAh(push, screen->fence.bo->offset);
|
||||
PUSH_DATA (push, screen->fence.bo->offset);
|
||||
|
|
|
|||
|
|
@ -65,14 +65,9 @@ nv50_constbufs_validate(struct nv50_context *nv50)
|
|||
PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
|
||||
}
|
||||
while (words) {
|
||||
unsigned nr;
|
||||
|
||||
if (!PUSH_SPACE(push, 16))
|
||||
break;
|
||||
nr = PUSH_AVAIL(push);
|
||||
assert(nr >= 16);
|
||||
nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);
|
||||
unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
PUSH_SPACE(push, nr + 3);
|
||||
BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
|
||||
PUSH_DATA (push, (start << 8) | b);
|
||||
BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
|
||||
|
|
|
|||
|
|
@ -187,14 +187,7 @@ nv50_sifc_linear_u8(struct nouveau_context *nv,
|
|||
PUSH_DATA (push, 0);
|
||||
|
||||
while (count) {
|
||||
unsigned nr;
|
||||
|
||||
if (!PUSH_SPACE(push, 16))
|
||||
break;
|
||||
nr = PUSH_AVAIL(push);
|
||||
assert(nr >= 16);
|
||||
nr = MIN2(count, nr - 1);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);
|
||||
PUSH_DATAp(push, src, nr);
|
||||
|
|
@ -395,12 +388,9 @@ nv50_cb_push(struct nouveau_context *nv,
|
|||
nouveau_pushbuf_validate(push);
|
||||
|
||||
while (words) {
|
||||
unsigned nr;
|
||||
|
||||
nr = PUSH_AVAIL(push);
|
||||
nr = MIN2(nr - 7, words);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
|
||||
unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
PUSH_SPACE(push, nr + 7);
|
||||
BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
|
||||
PUSH_DATAh(push, bo->offset + base);
|
||||
PUSH_DATA (push, bo->offset + base);
|
||||
|
|
|
|||
|
|
@ -535,7 +535,8 @@ nvc0_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
|
|||
/* we need to do it after possible flush in MARK_RING */
|
||||
*sequence = ++screen->base.fence.sequence;
|
||||
|
||||
BEGIN_NVC0(push, NVC0_3D(QUERY_ADDRESS_HIGH), 4);
|
||||
assert(PUSH_AVAIL(push) >= 5);
|
||||
PUSH_DATA (push, NVC0_FIFO_PKHDR_SQ(NVC0_3D(QUERY_ADDRESS_HIGH), 4));
|
||||
PUSH_DATAh(push, screen->fence.bo->offset);
|
||||
PUSH_DATA (push, screen->fence.bo->offset);
|
||||
PUSH_DATA (push, *sequence);
|
||||
|
|
|
|||
|
|
@ -188,14 +188,10 @@ nvc0_m2mf_push_linear(struct nouveau_context *nv,
|
|||
nouveau_pushbuf_validate(push);
|
||||
|
||||
while (count) {
|
||||
unsigned nr;
|
||||
unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
if (!PUSH_SPACE(push, 16))
|
||||
if (!PUSH_SPACE(push, nr + 9))
|
||||
break;
|
||||
nr = PUSH_AVAIL(push);
|
||||
assert(nr >= 16);
|
||||
nr = MIN2(count, nr - 9);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
|
||||
|
||||
BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);
|
||||
PUSH_DATAh(push, dst->offset + offset);
|
||||
|
|
@ -234,14 +230,10 @@ nve4_p2mf_push_linear(struct nouveau_context *nv,
|
|||
nouveau_pushbuf_validate(push);
|
||||
|
||||
while (count) {
|
||||
unsigned nr;
|
||||
unsigned nr = MIN2(count, (NV04_PFIFO_MAX_PACKET_LEN - 1));
|
||||
|
||||
if (!PUSH_SPACE(push, 16))
|
||||
if (!PUSH_SPACE(push, nr + 10))
|
||||
break;
|
||||
nr = PUSH_AVAIL(push);
|
||||
assert(nr >= 16);
|
||||
nr = MIN2(count, nr - 8);
|
||||
nr = MIN2(nr, (NV04_PFIFO_MAX_PACKET_LEN - 1));
|
||||
|
||||
BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2);
|
||||
PUSH_DATAh(push, dst->offset + offset);
|
||||
|
|
@ -571,9 +563,7 @@ nvc0_cb_bo_push(struct nouveau_context *nv,
|
|||
PUSH_DATA (push, bo->offset + base);
|
||||
|
||||
while (words) {
|
||||
unsigned nr = PUSH_AVAIL(push);
|
||||
nr = MIN2(nr, words);
|
||||
nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
|
||||
unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN - 1);
|
||||
|
||||
PUSH_SPACE(push, nr + 2);
|
||||
PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue