i915g: implement cache flushing
With an extremely dumb strategy. But it's the same i915c employs. Also improve the hw_atom code slightly by statically specifying the required batch space. For extremely variably stuff (shaders, constants) it would probably be better to add a new parameter to the hw_atom->validate function. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
f90fa55347
commit
d42c9433b0
|
@ -81,6 +81,8 @@ i915_fill_blit(struct i915_context *i915,
|
|||
OUT_BATCH(((y + h) << 16) | (x + w));
|
||||
OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset);
|
||||
OUT_BATCH(color);
|
||||
|
||||
i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -153,4 +155,6 @@ i915_copy_blit(struct i915_context *i915,
|
|||
OUT_BATCH((src_y << 16) | src_x);
|
||||
OUT_BATCH(((int) src_pitch & 0xffff));
|
||||
OUT_RELOC_FENCED(src_buffer, I915_USAGE_2D_SOURCE, src_offset);
|
||||
|
||||
i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ i915_create_context(struct pipe_screen *screen, void *priv)
|
|||
i915->hardware_dirty = ~0;
|
||||
i915->immediate_dirty = ~0;
|
||||
i915->dynamic_dirty = ~0;
|
||||
i915->flush_dirty = 0;
|
||||
|
||||
/* Batch stream debugging is a bit hacked up at the moment:
|
||||
*/
|
||||
|
|
|
@ -246,6 +246,7 @@ struct i915_context {
|
|||
unsigned hardware_dirty;
|
||||
unsigned immediate_dirty;
|
||||
unsigned dynamic_dirty;
|
||||
unsigned flush_dirty;
|
||||
|
||||
struct i915_winsys_buffer *validation_buffers[2 + 1 + I915_TEX_UNITS];
|
||||
int num_validation_buffers;
|
||||
|
@ -289,6 +290,18 @@ struct i915_context {
|
|||
#define I915_HW_CONSTANTS (1<<I915_CACHE_CONSTANTS)
|
||||
#define I915_HW_IMMEDIATE (1<<(I915_MAX_CACHE+0))
|
||||
#define I915_HW_INVARIANT (1<<(I915_MAX_CACHE+1))
|
||||
#define I915_HW_FLUSH (1<<(I915_MAX_CACHE+1))
|
||||
|
||||
/* hw flush handling */
|
||||
#define I915_FLUSH_CACHE 1
|
||||
#define I915_PIPELINE_FLUSH 2
|
||||
|
||||
static INLINE
|
||||
void i915_set_flush_dirty(struct i915_context *i915, unsigned flush)
|
||||
{
|
||||
i915->hardware_dirty |= I915_HW_FLUSH;
|
||||
i915->flush_dirty |= flush;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -96,4 +96,6 @@ void i915_flush(struct i915_context *i915, struct pipe_fence_handle **fence)
|
|||
i915->hardware_dirty = ~0;
|
||||
i915->immediate_dirty = ~0;
|
||||
i915->dynamic_dirty = ~0;
|
||||
/* kernel emits flushes in between batchbuffers */
|
||||
i915->flush_dirty = 0;
|
||||
}
|
||||
|
|
|
@ -42,10 +42,25 @@ struct i915_tracked_hw_state {
|
|||
const char *name;
|
||||
void (*validate)(struct i915_context *);
|
||||
void (*emit)(struct i915_context *);
|
||||
unsigned dirty;
|
||||
unsigned dirty, batch_space;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
emit_flush(struct i915_context *i915)
|
||||
{
|
||||
/* Cache handling is very cheap atm. State handling can request to flushes:
|
||||
* - I915_FLUSH_CACHE which is a flush everything request and
|
||||
* - I915_PIPELINE_FLUSH which is specifically for the draw_offset flush.
|
||||
* Because the cache handling is so dumb, no explicit "invalidate map cache".
|
||||
* Also, the first is a strict superset of the latter, so the following logic
|
||||
* works. */
|
||||
if (i915->flush_dirty & I915_FLUSH_CACHE)
|
||||
OUT_BATCH(MI_FLUSH | FLUSH_MAP_CACHE);
|
||||
else if (i915->flush_dirty & I915_PIPELINE_FLUSH)
|
||||
OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE);
|
||||
}
|
||||
|
||||
static void
|
||||
validate_immediate(struct i915_context *i915)
|
||||
{
|
||||
|
@ -82,21 +97,25 @@ validate_map(struct i915_context *i915)
|
|||
}
|
||||
|
||||
const static struct i915_tracked_hw_state hw_atoms[] = {
|
||||
{ "flush", NULL, emit_flush, I915_HW_FLUSH, 1 },
|
||||
{ "immediate", validate_immediate, NULL, I915_HW_IMMEDIATE },
|
||||
{ "static", validate_static, NULL, I915_HW_STATIC },
|
||||
{ "map", validate_map, NULL, I915_HW_MAP }
|
||||
};
|
||||
|
||||
static boolean
|
||||
i915_validate_state(struct i915_context *i915)
|
||||
i915_validate_state(struct i915_context *i915, unsigned *batch_space)
|
||||
{
|
||||
int i;
|
||||
|
||||
i915->num_validation_buffers = 0;
|
||||
*batch_space = 0;
|
||||
|
||||
for (i = 0; i < Elements(hw_atoms); i++)
|
||||
if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].validate)
|
||||
if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].validate) {
|
||||
hw_atoms[i].validate(i915);
|
||||
*batch_space += hw_atoms[i].batch_space;
|
||||
}
|
||||
|
||||
if (i915->num_validation_buffers == 0)
|
||||
return TRUE;
|
||||
|
@ -108,11 +127,22 @@ i915_validate_state(struct i915_context *i915)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_state(struct i915_context *i915)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Elements(hw_atoms); i++)
|
||||
if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].emit)
|
||||
hw_atoms[i].emit(i915);
|
||||
}
|
||||
|
||||
/* Push the state into the sarea and/or texture memory.
|
||||
*/
|
||||
void
|
||||
i915_emit_hardware_state(struct i915_context *i915 )
|
||||
{
|
||||
unsigned batch_space;
|
||||
/* XXX: there must be an easier way */
|
||||
const unsigned dwords = ( 14 +
|
||||
7 +
|
||||
|
@ -138,20 +168,21 @@ i915_emit_hardware_state(struct i915_context *i915 )
|
|||
if (I915_DBG_ON(DBG_ATOMS))
|
||||
i915_dump_hardware_dirty(i915, __FUNCTION__);
|
||||
|
||||
if (!i915_validate_state(i915)) {
|
||||
if (!i915_validate_state(i915, &batch_space)) {
|
||||
FLUSH_BATCH(NULL);
|
||||
assert(i915_validate_state(i915));
|
||||
assert(i915_validate_state(i915, &batch_space));
|
||||
}
|
||||
|
||||
if(!BEGIN_BATCH(dwords, relocs)) {
|
||||
if(!BEGIN_BATCH(batch_space + dwords, relocs)) {
|
||||
FLUSH_BATCH(NULL);
|
||||
assert(i915_validate_state(i915));
|
||||
assert(BEGIN_BATCH(dwords, relocs));
|
||||
assert(i915_validate_state(i915, &batch_space));
|
||||
assert(BEGIN_BATCH(batch_space + dwords, relocs));
|
||||
}
|
||||
|
||||
save_ptr = (uintptr_t)i915->batch->ptr;
|
||||
save_relocs = i915->batch->relocs;
|
||||
|
||||
emit_state(i915);
|
||||
/* 14 dwords, 0 relocs */
|
||||
if (i915->hardware_dirty & I915_HW_INVARIANT)
|
||||
{
|
||||
|
|
|
@ -169,6 +169,9 @@ static void update_framebuffer(struct i915_context *i915)
|
|||
i915->current.draw_size = (w - 1 + x) | ((h - 1 + y) << 16);
|
||||
|
||||
i915->hardware_dirty |= I915_HW_STATIC;
|
||||
|
||||
/* flush the cache in case we sample from the old renderbuffers */
|
||||
i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
|
||||
}
|
||||
|
||||
struct i915_tracked_state i915_hw_framebuffer = {
|
||||
|
|
Loading…
Reference in New Issue