sna: Last ditch attempt to make extra large batches fit

If we have unfortunate fragmentation, e.g. a cursor is pinned in the
middle of an aperture, we can struggle to fit large objects, especially
fenced objects on gen2/gen3. We do have one last trick up our sleeves
that we can try: disable all of the outputs and cursors and try
submitting the batch in as pristine an aperture as we can arrange. We
can only hope that the subsequent restoration of the outputs is more
conducive to future batches (and so not lead us into continual flicker).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2014-09-15 11:36:20 +01:00
parent 435fe185e3
commit d470f0f520
3 changed files with 71 additions and 2 deletions

View File

@ -3200,7 +3200,7 @@ static void dump_fence_regs(struct kgem *kgem)
static int do_execbuf(struct kgem *kgem, struct drm_i915_gem_execbuffer2 *execbuf)
{
int ret;
int ret, err;
retry:
ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
@ -3216,7 +3216,28 @@ retry:
goto retry;
/* last gasp */
return do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
if (ret == 0)
return 0;
xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
"Failed to submit rendering commands, trying again with outputs disabled.\n");
/* One last trick up our sleeve for when we run out of space.
* We turn everything off to free up our pinned framebuffers,
* sprites and cursors, and try one last time.
*/
err = errno;
if (sna_mode_disable(container_of(kgem, struct sna, kgem))) {
kgem_cleanup_cache(kgem);
ret = do_ioctl(kgem->fd,
DRM_IOCTL_I915_GEM_EXECBUFFER2,
execbuf);
sna_mode_enable(container_of(kgem, struct sna, kgem));
}
errno = err;
return ret;
}
void _kgem_submit(struct kgem *kgem)

View File

@ -426,6 +426,8 @@ bool sna_mode_wants_tear_free(struct sna *sna);
void sna_mode_adjust_frame(struct sna *sna, int x, int y);
extern void sna_mode_discover(struct sna *sna);
extern void sna_mode_check(struct sna *sna);
extern bool sna_mode_disable(struct sna *sna);
extern void sna_mode_enable(struct sna *sna);
extern void sna_mode_reset(struct sna *sna);
extern void sna_mode_wakeup(struct sna *sna);
extern void sna_mode_redisplay(struct sna *sna);

View File

@ -5785,6 +5785,52 @@ sna_mode_set_primary(struct sna *sna)
#endif
}
bool
sna_mode_disable(struct sna *sna)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
int i;
if (sna->flags & SNA_IS_HOSTED)
return false;
if (!sna->scrn->vtSema)
return false;
sna_hide_cursors(sna->scrn);
for (i = 0; i < sna->mode.num_real_crtc; i++)
sna_crtc_disable(config->crtc[i]);
while (sna_mode_has_pending_events(sna))
sna_mode_wakeup(sna);
kgem_clean_scanout_cache(&sna->kgem);
return true;
}
void
sna_mode_enable(struct sna *sna)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
int i;
if (sna->flags & SNA_IS_HOSTED)
return;
if (!sna->scrn->vtSema)
return;
for (i = 0; i < sna->mode.num_real_crtc; i++) {
xf86CrtcPtr crtc = config->crtc[i];
assert(to_sna_crtc(crtc) != NULL);
if (!crtc->enabled)
continue;
__sna_crtc_set_mode(crtc);
}
}
void
sna_mode_close(struct sna *sna)
{