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/nv50 | |
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/nv50')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.c | 82 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_screen.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_screen.h | 3 |
3 files changed, 85 insertions, 2 deletions
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); diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index fb0d94b5b01..b6e53f6fdea 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -176,7 +176,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 256; case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: - return 64; + return NOUVEAU_MIN_BUFFER_MAP_ALIGN; case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 8784f36d417..2e8af436e36 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -98,7 +98,8 @@ nv50_resource_validate(struct nv04_resource *res, uint32_t flags) { if (likely(res->bo)) { if (flags & NOUVEAU_BO_WR) - res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | + NOUVEAU_BUFFER_STATUS_DIRTY; if (flags & NOUVEAU_BO_RD) res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; |