From: Axel Davy Date: Sun, 4 Dec 2016 19:34:59 +0000 (+0100) Subject: st/nine: Implement new buffer upload path X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bad7f7cc638391acc93f070fce3e1b7035dc48f8;p=mesa.git st/nine: Implement new buffer upload path This new buffer upload path enables to lock faster than the normal path when using DISCARD/NOOVERWRITE. v2: Diverse cleanups and fixes. v3: Fix allocation size for 'lone' buffers and add more debug info. v4: Rewrite of the path to handle when DISCARD/NOOVERWRITE is not used anymore. The resource content is copied to the new resource used. v5: flush for safety after unmap (not sure it is really required here, but safer to flush). v6: Do not use the path if persistent coherent mapping is unavailable. Fix buffer creation flags. v7: Do not flush since it is not needed. Signed-off-by: Axel Davy --- diff --git a/src/gallium/state_trackers/nine/Makefile.sources b/src/gallium/state_trackers/nine/Makefile.sources index 2bb08a26122..56698a19f10 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 c745d77c2c2..b22713b3517 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,10 @@ 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) && + pParams->device->buffer_upload; /* if (pDesc->Usage & D3DUSAGE_DONOTCLIP) { } */ /* if (pDesc->Usage & D3DUSAGE_NONSECURE) { } */ /* if (pDesc->Usage & D3DUSAGE_NPATCHES) { } */ @@ -161,12 +166,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); } @@ -264,6 +275,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, @@ -275,8 +288,67 @@ NineBuffer9_Lock( struct NineBuffer9 *This, This->maps = newmaps; } - This->maps[This->nmaps].is_pipe_secondary = FALSE; + if (This->buf && !This->discard_nooverwrite_only) { + struct pipe_box src_box; + unsigned offset; + struct pipe_resource *src_res; + DBG("Disabling nine_subbuffer for a buffer having" + "used a nine_subbuffer buffer\n"); + /* Copy buffer content to the buffer resource, which + * we will now use. + * Note: The behaviour may be different from what is expected + * with double lock. However applications can't really make expectations + * about double locks, and don't really use them, so that's ok. */ + src_res = nine_upload_buffer_resource_and_offset(This->buf, &offset); + u_box_1d(offset, This->size, &src_box); + + pipe = NineDevice9_GetPipe(device); + pipe->resource_copy_region(pipe, This->base.resource, 0, 0, 0, 0, + src_res, 0, &src_box); + /* Release previous resource */ + 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; + /* Rebind buffer */ + 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 && (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; + } + 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); @@ -328,15 +400,18 @@ 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); - /* We need to flush in case the driver does implicit copies */ - if (This->maps[This->nmaps].is_pipe_secondary) - pipe->flush(pipe, NULL, 0); - else - 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); + /* We need to flush in case the driver does implicit copies */ + if (This->maps[This->nmaps].is_pipe_secondary) + pipe->flush(pipe, NULL, 0); + else + 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 e9ee31ef7f7..b04a0a721bb 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 91c4535a144..9f2575309a5 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,9 @@ NineDevice9_dtor( struct NineDevice9 *This ) FREE(This->swapchains); } + if (This->buffer_upload) + 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 81c4ef97f41..71b88a42b4b 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 4029a8d6a3a..cbd75fb928c 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 4802105c952..e695082a0c5 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 00000000000..a71f0195a2a --- /dev/null +++ b/src/gallium/state_trackers/nine/nine_buffer_upload.c @@ -0,0 +1,294 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2016 Axel Davy + * 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; + 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; + int i; + + DBG("\n"); + + if (!pipe->screen->get_param(pipe->screen, + PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT)) + return NULL; + + upload = CALLOC_STRUCT(nine_buffer_upload); + + 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->buffers = CALLOC(num_buffers, sizeof(struct nine_buffer_group)); + if (!upload->buffers) + goto buffers_fail; + + 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]); + slab_destroy(&upload->buffer_pool); + 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; + + DBG("Allocating buffer\n"); + 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 = buffer_size; + resource.height0 = 1; + resource.depth0 = 1; + resource.array_size = 1; + resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | + PIPE_RESOURCE_FLAG_MAP_COHERENT; + + 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, buffer_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; + } + + DBG("Using buffer group %d\n", i); + + buf->parent = group; + buf->resource = NULL; + 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 00000000000..b7088250a83 --- /dev/null +++ b/src/gallium/state_trackers/nine/nine_buffer_upload.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2016 Axel Davy + * 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 027f290d8a3..df1d1717539 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