diff options
author | Chia-I Wu <[email protected]> | 2013-07-14 03:56:44 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2013-07-14 05:59:52 +0800 |
commit | 62c546bbf87afe32e49c100e245e04bc35304481 (patch) | |
tree | dfe218a3ebc658b1fa7e381877ff2bb43df2f39a /src/gallium/drivers/ilo/ilo_state.c | |
parent | 6bcbb0dc82f9f72c747ef39ed80a4ee0d883ce8e (diff) |
ilo: skip 3DSTATE_INDEX_BUFFER when possible
When only the offset to the index buffer is changed, we can skip the
3DSTATE_INDEX_BUFFER if we always use 0 for the offset, and add
(offset / index_size) to Start Vertex Location in 3DPRIMITIVE.
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_state.c')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.c | 106 |
1 files changed, 59 insertions, 47 deletions
diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 070bc288528..59cc8ff3621 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -128,39 +128,53 @@ finalize_constant_buffers(struct ilo_context *ilo) static void finalize_index_buffer(struct ilo_context *ilo) { - struct pipe_resource *res; - unsigned offset, size; - bool uploaded = false; + const struct pipe_resource *current_hw_res = ilo->ib.hw_resource; + const bool need_upload = (ilo->draw->indexed && + (ilo->ib.user_buffer || ilo->ib.offset % ilo->ib.index_size)); - if (!ilo->draw->indexed) + if (!(ilo->dirty & ILO_DIRTY_IB) && !need_upload) return; - res = ilo->ib.resource; - offset = ilo->ib.state.index_size * ilo->draw->start; - size = ilo->ib.state.index_size * ilo->draw->count; + if (need_upload) { + const unsigned offset = ilo->ib.index_size * ilo->draw->start; + const unsigned size = ilo->ib.index_size * ilo->draw->count; + unsigned hw_offset; - if (ilo->ib.state.user_buffer) { - u_upload_data(ilo->uploader, 0, size, - ilo->ib.state.user_buffer + offset, &offset, &res); - uploaded = true; - } - else if (unlikely(ilo->ib.state.offset % ilo->ib.state.index_size)) { - u_upload_buffer(ilo->uploader, 0, ilo->ib.state.offset + offset, size, - ilo->ib.state.buffer, &offset, &res); - uploaded = true; - } - - if (uploaded) { - ilo->ib.resource = res; + if (ilo->ib.user_buffer) { + u_upload_data(ilo->uploader, 0, size, + ilo->ib.user_buffer + offset, &hw_offset, &ilo->ib.hw_resource); + } + else { + u_upload_buffer(ilo->uploader, 0, ilo->ib.offset + offset, size, + ilo->ib.buffer, &hw_offset, &ilo->ib.hw_resource); + } - assert(offset % ilo->ib.state.index_size == 0); - ilo->ib.draw_start_offset = offset / ilo->ib.state.index_size; + /* the HW offset should be aligned */ + assert(hw_offset % ilo->ib.index_size == 0); + ilo->ib.draw_start_offset = hw_offset / ilo->ib.index_size; - /* could be negative */ + /* + * INDEX[ilo->draw->start] in the original buffer is INDEX[0] in the HW + * resource + */ ilo->ib.draw_start_offset -= ilo->draw->start; + } + else { + pipe_resource_reference(&ilo->ib.hw_resource, ilo->ib.buffer); - ilo->dirty |= ILO_DIRTY_IB; + /* note that index size may be zero when the draw is not indexed */ + if (ilo->draw->indexed) + ilo->ib.draw_start_offset = ilo->ib.offset / ilo->ib.index_size; + else + ilo->ib.draw_start_offset = 0; } + + /* treat the IB as clean if the HW states do not change */ + if (ilo->ib.hw_resource == current_hw_res && + ilo->ib.hw_index_size == ilo->ib.index_size) + ilo->dirty &= ~ILO_DIRTY_IB; + else + ilo->ib.hw_index_size = ilo->ib.index_size; } /** @@ -906,28 +920,16 @@ ilo_set_index_buffer(struct pipe_context *pipe, struct ilo_context *ilo = ilo_context(pipe); if (state) { - pipe_resource_reference(&ilo->ib.state.buffer, state->buffer); - ilo->ib.state.offset = state->offset; - ilo->ib.state.index_size = state->index_size; - - /* state->offset does not apply for user buffer */ - ilo->ib.state.user_buffer = state->user_buffer; - - /* - * when there is no state->buffer or state->offset is misaligned, - * ilo_finalize_3d_states() will set these to the valid values - */ - pipe_resource_reference(&ilo->ib.resource, state->buffer); - ilo->ib.draw_start_offset = state->offset / state->index_size; + pipe_resource_reference(&ilo->ib.buffer, state->buffer); + ilo->ib.user_buffer = state->user_buffer; + ilo->ib.offset = state->offset; + ilo->ib.index_size = state->index_size; } else { - pipe_resource_reference(&ilo->ib.state.buffer, NULL); - ilo->ib.state.offset = 0; - ilo->ib.state.index_size = 0; - ilo->ib.state.user_buffer = NULL; - - pipe_resource_reference(&ilo->ib.resource, NULL); - ilo->ib.draw_start_offset = 0; + pipe_resource_reference(&ilo->ib.buffer, NULL); + ilo->ib.user_buffer = NULL; + ilo->ib.offset = 0; + ilo->ib.index_size = 0; } ilo->dirty |= ILO_DIRTY_IB; @@ -1302,8 +1304,8 @@ ilo_cleanup_states(struct ilo_context *ilo) pipe_resource_reference(&ilo->vb.states[i].buffer, NULL); } - pipe_resource_reference(&ilo->ib.state.buffer, NULL); - pipe_resource_reference(&ilo->ib.resource, NULL); + pipe_resource_reference(&ilo->ib.buffer, NULL); + pipe_resource_reference(&ilo->ib.hw_resource, NULL); for (i = 0; i < ilo->so.count; i++) pipe_so_target_reference(&ilo->so.states[i], NULL); @@ -1358,9 +1360,19 @@ ilo_mark_states_with_resource_dirty(struct ilo_context *ilo, } } - if (ilo->ib.state.buffer == res) + if (ilo->ib.buffer == res) { states |= ILO_DIRTY_IB; + /* + * finalize_index_buffer() has an optimization that clears + * ILO_DIRTY_IB when the HW states do not change. However, it fails + * to flush the VF cache when the HW states do not change, but the + * contents of the IB has changed. Here, we set the index size to an + * invalid value to avoid the optimization. + */ + ilo->ib.hw_index_size = 0; + } + for (i = 0; i < ilo->so.count; i++) { if (ilo->so.states[i]->buffer == res) { states |= ILO_DIRTY_SO; |