[Intel-gfx] [PATCH] i830 uxa: track fence reg usage exactly
Daniel Vetter
daniel.vetter at ffwll.ch
Thu Apr 22 22:48:47 CEST 2010
This tells libdrm to not take fence registers into account. Instead
it checks for fence register availability for the current batchbuffer
in the various uxa_prepare_* hooks where it's known how many fences
are needed _exactly_.
Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
src/i830.h | 13 ++++++-
src/i830_batchbuffer.c | 2 +
src/i830_driver.c | 32 ++++++++++++++++
src/i830_render.c | 12 +++---
src/i830_uxa.c | 95 +++++++++++++++++++++++++++++++++++++++++-------
src/i915_render.c | 13 ++++---
6 files changed, 139 insertions(+), 28 deletions(-)
diff --git a/src/i830.h b/src/i830.h
index 88949f6..fd9a798 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -71,11 +71,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i915_drm.h"
#include "uxa.h"
+struct intel_pixmap;
Bool i830_uxa_init(ScreenPtr pScreen);
void i830_uxa_create_screen_resources(ScreenPtr pScreen);
void i830_uxa_block_handler(ScreenPtr pScreen);
-Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
- int num_bos);
+Bool i830_get_aperture_space(ScrnInfoPtr scrn,
+ struct intel_pixmap ** pixmap_table,
+ int num_pixmaps);
/* classic doubly-link circular list */
struct list {
@@ -152,6 +154,7 @@ struct intel_pixmap {
uint32_t batch_write_domain;
uint32_t batch_read_domains;
struct list flush, batch, in_flight;
+ unsigned int fence_allocated : 1;
};
struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap);
@@ -262,6 +265,12 @@ typedef struct intel_screen_private {
struct list flush_pixmaps;
struct list in_flight;
+ /** Available fence registers */
+ int available_fences;
+ int unfenced_relocs;
+ /** Fence registers used in current batchbuffer */
+ int used_fences;
+
/* For Xvideo */
Bool use_drmmode_overlay;
#ifdef INTEL_XVMC
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 492472e..b41e567 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -176,8 +176,10 @@ void intel_batch_submit(ScrnInfoPtr scrn)
batch);
entry->batch_read_domains = entry->batch_write_domain = 0;
+ entry->fence_allocated = 0;
list_del(&entry->batch);
}
+ intel->used_fences = 0;
/* Mark that we need to flush whatever potential rendering we've done in the
* blockhandler. We could set this less often, but it's probably not worth
diff --git a/src/i830_driver.c b/src/i830_driver.c
index db8af06..b84c3a0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1051,6 +1051,38 @@ void i830_init_bufmgr(ScrnInfoPtr scrn)
intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
+ intel->unfenced_relocs =
+ drm_intel_bufmgr_gem_disable_fence_accounting(intel->bufmgr);
+
+ if (!IS_I965G(intel)) {
+ drm_i915_getparam_t gp;
+ int ret;
+
+ gp.param = I915_PARAM_NUM_FENCES_AVAIL;
+ gp.value = &intel->available_fences;
+ ret = ioctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp);
+ if (ret) {
+ fprintf(stderr, "get fences failed: %d [%d]\n", ret,
+ errno);
+ fprintf(stderr, "param: %d, val: %d\n", gp.param,
+ *gp.value);
+ intel->available_fences = 0;
+ } else {
+ /* XXX The kernel reports the total number of fences,
+ * including any that may be pinned.
+ *
+ * libdrm subtracts to fences for maximal two scanout
+ * buffers. But we know that there's (currently) only
+ * at most one tiled scanout buffer, so subtract just
+ * one. */
+ intel->available_fences -= 1;
+ if (intel->available_fences < 0)
+ intel->available_fences = 0;
+ }
+ } else
+ intel->available_fences = 0;
+
+ intel->used_fences = 0;
list_init(&intel->batch_pixmaps);
list_init(&intel->flush_pixmaps);
diff --git a/src/i830_render.c b/src/i830_render.c
index 8e559c9..b415fe9 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -438,11 +438,10 @@ i830_prepare_composite(int op, PicturePtr source_picture,
{
ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(source),
- mask ? i830_get_pixmap_bo(mask) : NULL,
- i830_get_pixmap_bo(dest),
+ struct intel_pixmap *pixmap_table[] = {
+ i830_get_pixmap_intel(source),
+ mask ? i830_get_pixmap_intel(mask) : NULL,
+ i830_get_pixmap_intel(dest),
};
intel->render_source_picture = source_picture;
@@ -464,7 +463,8 @@ i830_prepare_composite(int op, PicturePtr source_picture,
if (!i830_get_dest_format(dest_picture, &intel->render_dest_format))
return FALSE;
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ if (!i830_get_aperture_space(scrn, pixmap_table,
+ ARRAY_SIZE(pixmap_table)))
return FALSE;
if (mask) {
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index 984069e..8ed1198 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -80,11 +80,67 @@ const int I830PatternROP[16] = {
static int uxa_pixmap_index;
+static Bool
+i830_get_fence_registers(ScrnInfoPtr scrn,
+ struct intel_pixmap ** pixmap_table,
+ int num_pixmaps)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ int i, retried = 0;
+ int reserved_fences;
+
+ if (IS_I965G(intel))
+ return TRUE;
+
+retry:
+ reserved_fences = 0;
+ for (i = 0; i < num_pixmaps; i++) {
+ if (pixmap_table[i]->tiling == I915_TILING_NONE)
+ continue;
+
+ if (pixmap_table[i]->fence_allocated)
+ continue;
+
+ pixmap_table[i]->fence_allocated = 1;
+ reserved_fences++;
+ }
+
+ if (reserved_fences + intel->used_fences
+ <= intel->available_fences) {
+ intel->used_fences += reserved_fences;
+ return TRUE;
+ }
+
+ if (retried) {
+ intel_debug_fallback(scrn, "Couldn't get fence "
+ "registers for BOs\n");
+ return FALSE;
+ }
+
+ intel_batch_submit(scrn);
+ for (i = 0; i < num_pixmaps; i++)
+ pixmap_table[i]->fence_allocated = 0;
+ retried = 1;
+ goto retry;
+}
+
Bool
-i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
- int num_bos)
+i830_get_aperture_space(ScrnInfoPtr scrn,
+ struct intel_pixmap ** pixmap_table,
+ int num_pixmaps)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
+ drm_intel_bo *bo_table[num_pixmaps + 1];
+ int i;
+
+ bo_table[0] = NULL; /* for the batch bo */
+
+ for (i = 0; i < num_pixmaps; i++) {
+ if (pixmap_table[i])
+ bo_table[i + 1] = pixmap_table[i]->bo;
+ else
+ bo_table[i + 1] = NULL;
+ }
if (intel->batch_bo == NULL) {
intel_debug_fallback(scrn, "VT inactive\n");
@@ -92,16 +148,21 @@ i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
}
bo_table[0] = intel->batch_bo;
- if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) {
+ if (drm_intel_bufmgr_check_aperture_space(bo_table, num_pixmaps) != 0) {
intel_batch_submit(scrn);
bo_table[0] = intel->batch_bo;
- if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) !=
- 0) {
+ if (drm_intel_bufmgr_check_aperture_space(bo_table,
+ num_pixmaps) != 0) {
intel_debug_fallback(scrn, "Couldn't get aperture "
"space for BOs\n");
return FALSE;
}
}
+
+ if (!intel->unfenced_relocs)
+ return i830_get_fence_registers(scrn, pixmap_table,
+ num_pixmaps);
+
return TRUE;
}
@@ -203,9 +264,8 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
{
ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(pixmap),
+ struct intel_pixmap *pixmap_table[] = {
+ i830_get_pixmap_intel(pixmap),
};
if (IS_GEN6(intel)) {
@@ -237,7 +297,12 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
return FALSE;
}
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ if (!i830_get_aperture_space(scrn, pixmap_table,
+ ARRAY_SIZE(pixmap_table)))
+ return FALSE;
+
+ if (!i830_get_fence_registers(scrn, pixmap_table,
+ ARRAY_SIZE(pixmap_table)))
return FALSE;
intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16;
@@ -321,10 +386,9 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
{
ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(source),
- i830_get_pixmap_bo(dest),
+ struct intel_pixmap *pixmap_table[] = {
+ i830_get_pixmap_intel(source),
+ i830_get_pixmap_intel(dest),
};
if (IS_GEN6(intel)) {
@@ -343,9 +407,12 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
return FALSE;
}
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ if (!i830_get_aperture_space(scrn, pixmap_table, ARRAY_SIZE(pixmap_table)))
return FALSE;
+ if (!i830_get_fence_registers(scrn, pixmap_table,
+ ARRAY_SIZE(pixmap_table)))
+ return FALSE;
if (!intel_check_pitch_2d(source))
return FALSE;
if (!intel_check_pitch_2d(dest))
diff --git a/src/i915_render.c b/src/i915_render.c
index 98b5b88..cbc82f7 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -367,11 +367,10 @@ i915_prepare_composite(int op, PicturePtr source_picture,
{
ScrnInfoPtr scrn = xf86Screens[source_picture->pDrawable->pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(source),
- mask ? i830_get_pixmap_bo(mask) : NULL,
- i830_get_pixmap_bo(dest),
+ struct intel_pixmap *pixmap_table[] = {
+ i830_get_pixmap_intel(source),
+ mask ? i830_get_pixmap_intel(mask) : NULL,
+ i830_get_pixmap_intel(dest),
};
int tex_unit = 0;
@@ -424,8 +423,10 @@ i915_prepare_composite(int op, PicturePtr source_picture,
&intel->i915_render_state.dst_format))
return FALSE;
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ if (!i830_get_aperture_space(scrn, pixmap_table,
+ ARRAY_SIZE(pixmap_table)))
return FALSE;
+
intel->dst_coord_adjust = 0;
intel->src_coord_adjust = 0;
intel->mask_coord_adjust = 0;
--
1.7.0.4
More information about the Intel-gfx
mailing list