[Mesa-dev] [PATCH 2/2] gallium: add flag PIPE_TRANSFER_MAP_PERMANENTLY
Marek Olšák
maraeo at gmail.com
Tue Jul 23 05:30:38 PDT 2013
FYI, OpenGL 4.4, which was released yesterday, adds GL_MAP_PERSISTENT
and GL_MAP_COHERENT bits as valid parameters of glMapBufferRange and
glBufferStorage, allowing to use buffers for rendering while they are
mapped and upload/download data to/from the buffers simultaneously.
It's now clear that Gallium will have to support it at some point,
it's only a matter of when. And once we have it, gallium can use it
for faster buffer uploads.
Marek
On Mon, Jan 2, 2012 at 1:22 AM, Marek Olšák <maraeo at gmail.com> wrote:
> Please see the diff for further info.
>
> This paves the way for moving user buffer uploads out of drivers and should
> allow to clean up the mess in u_upload_mgr in the meantime.
>
> For now only allowed for buffers on r300 and r600.
> ---
> src/gallium/drivers/i915/i915_resource_buffer.c | 7 ++++++-
> src/gallium/drivers/i915/i915_resource_texture.c | 7 ++++++-
> src/gallium/drivers/llvmpipe/lp_texture.c | 4 ++++
> src/gallium/drivers/nouveau/nouveau_buffer.c | 8 +++++++-
> src/gallium/drivers/nv50/nv50_transfer.c | 2 +-
> src/gallium/drivers/nvc0/nvc0_transfer.c | 2 +-
> src/gallium/drivers/nvfx/nvfx_transfer.c | 3 +++
> src/gallium/drivers/r300/r300_transfer.c | 4 ++++
> src/gallium/drivers/r600/r600_texture.c | 4 ++++
> src/gallium/drivers/svga/svga_resource_buffer.c | 4 ++++
> src/gallium/drivers/svga/svga_resource_texture.c | 2 +-
> src/gallium/include/pipe/p_defines.h | 16 ++++++++++++++++
> 12 files changed, 57 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c
> index 77c0345..c54e481 100644
> --- a/src/gallium/drivers/i915/i915_resource_buffer.c
> +++ b/src/gallium/drivers/i915/i915_resource_buffer.c
> @@ -68,8 +68,13 @@ i915_get_transfer(struct pipe_context *pipe,
> const struct pipe_box *box)
> {
> struct i915_context *i915 = i915_context(pipe);
> - struct pipe_transfer *transfer = util_slab_alloc(&i915->transfer_pool);
> + struct pipe_transfer *transfer;
>
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> + transfer = util_slab_alloc(&i915->transfer_pool);
> if (transfer == NULL)
> return NULL;
>
> diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c
> index 8ff733a..64d071c 100644
> --- a/src/gallium/drivers/i915/i915_resource_texture.c
> +++ b/src/gallium/drivers/i915/i915_resource_texture.c
> @@ -720,9 +720,14 @@ i915_texture_get_transfer(struct pipe_context *pipe,
> {
> struct i915_context *i915 = i915_context(pipe);
> struct i915_texture *tex = i915_texture(resource);
> - struct i915_transfer *transfer = util_slab_alloc(&i915->texture_transfer_pool);
> + struct i915_transfer *transfer;
> boolean use_staging_texture = FALSE;
>
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> + transfer = util_slab_alloc(&i915->texture_transfer_pool);
> if (transfer == NULL)
> return NULL;
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
> index ca38571..d86d493 100644
> --- a/src/gallium/drivers/llvmpipe/lp_texture.c
> +++ b/src/gallium/drivers/llvmpipe/lp_texture.c
> @@ -587,6 +587,10 @@ llvmpipe_get_transfer(struct pipe_context *pipe,
> assert(resource);
> assert(level <= resource->last_level);
>
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> /*
> * Transfers, like other pipe operations, must happen in order, so flush the
> * context if necessary.
> diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c
> index f822625..02186ba 100644
> --- a/src/gallium/drivers/nouveau/nouveau_buffer.c
> +++ b/src/gallium/drivers/nouveau/nouveau_buffer.c
> @@ -172,7 +172,13 @@ nouveau_buffer_transfer_get(struct pipe_context *pipe,
> {
> struct nv04_resource *buf = nv04_resource(resource);
> struct nouveau_context *nv = nouveau_context(pipe);
> - struct nouveau_transfer *xfr = CALLOC_STRUCT(nouveau_transfer);
> + struct nouveau_transfer *xfr;
> +
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> + xfr = CALLOC_STRUCT(nouveau_transfer);
> if (!xfr)
> return NULL;
>
> diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
> index 6f860e7..8ddebeb 100644
> --- a/src/gallium/drivers/nv50/nv50_transfer.c
> +++ b/src/gallium/drivers/nv50/nv50_transfer.c
> @@ -243,7 +243,7 @@ nv50_miptree_transfer_new(struct pipe_context *pctx,
> uint32_t size;
> int ret;
>
> - if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
> + if (usage & (PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_MAP_PERMANENTLY))
> return NULL;
>
> tx = CALLOC_STRUCT(nv50_transfer);
> diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
> index f168637..c04f41f 100644
> --- a/src/gallium/drivers/nvc0/nvc0_transfer.c
> +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
> @@ -243,7 +243,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
> uint32_t size;
> int ret;
>
> - if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
> + if (usage & (PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_MAP_PERMANENTLY))
> return NULL;
>
> tx = CALLOC_STRUCT(nvc0_transfer);
> diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c
> index 7a218b1..605af8e 100644
> --- a/src/gallium/drivers/nvfx/nvfx_transfer.c
> +++ b/src/gallium/drivers/nvfx/nvfx_transfer.c
> @@ -26,6 +26,9 @@ nvfx_transfer_new(struct pipe_context *pipe,
> unsigned usage,
> const struct pipe_box *box)
> {
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> if((usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DONTBLOCK)) == PIPE_TRANSFER_DONTBLOCK)
> {
> struct nouveau_bo* bo = ((struct nvfx_resource*)pt)->bo;
> diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
> index afdd530..91e861a 100644
> --- a/src/gallium/drivers/r300/r300_transfer.c
> +++ b/src/gallium/drivers/r300/r300_transfer.c
> @@ -89,6 +89,10 @@ r300_texture_get_transfer(struct pipe_context *ctx,
> struct pipe_resource base;
> boolean referenced_cs, referenced_hw;
>
> + if (usage & (PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_MAP_PERMANENTLY)) {
> + return NULL;
> + }
> +
> referenced_cs =
> r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf);
> if (referenced_cs) {
> diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
> index 8fe54c8..decd941 100644
> --- a/src/gallium/drivers/r600/r600_texture.c
> +++ b/src/gallium/drivers/r600/r600_texture.c
> @@ -630,6 +630,10 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
> int r;
> boolean use_staging_texture = FALSE;
>
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> /* We cannot map a tiled texture directly because the data is
> * in a different order, therefore we do detiling using a blit.
> *
> diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
> index fa713ee..57ec752 100644
> --- a/src/gallium/drivers/svga/svga_resource_buffer.c
> +++ b/src/gallium/drivers/svga/svga_resource_buffer.c
> @@ -74,6 +74,10 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
> struct svga_buffer *sbuf = svga_buffer(resource);
> struct pipe_transfer *transfer;
>
> + if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
> + return NULL;
> + }
> +
> transfer = CALLOC_STRUCT(pipe_transfer);
> if (transfer == NULL) {
> return NULL;
> diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
> index 697c1d3..4eb1068 100644
> --- a/src/gallium/drivers/svga/svga_resource_texture.c
> +++ b/src/gallium/drivers/svga/svga_resource_texture.c
> @@ -259,7 +259,7 @@ svga_texture_get_transfer(struct pipe_context *pipe,
> unsigned nblocksy = util_format_get_nblocksy(texture->format, box->height);
>
> /* We can't map texture storage directly */
> - if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
> + if (usage & (PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_MAP_PERMANENTLY))
> return NULL;
>
> assert(box->depth == 1);
> diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
> index 3b3940d..91d8b1e 100644
> --- a/src/gallium/include/pipe/p_defines.h
> +++ b/src/gallium/include/pipe/p_defines.h
> @@ -226,6 +226,22 @@ enum pipe_transfer_usage {
> PIPE_TRANSFER_MAP_DIRECTLY = (1 << 2),
>
> /**
> + * The transfer should map the resource storage directly and the GPU should
> + * be able to see what the CPU has written. Such a storage may stay mapped
> + * while issuing draw commands which use it. The only allowed usage is
> + * non-overlapping writes which are suballocated out of a big buffer.
> + * The minimum allowed alignment of suballocations is 256 bytes (this is
> + * a subject to change).
> + * The flag is intended to be used to avoid mapping and unmapping
> + * resources repeatedly when doing uploads and draws intermixed.
> + *
> + * The driver may return NULL if that isn't possible, and the state
> + * tracker needs to cope with that and use an alternative path
> + * without this flag.
> + */
> + PIPE_TRANSFER_MAP_PERMANENTLY = (1 << 3),
> +
> + /**
> * Discards the memory within the mapped region.
> *
> * It should not be used with PIPE_TRANSFER_READ.
> --
> 1.7.4.1
>
More information about the mesa-dev
mailing list