Commit a00b10c3 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Only enforce fence limits inside the GTT.

So long as we adhere to the fence registers rules for alignment and no
overlaps (including with unfenced accesses to linear memory) and account
for the tiled access in our size allocation, we do not have to allocate
the full fenced region for the object. This allows us to fight the bloat
tiling imposed on pre-i965 chipsets and frees up RAM for real use. [Inside
the GTT we still suffer the additional alignment constraints, so it doesn't
magic allow us to render larger scenes without stalls -- we need the
expanded GTT and fence pipelining to overcome those...]
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 7465378f
......@@ -130,7 +130,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
if (obj->fence_reg != I915_FENCE_REG_NONE)
seq_printf(m, " (fence: %d)", obj->fence_reg);
if (obj->gtt_space != NULL)
seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset);
seq_printf(m, " (gtt offset: %08x, size: %08x)",
obj->gtt_offset, (unsigned int)obj->gtt_space->size);
if (obj->pin_mappable || obj->fault_mappable)
seq_printf(m, " (mappable)");
if (obj->ring != NULL)
......
......@@ -770,6 +770,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_BLT:
value = HAS_BLT(dev);
break;
case I915_PARAM_HAS_RELAXED_FENCING:
value = 1;
break;
default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
......
......@@ -746,6 +746,8 @@ struct drm_i915_gem_object {
* Advice: are the backing pages purgeable?
*/
unsigned int madv : 2;
unsigned int fenceable : 1;
unsigned int mappable : 1;
/**
* Current tiling mode for the object.
......@@ -1005,7 +1007,7 @@ struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev,
size_t size);
void i915_gem_free_object(struct drm_gem_object *obj);
int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment,
bool mappable);
bool mappable, bool need_fence);
void i915_gem_object_unpin(struct drm_gem_object *obj);
int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_release_mmap(struct drm_gem_object *obj);
......@@ -1068,10 +1070,6 @@ int i915_gem_evict_inactive(struct drm_device *dev);
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
int tiling_mode);
bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
int tiling_mode);
/* i915_gem_debug.c */
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
......
This diff is collapsed.
......@@ -181,7 +181,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
/* Check pitch constriants for all chips & tiling formats */
bool
static bool
i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
{
int tile_width;
......@@ -232,25 +232,35 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
return true;
}
bool
i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
/* Is the current GTT allocation valid for the change in tiling? */
static bool
i915_gem_object_fence_ok(struct drm_gem_object *obj, int tiling_mode)
{
struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
if (obj_priv->gtt_space == NULL)
return true;
u32 size;
if (tiling_mode == I915_TILING_NONE)
return true;
if (INTEL_INFO(dev)->gen >= 4)
if (INTEL_INFO(obj->dev)->gen >= 4)
return true;
if (obj_priv->gtt_offset & (obj->size - 1))
/*
* Previous chips need to be aligned to the size of the smallest
* fence register that can contain the object.
*/
if (INTEL_INFO(obj->dev)->gen == 3)
size = 1024*1024;
else
size = 512*1024;
while (size < obj_priv->base.size)
size <<= 1;
if (obj_priv->gtt_offset & (size - 1))
return false;
if (IS_GEN3(dev)) {
if (INTEL_INFO(obj->dev)->gen == 3) {
if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
return false;
} else {
......@@ -331,7 +341,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
* tiling mode. Otherwise we can just leave it alone, but
* need to ensure that any fence register is cleared.
*/
if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
if (!i915_gem_object_fence_ok(obj, args->tiling_mode))
ret = i915_gem_object_unbind(obj);
else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
ret = i915_gem_object_put_fence_reg(obj, true);
......
......@@ -1461,7 +1461,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
BUG();
}
ret = i915_gem_object_pin(obj, alignment, true);
ret = i915_gem_object_pin(obj, alignment,
!pipelined, obj_priv->tiling_mode);
if (ret)
return ret;
......@@ -4353,7 +4354,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
/* we only need to pin inside GTT if cursor is non-phy */
mutex_lock(&dev->struct_mutex);
if (!dev_priv->info->cursor_needs_physical) {
ret = i915_gem_object_pin(bo, PAGE_SIZE, true);
ret = i915_gem_object_pin(bo, PAGE_SIZE, true, false);
if (ret) {
DRM_ERROR("failed to pin cursor bo\n");
goto fail_locked;
......@@ -5517,7 +5518,7 @@ intel_alloc_context_page(struct drm_device *dev)
}
mutex_lock(&dev->struct_mutex);
ret = i915_gem_object_pin(ctx, 4096, true);
ret = i915_gem_object_pin(ctx, 4096, false, false);
if (ret) {
DRM_ERROR("failed to pin power context: %d\n", ret);
goto err_unref;
......
......@@ -781,7 +781,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret != 0)
return ret;
ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
ret = i915_gem_object_pin(new_bo, PAGE_SIZE, false, false);
if (ret != 0)
return ret;
......@@ -1423,7 +1423,7 @@ void intel_setup_overlay(struct drm_device *dev)
}
overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
} else {
ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true, false);
if (ret) {
DRM_ERROR("failed to pin overlay register bo\n");
goto out_free_bo;
......
......@@ -547,7 +547,7 @@ static int init_status_page(struct intel_ring_buffer *ring)
obj_priv = to_intel_bo(obj);
obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
ret = i915_gem_object_pin(obj, 4096, true);
ret = i915_gem_object_pin(obj, 4096, true, false);
if (ret != 0) {
goto err_unref;
}
......@@ -603,7 +603,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
ring->gem_object = obj;
ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false);
if (ret)
goto err_unref;
......
......@@ -287,6 +287,7 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_EXECBUF2 9
#define I915_PARAM_HAS_BSD 10
#define I915_PARAM_HAS_BLT 11
#define I915_PARAM_HAS_RELAXED_FENCING 12
typedef struct drm_i915_getparam {
int param;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment