sna: Replace GPU render operations with CPU callbacks after wedged

If we find the GPU is wedged, replace some of the lowlevel render
operations with CPU equivalents to simplify some fallbacks that still
need to operate on GPU bo (such as copying DRI buffers).

References: https://bugs.freedesktop.org/show_bug.cgi?id=85058
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2014-10-16 07:46:26 +01:00
parent 9a5ca59d2b
commit 3812dfce17
4 changed files with 119 additions and 101 deletions

View File

@ -282,6 +282,13 @@ static void assert_bo_retired(struct kgem_bo *bo)
#define assert_bo_retired(bo)
#endif
static void
__kgem_set_wedged(struct kgem *kgem)
{
kgem->wedged = true;
sna_render_mark_wedged(container_of(kgem, struct sna, kgem));
}
static void kgem_sna_reset(struct kgem *kgem)
{
struct sna *sna = container_of(kgem, struct sna, kgem);
@ -3343,7 +3350,7 @@ void _kgem_submit(struct kgem *kgem)
if (!kgem->wedged) {
xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
"Failed to submit rendering commands, disabling acceleration.\n");
kgem->wedged = true;
__kgem_set_wedged(kgem);
}
#if !NDEBUG
@ -3451,8 +3458,7 @@ void kgem_throttle(struct kgem *kgem)
if (kgem->wedged)
return;
kgem->wedged = __kgem_throttle(kgem, true);
if (kgem->wedged) {
if (__kgem_throttle(kgem, true)) {
static int once;
char path[128];
@ -3465,6 +3471,7 @@ void kgem_throttle(struct kgem *kgem)
once = 1;
}
__kgem_set_wedged(kgem);
kgem->need_throttle = false;
}
}

View File

@ -862,74 +862,6 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
_kgem_set_mode(&sna->kgem, mode);
}
static bool can_copy_cpu(struct sna *sna,
struct kgem_bo *src,
struct kgem_bo *dst)
{
if (src->tiling != dst->tiling)
return false;
if (src->pitch != dst->pitch)
return false;
if (!kgem_bo_can_map__cpu(&sna->kgem, src, false))
return false;
if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true))
return false;
DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle));
return true;
}
static void
sna_dri2_copy_fallback(struct sna *sna,
const DrawableRec *draw,
struct kgem_bo *src_bo, int sx, int sy,
struct kgem_bo *dst_bo, int dx, int dy,
const BoxRec *box, int n)
{
void *dst, *src;
bool clipped;
clipped = (n > 1 ||
box->x1 + sx > 0 ||
box->y1 + sy > 0 ||
box->x2 + sx < draw->width ||
box->y2 + sy < draw->height);
dst = src = NULL;
if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) {
dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
src = kgem_bo_map__cpu(&sna->kgem, src_bo);
}
if (dst == NULL || src == NULL) {
dst = kgem_bo_map__gtt(&sna->kgem, dst_bo);
src = kgem_bo_map__gtt(&sna->kgem, src_bo);
if (dst == NULL || src == NULL)
return;
} else {
kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false);
}
DBG(("%s: src(%d, %d), dst(%d, %d) x %d\n",
__FUNCTION__, sx, sy, dx, dy, n));
if (sigtrap_get() == 0) {
do {
memcpy_blt(src, dst, draw->bitsPerPixel,
src_bo->pitch, dst_bo->pitch,
box->x1 + sx, box->y1 + sy,
box->x1 + dx, box->y1 + dy,
box->x2 - box->x1, box->y2 - box->y1);
box++;
} while (--n);
sigtrap_put();
}
}
static bool is_front(int attachment)
{
return attachment == DRI2BufferFrontLeft;
@ -950,6 +882,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
struct kgem_bo *dst_bo;
const BoxRec *boxes;
int16_t dx, dy, sx, sy;
unsigned flags;
int n;
/* To hide a stale DRI2Buffer, one may choose to substitute
@ -1071,7 +1004,6 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
assert(dst_bo->refcnt);
if (is_front(dst->attachment)) {
struct sna_pixmap *priv;
unsigned int flags;
flags = MOVE_WRITE | __MOVE_FORCE;
if (clip.data)
@ -1135,38 +1067,32 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
}
DamageRegionAppend(&pixmap->drawable, region);
if (wedged(sna)) {
fallback:
sna_dri2_copy_fallback(sna, src_draw,
src_bo, sx, sy,
dst_bo, dx, dy,
boxes, n);
} else {
unsigned flags;
DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
__FUNCTION__,
boxes[0].x1, boxes[0].y1,
boxes[0].x2, boxes[0].y2,
n, sx, sy, dx, dy));
DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
__FUNCTION__,
boxes[0].x1, boxes[0].y1,
boxes[0].x2, boxes[0].y2,
n, sx, sy, dx, dy));
flags = COPY_LAST;
if (sync)
flags |= COPY_SYNC;
if (!sna->render.copy_boxes(sna, GXcopy,
src_draw, src_bo, sx, sy,
dst_draw, dst_bo, dx, dy,
boxes, n, flags))
goto fallback;
flags = COPY_LAST;
if (sync)
flags |= COPY_SYNC;
if (!sna->render.copy_boxes(sna, GXcopy,
src_draw, src_bo, sx, sy,
dst_draw, dst_bo, dx, dy,
boxes, n, flags))
memcpy_copy_boxes(sna, GXcopy,
src_draw, src_bo, sx, sy,
dst_draw, dst_bo, dx, dy,
boxes, n, flags);
DBG(("%s: flushing? %d\n", __FUNCTION__, sync));
if (sync) { /* STAT! */
struct kgem_request *rq = sna->kgem.next_request;
kgem_submit(&sna->kgem);
if (rq->bo) {
bo = ref(rq->bo);
DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle));
}
DBG(("%s: flushing? %d\n", __FUNCTION__, sync));
if (sync) { /* STAT! */
struct kgem_request *rq = sna->kgem.next_request;
kgem_submit(&sna->kgem);
if (rq->bo) {
bo = ref(rq->bo);
DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle));
}
}

