mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 04:38:03 +02:00
i915tex: Catch cases where not all state is emitted for a new batchbuffer.
This could lead to incorrect rendering or even lockups.
This commit is contained in:
parent
0967e1270d
commit
718d2dfbbd
6 changed files with 57 additions and 2 deletions
|
|
@ -281,7 +281,7 @@ get_state_size(struct i915_hw_state *state)
|
||||||
/* Push the state into the sarea and/or texture memory.
|
/* Push the state into the sarea and/or texture memory.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
i915_emit_state(struct intel_context *intel)
|
i915_do_emit_state(struct intel_context *intel)
|
||||||
{
|
{
|
||||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||||
struct i915_hw_state *state = i915->current;
|
struct i915_hw_state *state = i915->current;
|
||||||
|
|
@ -298,10 +298,33 @@ i915_emit_state(struct intel_context *intel)
|
||||||
*/
|
*/
|
||||||
intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
|
intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
|
||||||
|
|
||||||
|
|
||||||
|
/* Workaround. There are cases I haven't been able to track down
|
||||||
|
* where we aren't emitting a full state at the start of a new
|
||||||
|
* batchbuffer. This code spots that we are on a new batchbuffer
|
||||||
|
* and forces a full state emit no matter what.
|
||||||
|
*
|
||||||
|
* In the normal case state->emitted is already zero, this code is
|
||||||
|
* another set of checks to make sure it really is.
|
||||||
|
*/
|
||||||
|
if (intel->batch->id != intel->last_state_batch_id ||
|
||||||
|
intel->batch->map == intel->batch->ptr)
|
||||||
|
{
|
||||||
|
state->emitted = 0;
|
||||||
|
intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Do this here as we may have flushed the batchbuffer above,
|
/* Do this here as we may have flushed the batchbuffer above,
|
||||||
* causing more state to be dirty!
|
* causing more state to be dirty!
|
||||||
*/
|
*/
|
||||||
dirty = get_dirty(state);
|
dirty = get_dirty(state);
|
||||||
|
state->emitted |= dirty;
|
||||||
|
assert(get_dirty(state) == 0);
|
||||||
|
|
||||||
|
if (intel->batch->id != intel->last_state_batch_id) {
|
||||||
|
assert(dirty & I915_UPLOAD_CTX);
|
||||||
|
intel->last_state_batch_id = intel->batch->id;
|
||||||
|
}
|
||||||
|
|
||||||
if (INTEL_DEBUG & DEBUG_STATE)
|
if (INTEL_DEBUG & DEBUG_STATE)
|
||||||
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
|
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
|
||||||
|
|
@ -424,7 +447,29 @@ i915_emit_state(struct intel_context *intel)
|
||||||
i915_disassemble_program(state->Program, state->ProgramSize);
|
i915_disassemble_program(state->Program, state->ProgramSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->emitted |= dirty;
|
intel->batch->dirty_state &= ~dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
i915_emit_state(struct intel_context *intel)
|
||||||
|
{
|
||||||
|
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||||
|
|
||||||
|
i915_do_emit_state( intel );
|
||||||
|
|
||||||
|
/* Second chance - catch batchbuffer wrap in the middle of state
|
||||||
|
* emit. This shouldn't happen but it has been observed in
|
||||||
|
* testing.
|
||||||
|
*/
|
||||||
|
if (get_dirty( i915->current )) {
|
||||||
|
/* Force a full re-emit if this happens.
|
||||||
|
*/
|
||||||
|
i915->current->emitted = 0;
|
||||||
|
i915_do_emit_state( intel );
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(get_dirty(i915->current) == 0);
|
||||||
|
assert((intel->batch->dirty_state & (1<<1)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,8 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch)
|
||||||
|
|
||||||
batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
|
batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
|
||||||
batch->ptr = batch->map;
|
batch->ptr = batch->map;
|
||||||
|
batch->dirty_state = ~0;
|
||||||
|
batch->id = batch->intel->intelScreen->batch_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*======================================================================
|
/*======================================================================
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ struct intel_batchbuffer
|
||||||
struct buffer_reloc reloc[MAX_RELOCS];
|
struct buffer_reloc reloc[MAX_RELOCS];
|
||||||
GLuint nr_relocs;
|
GLuint nr_relocs;
|
||||||
GLuint size;
|
GLuint size;
|
||||||
|
|
||||||
|
GLuint dirty_state;
|
||||||
|
GLuint id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
|
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,7 @@ struct intel_context
|
||||||
struct _DriFenceObject *first_swap_fence;
|
struct _DriFenceObject *first_swap_fence;
|
||||||
|
|
||||||
struct intel_batchbuffer *batch;
|
struct intel_batchbuffer *batch;
|
||||||
|
GLuint last_state_batch_id;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ typedef struct
|
||||||
struct _DriBufferPool *regionPool;
|
struct _DriBufferPool *regionPool;
|
||||||
struct _DriBufferPool *staticPool;
|
struct _DriBufferPool *staticPool;
|
||||||
unsigned int maxBatchSize;
|
unsigned int maxBatchSize;
|
||||||
|
unsigned batch_id;
|
||||||
GLboolean havePools;
|
GLboolean havePools;
|
||||||
} intelScreenPrivate;
|
} intelScreenPrivate;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,9 @@ intelStartInlinePrimitive(struct intel_context *intel,
|
||||||
BEGIN_BATCH(2, batch_flags);
|
BEGIN_BATCH(2, batch_flags);
|
||||||
OUT_BATCH(0);
|
OUT_BATCH(0);
|
||||||
|
|
||||||
|
assert(intel->batch->id == intel->last_state_batch_id);
|
||||||
|
assert((intel->batch->dirty_state & (1<<1)) == 0);
|
||||||
|
|
||||||
intel->prim.start_ptr = intel->batch->ptr;
|
intel->prim.start_ptr = intel->batch->ptr;
|
||||||
intel->prim.primitive = prim;
|
intel->prim.primitive = prim;
|
||||||
intel->prim.flush = intel_flush_inline_primitive;
|
intel->prim.flush = intel_flush_inline_primitive;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue