[Nouveau] [PATCH 1/3] nv50: remove vtxbuf stateobject after a referenced vtxbuf is mapped
Maarten Maathuis
madman2003 at gmail.com
Wed Dec 30 13:37:46 PST 2009
Same patch from before, without the debatable unmap change.
On Wed, Dec 30, 2009 at 10:36 PM, Maarten Maathuis <madman2003 at gmail.com> wrote:
> - This avoids problematic "reloc'ed while mapped" messages and
> some associated corruption as well.
>
> Signed-off-by: Maarten Maathuis <madman2003 at gmail.com>
> ---
> src/gallium/drivers/nouveau/nouveau_screen.c | 21 +++++++++++++++++++++
> src/gallium/drivers/nouveau/nouveau_screen.h | 3 +++
> src/gallium/drivers/nouveau/nouveau_stateobj.h | 13 +++++++++++++
> src/gallium/drivers/nv50/nv50_screen.c | 23 +++++++++++++++++++++++
> src/gallium/drivers/nv50/nv50_screen.h | 2 ++
> src/gallium/drivers/nv50/nv50_state_validate.c | 3 +++
> 6 files changed, 65 insertions(+), 0 deletions(-)
>
> diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
> index 0437af3..7ebc94e 100644
> --- a/src/gallium/drivers/nouveau/nouveau_screen.c
> +++ b/src/gallium/drivers/nouveau/nouveau_screen.c
> @@ -127,8 +127,18 @@ nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
> unsigned usage)
> {
> struct nouveau_bo *bo = nouveau_bo(pb);
> + struct nouveau_screen *nscreen = nouveau_screen(pscreen);
> int ret;
>
> + if (nscreen->pre_pipebuffer_map_callback) {
> + ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
> + if (ret) {
> + debug_printf("pre_pipebuffer_map_callback failed %d\n",
> + ret);
> + return NULL;
> + }
> + }
> +
> ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
> if (ret) {
> debug_printf("map failed: %d\n", ret);
> @@ -143,11 +153,22 @@ nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb,
> unsigned offset, unsigned length, unsigned usage)
> {
> struct nouveau_bo *bo = nouveau_bo(pb);
> + struct nouveau_screen *nscreen = nouveau_screen(pscreen);
> uint32_t flags = nouveau_screen_map_flags(usage);
> int ret;
>
> + if (nscreen->pre_pipebuffer_map_callback) {
> + ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
> + if (ret) {
> + debug_printf("pre_pipebuffer_map_callback failed %d\n",
> + ret);
> + return NULL;
> + }
> + }
> +
> ret = nouveau_bo_map_range(bo, offset, length, flags);
> if (ret) {
> + nouveau_bo_unmap(bo);
> if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
> debug_printf("map_range failed: %d\n", ret);
> return NULL;
> diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
> index ebfc67a..a7927d8 100644
> --- a/src/gallium/drivers/nouveau/nouveau_screen.h
> +++ b/src/gallium/drivers/nouveau/nouveau_screen.h
> @@ -5,6 +5,9 @@ struct nouveau_screen {
> struct pipe_screen base;
> struct nouveau_device *device;
> struct nouveau_channel *channel;
> +
> + int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen,
> + struct pipe_buffer *pb, unsigned usage);
> };
>
> static inline struct nouveau_screen *
> diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
> index 9aee9e4..b8c83db 100644
> --- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
> +++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
> @@ -98,6 +98,19 @@ so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
> so_data(so, data);
> }
>
> +/* Determine if this buffer object is referenced by this state object. */
> +static INLINE bool
> +so_bo_is_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo)
> +{
> + int i;
> +
> + for (i = 0; i < so->cur_reloc; i++)
> + if (so->reloc[i].bo == bo)
> + return true;
> +
> + return false;
> +}
> +
> static INLINE void
> so_dump(struct nouveau_stateobj *so)
> {
> diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
> index 7e039ea..1778a74 100644
> --- a/src/gallium/drivers/nv50/nv50_screen.c
> +++ b/src/gallium/drivers/nv50/nv50_screen.c
> @@ -189,6 +189,28 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
> FREE(screen);
> }
>
> +static int
> +nv50_pre_pipebuffer_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
> + unsigned usage)
> +{
> + struct nv50_screen *screen = nv50_screen(pscreen);
> + struct nv50_context *ctx = screen->cur_ctx;
> +
> + if (!(pb->usage & PIPE_BUFFER_USAGE_VERTEX))
> + return 0;
> +
> + /* Our vtxbuf got mapped, it can no longer be considered part of current
> + * state, remove it to avoid emitting reloc markers.
> + */
> + if (ctx && ctx->state.vtxbuf && so_bo_is_reloc(ctx->state.vtxbuf,
> + nouveau_bo(pb))) {
> + so_ref(NULL, &ctx->state.vtxbuf);
> + ctx->dirty |= NV50_NEW_ARRAYS;
> + }
> +
> + return 0;
> +}
> +
> struct pipe_screen *
> nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
> {
> @@ -216,6 +238,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
> pscreen->get_param = nv50_screen_get_param;
> pscreen->get_paramf = nv50_screen_get_paramf;
> pscreen->is_format_supported = nv50_screen_is_format_supported;
> + screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map;
>
> nv50_screen_init_miptree_functions(pscreen);
> nv50_transfer_init_screen_functions(pscreen);
> diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
> index 61e24a5..a038a4e 100644
> --- a/src/gallium/drivers/nv50/nv50_screen.h
> +++ b/src/gallium/drivers/nv50/nv50_screen.h
> @@ -2,6 +2,7 @@
> #define __NV50_SCREEN_H__
>
> #include "nouveau/nouveau_screen.h"
> +#include "nv50_context.h"
>
> struct nv50_screen {
> struct nouveau_screen base;
> @@ -9,6 +10,7 @@ struct nv50_screen {
> struct nouveau_winsys *nvws;
>
> unsigned cur_pctx;
> + struct nv50_context *cur_ctx;
>
> struct nouveau_grobj *tesla;
> struct nouveau_grobj *eng2d;
> diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
> index c8bdf9d..6827863 100644
> --- a/src/gallium/drivers/nv50/nv50_state_validate.c
> +++ b/src/gallium/drivers/nv50/nv50_state_validate.c
> @@ -185,6 +185,9 @@ nv50_state_emit(struct nv50_context *nv50)
> struct nv50_screen *screen = nv50->screen;
> struct nouveau_channel *chan = screen->base.channel;
>
> + /* I don't want to copy headers from the winsys. */
> + screen->cur_ctx = nv50;
> +
> if (nv50->pctx_id != screen->cur_pctx) {
> if (nv50->state.fb)
> nv50->state.dirty |= NV50_NEW_FRAMEBUFFER;
> --
> 1.6.6.rc4
>
>
More information about the Nouveau
mailing list