nv50: remove vtxbuf stateobject after a referenced vtxbuf is mapped
- This avoids problematic "reloc'ed while mapped" messages and some associated corruption as well. Signed-off-by: Maarten Maathuis <madman2003@gmail.com>
This commit is contained in:
parent
3e18bad36d
commit
c306ef5e81
|
@ -127,8 +127,18 @@ nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
|
||||||
unsigned usage)
|
unsigned usage)
|
||||||
{
|
{
|
||||||
struct nouveau_bo *bo = nouveau_bo(pb);
|
struct nouveau_bo *bo = nouveau_bo(pb);
|
||||||
|
struct nouveau_screen *nscreen = nouveau_screen(pscreen);
|
||||||
int ret;
|
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));
|
ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug_printf("map failed: %d\n", 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)
|
unsigned offset, unsigned length, unsigned usage)
|
||||||
{
|
{
|
||||||
struct nouveau_bo *bo = nouveau_bo(pb);
|
struct nouveau_bo *bo = nouveau_bo(pb);
|
||||||
|
struct nouveau_screen *nscreen = nouveau_screen(pscreen);
|
||||||
uint32_t flags = nouveau_screen_map_flags(usage);
|
uint32_t flags = nouveau_screen_map_flags(usage);
|
||||||
int ret;
|
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);
|
ret = nouveau_bo_map_range(bo, offset, length, flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
nouveau_bo_unmap(bo);
|
||||||
if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
|
if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
|
||||||
debug_printf("map_range failed: %d\n", ret);
|
debug_printf("map_range failed: %d\n", ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -5,6 +5,9 @@ struct nouveau_screen {
|
||||||
struct pipe_screen base;
|
struct pipe_screen base;
|
||||||
struct nouveau_device *device;
|
struct nouveau_device *device;
|
||||||
struct nouveau_channel *channel;
|
struct nouveau_channel *channel;
|
||||||
|
|
||||||
|
int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen,
|
||||||
|
struct pipe_buffer *pb, unsigned usage);
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct nouveau_screen *
|
static inline struct nouveau_screen *
|
||||||
|
|
|
@ -98,6 +98,19 @@ so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
|
||||||
so_data(so, data);
|
so_data(so, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if this buffer object is referenced by this state object. */
|
||||||
|
static INLINE boolean
|
||||||
|
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
|
static INLINE void
|
||||||
so_dump(struct nouveau_stateobj *so)
|
so_dump(struct nouveau_stateobj *so)
|
||||||
{
|
{
|
||||||
|
|
|
@ -189,6 +189,28 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
|
||||||
FREE(screen);
|
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 *
|
struct pipe_screen *
|
||||||
nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
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_param = nv50_screen_get_param;
|
||||||
pscreen->get_paramf = nv50_screen_get_paramf;
|
pscreen->get_paramf = nv50_screen_get_paramf;
|
||||||
pscreen->is_format_supported = nv50_screen_is_format_supported;
|
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_screen_init_miptree_functions(pscreen);
|
||||||
nv50_transfer_init_screen_functions(pscreen);
|
nv50_transfer_init_screen_functions(pscreen);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __NV50_SCREEN_H__
|
#define __NV50_SCREEN_H__
|
||||||
|
|
||||||
#include "nouveau/nouveau_screen.h"
|
#include "nouveau/nouveau_screen.h"
|
||||||
|
#include "nv50_context.h"
|
||||||
|
|
||||||
struct nv50_screen {
|
struct nv50_screen {
|
||||||
struct nouveau_screen base;
|
struct nouveau_screen base;
|
||||||
|
@ -9,6 +10,7 @@ struct nv50_screen {
|
||||||
struct nouveau_winsys *nvws;
|
struct nouveau_winsys *nvws;
|
||||||
|
|
||||||
unsigned cur_pctx;
|
unsigned cur_pctx;
|
||||||
|
struct nv50_context *cur_ctx;
|
||||||
|
|
||||||
struct nouveau_grobj *tesla;
|
struct nouveau_grobj *tesla;
|
||||||
struct nouveau_grobj *eng2d;
|
struct nouveau_grobj *eng2d;
|
||||||
|
|
|
@ -185,6 +185,9 @@ nv50_state_emit(struct nv50_context *nv50)
|
||||||
struct nv50_screen *screen = nv50->screen;
|
struct nv50_screen *screen = nv50->screen;
|
||||||
struct nouveau_channel *chan = screen->base.channel;
|
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->pctx_id != screen->cur_pctx) {
|
||||||
if (nv50->state.fb)
|
if (nv50->state.fb)
|
||||||
nv50->state.dirty |= NV50_NEW_FRAMEBUFFER;
|
nv50->state.dirty |= NV50_NEW_FRAMEBUFFER;
|
||||||
|
|
Loading…
Reference in New Issue