diff options
author | Marek Olšák <maraeo@gmail.com> | 2011-01-28 22:04:09 +0100 |
---|---|---|
committer | Marek Olšák <maraeo@gmail.com> | 2011-01-30 03:29:48 +0100 |
commit | 8c631cfeae29b5236928f759e222aa35e6e4984c (patch) | |
tree | e33a9fbf1e7f929dbfe5524ffe01dfc102749b6b | |
parent | 15730a8207374936e354d945730070cb29c9547c (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.c | 65 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 120 |
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 | ||
202 | void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw) | 202 | void 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 | ||
217 | void r600_upload_user_buffers(struct r600_pipe_context *rctx) | 214 | void 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, | |||
207 | struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, | 208 | struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, |
208 | struct winsys_handle *whandle); | 209 | struct winsys_handle *whandle); |
209 | void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); | 210 | void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); |
210 | void r600_upload_user_buffers(struct r600_pipe_context *rctx); | 211 | void 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 */ |
213 | void r600_init_query_functions(struct r600_pipe_context *rctx); | 215 | void r600_init_query_functions(struct r600_pipe_context *rctx); |
@@ -279,7 +281,6 @@ void r600_delete_ps_shader(struct pipe_context *ctx, void *state); | |||
279 | void r600_delete_vs_shader(struct pipe_context *ctx, void *state); | 281 | void r600_delete_vs_shader(struct pipe_context *ctx, void *state); |
280 | void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, | 282 | void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, |
281 | struct pipe_resource *buffer); | 283 | struct pipe_resource *buffer); |
282 | void r600_vertex_buffer_update(struct r600_pipe_context *rctx); | ||
283 | void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info); | 284 | void 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 | ||
410 | void r600_vertex_buffer_update(struct r600_pipe_context *rctx) | 417 | static 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 | } |