diff options
author | Keith Packard <keithp@keithp.com> | 2008-11-21 01:49:39 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-12-17 10:28:25 -0800 |
commit | b13f4e1a32ab98fa719a3233cad59ff4d49cfb38 (patch) | |
tree | 2db858f4c271637c86ae3a4a1d65df00a16e35f6 | |
parent | 731cd5526e5c732d51307b26e784f454a724a699 (diff) |
intel: Dump out memory usage information when the kernel fails to pin
The execbuffer ioctl returns ENOMEM when it fails to pin all of the buffers
in the GTT. This is usually caused by the DRM client attempting to use too
much memory in a single request. Dumping out the requested and available
memory values should help point out failures in the DRM code to catch over
commitments of this form.
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | libdrm/intel/intel_bufmgr_gem.c | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 9605cc7c..c94f82e2 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -163,6 +163,12 @@ struct _drm_intel_bo_gem { static void drm_intel_gem_bo_reference_locked(drm_intel_bo *bo); +static unsigned int +drm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count); + +static unsigned int +drm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count); + static int logbase2(int n) { @@ -915,6 +921,14 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf); } while (ret != 0 && errno == EAGAIN); + if (ret != 0 && errno == ENOMEM) { + fprintf(stderr, "Execbuffer fails to pin. Estimate: %u. Actual: %u. Available: %u\n", + drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, + bufmgr_gem->exec_count), + drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, + bufmgr_gem->exec_count), + bufmgr_gem->gtt_size); + } drm_intel_update_buffer_offsets (bufmgr_gem); if (bufmgr_gem->bufmgr.debug) @@ -1102,6 +1116,43 @@ drm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo) } /** + * Return a conservative estimate for the amount of aperture required + * for a collection of buffers. This may double-count some buffers. + */ +static unsigned int +drm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count) +{ + int i; + unsigned int total = 0; + + for (i = 0; i < count; i++) { + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo_array[i]; + if (bo_gem != NULL) + total += bo_gem->reloc_tree_size; + } + return total; +} + +/** + * Return the amount of aperture needed for a collection of buffers. + * This avoids double counting any buffers, at the cost of looking + * at every buffer in the set. + */ +static unsigned int +drm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count) +{ + int i; + unsigned int total = 0; + + for (i = 0; i < count; i++) + total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); + + for (i = 0; i < count; i++) + drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); + return total; +} + +/** * Return -1 if the batchbuffer should be flushed before attempting to * emit rendering referencing the buffers pointed to by bo_array. * @@ -1123,24 +1174,13 @@ drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo_array[0]->bufmgr; unsigned int total = 0; unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4; - int i; - for (i = 0; i < count; i++) { - drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo_array[i]; - if (bo_gem != NULL) - total += bo_gem->reloc_tree_size; - } + total = drm_intel_gem_estimate_batch_space(bo_array, count); + + if (total > threshold) + total = drm_intel_gem_compute_batch_space(bo_array, count); if (total > threshold) { - total = 0; - for (i = 0; i < count; i++) - total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); - - for (i = 0; i < count; i++) - drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); - } - - if (total > bufmgr_gem->gtt_size * 3 / 4) { DBG("check_space: overflowed available aperture, %dkb vs %dkb\n", total / 1024, (int)bufmgr_gem->gtt_size / 1024); return -1; |