From 8d0a540020f6389ca5efcd0e1fbef45a4a1f5b6a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 29 Jan 2011 13:58:02 +0100 Subject: [PATCH] r300g: rework vertex format fallback 1) Only translate the [min_index, max_index] range. 2) Upload translated vertices via the uploader. 3) Rename valid_vertex_buffer[] to real_vertex_buffer[] --- src/gallium/drivers/r300/r300_context.c | 4 +- src/gallium/drivers/r300/r300_context.h | 4 +- src/gallium/drivers/r300/r300_emit.c | 8 +- src/gallium/drivers/r300/r300_render.c | 8 +- .../drivers/r300/r300_render_translate.c | 118 ++++++++++-------- src/gallium/drivers/r300/r300_screen_buffer.c | 13 +- src/gallium/drivers/r300/r300_state.c | 9 +- 7 files changed, 86 insertions(+), 78 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index c8966ee59a5..114fb316c05 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -84,9 +84,9 @@ static void r300_release_referenced_objects(struct r300_context *r300) pipe_resource_reference(&r300->vbo, NULL); /* Vertex buffers. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { + for (i = 0; i < r300->real_vertex_buffer_count; i++) { pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); + pipe_resource_reference(&r300->real_vertex_buffer[i], NULL); } /* If there are any queries pending or not destroyed, remove them now. */ diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 57ecfb168f8..430a0ddbb5c 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -445,6 +445,7 @@ struct r300_translate_context { /* Saved and new vertex element state. */ void *saved_velems, *new_velems; + unsigned vb_slot; }; struct r300_context { @@ -560,8 +561,9 @@ struct r300_context { /* May contain user buffers. */ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; /* Contains only non-user buffers. */ - struct pipe_resource *valid_vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS]; int vertex_buffer_count; + int real_vertex_buffer_count; /* with the translated buffer. */ int vertex_buffer_max_index; boolean any_user_vbs; /* Vertex elements for Gallium. */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 2157cb3ede7..34f87f74d3e 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -847,7 +847,7 @@ static void r300_update_vertex_arrays_cb(struct r300_context *r300, unsigned pac void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_resource **valid_vbuf = r300->valid_vertex_buffer; + struct pipe_resource **valid_vbuf = r300->real_vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; struct r300_buffer *buf; int i; @@ -1227,9 +1227,9 @@ validate: r300_buffer(r300->vbo)->domain, 0); /* ...vertex buffers for HWTCL path... */ if (do_validate_vertex_buffers) { - struct pipe_resource **buf = r300->valid_vertex_buffer; - struct pipe_resource **last = r300->valid_vertex_buffer + - r300->vertex_buffer_count; + struct pipe_resource **buf = r300->real_vertex_buffer; + struct pipe_resource **last = r300->real_vertex_buffer + + r300->real_vertex_buffer_count; for (; buf != last; buf++) { if (!*buf) continue; diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index b35822c82f8..41ddd748bbf 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -325,7 +325,7 @@ static boolean immd_is_good_idea(struct r300_context *r300, vbi = velem->vertex_buffer_index; if (!checked[vbi]) { - buf = r300->valid_vertex_buffer[vbi]; + buf = r300->real_vertex_buffer[vbi]; if (!(r300_buffer(buf)->domain & R300_DOMAIN_GTT)) { return FALSE; @@ -390,7 +390,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Map the buffer. */ if (!transfer[vbi]) { map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, - r300->valid_vertex_buffer[vbi], + r300->real_vertex_buffer[vbi], PIPE_TRANSFER_READ, &transfer[vbi]); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; @@ -787,7 +787,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, (indexed ? PREP_INDEXED : 0), indexed ? 256 : 6); - for (i = 0; i < r300->vertex_buffer_count; i++) { + for (i = 0; i < r300->real_vertex_buffer_count; i++) { if (r300->vertex_buffer[i].buffer) { void *buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, @@ -810,7 +810,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, draw_flush(r300->draw); r300->draw_vbo_locked = FALSE; - for (i = 0; i < r300->vertex_buffer_count; i++) { + for (i = 0; i < r300->real_vertex_buffer_count; i++) { if (r300->vertex_buffer[i].buffer) { pipe_buffer_unmap(pipe, vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c index c48062c8084..3b544ae63b7 100644 --- a/src/gallium/drivers/r300/r300_render_translate.c +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -30,9 +30,8 @@ #include "r300_context.h" #include "translate/translate.h" #include "util/u_index_modify.h" +#include "util/u_upload_mgr.h" -/* XXX Optimization: use min_index and translate only that range. */ -/* XXX Use the uploader. */ void r300_begin_vertex_translate(struct r300_context *r300, int min_index, int max_index) { @@ -43,11 +42,12 @@ void r300_begin_vertex_translate(struct r300_context *r300, struct translate *tr; struct r300_vertex_element_state *ve = r300->velems; boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; - void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; - struct pipe_resource *out_buffer; - unsigned i, num_verts; - unsigned slot; + uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}; + struct pipe_resource *out_buffer = NULL; + unsigned i, num_verts, out_offset; + struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + boolean flushed; /* Initialize the translate key, i.e. the recipe how vertices should be * translated. */ @@ -59,6 +59,7 @@ void r300_begin_vertex_translate(struct r300_context *r300, /* Check for support. */ if (ve->velem[i].src_format == ve->hw_format[i] && + /* These two are r300-specific. */ (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 && vb->stride % 4 == 0) { continue; @@ -66,23 +67,23 @@ void r300_begin_vertex_translate(struct r300_context *r300, /* Workaround for translate: output floats instead of halfs. */ switch (output_format) { - case PIPE_FORMAT_R16_FLOAT: - output_format = PIPE_FORMAT_R32_FLOAT; - output_format_size = 4; - break; - case PIPE_FORMAT_R16G16_FLOAT: - output_format = PIPE_FORMAT_R32G32_FLOAT; - output_format_size = 8; - break; - case PIPE_FORMAT_R16G16B16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32_FLOAT; - output_format_size = 12; - break; - case PIPE_FORMAT_R16G16B16A16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - output_format_size = 16; - break; - default:; + case PIPE_FORMAT_R16_FLOAT: + output_format = PIPE_FORMAT_R32_FLOAT; + output_format_size = 4; + break; + case PIPE_FORMAT_R16G16_FLOAT: + output_format = PIPE_FORMAT_R32G32_FLOAT; + output_format_size = 8; + break; + case PIPE_FORMAT_R16G16B16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + output_format_size = 12; + break; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + output_format_size = 16; + break; + default:; } /* Add this vertex element. */ @@ -91,7 +92,7 @@ void r300_begin_vertex_translate(struct r300_context *r300, te->instance_divisor;*/ te->input_buffer = ve->velem[i].vertex_buffer_index; te->input_format = ve->velem[i].src_format; - te->input_offset = vb->buffer_offset + ve->velem[i].src_offset; + te->input_offset = ve->velem[i].src_offset; te->output_format = output_format; te->output_offset = key.output_stride; @@ -112,19 +113,22 @@ void r300_begin_vertex_translate(struct r300_context *r300, vb_map[i] = pipe_buffer_map(pipe, vb->buffer, PIPE_TRANSFER_READ, &vb_transfer[i]); - tr->set_buffer(tr, i, vb_map[i], vb->stride, max_index); + tr->set_buffer(tr, i, + vb_map[i] + vb->buffer_offset + vb->stride * min_index, + vb->stride, ~0); } } /* Create and map the output buffer. */ - num_verts = max_index + 1; + num_verts = max_index + 1 - min_index; - out_buffer = pipe_buffer_create(&r300->screen->screen, - PIPE_BIND_VERTEX_BUFFER, - key.output_stride * num_verts); + u_upload_alloc(r300->upload_vb, + key.output_stride * min_index, + key.output_stride * num_verts, + &out_offset, &out_buffer, &flushed, + (void**)&out_map); - out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, - &out_transfer); + out_offset -= key.output_stride * min_index; /* Translate. */ tr->run(tr, 0, num_verts, 0, out_map); @@ -136,48 +140,46 @@ void r300_begin_vertex_translate(struct r300_context *r300, } } - pipe_buffer_unmap(pipe, out_transfer); - /* Setup the new vertex buffer in the first free slot. */ - slot = ~0; + r300->tran.vb_slot = ~0; for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; - - if (!vb->buffer) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], out_buffer); - vb->buffer_offset = 0; - vb->stride = key.output_stride; - slot = i; - /* XXX probably need to preserve the real count for u_blitter_save_*. */ - r300->vertex_buffer_count = MAX2(r300->vertex_buffer_count, i+1); + if (!r300->vertex_buffer[i].buffer) { + r300->tran.vb_slot = i; + + if (i >= r300->vertex_buffer_count) { + r300->real_vertex_buffer_count = i+1; + } + + /* r300-specific: */ r300->validate_buffers = TRUE; + r300->vertex_arrays_dirty = TRUE; break; } } - /* XXX This may fail. */ - assert(slot != ~0); - - /* Save and replace vertex elements. */ - { - struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - r300->tran.saved_velems = r300->velems; + if (r300->tran.vb_slot != ~0) { + /* Setup the new vertex buffer. */ + pipe_resource_reference(&r300->real_vertex_buffer[r300->tran.vb_slot], out_buffer); + r300->vertex_buffer[r300->tran.vb_slot].buffer_offset = out_offset; + r300->vertex_buffer[r300->tran.vb_slot].stride = key.output_stride; + /* Setup new vertex elements. */ for (i = 0; i < ve->count; i++) { if (vb_translated[ve->velem[i].vertex_buffer_index]) { te = &key.element[tr_elem_index[i]]; new_velems[i].instance_divisor = ve->velem[i].instance_divisor; new_velems[i].src_format = te->output_format; new_velems[i].src_offset = te->output_offset; - new_velems[i].vertex_buffer_index = slot; + new_velems[i].vertex_buffer_index = r300->tran.vb_slot; } else { memcpy(&new_velems[i], &ve->velem[i], sizeof(struct pipe_vertex_element)); } } + r300->tran.saved_velems = r300->velems; r300->tran.new_velems = - pipe->create_vertex_elements_state(pipe, ve->count, new_velems); + pipe->create_vertex_elements_state(pipe, ve->count, new_velems); pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems); } @@ -188,9 +190,19 @@ void r300_end_vertex_translate(struct r300_context *r300) { struct pipe_context *pipe = &r300->context; + if (r300->tran.new_velems == NULL) { + return; + } + /* Restore vertex elements. */ pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems); + r300->tran.saved_velems = NULL; pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems); + r300->tran.new_velems = NULL; + + /* Delete the now-unused VBO. */ + pipe_resource_reference(&r300->real_vertex_buffer[r300->tran.vb_slot], NULL); + r300->real_vertex_buffer_count = r300->vertex_buffer_count; } /* XXX Use the uploader. */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index cc3c1d7687e..af6fa1048c8 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -87,7 +87,7 @@ void r300_upload_user_buffers(struct r300_context *r300, int i, nr = r300->velems->count; unsigned count = max_index + 1 - min_index; boolean flushed; - boolean uploaded[16] = {0}; + boolean uploaded[32] = {0}; for (i = 0; i < nr; i++) { unsigned index = r300->velems->velem[i].vertex_buffer_index; @@ -105,16 +105,10 @@ void r300_upload_user_buffers(struct r300_context *r300, size = r300->velems->hw_format_size[i]; } - DBG(r300, DBG_UPLOAD, - "Uploading %i bytes, index: %i, buffer: %p, userptr: %p " - "offset: %i, stride: %i.\n", - size, index, userbuf, userbuf->user_buffer, - vb->buffer_offset, vb->stride); - u_upload_data(r300->upload_vb, first, size, userbuf->user_buffer + first, &vb->buffer_offset, - &r300->valid_vertex_buffer[index], + &r300->real_vertex_buffer[index], &flushed); vb->buffer_offset -= first; @@ -127,10 +121,9 @@ void r300_upload_user_buffers(struct r300_context *r300, } uploaded[index] = TRUE; } else { - assert(r300->valid_vertex_buffer[index]); + assert(r300->real_vertex_buffer[index]); } } - DBG(r300, DBG_UPLOAD, "-------\n"); } static void r300_buffer_destroy(struct pipe_screen *screen, diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index ba456d413f6..dad41ab91ed 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1560,21 +1560,22 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, /* Reference our buffer. */ pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); if (vbo->buffer && r300_is_user_buffer(vbo->buffer)) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); + pipe_resource_reference(&r300->real_vertex_buffer[i], NULL); } else { - pipe_resource_reference(&r300->valid_vertex_buffer[i], vbo->buffer); + pipe_resource_reference(&r300->real_vertex_buffer[i], vbo->buffer); } } - for (; i < r300->vertex_buffer_count; i++) { + for (; i < r300->real_vertex_buffer_count; i++) { /* Dereference any old buffers. */ pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); + pipe_resource_reference(&r300->real_vertex_buffer[i], NULL); } memcpy(r300->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); r300->vertex_buffer_count = count; + r300->real_vertex_buffer_count = count; } static void r300_set_index_buffer(struct pipe_context* pipe, -- 2.30.2