diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c index 2b39c2592e0..b133997641a 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c @@ -1373,6 +1373,16 @@ nv50_blit_3d(struct nv50_context *nv50, const struct pipe_blit_info *info) nv50_state_validate_3d(nv50, ~0); + /* When flipping a surface from zeta <-> color "mode", we have to wait for + * the GPU to flush its current draws. + */ + struct nv50_miptree *mt = nv50_miptree(dst); + bool serialize = util_format_is_depth_or_stencil(info->dst.format); + if (serialize && mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { + BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1); + PUSH_DATA (push, 0); + } + x_range = (float)info->src.box.width / (float)info->dst.box.width; y_range = (float)info->src.box.height / (float)info->dst.box.height; @@ -1475,6 +1485,12 @@ nv50_blit_3d(struct nv50_context *nv50, const struct pipe_blit_info *info) BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1); PUSH_DATA (push, 1); + /* mark the surface as reading, which will force a serialize next time it's + * used for writing. + */ + if (serialize) + mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + nv50_blitctx_post_blit(blit); } diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c index 725e391d4f7..e0b81b679a2 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c @@ -1239,9 +1239,19 @@ nvc0_blit_3d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) } } + bool serialize = false; + struct nv50_miptree *mt = nv50_miptree(dst); if (screen->eng3d->oclass >= TU102_3D_CLASS) { IMMED_NVC0(push, SUBC_3D(TU102_3D_SET_COLOR_RENDER_TO_ZETA_SURFACE), util_format_is_depth_or_stencil(info->dst.format)); + } else { + /* When flipping a surface from zeta <-> color "mode", we have to wait for + * the GPU to flush its current draws. + */ + serialize = util_format_is_depth_or_stencil(info->dst.format); + if (serialize && mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { + IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); + } } IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 0); @@ -1386,6 +1396,11 @@ nvc0_blit_3d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1); if (screen->eng3d->oclass >= TU102_3D_CLASS) IMMED_NVC0(push, SUBC_3D(TU102_3D_SET_COLOR_RENDER_TO_ZETA_SURFACE), 0); + else if (serialize) + /* mark the surface as reading, which will force a serialize next time + * it's used for writing. + */ + mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_READING; } static void