summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2011-01-28 22:04:09 +0100
committerMarek Olšák <maraeo@gmail.com>2011-01-30 03:29:48 +0100
commit8c631cfeae29b5236928f759e222aa35e6e4984c (patch)
treee33a9fbf1e7f929dbfe5524ffe01dfc102749b6b
parent15730a8207374936e354d945730070cb29c9547c (diff)
r600g: rework vertex buffer uploads
Only upload the [min_index, max_index] range instead of [0, userbuf_size]. This an important optimization. Framerate in Lightsmark: Before: 22 fps After: 75 fps The same optimization is already in r300g.
-rw-r--r--src/gallium/drivers/r600/r600_buffer.c65
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h5
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c120
3 files changed, 106 insertions, 84 deletions
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index 024bbc29168..6ebe6ab2364 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -201,39 +201,52 @@ struct u_resource_vtbl r600_buffer_vtbl =
201 201
202void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw) 202void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw)
203{ 203{
204 204 struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer);
205 if (r600_is_user_buffer(draw->index_buffer)) { 205 boolean flushed;
206 struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer); 206
207 boolean flushed; 207 u_upload_data(rctx->upload_vb, 0,
208 208 draw->info.count * draw->index_size,
209 u_upload_data(rctx->upload_vb, 0, 209 rbuffer->user_buffer,
210 draw->info.count * draw->index_size, 210 &draw->index_buffer_offset,
211 rbuffer->user_buffer, 211 &draw->index_buffer, &flushed);
212 &draw->index_buffer_offset,
213 &draw->index_buffer, &flushed);
214 }
215} 212}
216 213
217void r600_upload_user_buffers(struct r600_pipe_context *rctx) 214void r600_upload_user_buffers(struct r600_pipe_context *rctx,
215 int min_index, int max_index)
218{ 216{
219 int i, nr; 217 int i, nr = rctx->vertex_elements->count;
220 218 unsigned count = max_index + 1 - min_index;
221 nr = rctx->vertex_elements->count; 219 boolean flushed;
222 nr = rctx->nvertex_buffer; 220 boolean uploaded[32] = {0};
223 221
224 for (i = 0; i < nr; i++) { 222 for (i = 0; i < nr; i++) {
225 struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; 223 unsigned index = rctx->vertex_elements->elements[i].vertex_buffer_index;
226 224 struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[index];
227 if (r600_is_user_buffer(vb->buffer)) { 225 struct r600_resource_buffer *userbuf = r600_buffer(vb->buffer);
228 struct r600_resource_buffer *rbuffer = r600_buffer(vb->buffer); 226
229 boolean flushed; 227 if (userbuf && userbuf->user_buffer && !uploaded[index]) {
230 228 unsigned first, size;
231 u_upload_data(rctx->upload_vb, 0, 229
232 vb->buffer->width0, 230 if (vb->stride) {
233 rbuffer->user_buffer, 231 first = vb->stride * min_index;
232 size = vb->stride * count;
233 } else {
234 first = 0;
235 size = rctx->vertex_elements->hw_format_size[i];
236 }
237
238 u_upload_data(rctx->upload_vb, first, size,
239 userbuf->user_buffer + first,
234 &vb->buffer_offset, 240 &vb->buffer_offset,
235 &vb->buffer, 241 &rctx->real_vertex_buffer[index],
236 &flushed); 242 &flushed);
243
244 vb->buffer_offset -= first;
245
246 /* vertex_arrays_dirty = TRUE; */
247 uploaded[index] = TRUE;
248 } else {
249 assert(rctx->real_vertex_buffer[index]);
237 } 250 }
238 } 251 }
239} 252}
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index a0164868f34..360ee2af1fc 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -144,6 +144,7 @@ struct r600_pipe_context {
144 struct pipe_framebuffer_state framebuffer; 144 struct pipe_framebuffer_state framebuffer;
145 struct pipe_index_buffer index_buffer; 145 struct pipe_index_buffer index_buffer;
146 struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; 146 struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
147 struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS];
147 unsigned nvertex_buffer; 148 unsigned nvertex_buffer;
148 unsigned cb_target_mask; 149 unsigned cb_target_mask;
149 /* for saving when using blitter */ 150 /* for saving when using blitter */
@@ -207,7 +208,8 @@ unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
207struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, 208struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
208 struct winsys_handle *whandle); 209 struct winsys_handle *whandle);
209void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); 210void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw);
210void r600_upload_user_buffers(struct r600_pipe_context *rctx); 211void r600_upload_user_buffers(struct r600_pipe_context *rctx,
212 int min_index, int max_index);
211 213
212/* r600_query.c */ 214/* r600_query.c */
213void r600_init_query_functions(struct r600_pipe_context *rctx); 215void r600_init_query_functions(struct r600_pipe_context *rctx);
@@ -279,7 +281,6 @@ void r600_delete_ps_shader(struct pipe_context *ctx, void *state);
279void r600_delete_vs_shader(struct pipe_context *ctx, void *state); 281void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
280void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, 282void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
281 struct pipe_resource *buffer); 283 struct pipe_resource *buffer);
282void r600_vertex_buffer_update(struct r600_pipe_context *rctx);
283void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info); 284void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info);
284 285
285/* 286/*
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 26e5981e982..409a07bda17 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -121,20 +121,10 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state)
121 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 121 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
122 struct r600_vertex_element *v = (struct r600_vertex_element*)state; 122 struct r600_vertex_element *v = (struct r600_vertex_element*)state;
123 123
124 /* delete previous translated vertex elements */
125 if (rctx->tran.new_velems) {
126 r600_end_vertex_translate(rctx);
127 }
128
129 rctx->vertex_elements = v; 124 rctx->vertex_elements = v;
130 if (v) { 125 if (v) {
131 rctx->states[v->rstate.id] = &v->rstate; 126 rctx->states[v->rstate.id] = &v->rstate;
132 r600_context_pipe_state_set(&rctx->ctx, &v->rstate); 127 r600_context_pipe_state_set(&rctx->ctx, &v->rstate);
133 r600_vertex_buffer_update(rctx);
134 }
135
136 if (v) {
137// rctx->vs_rebuild = TRUE;
138 } 128 }
139} 129}
140 130
@@ -175,45 +165,62 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
175{ 165{
176 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 166 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
177 struct pipe_vertex_buffer *vbo; 167 struct pipe_vertex_buffer *vbo;
178 unsigned max_index = (unsigned)-1; 168 unsigned max_index = ~0;
179 169 int i;
180 if (rctx->family >= CHIP_CEDAR) {
181 for (int i = 0; i < rctx->nvertex_buffer; i++) {
182 pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
183 evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
184 }
185 } else {
186 for (int i = 0; i < rctx->nvertex_buffer; i++) {
187 pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
188 r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
189 }
190 }
191 memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count);
192 170
193 for (int i = 0; i < count; i++) { 171 for (i = 0; i < count; i++) {
194 vbo = (struct pipe_vertex_buffer*)&buffers[i]; 172 vbo = (struct pipe_vertex_buffer*)&buffers[i];
195 173
196 rctx->vertex_buffer[i].buffer = NULL; 174 pipe_resource_reference(&rctx->vertex_buffer[i].buffer, vbo->buffer);
197 if (buffers[i].buffer == NULL) 175 pipe_resource_reference(&rctx->real_vertex_buffer[i], NULL);
176
177 if (!vbo->buffer) {
178 /* Zero states. */
179 if (rctx->family >= CHIP_CEDAR) {
180 evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
181 } else {
182 r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
183 }
198 continue; 184 continue;
199 if (r600_is_user_buffer(buffers[i].buffer)) 185 }
186
187 if (r600_is_user_buffer(vbo->buffer)) {
200 rctx->any_user_vbs = TRUE; 188 rctx->any_user_vbs = TRUE;
201 pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); 189 continue;
190 }
191
192 pipe_resource_reference(&rctx->real_vertex_buffer[i], vbo->buffer);
202 193
203 /* The stride of zero means we will be fetching only the first 194 /* The stride of zero means we will be fetching only the first
204 * vertex, so don't care about max_index. */ 195 * vertex, so don't care about max_index. */
205 if (!vbo->stride) 196 if (!vbo->stride) {
206 continue; 197 continue;
198 }
207 199
208 if (vbo->max_index == ~0) { 200 /* Update the maximum index. */
209 vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; 201 {
202 unsigned vbo_max_index =
203 (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
204 max_index = MIN2(max_index, vbo_max_index);
210 } 205 }
211 max_index = MIN2(vbo->max_index, max_index);
212 } 206 }
207
208 for (; i < rctx->nvertex_buffer; i++) {
209 pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
210 pipe_resource_reference(&rctx->real_vertex_buffer[i], NULL);
211
212 /* Zero states. */
213 if (rctx->family >= CHIP_CEDAR) {
214 evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
215 } else {
216 r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
217 }
218 }
219
220 memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count);
221
213 rctx->nvertex_buffer = count; 222 rctx->nvertex_buffer = count;
214 rctx->vb_max_index = max_index; 223 rctx->vb_max_index = max_index;
215
216 r600_vertex_buffer_update(rctx);
217} 224}
218 225
219 226
@@ -407,30 +414,13 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
407 pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL); 414 pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL);
408} 415}
409 416
410void r600_vertex_buffer_update(struct r600_pipe_context *rctx) 417static void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
411{ 418{
412 struct r600_pipe_state *rstate; 419 struct r600_pipe_state *rstate;
413 struct r600_resource *rbuffer; 420 struct r600_resource *rbuffer;
414 struct pipe_vertex_buffer *vertex_buffer; 421 struct pipe_vertex_buffer *vertex_buffer;
415 unsigned i, offset; 422 unsigned i, offset;
416 423
417 /* we don't update until we know vertex elements */
418 if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer)
419 return;
420
421 if (rctx->vertex_elements->incompatible_layout) {
422 /* translate rebind new vertex elements so
423 * return once translated
424 */
425 r600_begin_vertex_translate(rctx);
426 return;
427 }
428
429 if (rctx->any_user_vbs) {
430 r600_upload_user_buffers(rctx);
431 rctx->any_user_vbs = FALSE;
432 }
433
434 if (rctx->vertex_elements->vbuffer_need_offset) { 424 if (rctx->vertex_elements->vbuffer_need_offset) {
435 /* one resource per vertex elements */ 425 /* one resource per vertex elements */
436 rctx->nvs_resource = rctx->vertex_elements->count; 426 rctx->nvs_resource = rctx->vertex_elements->count;
@@ -449,12 +439,12 @@ void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
449 unsigned vbuffer_index; 439 unsigned vbuffer_index;
450 vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; 440 vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index;
451 vertex_buffer = &rctx->vertex_buffer[vbuffer_index]; 441 vertex_buffer = &rctx->vertex_buffer[vbuffer_index];
452 rbuffer = (struct r600_resource*)vertex_buffer->buffer; 442 rbuffer = (struct r600_resource*)rctx->real_vertex_buffer[vbuffer_index];
453 offset = rctx->vertex_elements->vbuffer_offset[i]; 443 offset = rctx->vertex_elements->vbuffer_offset[i];
454 } else { 444 } else {
455 /* bind vertex buffer once */ 445 /* bind vertex buffer once */
456 vertex_buffer = &rctx->vertex_buffer[i]; 446 vertex_buffer = &rctx->vertex_buffer[i];
457 rbuffer = (struct r600_resource*)vertex_buffer->buffer; 447 rbuffer = (struct r600_resource*)rctx->real_vertex_buffer[i];
458 offset = 0; 448 offset = 0;
459 } 449 }
460 if (vertex_buffer == NULL || rbuffer == NULL) 450 if (vertex_buffer == NULL || rbuffer == NULL)
@@ -483,6 +473,16 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
483 struct r600_drawl draw = {}; 473 struct r600_drawl draw = {};
484 unsigned prim; 474 unsigned prim;
485 475
476 if (rctx->vertex_elements->incompatible_layout) {
477 r600_begin_vertex_translate(rctx);
478 }
479
480 if (rctx->any_user_vbs) {
481 r600_upload_user_buffers(rctx, info->min_index, info->max_index);
482 }
483
484 r600_vertex_buffer_update(rctx);
485
486 draw.info = *info; 486 draw.info = *info;
487 draw.ctx = ctx; 487 draw.ctx = ctx;
488 if (info->indexed && rctx->index_buffer.buffer) { 488 if (info->indexed && rctx->index_buffer.buffer) {
@@ -497,7 +497,10 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
497 pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer); 497 pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer);
498 draw.index_buffer_offset = draw.info.start * draw.index_size; 498 draw.index_buffer_offset = draw.info.start * draw.index_size;
499 draw.info.start = 0; 499 draw.info.start = 0;
500 r600_upload_index_buffer(rctx, &draw); 500
501 if (r600_is_user_buffer(draw.index_buffer)) {
502 r600_upload_index_buffer(rctx, &draw);
503 }
501 } else { 504 } else {
502 draw.info.index_bias = info->start; 505 draw.info.index_bias = info->start;
503 } 506 }
@@ -572,4 +575,9 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
572 } 575 }
573 576
574 pipe_resource_reference(&draw.index_buffer, NULL); 577 pipe_resource_reference(&draw.index_buffer, NULL);
578
579 /* delete previous translated vertex elements */
580 if (rctx->tran.new_velems) {
581 r600_end_vertex_translate(rctx);
582 }
575} 583}