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.
This commit is contained in:
Chia-I Wu 2013-06-13 18:22:40 +08:00
parent 5f15050dc9
commit c7e9b15010
4 changed files with 112 additions and 9 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 {
/*