From 48a45ec24ae74c00d1487552e94d9f824a428f58 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Tue, 8 Jan 2013 16:13:11 +0100 Subject: nouveau: improve buffer transfers Save double memcpy on uploads to VRAM in most cases. Properly handle FLUSH_EXPLICIT. Reallocate on DISCARD_WHOLE_RESOURCE to avoid sync. --- src/gallium/drivers/nv50/nv50_context.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'src/gallium/drivers/nv50/nv50_context.c') diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 08e576a214e..b8b29a3b5d7 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -42,6 +42,8 @@ nv50_flush(struct pipe_context *pipe, nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); PUSH_KICK(screen->pushbuf); + + nouveau_context_update_frame_stats(nouveau_context(pipe)); } static void @@ -115,6 +117,83 @@ nv50_destroy(struct pipe_context *pipe) nouveau_context_destroy(&nv50->base); } +static int +nv50_invalidate_resource_storage(struct nouveau_context *ctx, + struct pipe_resource *res, + int ref) +{ + struct nv50_context *nv50 = nv50_context(&ctx->pipe); + unsigned s, i; + + if (res->bind & PIPE_BIND_RENDER_TARGET) { + for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) { + if (nv50->framebuffer.cbufs[i] && + nv50->framebuffer.cbufs[i]->texture == res) { + nv50->dirty |= NV50_NEW_FRAMEBUFFER; + nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB); + if (!--ref) + return ref; + } + } + } + if (res->bind & PIPE_BIND_DEPTH_STENCIL) { + if (nv50->framebuffer.zsbuf && + nv50->framebuffer.zsbuf->texture == res) { + nv50->dirty |= NV50_NEW_FRAMEBUFFER; + nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB); + if (!--ref) + return ref; + } + } + + if (res->bind & PIPE_BIND_VERTEX_BUFFER) { + for (i = 0; i < nv50->num_vtxbufs; ++i) { + if (nv50->vtxbuf[i].buffer == res) { + nv50->dirty |= NV50_NEW_ARRAYS; + nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX); + if (!--ref) + return ref; + } + } + } + if (res->bind & PIPE_BIND_INDEX_BUFFER) { + if (nv50->idxbuf.buffer == res) + if (!--ref) + return ref; + } + + if (res->bind & PIPE_BIND_SAMPLER_VIEW) { + for (s = 0; s < 5; ++s) { + for (i = 0; i < nv50->num_textures[s]; ++i) { + if (nv50->textures[s][i] && + nv50->textures[s][i]->texture == res) { + nv50->dirty |= NV50_NEW_TEXTURES; + nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES); + if (!--ref) + return ref; + } + } + } + } + + if (res->bind & PIPE_BIND_CONSTANT_BUFFER) { + for (s = 0; s < 5; ++s) { + for (i = 0; i < nv50->num_vtxbufs; ++i) { + if (!nv50->constbuf[s][i].user && + nv50->constbuf[s][i].u.buf == res) { + nv50->dirty |= NV50_NEW_CONSTBUF; + nv50->constbuf_dirty[s] |= 1 << i; + nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i)); + if (!--ref) + return ref; + } + } + } + } + + return ref; +} + struct pipe_context * nv50_create(struct pipe_screen *pscreen, void *priv) { @@ -133,6 +212,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv) goto out_err; nv50->base.pushbuf = screen->base.pushbuf; + nv50->base.client = screen->base.client; ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT, &nv50->bufctx_3d); @@ -168,6 +248,8 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50_init_state_functions(nv50); nv50_init_resource_functions(pipe); + nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage; + #ifdef NV50_WITH_DRAW_MODULE /* no software fallbacks implemented */ nv50->draw = draw_create(pipe); -- cgit v1.2.3