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:
GKraats 2023-12-20 01:39:00 +01:00
parent 93e96da945
commit ed2123158d
4 changed files with 82 additions and 33 deletions

View file

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

View file

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

View file

@ -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);
/*@}*/
/**

View file

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