[Mesa-dev] [PATCH 84/84] st/nine: Implement new buffer upload path

Axel Davy axel.davy at ens.fr
Thu Dec 8 23:49:50 UTC 2016


There seems to be a regression with this patch.

I noticed one mistake: nine_upload_create_buffer should initialize 
buf->resource to NULL.
However someone reports crash after GTT memory exhaustion.

I can't find the mistake. Anyone ?

Axel

On 07/12/2016 23:55, Axel Davy wrote:
> This new buffer upload path enables to lock
> faster than the normal path when using
> DISCARD/NOOVERWRITE.
>
> Signed-off-by: Axel Davy <axel.davy at ens.fr>
> ---
>   src/gallium/state_trackers/nine/Makefile.sources   |   2 +
>   src/gallium/state_trackers/nine/buffer9.c          |  75 +++++-
>   src/gallium/state_trackers/nine/buffer9.h          |   9 +-
>   src/gallium/state_trackers/nine/device9.c          |   5 +
>   src/gallium/state_trackers/nine/device9.h          |   3 +
>   src/gallium/state_trackers/nine/indexbuffer9.c     |  10 +-
>   src/gallium/state_trackers/nine/indexbuffer9.h     |   2 -
>   .../state_trackers/nine/nine_buffer_upload.c       | 288 +++++++++++++++++++++
>   .../state_trackers/nine/nine_buffer_upload.h       |  59 +++++
>   src/gallium/state_trackers/nine/vertexbuffer9.c    |   3 +-
>   10 files changed, 435 insertions(+), 21 deletions(-)
>   create mode 100644 src/gallium/state_trackers/nine/nine_buffer_upload.c
>   create mode 100644 src/gallium/state_trackers/nine/nine_buffer_upload.h
>
> diff --git a/src/gallium/state_trackers/nine/Makefile.sources b/src/gallium/state_trackers/nine/Makefile.sources
> index 2bb08a2..56698a1 100644
> --- a/src/gallium/state_trackers/nine/Makefile.sources
> +++ b/src/gallium/state_trackers/nine/Makefile.sources
> @@ -23,6 +23,8 @@ C_SOURCES := \
>   	indexbuffer9.h \
>   	iunknown.c \
>   	iunknown.h \
> +	nine_buffer_upload.c \
> +	nine_buffer_upload.h \
>   	nine_csmt_helper.h \
>   	nine_debug.c \
>   	nine_debug.h \
> diff --git a/src/gallium/state_trackers/nine/buffer9.c b/src/gallium/state_trackers/nine/buffer9.c
> index 9a7c30c..aa97cf9 100644
> --- a/src/gallium/state_trackers/nine/buffer9.c
> +++ b/src/gallium/state_trackers/nine/buffer9.c
> @@ -23,6 +23,7 @@
>   
>   #include "buffer9.h"
>   #include "device9.h"
> +#include "nine_buffer_upload.h"
>   #include "nine_helpers.h"
>   #include "nine_pipe.h"
>   
> @@ -100,6 +101,9 @@ NineBuffer9_ctor( struct NineBuffer9 *This,
>       else
>           info->usage = PIPE_USAGE_DYNAMIC;
>   
> +    /* When Writeonly is not set, we don't want to enable the
> +     * optimizations */
> +    This->discard_nooverwrite_only = !!(Usage & D3DUSAGE_WRITEONLY);
>       /* if (pDesc->Usage & D3DUSAGE_DONOTCLIP) { } */
>       /* if (pDesc->Usage & D3DUSAGE_NONSECURE) { } */
>       /* if (pDesc->Usage & D3DUSAGE_NPATCHES) { } */
> @@ -161,12 +165,18 @@ NineBuffer9_dtor( struct NineBuffer9 *This )
>               list_del(&This->managed.list2);
>       }
>   
> +    if (This->buf)
> +        nine_upload_release_buffer(This->base.base.device->buffer_upload, This->buf);
> +
>       NineResource9_dtor(&This->base);
>   }
>   
>   struct pipe_resource *
> -NineBuffer9_GetResource( struct NineBuffer9 *This )
> +NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset )
>   {
> +    if (This->buf)
> +        return nine_upload_buffer_resource_and_offset(This->buf, offset);
> +    *offset = 0;
>       return NineResource9_GetResource(&This->base);
>   }
>   
> @@ -260,6 +270,8 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
>       if (Flags & D3DLOCK_DONOTWAIT && !(This->base.usage & D3DUSAGE_DYNAMIC))
>           usage |= PIPE_TRANSFER_DONTBLOCK;
>   
> +    This->discard_nooverwrite_only &= !!(Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE));
> +
>       if (This->nmaps == This->maxmaps) {
>           struct NineTransfer *newmaps =
>               REALLOC(This->maps, sizeof(struct NineTransfer)*This->maxmaps,
> @@ -271,8 +283,52 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
>           This->maps = newmaps;
>       }
>   
> -    This->maps[This->nmaps].is_pipe_secondary = FALSE;
> +    if (This->buf &&
> +        (!This->discard_nooverwrite_only ||
> +         (This->discard_nooverwrite_only && (Flags & D3DLOCK_DISCARD)))) {
> +        /* Release previous buffer */
> +        if (This->nmaps >= 1)
> +            This->maps[This->nmaps-1].should_destroy_buf = true;
> +        else
> +            nine_upload_release_buffer(device->buffer_upload, This->buf);
> +        This->buf = NULL;
> +        /* Mapping a nine_subbuffer without discard/nooverwrite.
> +         * Since that will hurt (we'll wait the entire buffer
> +         * to be idle), we'll won't nine_subbuffer for this buffer
> +         * in fear that happens again. */
> +        if (This->buf && !This->discard_nooverwrite_only) {
> +            DBG("Disabling nine_subbuffer for a buffer having"
> +                "used a nine_subbuffer buffer\n");
> +            /* Rebind previous resource */
> +            NineBuffer9_RebindIfRequired(This, device);
> +        }
> +    }
> +
> +    This->maps[This->nmaps].transfer = NULL;
> +    This->maps[This->nmaps].is_pipe_secondary = false;
> +    This->maps[This->nmaps].buf = NULL;
> +    This->maps[This->nmaps].should_destroy_buf = false;
> +
> +    if (This->discard_nooverwrite_only) {
> +        if (!This->buf) {
> +            This->buf = nine_upload_create_buffer(device->buffer_upload, This->base.info.width0);
> +            NineBuffer9_RebindIfRequired(This, device);
> +        }
> +
> +        if (This->buf) {
> +            This->maps[This->nmaps].buf = This->buf;
> +            This->nmaps++;
> +            *ppbData = nine_upload_buffer_get_map(This->buf) + OffsetToLock;
> +            return D3D_OK;
> +        } else {
> +            /* fallback to normal path, and don't try again */
> +            This->discard_nooverwrite_only = false;
> +        }
> +    }
>   
> +    /* When csmt is active, we want to avoid stalls as much as possible,
> +     * and thus we want to create a new resource on discard and map it
> +     * with the secondary pipe, instead of waiting on the main pipe. */
>       if (Flags & D3DLOCK_DISCARD && device->csmt_active) {
>           struct pipe_screen *screen = NineDevice9_GetScreen(device);
>           struct pipe_resource *new_res = screen->resource_create(screen, &This->base.info);
> @@ -324,12 +380,15 @@ NineBuffer9_Unlock( struct NineBuffer9 *This )
>       user_assert(This->nmaps > 0, D3DERR_INVALIDCALL);
>       This->nmaps--;
>       if (This->base.pool != D3DPOOL_MANAGED) {
> -        pipe = This->maps[This->nmaps].is_pipe_secondary ?
> -            device->pipe_secondary :
> -            nine_context_get_pipe_acquire(device);
> -        pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer);
> -        if (!This->maps[This->nmaps].is_pipe_secondary)
> -            nine_context_get_pipe_release(device);
> +        if (!This->maps[This->nmaps].buf) {
> +            pipe = This->maps[This->nmaps].is_pipe_secondary ?
> +                device->pipe_secondary :
> +                nine_context_get_pipe_acquire(device);
> +            pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer);
> +            if (!This->maps[This->nmaps].is_pipe_secondary)
> +                nine_context_get_pipe_release(device);
> +        } else if (This->maps[This->nmaps].should_destroy_buf)
> +            nine_upload_release_buffer(device->buffer_upload, This->maps[This->nmaps].buf);
>       } else {
>           BASEBUF_REGISTER_UPDATE(This);
>       }
> diff --git a/src/gallium/state_trackers/nine/buffer9.h b/src/gallium/state_trackers/nine/buffer9.h
> index e9ee31e..369fd86 100644
> --- a/src/gallium/state_trackers/nine/buffer9.h
> +++ b/src/gallium/state_trackers/nine/buffer9.h
> @@ -25,6 +25,7 @@
>   #define _NINE_BUFFER9_H_
>   
>   #include "device9.h"
> +#include "nine_buffer_upload.h"
>   #include "nine_state.h"
>   #include "resource9.h"
>   #include "pipe/p_context.h"
> @@ -38,6 +39,8 @@ struct pipe_transfer;
>   struct NineTransfer {
>       struct pipe_transfer *transfer;
>       bool is_pipe_secondary;
> +    struct nine_subbuffer *buf; /* NULL unless subbuffer are used */
> +    bool should_destroy_buf; /* if the subbuffer should be destroyed */
>   };
>   
>   struct NineBuffer9
> @@ -50,6 +53,10 @@ struct NineBuffer9
>       UINT size;
>   
>       int16_t bind_count; /* to Device9->state.stream */
> +    /* Whether only discard and nooverwrite were used so far
> +     * for this buffer. Allows some optimization. */
> +    boolean discard_nooverwrite_only;
> +    struct nine_subbuffer *buf;
>   
>       /* Specific to managed buffers */
>       struct {
> @@ -79,7 +86,7 @@ void
>   NineBuffer9_dtor( struct NineBuffer9 *This );
>   
>   struct pipe_resource *
> -NineBuffer9_GetResource( struct NineBuffer9 *This );
> +NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset );
>   
>   HRESULT NINE_WINAPI
>   NineBuffer9_Lock( struct NineBuffer9 *This,
> diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c
> index 91f09de..9a5cfa4 100644
> --- a/src/gallium/state_trackers/nine/device9.c
> +++ b/src/gallium/state_trackers/nine/device9.c
> @@ -34,6 +34,7 @@
>   #include "texture9.h"
>   #include "cubetexture9.h"
>   #include "volumetexture9.h"
> +#include "nine_buffer_upload.h"
>   #include "nine_helpers.h"
>   #include "nine_pipe.h"
>   #include "nine_ff.h"
> @@ -282,6 +283,8 @@ NineDevice9_ctor( struct NineDevice9 *This,
>       if (This->csmt_active)
>           DBG("\033[1;32mCSMT is active\033[0m\n");
>   
> +    This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4);
> +
>       /* Initialize a dummy VBO to be used when a vertex declaration does not
>        * specify all the inputs needed by vertex shader, on win default behavior
>        * is to pass 0,0,0,0 to the shader */
> @@ -571,6 +574,8 @@ NineDevice9_dtor( struct NineDevice9 *This )
>           FREE(This->swapchains);
>       }
>   
> +    nine_upload_destroy(This->buffer_upload);
> +
>       /* Destroy cso first */
>       if (This->context.cso) { cso_destroy_context(This->context.cso); }
>       if (This->cso_sw) { cso_destroy_context(This->cso_sw); }
> diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h
> index 81c4ef9..71b88a4 100644
> --- a/src/gallium/state_trackers/nine/device9.h
> +++ b/src/gallium/state_trackers/nine/device9.h
> @@ -63,6 +63,9 @@ struct NineDevice9
>       struct csmt_context *csmt_ctx;
>       BOOL csmt_active;
>   
> +    /* For DISCARD/NOOVERWRITE */
> +    struct nine_buffer_upload *buffer_upload;
> +
>       /* creation parameters */
>       D3DCAPS9 caps;
>       D3DDEVICE_CREATION_PARAMETERS params;
> diff --git a/src/gallium/state_trackers/nine/indexbuffer9.c b/src/gallium/state_trackers/nine/indexbuffer9.c
> index 4029a8d..cbd75fb 100644
> --- a/src/gallium/state_trackers/nine/indexbuffer9.c
> +++ b/src/gallium/state_trackers/nine/indexbuffer9.c
> @@ -49,7 +49,7 @@ NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This,
>       if (FAILED(hr))
>           return hr;
>   
> -    This->buffer.buffer = NineIndexBuffer9_GetResource(This);
> +    This->buffer.buffer = NULL;
>       This->buffer.offset = 0;
>   
>       switch (pDesc->Format) {
> @@ -77,16 +77,10 @@ const struct pipe_index_buffer *
>   NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This )
>   {
>       /* The resource may change */
> -    This->buffer.buffer = NineIndexBuffer9_GetResource(This);
> +    This->buffer.buffer = NineBuffer9_GetResource(&This->base, &This->buffer.offset);
>       return &This->buffer;
>   }
>   
> -struct pipe_resource *
> -NineIndexBuffer9_GetResource( struct NineIndexBuffer9 *This )
> -{
> -    return NineBuffer9_GetResource(&This->base);
> -}
> -
>   HRESULT NINE_WINAPI
>   NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This,
>                          UINT OffsetToLock,
> diff --git a/src/gallium/state_trackers/nine/indexbuffer9.h b/src/gallium/state_trackers/nine/indexbuffer9.h
> index 4802105..e695082 100644
> --- a/src/gallium/state_trackers/nine/indexbuffer9.h
> +++ b/src/gallium/state_trackers/nine/indexbuffer9.h
> @@ -66,8 +66,6 @@ NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This );
>   const struct pipe_index_buffer *
>   NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This );
>   
> -struct pipe_resource *
> -NineIndexBuffer9_GetResource( struct NineIndexBuffer9 *This );
>   /*** Direct3D public ***/
>   
>   HRESULT NINE_WINAPI
> diff --git a/src/gallium/state_trackers/nine/nine_buffer_upload.c b/src/gallium/state_trackers/nine/nine_buffer_upload.c
> new file mode 100644
> index 0000000..d2a030a
> --- /dev/null
> +++ b/src/gallium/state_trackers/nine/nine_buffer_upload.c
> @@ -0,0 +1,288 @@
> +/**************************************************************************
> + *
> + * Copyright 2009 VMware, Inc.
> + * Copyright 2016 Axel Davy <axel.davy at ens.fr>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +/* Adapted from u_upload_mgr.
> + * Makes suballocations from bigger allocations,
> + * while enabling fast mapping. */
> +
> +#include "pipe/p_defines.h"
> +#include "util/u_inlines.h"
> +#include "pipe/p_context.h"
> +#include "util/u_memory.h"
> +#include "util/u_math.h"
> +#include "util/slab.h"
> +
> +#include "nine_buffer_upload.h"
> +
> +#include "nine_debug.h"
> +
> +#define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER)
> +
> +struct nine_buffer_group {
> +    unsigned refcount; /* How many sub-buffers live inside the buffer */
> +    struct pipe_resource *resource;
> +    struct pipe_transfer *transfer;
> +    uint8_t *map;
> +    unsigned free_offset; /* Aligned offset to the upload buffer, pointing
> +                           * at the first unused byte. */
> +};
> +
> +struct nine_subbuffer {
> +    struct nine_buffer_group *parent; /* Can be NULL */
> +    struct pipe_resource *resource; /* The parent resource if apply */
> +    unsigned offset; /* offset inside the resource */
> +    /* If there is no parent, the resource map. Else NULL. */
> +    struct pipe_transfer *transfer;
> +    uint8_t *map;
> +};
> +
> +struct nine_buffer_upload {
> +    struct pipe_context *pipe;
> +    struct slab_mempool buffer_pool;
> +
> +    unsigned buffers_size; /* Size of the big allocated buffers */
> +    unsigned num_buffers;
> +    boolean map_persistent; /* If persistent mappings are supported.
> +                             * If not just behaves like normal allocator */
> +    struct nine_buffer_group *buffers;
> +};
> +
> +static void
> +nine_upload_create_buffer_group(struct nine_buffer_upload *upload,
> +                                struct nine_buffer_group *group)
> +{
> +    struct pipe_resource resource;
> +    struct pipe_screen *screen = upload->pipe->screen;
> +    DBG("%p %p\n", upload, group);
> +
> +    memset(&resource, 0, sizeof resource);
> +    resource.target = PIPE_BUFFER;
> +    resource.format = PIPE_FORMAT_R8_UNORM;
> +    resource.bind = PIPE_BIND_VERTEX_BUFFER;
> +    resource.usage = PIPE_USAGE_STREAM;
> +    resource.width0 = upload->buffers_size;
> +    resource.height0 = 1;
> +    resource.depth0 = 1;
> +    resource.array_size = 1;
> +    resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT |
> +                     PIPE_RESOURCE_FLAG_MAP_COHERENT;
> +
> +    group->refcount = 0;
> +    group->resource = screen->resource_create(screen, &resource);
> +    if (group->resource == NULL)
> +        return;
> +
> +    group->map = pipe_buffer_map_range(upload->pipe, group->resource,
> +                                       0, upload->buffers_size,
> +                                       PIPE_TRANSFER_WRITE |
> +                                       PIPE_TRANSFER_PERSISTENT |
> +                                       PIPE_TRANSFER_COHERENT,
> +                                       &group->transfer);
> +    if (group->map == NULL) {
> +        group->transfer = NULL;
> +        pipe_resource_reference(&group->resource, NULL);
> +        return;
> +    }
> +
> +    group->free_offset = 0;
> +}
> +
> +static void
> +nine_upload_destroy_buffer_group(struct nine_buffer_upload *upload,
> +                                 struct nine_buffer_group *group)
> +{
> +    DBG("%p %p\n", upload, group);
> +    assert(group->refcount == 0);
> +
> +    if (group->transfer)
> +        pipe_transfer_unmap(upload->pipe, group->transfer);
> +    if (group->resource)
> +        pipe_resource_reference(&group->resource, NULL);
> +    group->transfer = NULL;
> +    group->map = NULL;
> +}
> +
> +struct nine_buffer_upload *
> +nine_upload_create(struct pipe_context *pipe, unsigned buffers_size,
> +                   unsigned num_buffers)
> +{
> +    struct nine_buffer_upload *upload = CALLOC_STRUCT(nine_buffer_upload);
> +    int i;
> +
> +    DBG("\n");
> +
> +    if (!upload)
> +        return NULL;
> +
> +    slab_create(&upload->buffer_pool, sizeof(struct nine_subbuffer), 4096);
> +
> +    upload->pipe = pipe;
> +    upload->buffers_size = align(buffers_size, 4096);
> +    upload->num_buffers = num_buffers;
> +    upload->map_persistent =
> +        pipe->screen->get_param(pipe->screen,
> +                                PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT);
> +
> +    upload->buffers = CALLOC(num_buffers, sizeof(struct nine_buffer_group));
> +    if (!upload->buffers)
> +        goto buffers_fail;
> +
> +    if (upload->map_persistent) {
> +        for (i = 0; i < num_buffers; i++)
> +            nine_upload_create_buffer_group(upload, &upload->buffers[i]);
> +    }
> +    return upload;
> +
> +buffers_fail:
> +    slab_destroy(&upload->buffer_pool);
> +    FREE(upload);
> +    return NULL;
> +}
> +
> +void
> +nine_upload_destroy(struct nine_buffer_upload *upload)
> +{
> +    int i;
> +
> +    DBG("%p\n", upload);
> +
> +    for (i = 0; i < upload->num_buffers; i++)
> +        nine_upload_destroy_buffer_group(upload, &upload->buffers[i]);
> +    FREE(upload);
> +}
> +
> +struct nine_subbuffer *
> +nine_upload_create_buffer(struct nine_buffer_upload *upload,
> +                          unsigned buffer_size)
> +{
> +    struct nine_subbuffer *buf = slab_alloc_st(&upload->buffer_pool);
> +    struct nine_buffer_group *group = NULL;
> +    unsigned size = align(buffer_size, 4096);
> +    int i = 0;
> +
> +    DBG("%p %d\n", upload, buffer_size);
> +
> +    if (!buf)
> +        return NULL;
> +
> +    for (i = 0; i < upload->num_buffers; i++) {
> +        group = &upload->buffers[i];
> +        if (group->resource &&
> +            group->free_offset + size <= upload->buffers_size)
> +            break;
> +    }
> +
> +    if (i == upload->num_buffers) {
> +        /* Allocate lonely buffer */
> +        struct pipe_resource resource;
> +        struct pipe_screen *screen = upload->pipe->screen;
> +
> +        buf->parent = NULL;
> +
> +        memset(&resource, 0, sizeof resource);
> +        resource.target = PIPE_BUFFER;
> +        resource.format = PIPE_FORMAT_R8_UNORM;
> +        resource.bind = PIPE_BIND_VERTEX_BUFFER;
> +        resource.usage = PIPE_USAGE_STREAM;
> +        resource.width0 = upload->buffers_size;
> +        resource.height0 = 1;
> +        resource.depth0 = 1;
> +        resource.array_size = 1;
> +        resource.flags = 0;
> +
> +        buf->resource = screen->resource_create(screen, &resource);
> +        if (buf->resource == NULL) {
> +            slab_free_st(&upload->buffer_pool, buf);
> +            return NULL;
> +        }
> +
> +        buf->map = pipe_buffer_map_range(upload->pipe, buf->resource,
> +                                         0, upload->buffers_size,
> +                                         PIPE_TRANSFER_WRITE |
> +                                         PIPE_TRANSFER_PERSISTENT |
> +                                         PIPE_TRANSFER_COHERENT,
> +                                         &buf->transfer);
> +        if (buf->map == NULL) {
> +            pipe_resource_reference(&buf->resource, NULL);
> +            slab_free_st(&upload->buffer_pool, buf);
> +            return NULL;
> +        }
> +        buf->offset = 0;
> +        return buf;
> +    }
> +
> +    buf->parent = group;
> +    pipe_resource_reference(&buf->resource, group->resource);
> +    buf->offset = group->free_offset;
> +
> +    group->free_offset += size;
> +    group->refcount += 1;
> +
> +    return buf;
> +}
> +
> +void
> +nine_upload_release_buffer(struct nine_buffer_upload *upload,
> +                           struct nine_subbuffer *buf)
> +{
> +    DBG("%p %p %p\n", upload, buf, buf->parent);
> +
> +    if (buf->parent) {
> +        pipe_resource_reference(&buf->resource, NULL);
> +        buf->parent->refcount--;
> +        if (buf->parent->refcount == 0) {
> +            /* Allocate new buffer */
> +            nine_upload_destroy_buffer_group(upload, buf->parent);
> +            nine_upload_create_buffer_group(upload, buf->parent);
> +        }
> +    } else {
> +        /* lonely buffer */
> +        if (buf->transfer)
> +            pipe_transfer_unmap(upload->pipe, buf->transfer);
> +        pipe_resource_reference(&buf->resource, NULL);
> +    }
> +
> +    slab_free_st(&upload->buffer_pool, buf);
> +}
> +
> +uint8_t *
> +nine_upload_buffer_get_map(struct nine_subbuffer *buf)
> +{
> +    if (buf->parent) {
> +        return buf->parent->map + buf->offset;
> +    }
> +    /* lonely buffer */
> +    return buf->map;
> +}
> +
> +struct pipe_resource *
> +nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf,
> +                                       unsigned *offset)
> +{
> +    *offset = buf->offset;
> +    return buf->resource;
> +}
> diff --git a/src/gallium/state_trackers/nine/nine_buffer_upload.h b/src/gallium/state_trackers/nine/nine_buffer_upload.h
> new file mode 100644
> index 0000000..b708825
> --- /dev/null
> +++ b/src/gallium/state_trackers/nine/nine_buffer_upload.h
> @@ -0,0 +1,59 @@
> +/**************************************************************************
> + *
> + * Copyright 2009 VMware, Inc.
> + * Copyright 2016 Axel Davy <axel.davy at ens.fr>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +#ifndef _NINE_BUFFER_UPLOAD_H_
> +#define _NINE_BUFFER_UPLOAD_H_
> +
> +#include "pipe/p_defines.h"
> +
> +struct nine_buffer_upload;
> +struct nine_subbuffer;
> +
> +struct nine_buffer_upload *
> +nine_upload_create(struct pipe_context *pipe, unsigned buffers_size,
> +                   unsigned num_buffers);
> +
> +void
> +nine_upload_destroy(struct nine_buffer_upload *upload);
> +
> +struct nine_subbuffer *
> +nine_upload_create_buffer(struct nine_buffer_upload *upload,
> +                          unsigned buffer_size);
> +
> +void
> +nine_upload_release_buffer(struct nine_buffer_upload *upload,
> +                           struct nine_subbuffer *buf);
> +
> +uint8_t *
> +nine_upload_buffer_get_map(struct nine_subbuffer *buf);
> +
> +struct pipe_resource *
> +nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf,
> +                                       unsigned *offset);
> +
> +#endif /* _NINE_BUFFER_UPLOAD_H_ */
> diff --git a/src/gallium/state_trackers/nine/vertexbuffer9.c b/src/gallium/state_trackers/nine/vertexbuffer9.c
> index 027f290..df1d171 100644
> --- a/src/gallium/state_trackers/nine/vertexbuffer9.c
> +++ b/src/gallium/state_trackers/nine/vertexbuffer9.c
> @@ -65,8 +65,7 @@ NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This )
>   struct pipe_resource *
>   NineVertexBuffer9_GetResource( struct NineVertexBuffer9 *This, unsigned *offset )
>   {
> -    *offset = 0;
> -    return NineBuffer9_GetResource(&This->base);
> +    return NineBuffer9_GetResource(&This->base, offset);
>   }
>   
>   HRESULT NINE_WINAPI




More information about the mesa-dev mailing list