View File

@ -2297,3 +2297,81 @@ cleanup_boxes:
return ret;
}
static bool can_copy_cpu(struct sna *sna,
struct kgem_bo *src,
struct kgem_bo *dst)
{
if (src->tiling != dst->tiling)
return false;
if (src->pitch != dst->pitch)
return false;
if (!kgem_bo_can_map__cpu(&sna->kgem, src, false))
return false;
if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true))
return false;
DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle));
return true;
}
bool
memcpy_copy_boxes(struct sna *sna, uint8_t op,
const DrawableRec *src_draw, struct kgem_bo *src_bo, int16_t sx, int16_t sy,
const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy,
const BoxRec *box, int n, unsigned flags)
{
void *dst, *src;
bool clipped;
if (op != GXcopy)
return false;
clipped = (n > 1 ||
box->x1 + dx > 0 ||
box->y1 + dy > 0 ||
box->x2 + dx < dst_draw->width ||
box->y2 + dy < dst_draw->height);
dst = src = NULL;
if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) {
dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
src = kgem_bo_map__cpu(&sna->kgem, src_bo);
}
if (dst == NULL || src == NULL) {
dst = kgem_bo_map__gtt(&sna->kgem, dst_bo);
src = kgem_bo_map__gtt(&sna->kgem, src_bo);
if (dst == NULL || src == NULL)
return false;
} else {
kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false);
}
DBG(("%s: src(%d, %d), dst(%d, %d) x %d\n",
__FUNCTION__, sx, sy, dx, dy, n));
if (sigtrap_get() == 0) {
do {
memcpy_blt(src, dst, dst_draw->bitsPerPixel,
src_bo->pitch, dst_bo->pitch,
box->x1 + sx, box->y1 + sy,
box->x1 + dx, box->y1 + dy,
box->x2 - box->x1, box->y2 - box->y1);
box++;
} while (--n);
sigtrap_put();
}
return true;
}
void
sna_render_mark_wedged(struct sna *sna)
{
sna->render.copy_boxes = memcpy_copy_boxes;
}

View File

@ -620,6 +620,8 @@ const char *gen6_render_init(struct sna *sna, const char *backend);
const char *gen7_render_init(struct sna *sna, const char *backend);
const char *gen8_render_init(struct sna *sna, const char *backend);
void sna_render_mark_wedged(struct sna *sna);
bool sna_tiling_composite(uint32_t op,
PicturePtr src,
PicturePtr mask,
@ -707,6 +709,11 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
const BoxRec *box, int nbox);
bool memcpy_copy_boxes(struct sna *sna, uint8_t op,
const DrawableRec *src_draw, struct kgem_bo *src_bo, int16_t sx, int16_t sy,
const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy,
const BoxRec *box, int n, unsigned flags);
bool _sna_get_pixel_from_rgba(uint32_t *pixel,
uint16_t red,
uint16_t green,