X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_screen_buffer.c;h=c92ec56507c2f679b7951ce59a4eeaa3d4c22652;hb=ff5a9868c8d5041a3d944ce300c857934f4e8251;hp=3e2b5afe6f439da74b512f62ffc6a63fd6abcc08;hpb=b4a191e351ff1ac1cd27cd7e02d169958a78ca86;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 3e2b5afe6f4..c92ec56507c 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -31,294 +31,166 @@ #include "util/u_math.h" #include "r300_screen_buffer.h" -#include "r300_winsys.h" -unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - enum r300_reference_domain domain) +void r300_upload_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned index_size, unsigned *start, + unsigned count, const uint8_t *ptr) { - struct r300_context *r300 = r300_context(context); - struct r300_buffer *rbuf = r300_buffer(buf); - - if (r300_buffer_is_user_buffer(buf)) - return PIPE_UNREFERENCED; - - if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf, domain)) - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; - - return PIPE_UNREFERENCED; -} - -static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned face, unsigned level) -{ - return r300_buffer_is_referenced(context, buf, R300_REF_CS); -} - -/* External helper, not required to implent u_resource_vtbl: - */ -int r300_upload_index_buffer(struct r300_context *r300, - struct pipe_resource **index_buffer, - unsigned index_size, - unsigned start, - unsigned count) -{ - struct pipe_resource *upload_buffer = NULL; - unsigned index_offset = start * index_size; - int ret = 0; - - if (r300_buffer_is_user_buffer(*index_buffer)) { - ret = u_upload_buffer(r300->upload_ib, - index_offset, - count * index_size, - *index_buffer, - &index_offset, - &upload_buffer); - if (ret) { - goto done; - } - *index_buffer = upload_buffer; - } - done: - // if (upload_buffer) - // pipe_resource_reference(&upload_buffer, NULL); - return ret; -} + unsigned index_offset; -/* External helper, not required to implement u_resource_vtbl: - */ -int r300_upload_user_buffers(struct r300_context *r300) -{ - enum pipe_error ret = PIPE_OK; - int i, nr; - - nr = r300->vertex_buffer_count; - - for (i = 0; i < nr; i++) { - if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { - struct pipe_resource *upload_buffer = NULL; - unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ - unsigned size = r300->vertex_buffer[i].buffer->width0; - unsigned upload_offset; - ret = u_upload_buffer(r300->upload_vb, - offset, size, - r300->vertex_buffer[i].buffer, - &upload_offset, &upload_buffer); - if (ret) - return ret; - - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - r300->vertex_buffer[i].buffer = upload_buffer; - r300->vertex_buffer[i].buffer_offset = upload_offset; - } - } - return ret; -} + *index_buffer = NULL; -static struct r300_winsys_buffer * -r300_winsys_buffer_create(struct r300_screen *r300screen, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct r300_winsys_screen *rws = r300screen->rws; - struct r300_winsys_buffer *buf; + u_upload_data(r300->uploader, + 0, count * index_size, + ptr + (*start * index_size), + &index_offset, + index_buffer); - buf = rws->buffer_create(rws, alignment, usage, size); - return buf; -} - -static void r300_winsys_buffer_destroy(struct r300_screen *r300screen, - struct r300_buffer *rbuf) -{ - struct r300_winsys_screen *rws = r300screen->rws; - - if (rbuf->buf) { - rws->buffer_reference(rws, &rbuf->buf, NULL); - rbuf->buf = NULL; - } + *start = index_offset / index_size; } static void r300_buffer_destroy(struct pipe_screen *screen, struct pipe_resource *buf) { - struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_resource *rbuf = r300_resource(buf); + + align_free(rbuf->malloced_buffer); + + if (rbuf->buf) + pb_reference(&rbuf->buf, NULL); - r300_winsys_buffer_destroy(r300screen, rbuf); FREE(rbuf); } static void * -r300_buffer_transfer_map( struct pipe_context *pipe, - struct pipe_transfer *transfer ) +r300_buffer_transfer_map( struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **ptransfer ) { - struct r300_screen *r300screen = r300_screen(pipe->screen); - struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_context *r300 = r300_context(context); + struct radeon_winsys *rws = r300->screen->rws; + struct r300_resource *rbuf = r300_resource(resource); + struct pipe_transfer *transfer; uint8_t *map; - boolean flush = FALSE; - unsigned i; - if (rbuf->user_buffer) - return (uint8_t *) rbuf->user_buffer + transfer->box.x; + transfer = util_slab_alloc(&r300->pool_transfers); + transfer->resource = resource; + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; + transfer->stride = 0; + transfer->layer_stride = 0; + + if (rbuf->malloced_buffer) { + *ptransfer = transfer; + return rbuf->malloced_buffer + box->x; + } - if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) { - goto just_map; + if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE && + !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + assert(usage & PIPE_TRANSFER_WRITE); + + /* Check if mapping this buffer would cause waiting for the GPU. */ + if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, RADEON_USAGE_READWRITE) || + r300->rws->buffer_is_busy(rbuf->buf, RADEON_USAGE_READWRITE)) { + unsigned i; + struct pb_buffer *new_buf; + + /* Create a new one in the same pipe_resource. */ + new_buf = r300->rws->buffer_create(r300->rws, + rbuf->b.b.width0, R300_BUFFER_ALIGNMENT, + rbuf->b.b.bind, rbuf->domain); + if (new_buf) { + /* Discard the old buffer. */ + pb_reference(&rbuf->buf, NULL); + rbuf->buf = new_buf; + rbuf->cs_buf = r300->rws->buffer_get_cs_handle(rbuf->buf); + + /* We changed the buffer, now we need to bind it where the old one was bound. */ + for (i = 0; i < r300->nr_vertex_buffers; i++) { + if (r300->vertex_buffer[i].buffer == &rbuf->b.b) { + r300->vertex_arrays_dirty = TRUE; + break; + } + } + } + } } - /* check if the mapping is to a range we already flushed */ - if (transfer->usage & PIPE_TRANSFER_DISCARD) { - for (i = 0; i < rbuf->num_ranges; i++) { - if ((transfer->box.x >= rbuf->ranges[i].start) && - (transfer->box.x < rbuf->ranges[i].end)) - flush = TRUE; - - if (flush) { - /* unreference this hw buffer and allocate a new one */ - rws->buffer_reference(rws, &rbuf->buf, NULL); - - rbuf->num_ranges = 0; - rbuf->buf = r300_winsys_buffer_create(r300screen, - 16, - rbuf->b.b.bind, /* XXX */ - rbuf->b.b.width0); - break; - } - } + /* Buffers are never used for write, therefore mapping for read can be + * unsynchronized. */ + if (!(usage & PIPE_TRANSFER_WRITE)) { + usage |= PIPE_TRANSFER_UNSYNCHRONIZED; } -just_map: - map = rws->buffer_map(rws, rbuf->buf, transfer->usage); - if (map == NULL) - return NULL; + map = rws->buffer_map(rbuf->cs_buf, r300->cs, usage); - /* 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 r300_buffer_transfer_flush_region( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - struct r300_buffer *rbuf = r300_buffer(transfer->resource); - unsigned i; - unsigned offset = transfer->box.x + box->x; - unsigned length = box->width; - - assert(box->x + box->width <= transfer->box.width); - - if (rbuf->user_buffer) - return; - - if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) - return; - - /* mark the range as used */ - for(i = 0; i < rbuf->num_ranges; ++i) { - if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+box->width)) { - rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset); - rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length)); - return; - } + if (map == NULL) { + util_slab_free(&r300->pool_transfers, transfer); + return NULL; } - rbuf->ranges[rbuf->num_ranges].start = offset; - rbuf->ranges[rbuf->num_ranges].end = offset+length; - rbuf->num_ranges++; + *ptransfer = transfer; + return map + box->x; } static void r300_buffer_transfer_unmap( struct pipe_context *pipe, - struct pipe_transfer *transfer ) + struct pipe_transfer *transfer ) { - struct r300_screen *r300screen = r300_screen(pipe->screen); - struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_context *r300 = r300_context(pipe); - if (rbuf->buf) { - rws->buffer_unmap(rws, rbuf->buf); - } + util_slab_free(&r300->pool_transfers, transfer); } -struct u_resource_vtbl r300_buffer_vtbl = +static const struct u_resource_vtbl r300_buffer_vtbl = { - u_default_resource_get_handle, /* get_handle */ - r300_buffer_destroy, /* resource_destroy */ - r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */ - u_default_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ - r300_buffer_transfer_map, /* transfer_map */ - r300_buffer_transfer_flush_region, /* transfer_flush_region */ - r300_buffer_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + NULL, /* get_handle */ + r300_buffer_destroy, /* resource_destroy */ + r300_buffer_transfer_map, /* transfer_map */ + NULL, /* transfer_flush_region */ + r300_buffer_transfer_unmap, /* transfer_unmap */ + NULL /* transfer_inline_write */ }; struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; - unsigned alignment = 16; - - rbuf = CALLOC_STRUCT(r300_buffer); - if (!rbuf) - goto error1; + struct r300_resource *rbuf; - rbuf->magic = R300_BUFFER_MAGIC; + rbuf = MALLOC_STRUCT(r300_resource); rbuf->b.b = *templ; rbuf->b.vtbl = &r300_buffer_vtbl; pipe_reference_init(&rbuf->b.b.reference, 1); rbuf->b.b.screen = screen; + rbuf->domain = RADEON_DOMAIN_GTT; + rbuf->buf = NULL; + rbuf->malloced_buffer = NULL; + + /* Alloc constant buffers and SWTCL buffers in RAM. */ + if (templ->bind & PIPE_BIND_CONSTANT_BUFFER || + (!r300screen->caps.has_tcl && + (templ->bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)))) { + rbuf->malloced_buffer = align_malloc(templ->width0, 64); + return &rbuf->b.b; + } - if (rbuf->b.b.bind & R300_BIND_OQBO) - alignment = 4096; - - rbuf->buf = r300_winsys_buffer_create(r300screen, - alignment, - rbuf->b.b.bind, - rbuf->b.b.width0); - - if (!rbuf->buf) - goto error2; - - return &rbuf->b.b; -error2: - FREE(rbuf); -error1: - return NULL; -} - -struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, - void *ptr, - unsigned bytes, - unsigned bind) -{ - struct r300_buffer *rbuf; - - rbuf = CALLOC_STRUCT(r300_buffer); - if (!rbuf) - goto no_rbuf; + rbuf->buf = + r300screen->rws->buffer_create(r300screen->rws, + rbuf->b.b.width0, R300_BUFFER_ALIGNMENT, + rbuf->b.b.bind, rbuf->domain); + if (!rbuf->buf) { + FREE(rbuf); + return NULL; + } - rbuf->magic = R300_BUFFER_MAGIC; + rbuf->cs_buf = + r300screen->rws->buffer_get_cs_handle(rbuf->buf); - pipe_reference_init(&rbuf->b.b.reference, 1); - rbuf->b.vtbl = &r300_buffer_vtbl; - rbuf->b.b.screen = screen; - rbuf->b.b.format = PIPE_FORMAT_R8_UNORM; - rbuf->b.b.usage = PIPE_USAGE_IMMUTABLE; - rbuf->b.b.bind = bind; - rbuf->b.b.width0 = bytes; - rbuf->b.b.height0 = 1; - rbuf->b.b.depth0 = 1; - - rbuf->user_buffer = ptr; return &rbuf->b.b; - -no_rbuf: - return NULL; }