X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_resource_buffer.c;h=712fffc83d392e43effff93d3b4ae2ba33b864da;hb=4379dcc12d36bf9993a06c628c9426d4f54ba58d;hp=05e91cbfe5a51e587adcb67f6530e48ce7bbbc4f;hpb=ba72554f3e576c1674d52ab16d8d2edff9398b71;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index 05e91cbfe5a..712fffc83d3 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -42,16 +42,40 @@ /** - * Vertex and index buffers need hardware backing. Constant buffers - * do not. No other types of buffers currently supported. + * Determine what buffers eventually need hardware backing. + * + * Vertex- and index buffers need hardware backing. Constant buffers + * do on vgpu10. Staging texture-upload buffers do when they are + * supported. */ static inline boolean -svga_buffer_needs_hw_storage(unsigned usage) +svga_buffer_needs_hw_storage(const struct svga_screen *ss, + const struct pipe_resource *template) { - return (usage & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT)) != 0; -} + unsigned bind_mask = (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT); + + if (ss->sws->have_vgpu10) { + /* + * Driver-created upload const0- and staging texture upload buffers + * tagged with PIPE_BIND_CUSTOM + */ + bind_mask |= PIPE_BIND_CUSTOM; + /* Uniform buffer objects. + * Make sure we don't create hardware storage for state-tracker + * const0 buffers, because we frequently map them for reading. + * They are distinguished by having PIPE_USAGE_STREAM, but not + * PIPE_BIND_CUSTOM. + */ + if (template->usage != PIPE_USAGE_STREAM) + bind_mask |= PIPE_BIND_CONSTANT_BUFFER; + } + + if (template->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) + return TRUE; + return !!(template->bind & bind_mask); +} /** * Create a buffer transfer. @@ -105,7 +129,8 @@ svga_buffer_transfer_map(struct pipe_context *pipe, pipe_resource_reference(&sbuf->translated_indices.buffer, NULL); } - if ((usage & PIPE_TRANSFER_READ) && sbuf->dirty) { + if ((usage & PIPE_TRANSFER_READ) && sbuf->dirty && + !sbuf->key.coherent && !svga->swc->force_coherent) { enum pipe_error ret; /* Host-side buffers can only be dirtied with vgpu10 features @@ -114,10 +139,10 @@ svga_buffer_transfer_map(struct pipe_context *pipe, assert(svga_have_vgpu10(svga)); if (!sbuf->user) { - (void) svga_buffer_handle(svga, resource); + (void) svga_buffer_handle(svga, resource, sbuf->bind_flags); } - if (sbuf->dma.pending > 0) { + if (sbuf->dma.pending) { svga_buffer_upload_flush(svga, sbuf); svga_context_finish(svga); } @@ -139,7 +164,8 @@ svga_buffer_transfer_map(struct pipe_context *pipe, } if (usage & PIPE_TRANSFER_WRITE) { - if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { + if ((usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) && + !(resource->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)) { /* * Flush any pending primitives, finish writing any pending DMA * commands, and tell the host to discard the buffer contents on @@ -224,7 +250,7 @@ svga_buffer_transfer_map(struct pipe_context *pipe, } if (!sbuf->swbuf && !svga_buffer_has_hw_storage(sbuf)) { - if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) { + if (svga_buffer_create_hw_storage(ss, sbuf, sbuf->bind_flags) != PIPE_OK) { /* * We can't create a hardware buffer big enough, so create a malloc * buffer instead. @@ -283,28 +309,30 @@ done: static void -svga_buffer_transfer_flush_region( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) +svga_buffer_transfer_flush_region(struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) { struct svga_screen *ss = svga_screen(pipe->screen); struct svga_buffer *sbuf = svga_buffer(transfer->resource); - + struct svga_context *svga = svga_context(pipe); unsigned offset = transfer->box.x + box->x; unsigned length = box->width; assert(transfer->usage & PIPE_TRANSFER_WRITE); assert(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT); - mtx_lock(&ss->swc_mutex); - svga_buffer_add_range(sbuf, offset, offset + length); - pipe_mutex_unlock(ss->swc_mutex); + if (!(svga->swc->force_coherent || sbuf->key.coherent) || sbuf->swbuf) { + mtx_lock(&ss->swc_mutex); + svga_buffer_add_range(sbuf, offset, offset + length); + mtx_unlock(&ss->swc_mutex); + } } static void -svga_buffer_transfer_unmap( struct pipe_context *pipe, - struct pipe_transfer *transfer ) +svga_buffer_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) { struct svga_screen *ss = svga_screen(pipe->screen); struct svga_context *svga = svga_context(pipe); @@ -320,6 +348,9 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe, } if (svga_buffer_has_hw_storage(sbuf)) { + /* Note: we may wind up flushing here and unmapping other buffers + * which leads to recursively locking ss->swc_mutex. + */ svga_buffer_hw_storage_unmap(svga, sbuf); } @@ -335,22 +366,23 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe, sbuf->dma.flags.discard = TRUE; - svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0); + if (!(svga->swc->force_coherent || sbuf->key.coherent) || sbuf->swbuf) + svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0); } } - pipe_mutex_unlock(ss->swc_mutex); + mtx_unlock(&ss->swc_mutex); FREE(transfer); SVGA_STATS_TIME_POP(svga_sws(svga)); } static void -svga_buffer_destroy( struct pipe_screen *screen, - struct pipe_resource *buf ) +svga_buffer_destroy(struct pipe_screen *screen, + struct pipe_resource *buf) { - struct svga_screen *ss = svga_screen(screen); - struct svga_buffer *sbuf = svga_buffer( buf ); + struct svga_screen *ss = svga_screen(screen); + struct svga_buffer *sbuf = svga_buffer(buf); assert(!p_atomic_read(&buf->reference.count)); @@ -392,10 +424,11 @@ struct u_resource_vtbl svga_buffer_vtbl = struct pipe_resource * svga_buffer_create(struct pipe_screen *screen, - const struct pipe_resource *template) + const struct pipe_resource *template) { struct svga_screen *ss = svga_screen(screen); struct svga_buffer *sbuf; + unsigned bind_flags; SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATEBUFFER); @@ -407,39 +440,47 @@ svga_buffer_create(struct pipe_screen *screen, sbuf->b.vtbl = &svga_buffer_vtbl; pipe_reference_init(&sbuf->b.b.reference, 1); sbuf->b.b.screen = screen; - sbuf->bind_flags = template->bind; + bind_flags = template->bind & ~PIPE_BIND_CUSTOM; + + LIST_INITHEAD(&sbuf->surfaces); - if (template->bind & PIPE_BIND_CONSTANT_BUFFER) { + if (bind_flags & PIPE_BIND_CONSTANT_BUFFER) { /* Constant buffers can only have the PIPE_BIND_CONSTANT_BUFFER * flag set. */ if (ss->sws->have_vgpu10) { - sbuf->bind_flags = PIPE_BIND_CONSTANT_BUFFER; - - /* Constant buffer size needs to be in multiples of 16. */ - sbuf->b.b.width0 = align(sbuf->b.b.width0, 16); + bind_flags = PIPE_BIND_CONSTANT_BUFFER; } } - if (svga_buffer_needs_hw_storage(template->bind)) { + /* Although svga device only requires constant buffer size to be + * in multiples of 16, in order to allow bind_flags promotion, + * we are mandating all buffer size to be in multiples of 16. + */ + sbuf->b.b.width0 = align(sbuf->b.b.width0, 16); + + if (svga_buffer_needs_hw_storage(ss, template)) { - /* If the buffer will be used for vertex/index/stream data, set all - * the flags so that the buffer will be accepted for all those uses. + /* If the buffer is not used for constant buffer, set + * the vertex/index bind flags as well so that the buffer will be + * accepted for those uses. * Note that the PIPE_BIND_ flags we get from the state tracker are * just a hint about how the buffer may be used. And OpenGL buffer * object may be used for many different things. + * Also note that we do not unconditionally set the streamout + * bind flag since streamout buffer is an output buffer and + * might have performance implication. */ - if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) { - /* Not a constant buffer. The buffer may be used for vertex data, - * indexes or stream-out. + if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER) && + !(template->bind & PIPE_BIND_CUSTOM)) { + /* Not a constant- or staging buffer. + * The buffer may be used for vertex data or indexes. */ - sbuf->bind_flags |= (PIPE_BIND_VERTEX_BUFFER | - PIPE_BIND_INDEX_BUFFER); - if (ss->sws->have_vgpu10) - sbuf->bind_flags |= PIPE_BIND_STREAM_OUTPUT; + bind_flags |= (PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER); } - if (svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK) + if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK) goto error2; } else { @@ -451,6 +492,7 @@ svga_buffer_create(struct pipe_screen *screen, debug_reference(&sbuf->b.b.reference, (debug_reference_descriptor)debug_describe_resource, 0); + sbuf->bind_flags = bind_flags; sbuf->size = util_resource_size(&sbuf->b.b); ss->hud.total_resource_bytes += sbuf->size; @@ -471,7 +513,7 @@ struct pipe_resource * svga_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned bytes, - unsigned bind) + unsigned bind) { struct svga_buffer *sbuf; struct svga_screen *ss = svga_screen(screen); @@ -505,6 +547,3 @@ svga_user_buffer_create(struct pipe_screen *screen, no_sbuf: return NULL; } - - -