From c7e9b15010c32302d3cceac06ff8c34619deab7c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 13 Jun 2013 18:22:40 +0800 Subject: [PATCH] ilo: mapping a resource may make some states dirty When a resource is busy and is mapped with PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, the underlying bo is replaced. We need to mark states affected by the resource dirty. With this change, we no longer have to emit vertex buffers and index buffer unconditionally. --- src/gallium/drivers/ilo/ilo_3d.c | 7 -- src/gallium/drivers/ilo/ilo_state.c | 100 +++++++++++++++++++++++++ src/gallium/drivers/ilo/ilo_state.h | 5 ++ src/gallium/drivers/ilo/ilo_transfer.c | 9 ++- 4 files changed, 112 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index aba92a0375a..b2cbcf04e0c 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -661,13 +661,6 @@ ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO); } - /* - * The VBs and/or IB may have different BOs due to being mapped with - * PIPE_TRANSFER_DISCARD_x. We should track that instead of setting the - * dirty flags for the performance reason. - */ - ilo->dirty |= ILO_DIRTY_VERTEX_BUFFERS | ILO_DIRTY_INDEX_BUFFER; - /* If draw_vbo ever fails, return immediately. */ if (!draw_vbo(hw3d, ilo, info, &prim_generated, &prim_emitted)) return; diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 3fe19e0fba9..865bc5c7bd9 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -1156,3 +1156,103 @@ ilo_cleanup_states(struct ilo_context *ilo) for (i = 0; i < ilo->global_binding.count; i++) pipe_resource_reference(&ilo->global_binding.resources[i], NULL); } + +/** + * Mark all states that have the resource dirty. + */ +void +ilo_mark_states_with_resource_dirty(struct ilo_context *ilo, + const struct pipe_resource *res) +{ + uint32_t states = 0; + unsigned sh, i; + + if (res->target == PIPE_BUFFER) { + uint32_t vb_mask = ilo->vb.enabled_mask; + + while (vb_mask) { + const unsigned idx = u_bit_scan(&vb_mask); + + if (ilo->vb.states[idx].buffer == res) { + states |= ILO_DIRTY_VERTEX_BUFFERS; + break; + } + } + + if (ilo->ib.state.buffer == res) + states |= ILO_DIRTY_INDEX_BUFFER; + + for (i = 0; i < ilo->so.count; i++) { + if (ilo->so.states[i]->buffer == res) { + states |= ILO_DIRTY_STREAM_OUTPUT_TARGETS; + break; + } + } + } + + for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { + for (i = 0; i < ilo->view[sh].count; i++) { + struct pipe_sampler_view *view = ilo->view[sh].states[i]; + + if (view->texture == res) { + static const unsigned view_dirty_bits[PIPE_SHADER_TYPES] = { + [PIPE_SHADER_VERTEX] = ILO_DIRTY_VERTEX_SAMPLER_VIEWS, + [PIPE_SHADER_FRAGMENT] = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS, + [PIPE_SHADER_GEOMETRY] = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS, + [PIPE_SHADER_COMPUTE] = ILO_DIRTY_COMPUTE_SAMPLER_VIEWS, + }; + + states |= view_dirty_bits[sh]; + break; + } + } + + if (res->target == PIPE_BUFFER) { + for (i = 0; i < Elements(ilo->cbuf[sh].cso); i++) { + struct ilo_cbuf_cso *cbuf = &ilo->cbuf[sh].cso[i]; + + if (cbuf->resource == res) { + states |= ILO_DIRTY_CONSTANT_BUFFER; + break; + } + } + } + } + + for (i = 0; i < ilo->resource.count; i++) { + if (ilo->resource.states[i]->texture == res) { + states |= ILO_DIRTY_SHADER_RESOURCES; + break; + } + } + + /* for now? */ + if (res->target != PIPE_BUFFER) { + for (i = 0; i < ilo->fb.state.nr_cbufs; i++) { + if (ilo->fb.state.cbufs[i]->texture == res) { + states |= ILO_DIRTY_FRAMEBUFFER; + break; + } + } + + if (ilo->fb.state.zsbuf && ilo->fb.state.zsbuf->texture == res) + states |= ILO_DIRTY_FRAMEBUFFER; + } + + for (i = 0; i < ilo->cs_resource.count; i++) { + pipe_surface_reference(&ilo->cs_resource.states[i], NULL); + if (ilo->cs_resource.states[i]->texture == res) { + states |= ILO_DIRTY_COMPUTE_RESOURCES; + break; + } + } + + for (i = 0; i < ilo->global_binding.count; i++) { + if (ilo->global_binding.resources[i] == res) { + states |= ILO_DIRTY_GLOBAL_BINDING; + break; + } + } + + ilo->dirty |= states; +} diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index c73e8fb835b..8a0d5e7f14d 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -113,6 +113,7 @@ enum ilo_dirty_flags { ILO_DIRTY_ALL = 0xffffffff, }; +struct pipe_resource; struct ilo_context; void @@ -127,4 +128,8 @@ ilo_cleanup_states(struct ilo_context *ilo); void ilo_finalize_states(struct ilo_context *ilo); +void +ilo_mark_states_with_resource_dirty(struct ilo_context *ilo, + const struct pipe_resource *res); + #endif /* ILO_STATE_H */ diff --git a/src/gallium/drivers/ilo/ilo_transfer.c b/src/gallium/drivers/ilo/ilo_transfer.c index dcb9ab96d8b..9f68d4ad976 100644 --- a/src/gallium/drivers/ilo/ilo_transfer.c +++ b/src/gallium/drivers/ilo/ilo_transfer.c @@ -32,6 +32,7 @@ #include "ilo_cp.h" #include "ilo_context.h" #include "ilo_resource.h" +#include "ilo_state.h" #include "ilo_transfer.h" static bool @@ -135,8 +136,10 @@ choose_transfer_method(struct ilo_context *ilo, struct ilo_transfer *xfer) else if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { /* discard old bo and allocate a new one for mapping */ if ((tex && ilo_texture_alloc_bo(tex)) || - (buf && ilo_buffer_alloc_bo(buf))) + (buf && ilo_buffer_alloc_bo(buf))) { + ilo_mark_states_with_resource_dirty(ilo, res); will_stall = false; + } } else if (usage & PIPE_TRANSFER_FLUSH_EXPLICIT) { /* @@ -920,8 +923,10 @@ buf_pwrite(struct ilo_context *ilo, struct ilo_buffer *buf, if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { /* old data not needed so discard the old bo to avoid stalling */ - if (ilo_buffer_alloc_bo(buf)) + if (ilo_buffer_alloc_bo(buf)) { + ilo_mark_states_with_resource_dirty(ilo, &buf->base); will_stall = false; + } } else { /* -- 2.30.2