mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 15:38:09 +02:00
i915g: Screen corruption with ENOBUFS caused by fence register shortage
This commit solves the shortage-problem at the blit-functions by checking the number of fence-registers after updating the batch. If too many registers are used, the batch-entries and relocs for the current blit function are removed by setting batch->ptr and reloc_count to value before the blit call and calling drm_intel_gem_bo_clear_relocs. This truncated batch is flushed, and the batch is updated again for the current blit function. Cc: mesa-stable Signed-off-by: GKraats <vd.kraats@hccnet.nl> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26769>
This commit is contained in:
parent
93e96da945
commit
ed2123158d
4 changed files with 82 additions and 33 deletions
|
|
@ -101,4 +101,15 @@ i915_winsys_batchbuffer_reloc(struct i915_winsys_batchbuffer *batch,
|
|||
return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset, fenced);
|
||||
}
|
||||
|
||||
static inline void
|
||||
i915_winsys_batchbuffer_emit_start(struct i915_winsys_batchbuffer *batch)
|
||||
{
|
||||
batch->iws->emit_start(batch);
|
||||
}
|
||||
|
||||
static inline void
|
||||
i915_winsys_batchbuffer_emit_restart(struct i915_winsys_batchbuffer *batch)
|
||||
{
|
||||
batch->iws->emit_restart(batch);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,15 +37,11 @@ i915_fill_blit(struct i915_context *i915, unsigned cpp, unsigned rgba_mask,
|
|||
unsigned color)
|
||||
{
|
||||
unsigned BR13, CMD;
|
||||
bool flushed = false;
|
||||
|
||||
I915_DBG(DBG_BLIT, "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __func__,
|
||||
dst_buffer, dst_pitch, dst_offset, x, y, w, h);
|
||||
|
||||
if (!i915_winsys_validate_buffers(i915->batch, &dst_buffer, 1)) {
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(i915_winsys_validate_buffers(i915->batch, &dst_buffer, 1));
|
||||
}
|
||||
|
||||
switch (cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
|
@ -61,17 +57,25 @@ i915_fill_blit(struct i915_context *i915, unsigned cpp, unsigned rgba_mask,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!BEGIN_BATCH(6)) {
|
||||
i915_winsys_batchbuffer_emit_start(i915->batch);
|
||||
while (true) {
|
||||
if (!BEGIN_BATCH(6)) {
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(BEGIN_BATCH(6));
|
||||
}
|
||||
OUT_BATCH(CMD);
|
||||
OUT_BATCH(BR13);
|
||||
OUT_BATCH((y << 16) | x);
|
||||
OUT_BATCH(((y + h) << 16) | (x + w));
|
||||
OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset);
|
||||
OUT_BATCH(color);
|
||||
if (flushed || i915_winsys_validate_buffers(i915->batch, &dst_buffer, 0))
|
||||
break;
|
||||
i915_winsys_batchbuffer_emit_restart(i915->batch);
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(BEGIN_BATCH(6));
|
||||
assert(i915_winsys_validate_buffers(i915->batch, &dst_buffer, 0));
|
||||
flushed = true;
|
||||
}
|
||||
OUT_BATCH(CMD);
|
||||
OUT_BATCH(BR13);
|
||||
OUT_BATCH((y << 16) | x);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -86,18 +90,13 @@ i915_copy_blit(struct i915_context *i915, unsigned cpp,
|
|||
unsigned CMD, BR13;
|
||||
int dst_y2 = dst_y + h;
|
||||
int dst_x2 = dst_x + w;
|
||||
struct i915_winsys_buffer *buffers[2] = {src_buffer, dst_buffer};
|
||||
bool flushed = false;
|
||||
|
||||
I915_DBG(DBG_BLIT,
|
||||
"%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
|
||||
__func__, src_buffer, src_pitch, src_offset, src_x, src_y,
|
||||
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
|
||||
|
||||
if (!i915_winsys_validate_buffers(i915->batch, buffers, 2)) {
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(i915_winsys_validate_buffers(i915->batch, buffers, 2));
|
||||
}
|
||||
|
||||
switch (cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
|
@ -123,19 +122,27 @@ i915_copy_blit(struct i915_context *i915, unsigned cpp,
|
|||
* need for either at this stage.
|
||||
*/
|
||||
assert(dst_pitch > 0 && src_pitch > 0);
|
||||
|
||||
if (!BEGIN_BATCH(8)) {
|
||||
|
||||
i915_winsys_batchbuffer_emit_start(i915->batch);
|
||||
while (true) {
|
||||
if (!BEGIN_BATCH(8)) {
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(BEGIN_BATCH(8));
|
||||
}
|
||||
OUT_BATCH(CMD);
|
||||
OUT_BATCH(BR13);
|
||||
OUT_BATCH((dst_y << 16) | dst_x);
|
||||
OUT_BATCH((dst_y2 << 16) | dst_x2);
|
||||
OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset);
|
||||
OUT_BATCH((src_y << 16) | src_x);
|
||||
OUT_BATCH(((int)src_pitch & 0xffff));
|
||||
OUT_RELOC_FENCED(src_buffer, I915_USAGE_2D_SOURCE, src_offset);
|
||||
if (flushed || i915_winsys_validate_buffers(i915->batch, &dst_buffer, 0))
|
||||
break;
|
||||
i915_winsys_batchbuffer_emit_restart(i915->batch);
|
||||
FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
|
||||
assert(BEGIN_BATCH(8));
|
||||
assert(i915_winsys_validate_buffers(i915->batch, &dst_buffer, 0));
|
||||
flushed = true;
|
||||
}
|
||||
OUT_BATCH(CMD);
|
||||
OUT_BATCH(BR13);
|
||||
OUT_BATCH((dst_y << 16) | dst_x);
|
||||
OUT_BATCH((dst_y2 << 16) | dst_x2);
|
||||
OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ struct i915_winsys_batchbuffer {
|
|||
size_t size;
|
||||
|
||||
size_t relocs;
|
||||
|
||||
uint8_t *ptr_start;
|
||||
int reloc_count_start;
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
|
|
@ -130,6 +133,16 @@ struct i915_winsys {
|
|||
* Destroy a batchbuffer.
|
||||
*/
|
||||
void (*batchbuffer_destroy)(struct i915_winsys_batchbuffer *batch);
|
||||
|
||||
/**
|
||||
* Store start values of emit
|
||||
*/
|
||||
void (*emit_start)(struct i915_winsys_batchbuffer *batch);
|
||||
|
||||
/**
|
||||
* Go back to start values
|
||||
*/
|
||||
void (*emit_restart)(struct i915_winsys_batchbuffer *batch);
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ i915_drm_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch,
|
|||
for (i = 0; i < num_of_buffers; i++)
|
||||
bos[i+1] = intel_bo(buffer[i]);
|
||||
|
||||
ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers);
|
||||
ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers + 1);
|
||||
if (ret != 0)
|
||||
return false;
|
||||
|
||||
|
|
@ -227,6 +227,22 @@ i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch)
|
|||
FREE(batch);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_drm_batchbuffer_emit_start(struct i915_winsys_batchbuffer *ibatch)
|
||||
{
|
||||
struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
|
||||
ibatch->ptr_start = ibatch->ptr;
|
||||
ibatch->reloc_count_start = drm_intel_gem_bo_get_reloc_count(batch->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_drm_batchbuffer_emit_restart(struct i915_winsys_batchbuffer *ibatch)
|
||||
{
|
||||
struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
|
||||
drm_intel_gem_bo_clear_relocs(batch->bo, ibatch->reloc_count_start);
|
||||
ibatch->ptr = ibatch->ptr_start;
|
||||
}
|
||||
|
||||
void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws)
|
||||
{
|
||||
idws->base.batchbuffer_create = i915_drm_batchbuffer_create;
|
||||
|
|
@ -234,4 +250,6 @@ void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws)
|
|||
idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc;
|
||||
idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush;
|
||||
idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy;
|
||||
idws->base.emit_start = i915_drm_batchbuffer_emit_start;
|
||||
idws->base.emit_restart = i915_drm_batchbuffer_emit_restart;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue