diff options
Diffstat (limited to 'src/gallium/drivers/svga')
-rw-r--r-- | src/gallium/drivers/svga/svga_cmd.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_cmd.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_context.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_pipe_draw.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_pipe_flush.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer.c | 287 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer.h | 20 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer_upload.c | 50 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer_upload.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_texture.c | 68 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_screen.c | 22 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_screen.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_state_vdecl.c | 9 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_winsys.h | 7 |
15 files changed, 273 insertions, 257 deletions
diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c index 05eab8a517d..1ed1d5d25bb 100644 --- a/src/gallium/drivers/svga/svga_cmd.c +++ b/src/gallium/drivers/svga/svga_cmd.c @@ -422,7 +422,8 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc, struct svga_transfer *st, // IN SVGA3dTransferType transfer, // IN const SVGA3dCopyBox *boxes, // IN - uint32 numBoxes) // IN + uint32 numBoxes, // IN + SVGA3dSurfaceDMAFlags flags) // IN { struct svga_texture *texture = svga_texture(st->base.resource); SVGA3dCmdSurfaceDMA *cmd; @@ -465,7 +466,7 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc, pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize); pSuffix->suffixSize = sizeof *pSuffix; pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride; - memset(&pSuffix->flags, 0, sizeof pSuffix->flags); + pSuffix->flags = flags; swc->commit(swc); diff --git a/src/gallium/drivers/svga/svga_cmd.h b/src/gallium/drivers/svga/svga_cmd.h index 0e568d78e65..223ab17df81 100644 --- a/src/gallium/drivers/svga/svga_cmd.h +++ b/src/gallium/drivers/svga/svga_cmd.h @@ -102,7 +102,8 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc, struct svga_transfer *st, SVGA3dTransferType transfer, const SVGA3dCopyBox *boxes, - uint32 numBoxes); + uint32 numBoxes, + SVGA3dSurfaceDMAFlags flags); enum pipe_error SVGA3D_BufferDMA(struct svga_winsys_context *swc, diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index f0f875b2b23..4782b4bf70e 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -241,7 +241,8 @@ void svga_context_flush( struct svga_context *svga, if (SVGA_DEBUG & DEBUG_SYNC) { if (fence) - svga->pipe.screen->fence_finish( svga->pipe.screen, fence, 0); + svga->pipe.screen->fence_finish( svga->pipe.screen, fence, + PIPE_TIMEOUT_INFINITE); } if(pfence) diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index d98b9b0e000..2093bcae101 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -73,12 +73,6 @@ retry_draw_range_elements( struct svga_context *svga, if (ret) goto retry; - if (svga->curr.any_user_vertex_buffers) { - ret = svga_hwtnl_flush( svga->hwtnl ); - if (ret) - goto retry; - } - return PIPE_OK; retry: @@ -122,12 +116,6 @@ retry_draw_arrays( struct svga_context *svga, if (ret) goto retry; - if (svga->curr.any_user_vertex_buffers) { - ret = svga_hwtnl_flush( svga->hwtnl ); - if (ret) - goto retry; - } - return 0; retry: @@ -161,7 +149,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) /* We're switching between SW and HW drawing. Do a flush to avoid * mixing HW and SW rendering with the same vertex buffer. */ - pipe->flush(pipe, ~0, NULL); + pipe->flush(pipe, NULL); svga->prev_draw_swtnl = svga->state.sw.need_swtnl; } diff --git a/src/gallium/drivers/svga/svga_pipe_flush.c b/src/gallium/drivers/svga/svga_pipe_flush.c index 9357d827f28..4578c136cb8 100644 --- a/src/gallium/drivers/svga/svga_pipe_flush.c +++ b/src/gallium/drivers/svga/svga_pipe_flush.c @@ -32,7 +32,6 @@ static void svga_flush( struct pipe_context *pipe, - unsigned flags, struct pipe_fence_handle **fence ) { struct svga_context *svga = svga_context(pipe); @@ -45,29 +44,27 @@ static void svga_flush( struct pipe_context *pipe, */ svga_context_flush(svga, fence); - SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s flags %x fence_ptr %p\n", - __FUNCTION__, flags, fence ? *fence : 0x0); + SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n", + __FUNCTION__, fence ? *fence : 0x0); /* Enable to dump BMPs of the color/depth buffers each frame */ if (0) { - if (flags & PIPE_FLUSH_FRAME) { - struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; - static unsigned frame_no = 1; - char filename[256]; - unsigned i; + struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; + static unsigned frame_no = 1; + char filename[256]; + unsigned i; - for (i = 0; i < fb->nr_cbufs; i++) { - util_snprintf(filename, sizeof(filename), "cbuf%u_%04u", i, frame_no); - debug_dump_surface_bmp(&svga->pipe, filename, fb->cbufs[i]); - } - - if (0 && fb->zsbuf) { - util_snprintf(filename, sizeof(filename), "zsbuf_%04u", frame_no); - debug_dump_surface_bmp(&svga->pipe, filename, fb->zsbuf); - } + for (i = 0; i < fb->nr_cbufs; i++) { + util_snprintf(filename, sizeof(filename), "cbuf%u_%04u", i, frame_no); + debug_dump_surface_bmp(&svga->pipe, filename, fb->cbufs[i]); + } - ++frame_no; + if (0 && fb->zsbuf) { + util_snprintf(filename, sizeof(filename), "zsbuf_%04u", frame_no); + debug_dump_surface_bmp(&svga->pipe, filename, fb->zsbuf); } + + ++frame_no; } } diff --git a/src/gallium/drivers/svga/svga_resource.c b/src/gallium/drivers/svga/svga_resource.c index bed15ec02e5..6e0622a312b 100644 --- a/src/gallium/drivers/svga/svga_resource.c +++ b/src/gallium/drivers/svga/svga_resource.c @@ -33,7 +33,6 @@ svga_resource_from_handle(struct pipe_screen * screen, void svga_init_resource_functions(struct svga_context *svga) { - svga->pipe.is_resource_referenced = u_is_resource_referenced_vtbl; svga->pipe.get_transfer = u_get_transfer_vtbl; svga->pipe.transfer_map = u_transfer_map_vtbl; svga->pipe.transfer_flush_region = u_transfer_flush_region_vtbl; diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index e1f07d655b9..34ab9e143e6 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -51,53 +51,114 @@ svga_buffer_needs_hw_storage(unsigned usage) } -static unsigned int -svga_buffer_is_referenced( struct pipe_context *pipe, - struct pipe_resource *buf, - unsigned level, int layer) +/** + * Create a buffer transfer. + * + * Unlike texture DMAs (which are written immediately to the command buffer and + * therefore inherently serialized with other context operations), for buffers + * we try to coalesce multiple range mappings (i.e, multiple calls to this + * function) into a single DMA command, for better efficiency in command + * processing. This means we need to exercise extra care here to ensure that + * the end result is exactly the same as if one DMA was used for every mapped + * range. + */ +static struct pipe_transfer * +svga_buffer_get_transfer(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { + struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); - struct svga_buffer *sbuf = svga_buffer(buf); + struct svga_buffer *sbuf = svga_buffer(resource); + struct pipe_transfer *transfer; - /** - * XXX: Check this. - * The screen may cache buffer writes, but when we map, we map out - * of those cached writes, so we don't need to set a - * PIPE_REFERENCED_FOR_WRITE flag for cached buffers. - */ + transfer = CALLOC_STRUCT(pipe_transfer); + if (transfer == NULL) { + return NULL; + } - if (!sbuf->handle || ss->sws->surface_is_flushed(ss->sws, sbuf->handle)) - return PIPE_UNREFERENCED; + transfer->resource = resource; + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; - /** - * sws->surface_is_flushed() does not distinguish between read references - * and write references. So assume a reference is both, - * however, we make an exception for index- and vertex buffers, to avoid - * a flush in st_bufferobj_get_subdata, during display list replay. - */ + if (usage & PIPE_TRANSFER_WRITE) { + if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { + /* + * Finish writing any pending DMA commands, and tell the host to discard + * the buffer contents on the next DMA operation. + */ - if (sbuf->b.b.bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - return PIPE_REFERENCED_FOR_READ; + if (sbuf->dma.pending) { + svga_buffer_upload_flush(svga, sbuf); - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; -} + /* + * Instead of flushing the context command buffer, simply discard + * the current hwbuf, and start a new one. + */ + svga_buffer_destroy_hw_storage(ss, sbuf); + } + sbuf->map.num_ranges = 0; + sbuf->dma.flags.discard = TRUE; + } + if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) { + if (!sbuf->map.num_ranges) { + /* + * No pending ranges to upload so far, so we can tell the host to + * not synchronize on the next DMA command. + */ + sbuf->dma.flags.unsynchronized = TRUE; + } + } else { + /* + * Synchronizing, so finish writing any pending DMA command, and + * ensure the next DMA will be done in order. + */ + if (sbuf->dma.pending) { + svga_buffer_upload_flush(svga, sbuf); + + if (sbuf->hwbuf) { + /* + * We have a pending DMA upload from a hardware buffer, therefore + * we need to ensure that the host finishes processing that DMA + * command before the state tracker can start overwriting the + * hardware buffer. + * + * XXX: This could be avoided by tying the hardware buffer to + * the transfer (just as done with textures), which would allow + * overlapping DMAs commands to be queued on the same context + * buffer. However, due to the likelihood of software vertex + * processing, it is more convenient to hold on to the hardware + * buffer, allowing to quickly access the contents from the CPU + * without having to do a DMA download from the host. + */ + + if (usage & PIPE_TRANSFER_DONTBLOCK) { + /* + * Flushing the command buffer here will most likely cause + * the map of the hwbuf below to block, so preemptively + * return NULL here if DONTBLOCK is set to prevent unnecessary + * command buffer flushes. + */ + + FREE(transfer); + return NULL; + } + + svga_context_flush(svga, NULL); + } + } -static void * -svga_buffer_map_range( struct pipe_screen *screen, - struct pipe_resource *buf, - unsigned offset, - unsigned length, - unsigned usage ) -{ - struct svga_screen *ss = svga_screen(screen); - struct svga_winsys_screen *sws = ss->sws; - struct svga_buffer *sbuf = svga_buffer( buf ); - void *map; + sbuf->dma.flags.unsynchronized = FALSE; + } + } if (!sbuf->swbuf && !sbuf->hwbuf) { if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) { @@ -113,86 +174,120 @@ svga_buffer_map_range( struct pipe_screen *screen, } sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16); + if (!sbuf->swbuf) { + FREE(transfer); + return NULL; + } } } + return transfer; +} + + +/** + * Map a range of a buffer. + */ +static void * +svga_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct svga_buffer *sbuf = svga_buffer(transfer->resource); + + uint8_t *map; + if (sbuf->swbuf) { /* User/malloc buffer */ map = sbuf->swbuf; } else if (sbuf->hwbuf) { - map = sws->buffer_map(sws, sbuf->hwbuf, usage); + struct svga_screen *ss = svga_screen(pipe->screen); + struct svga_winsys_screen *sws = ss->sws; + + map = sws->buffer_map(sws, sbuf->hwbuf, transfer->usage); } else { map = NULL; } - if(map) { + if (map) { ++sbuf->map.count; - - if (usage & PIPE_TRANSFER_WRITE) { - assert(sbuf->map.count <= 1); - sbuf->map.writing = TRUE; - if (usage & PIPE_TRANSFER_FLUSH_EXPLICIT) - sbuf->map.flush_explicit = TRUE; - } + map += transfer->box.x; } return map; } - -static void -svga_buffer_flush_mapped_range( struct pipe_screen *screen, - struct pipe_resource *buf, - unsigned offset, unsigned length) +static void +svga_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) { - struct svga_buffer *sbuf = svga_buffer( buf ); - struct svga_screen *ss = svga_screen(screen); - + struct svga_screen *ss = svga_screen(pipe->screen); + struct svga_buffer *sbuf = svga_buffer(transfer->resource); + + unsigned offset = transfer->box.x + box->x; + unsigned length = box->width; + + assert(transfer->usage & PIPE_TRANSFER_WRITE); + assert(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT); + pipe_mutex_lock(ss->swc_mutex); - assert(sbuf->map.writing); - if(sbuf->map.writing) { - assert(sbuf->map.flush_explicit); - svga_buffer_add_range(sbuf, offset, offset + length); - } + svga_buffer_add_range(sbuf, offset, offset + length); pipe_mutex_unlock(ss->swc_mutex); } -static void -svga_buffer_unmap( struct pipe_screen *screen, - struct pipe_resource *buf) + +static void +svga_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; - struct svga_buffer *sbuf = svga_buffer( buf ); + struct svga_buffer *sbuf = svga_buffer(transfer->resource); pipe_mutex_lock(ss->swc_mutex); assert(sbuf->map.count); - if(sbuf->map.count) + if (sbuf->map.count) { --sbuf->map.count; + } - if(sbuf->hwbuf) + if (sbuf->hwbuf) { sws->buffer_unmap(sws, sbuf->hwbuf); + } + + if (transfer->usage & PIPE_TRANSFER_WRITE) { + if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { + /* + * Mapped range not flushed explicitly, so flush the whole buffer, + * and tell the host to discard the contents when processing the DMA + * command. + */ - if(sbuf->map.writing) { - if(!sbuf->map.flush_explicit) { - /* No mapped range was flushed -- flush the whole buffer */ SVGA_DBG(DEBUG_DMA, "flushing the whole buffer\n"); + sbuf->dma.flags.discard = TRUE; + svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0); } - - sbuf->map.writing = FALSE; - sbuf->map.flush_explicit = FALSE; } pipe_mutex_unlock(ss->swc_mutex); } +/** + * Destroy transfer + */ +static void +svga_buffer_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + FREE(transfer); +} + static void svga_buffer_destroy( struct pipe_screen *screen, @@ -221,62 +316,12 @@ svga_buffer_destroy( struct pipe_screen *screen, } -/* Keep the original code more or less intact, implement transfers in - * terms of the old functions. - */ -static void * -svga_buffer_transfer_map( struct pipe_context *pipe, - struct pipe_transfer *transfer ) -{ - uint8_t *map = svga_buffer_map_range( pipe->screen, - transfer->resource, - transfer->box.x, - transfer->box.width, - transfer->usage ); - if (map == NULL) - return NULL; - - /* map_buffer() returned a pointer to the beginning of the buffer, - * but transfers are expected to return a pointer to just the - * region specified in the box. - */ - return map + transfer->box.x; -} - - - -static void svga_buffer_transfer_flush_region( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - assert(box->x + box->width <= transfer->box.width); - - svga_buffer_flush_mapped_range(pipe->screen, - transfer->resource, - transfer->box.x + box->x, - box->width); -} - -static void svga_buffer_transfer_unmap( struct pipe_context *pipe, - struct pipe_transfer *transfer ) -{ - svga_buffer_unmap(pipe->screen, - transfer->resource); -} - - - - - - - struct u_resource_vtbl svga_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ svga_buffer_destroy, /* resource_destroy */ - svga_buffer_is_referenced, /* is_resource_referenced */ - u_default_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ + svga_buffer_get_transfer, /* get_transfer */ + svga_buffer_transfer_destroy, /* transfer_destroy */ svga_buffer_transfer_map, /* transfer_map */ svga_buffer_transfer_flush_region, /* transfer_flush_region */ svga_buffer_transfer_unmap, /* transfer_unmap */ diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h index c559f70ec12..95032213fa5 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.h +++ b/src/gallium/drivers/svga/svga_resource_buffer.h @@ -90,7 +90,9 @@ struct svga_buffer * Host surface handle. * * This is a platform independent abstraction for host SID. We create when - * trying to bind + * trying to bind. + * + * Only set for non-user buffers. */ struct svga_winsys_surface *handle; @@ -100,24 +102,10 @@ struct svga_buffer struct { /** * Number of concurrent mappings. - * - * XXX: It is impossible to guarantee concurrent maps work in all - * circumstances -- pipe_buffers really need transfer objects too. */ unsigned count; /** - * Whether this buffer is currently mapped for writing. - */ - boolean writing; - - /** - * Whether the application will tell us explicity which ranges it touched - * or not. - */ - boolean flush_explicit; - - /** * Dirty ranges. * * Ranges that were touched by the application and need to be uploaded to @@ -149,6 +137,8 @@ struct svga_buffer * A piece of GMR memory, with the same size of the buffer. It is created * when mapping the buffer, and will be used to upload vertex data to the * host. + * + * Only set for non-user buffers. */ struct svga_winsys_buffer *hwbuf; diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c index b7d54605e66..e5fcec08d6e 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c @@ -131,6 +131,8 @@ enum pipe_error svga_buffer_create_host_surface(struct svga_screen *ss, struct svga_buffer *sbuf) { + assert(!sbuf->user); + if(!sbuf->handle) { sbuf->key.flags = 0; @@ -252,7 +254,7 @@ svga_buffer_upload_command(struct svga_context *svga, * Patch up the upload DMA command reserved by svga_buffer_upload_command * with the final ranges. */ -static void +void svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf) { @@ -260,6 +262,10 @@ svga_buffer_upload_flush(struct svga_context *svga, unsigned i; struct pipe_resource *dummy; + if (!sbuf->dma.pending) { + return; + } + assert(sbuf->handle); assert(sbuf->hwbuf); assert(sbuf->map.num_ranges); @@ -296,6 +302,8 @@ svga_buffer_upload_flush(struct svga_context *svga, sbuf->head.next = sbuf->head.prev = NULL; #endif sbuf->dma.pending = FALSE; + sbuf->dma.flags.discard = FALSE; + sbuf->dma.flags.unsynchronized = FALSE; sbuf->dma.svga = NULL; sbuf->dma.boxes = NULL; @@ -306,7 +314,6 @@ svga_buffer_upload_flush(struct svga_context *svga, } - /** * Note a dirty range. * @@ -337,12 +344,6 @@ svga_buffer_add_range(struct svga_buffer *sbuf, /* * Try to grow one of the ranges. - * - * Note that it is not this function task to care about overlapping ranges, - * as the GMR was already given so it is too late to do anything. Situations - * where overlapping ranges may pose a problem should be detected via - * pipe_context::is_resource_referenced and the context that refers to the - * buffer should be flushed. */ for(i = 0; i < sbuf->map.num_ranges; ++i) { @@ -357,6 +358,11 @@ svga_buffer_add_range(struct svga_buffer *sbuf, if (dist <= 0) { /* * Ranges are contiguous or overlapping -- extend this one and return. + * + * Note that it is not this function's task to prevent overlapping + * ranges, as the GMR was already given so it is too late to do + * anything. If the ranges overlap here it must surely be because + * PIPE_TRANSFER_UNSYNCHRONIZED was set. */ sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start); @@ -380,8 +386,7 @@ svga_buffer_add_range(struct svga_buffer *sbuf, * pending DMA upload and start clean. */ - if(sbuf->dma.pending) - svga_buffer_upload_flush(sbuf->dma.svga, sbuf); + svga_buffer_upload_flush(sbuf->dma.svga, sbuf); assert(!sbuf->dma.pending); assert(!sbuf->dma.svga); @@ -662,6 +667,9 @@ svga_redefine_user_buffer(struct pipe_context *pipe, struct svga_buffer *sbuf = svga_buffer(resource); assert(sbuf->user); + assert(!sbuf->dma.pending); + assert(!sbuf->handle); + assert(!sbuf->hwbuf); /* * Release any uploaded user buffer. @@ -674,29 +682,9 @@ svga_redefine_user_buffer(struct pipe_context *pipe, pipe_mutex_lock(ss->swc_mutex); - if (offset + size > resource->width0) { - /* - * User buffers shouldn't have DMA directly, unless - * SVGA_COMBINE_USERBUFFERS is not set. - */ - - if (sbuf->dma.pending) { - svga_buffer_upload_flush(svga, sbuf); - } - - if (sbuf->handle) { - svga_buffer_destroy_host_surface(ss, sbuf); - } - - if (sbuf->hwbuf) { - svga_buffer_destroy_hw_storage(ss, sbuf); - } - - sbuf->key.size.width = sbuf->b.b.width0 = offset + size; - } + sbuf->key.size.width = sbuf->b.b.width0 = offset + size; pipe_mutex_unlock(ss->swc_mutex); - svga->curr.any_user_vertex_buffers = TRUE; svga->dirty |= SVGA_NEW_VBUFFER | SVGA_NEW_VELEMENT; } diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.h b/src/gallium/drivers/svga/svga_resource_buffer_upload.h index 11df3065263..13d8f3e299b 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.h +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.h @@ -28,6 +28,10 @@ void +svga_buffer_upload_flush(struct svga_context *svga, + struct svga_buffer *sbuf); + +void svga_buffer_add_range(struct svga_buffer *sbuf, unsigned start, unsigned end); diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 994f30719ae..b61f85955a2 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -48,31 +48,6 @@ #define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9) -static unsigned int -svga_texture_is_referenced( struct pipe_context *pipe, - struct pipe_resource *texture, - unsigned level, int layer) -{ - struct svga_texture *tex = svga_texture(texture); - struct svga_screen *ss = svga_screen(pipe->screen); - - /** - * The screen does not cache texture writes. - */ - - if (!tex->handle || ss->sws->surface_is_flushed(ss->sws, tex->handle)) - return PIPE_UNREFERENCED; - - /** - * sws->surface_is_flushed() does not distinguish between read references - * and write references. So assume a reference is both. - */ - - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; -} - - - /* * Helper function and arrays */ @@ -156,7 +131,8 @@ static INLINE void svga_transfer_dma_band(struct svga_context *svga, struct svga_transfer *st, SVGA3dTransferType transfer, - unsigned y, unsigned h, unsigned srcy) + unsigned y, unsigned h, unsigned srcy, + SVGA3dSurfaceDMAFlags flags) { struct svga_texture *texture = svga_texture(st->base.resource); SVGA3dCopyBox box; @@ -192,10 +168,10 @@ svga_transfer_dma_band(struct svga_context *svga, util_format_get_blocksize(texture->b.b.format) * 8 / (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format))); - ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1); + ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); - ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1); + ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags); assert(ret == PIPE_OK); } } @@ -204,7 +180,8 @@ svga_transfer_dma_band(struct svga_context *svga, static INLINE void svga_transfer_dma(struct svga_context *svga, struct svga_transfer *st, - SVGA3dTransferType transfer) + SVGA3dTransferType transfer, + SVGA3dSurfaceDMAFlags flags) { struct svga_texture *texture = svga_texture(st->base.resource); struct svga_screen *screen = svga_screen(texture->b.b.screen); @@ -223,7 +200,9 @@ svga_transfer_dma(struct svga_context *svga, if(!st->swbuf) { /* Do the DMA transfer in a single go */ - svga_transfer_dma_band(svga, st, transfer, st->base.box.y, st->base.box.height, 0); + svga_transfer_dma_band(svga, st, transfer, + st->base.box.y, st->base.box.height, 0, + flags); if(transfer == SVGA3D_READ_HOST_VRAM) { svga_context_flush(svga, &fence); @@ -269,7 +248,14 @@ svga_transfer_dma(struct svga_context *svga, } } - svga_transfer_dma_band(svga, st, transfer, y, h, srcy); + svga_transfer_dma_band(svga, st, transfer, y, h, srcy, flags); + + /* + * Prevent the texture contents to be discarded on the next band + * upload. + */ + + flags.discard = FALSE; if(transfer == SVGA3D_READ_HOST_VRAM) { svga_context_flush(svga, &fence); @@ -398,8 +384,11 @@ svga_texture_get_transfer(struct pipe_context *pipe, goto no_swbuf; } - if (usage & PIPE_TRANSFER_READ) - svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM); + if (usage & PIPE_TRANSFER_READ) { + SVGA3dSurfaceDMAFlags flags; + memset(&flags, 0, sizeof flags); + svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); + } return &st->base; @@ -458,7 +447,17 @@ svga_texture_transfer_destroy(struct pipe_context *pipe, struct svga_transfer *st = svga_transfer(transfer); if (st->base.usage & PIPE_TRANSFER_WRITE) { - svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM); + SVGA3dSurfaceDMAFlags flags; + + memset(&flags, 0, sizeof flags); + if (transfer->usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { + flags.discard = TRUE; + } + if (transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) { + flags.unsynchronized = TRUE; + } + + svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM, flags); ss->texture_timestamp++; tex->view_age[transfer->level] = ++(tex->age); if (transfer->resource->target == PIPE_TEXTURE_CUBE) @@ -481,7 +480,6 @@ struct u_resource_vtbl svga_texture_vtbl = { svga_texture_get_handle, /* get_handle */ svga_texture_destroy, /* resource_destroy */ - svga_texture_is_referenced, /* is_resource_referenced */ svga_texture_get_transfer, /* get_transfer */ svga_texture_transfer_destroy, /* transfer_destroy */ svga_texture_transfer_map, /* transfer_map */ diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index ef1d3098d51..6c987abe056 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -342,8 +342,7 @@ svga_is_format_supported( struct pipe_screen *screen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, - unsigned tex_usage, - unsigned geom_flags ) + unsigned tex_usage) { struct svga_winsys_screen *sws = svga_screen(screen)->sws; SVGA3dDevCapIndex index; @@ -412,27 +411,26 @@ svga_fence_reference(struct pipe_screen *screen, } -static int +static boolean svga_fence_signalled(struct pipe_screen *screen, - struct pipe_fence_handle *fence, - unsigned flag) + struct pipe_fence_handle *fence) { struct svga_winsys_screen *sws = svga_screen(screen)->sws; - return sws->fence_signalled(sws, fence, flag); + return sws->fence_signalled(sws, fence, 0) == 0; } -static int +static boolean svga_fence_finish(struct pipe_screen *screen, struct pipe_fence_handle *fence, - unsigned flag) + uint64_t timeout) { struct svga_winsys_screen *sws = svga_screen(screen)->sws; SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n", __FUNCTION__, fence); - return sws->fence_finish(sws, fence, flag); + return sws->fence_finish(sws, fence, 0) == 0; } @@ -498,6 +496,12 @@ svga_screen_create(struct svga_winsys_screen *sws) svga_init_screen_resource_functions(svgascreen); + if (sws->get_hw_version) { + svgascreen->hw_version = sws->get_hw_version(sws); + } else { + svgascreen->hw_version = SVGA3D_HWVERSION_WS65_B1; + } + svgascreen->use_ps30 = sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) && result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE; diff --git a/src/gallium/drivers/svga/svga_screen.h b/src/gallium/drivers/svga/svga_screen.h index 86ec89d88c1..6d8d287ce95 100644 --- a/src/gallium/drivers/svga/svga_screen.h +++ b/src/gallium/drivers/svga/svga_screen.h @@ -39,8 +39,6 @@ struct svga_winsys_screen; struct svga_winsys_context; struct SVGACmdMemory; -#define SVGA_COMBINE_USERBUFFERS 1 - /** * Subclass of pipe_screen */ @@ -49,6 +47,8 @@ struct svga_screen struct pipe_screen screen; struct svga_winsys_screen *sws; + SVGA3dHardwareVersion hw_version; + unsigned use_ps30; unsigned use_vs30; diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c index 958d00393f2..7c393a1da8d 100644 --- a/src/gallium/drivers/svga/svga_state_vdecl.c +++ b/src/gallium/drivers/svga/svga_state_vdecl.c @@ -78,7 +78,6 @@ upload_user_buffers( struct svga_context *svga ) buffer->b.b.width0); } - pipe_resource_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer ); svga->curr.vb[i].buffer_offset = buffer->uploaded.offset; } } @@ -110,6 +109,7 @@ static int emit_hw_vs_vdecl( struct svga_context *svga, for (i = 0; i < svga->curr.velems->count; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; unsigned usage, index; + struct svga_buffer *buffer = svga_buffer(vb->buffer); svga_generate_vdecl_semantics( i, &usage, &index ); @@ -127,6 +127,7 @@ static int emit_hw_vs_vdecl( struct svga_context *svga, svga_hwtnl_vdecl( svga->hwtnl, i, &decl, + buffer->uploaded.buffer ? buffer->uploaded.buffer : vb->buffer ); } @@ -148,14 +149,10 @@ static int emit_hw_vdecl( struct svga_context *svga, * userbuffers now and try to combine multiple userbuffers from * multiple draw calls into a single host buffer for performance. */ - if (svga->curr.any_user_vertex_buffers && - SVGA_COMBINE_USERBUFFERS) - { + if (svga->curr.any_user_vertex_buffers) { ret = upload_user_buffers( svga ); if (ret) return ret; - - svga->curr.any_user_vertex_buffers = FALSE; } return emit_hw_vs_vdecl( svga, dirty ); diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h index 5e4bdeff2ee..ae61cea083f 100644 --- a/src/gallium/drivers/svga/svga_winsys.h +++ b/src/gallium/drivers/svga/svga_winsys.h @@ -136,6 +136,9 @@ struct svga_winsys_screen void (*destroy)(struct svga_winsys_screen *sws); + SVGA3dHardwareVersion + (*get_hw_version)(struct svga_winsys_screen *sws); + boolean (*get_cap)(struct svga_winsys_screen *sws, SVGA3dDevCapIndex index, @@ -243,12 +246,12 @@ struct svga_winsys_screen /** * Map the entire data store of a buffer object into the client's address. - * flags is a bitmaks of PIPE_TRANSFER_* + * usage is a bitmask of PIPE_TRANSFER_* */ void * (*buffer_map)( struct svga_winsys_screen *sws, struct svga_winsys_buffer *buf, - unsigned flags ); + unsigned usage ); void (*buffer_unmap)( struct svga_winsys_screen *sws, |