diff options
author | Christoph Bumiller <[email protected]> | 2013-01-08 16:13:11 +0100 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2013-01-08 16:13:51 +0100 |
commit | 48a45ec24ae74c00d1487552e94d9f824a428f58 (patch) | |
tree | c2a160cb708b7a05f3340d889d6a0e676eb9d727 /src/gallium/drivers/nvc0/nvc0_context.c | |
parent | a75ddfd55d24363046f11b2fd2de25563698fa39 (diff) |
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.
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_context.c')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_context.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c index 6325ac859f4..23059a097b9 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nvc0/nvc0_context.c @@ -43,6 +43,8 @@ nvc0_flush(struct pipe_context *pipe, nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */ + + nouveau_context_update_frame_stats(&nvc0->base); } static void @@ -116,6 +118,87 @@ nvc0_default_kick_notify(struct nouveau_pushbuf *push) } } +static int +nvc0_invalidate_resource_storage(struct nouveau_context *ctx, + struct pipe_resource *res, + int ref) +{ + struct nvc0_context *nvc0 = nvc0_context(&ctx->pipe); + unsigned s, i; + + if (res->bind & PIPE_BIND_RENDER_TARGET) { + for (i = 0; i < nvc0->framebuffer.nr_cbufs; ++i) { + if (nvc0->framebuffer.cbufs[i] && + nvc0->framebuffer.cbufs[i]->texture == res) { + nvc0->dirty |= NVC0_NEW_FRAMEBUFFER; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB); + if (!--ref) + return ref; + } + } + } + if (res->bind & PIPE_BIND_DEPTH_STENCIL) { + if (nvc0->framebuffer.zsbuf && + nvc0->framebuffer.zsbuf->texture == res) { + nvc0->dirty |= NVC0_NEW_FRAMEBUFFER; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB); + if (!--ref) + return ref; + } + } + + if (res->bind & PIPE_BIND_VERTEX_BUFFER) { + for (i = 0; i < nvc0->num_vtxbufs; ++i) { + if (nvc0->vtxbuf[i].buffer == res) { + nvc0->dirty |= NVC0_NEW_ARRAYS; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX); + if (!--ref) + return ref; + } + } + } + if (res->bind & PIPE_BIND_INDEX_BUFFER) { + if (nvc0->idxbuf.buffer == res) { + nvc0->dirty |= NVC0_NEW_IDXBUF; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_IDX); + if (!--ref) + return ref; + } + } + + if (res->bind & PIPE_BIND_SAMPLER_VIEW) { + for (s = 0; s < 5; ++s) { + for (i = 0; i < nvc0->num_textures[s]; ++i) { + if (nvc0->textures[s][i] && + nvc0->textures[s][i]->texture == res) { + nvc0->textures_dirty[s] |= 1 << i; + nvc0->dirty |= NVC0_NEW_TEXTURES; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i)); + if (!--ref) + return ref; + } + } + } + } + + if (res->bind & PIPE_BIND_CONSTANT_BUFFER) { + for (s = 0; s < 5; ++s) { + for (i = 0; i < nvc0->num_vtxbufs; ++i) { + if (!nvc0->constbuf[s][i].user && + nvc0->constbuf[s][i].u.buf == res) { + nvc0->dirty |= NVC0_NEW_CONSTBUF; + nvc0->constbuf_dirty[s] |= 1 << i; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i)); + if (!--ref) + return ref; + } + } + } + } + + return ref; +} + struct pipe_context * nvc0_create(struct pipe_screen *pscreen, void *priv) { @@ -134,6 +217,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) goto out_err; nvc0->base.pushbuf = screen->base.pushbuf; + nvc0->base.client = screen->base.client; ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_COUNT, &nvc0->bufctx_3d); @@ -168,6 +252,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) nvc0_init_transfer_functions(nvc0); nvc0_init_resource_functions(pipe); + nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage; + #ifdef NVC0_WITH_DRAW_MODULE /* no software fallbacks implemented */ nvc0->draw = draw_create(pipe); |