drm/i915: Store required fence size/alignment for GGTT vma

The fence size/alignment is a combination of the vma size plus object
tiling parameters. Those parameters are rarely changed, making the fence
size/alignemnt roughly constant for the lifetime of the VMA. We can
simplify subsequent calculations by precalculating the size/alignment
required for GGTT vma taking fencing into account (with an update if we
do change the tiling or stride).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170109161613.11881-4-chris@chris-wilson.co.uk
This commit is contained in:
Chris Wilson 2017-01-09 16:16:11 +00:00
parent 0d4e8f1dbc
commit 944397f04f
6 changed files with 72 additions and 80 deletions

View File

@ -3360,11 +3360,10 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
int i915_gem_open(struct drm_device *dev, struct drm_file *file); int i915_gem_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_release(struct drm_device *dev, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file);
u64 i915_gem_get_ggtt_size(struct drm_i915_private *dev_priv, u64 size, u32 i915_gem_get_ggtt_size(struct drm_i915_private *dev_priv, u32 size,
int tiling_mode, unsigned int stride); int tiling_mode, unsigned int stride);
u64 i915_gem_get_ggtt_alignment(struct drm_i915_private *dev_priv, u64 size, u32 i915_gem_get_ggtt_alignment(struct drm_i915_private *dev_priv, u32 size,
int tiling_mode, unsigned int stride, int tiling_mode, unsigned int stride);
bool fenced);
int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level); enum i915_cache_level cache_level);

View File

@ -2026,10 +2026,10 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
* Return the required global GTT size for an object, taking into account * Return the required global GTT size for an object, taking into account
* potential fence register mapping. * potential fence register mapping.
*/ */
u64 i915_gem_get_ggtt_size(struct drm_i915_private *dev_priv, u32 i915_gem_get_ggtt_size(struct drm_i915_private *dev_priv,
u64 size, int tiling_mode, unsigned int stride) u32 size, int tiling_mode, unsigned int stride)
{ {
u64 ggtt_size; u32 ggtt_size;
GEM_BUG_ON(!size); GEM_BUG_ON(!size);
@ -2062,14 +2062,12 @@ u64 i915_gem_get_ggtt_size(struct drm_i915_private *dev_priv,
* @size: object size * @size: object size
* @tiling_mode: tiling mode * @tiling_mode: tiling mode
* @stride: tiling stride * @stride: tiling stride
* @fenced: is fenced alignment required or not
* *
* Return the required global GTT alignment for an object, taking into account * Return the required global GTT alignment for an object, taking into account
* potential fence register mapping. * potential fence register mapping.
*/ */
u64 i915_gem_get_ggtt_alignment(struct drm_i915_private *dev_priv, u64 size, u32 i915_gem_get_ggtt_alignment(struct drm_i915_private *dev_priv, u32 size,
int tiling_mode, unsigned int stride, int tiling_mode, unsigned int stride)
bool fenced)
{ {
GEM_BUG_ON(!size); GEM_BUG_ON(!size);
@ -2077,9 +2075,7 @@ u64 i915_gem_get_ggtt_alignment(struct drm_i915_private *dev_priv, u64 size,
* Minimum alignment is 4k (GTT page size), but might be greater * Minimum alignment is 4k (GTT page size), but might be greater
* if a fence register is needed for the object. * if a fence register is needed for the object.
*/ */
if (INTEL_GEN(dev_priv) >= 4 || if (INTEL_GEN(dev_priv) >= 4 || tiling_mode == I915_TILING_NONE)
(!fenced && (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv))) ||
tiling_mode == I915_TILING_NONE)
return 4096; return 4096;
/* /*
@ -3558,7 +3554,7 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
return; return;
if (--vma->obj->pin_display == 0) if (--vma->obj->pin_display == 0)
vma->display_alignment = 0; vma->display_alignment = 4096;
/* Bump the LRU to try and avoid premature eviction whilst flipping */ /* Bump the LRU to try and avoid premature eviction whilst flipping */
if (!i915_vma_is_active(vma)) if (!i915_vma_is_active(vma))
@ -3703,11 +3699,6 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
if (flags & PIN_MAPPABLE) { if (flags & PIN_MAPPABLE) {
u32 fence_size;
fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj));
/* If the required space is larger than the available /* If the required space is larger than the available
* aperture, we will not able to find a slot for the * aperture, we will not able to find a slot for the
* object and unbinding the object now will be in * object and unbinding the object now will be in
@ -3715,7 +3706,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
* the object in and out of the Global GTT and * the object in and out of the Global GTT and
* waste a lot of cycles under the mutex. * waste a lot of cycles under the mutex.
*/ */
if (fence_size > dev_priv->ggtt.mappable_end) if (vma->fence_size > dev_priv->ggtt.mappable_end)
return ERR_PTR(-E2BIG); return ERR_PTR(-E2BIG);
/* If NONBLOCK is set the caller is optimistically /* If NONBLOCK is set the caller is optimistically
@ -3734,7 +3725,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
* we could try to minimise harm to others. * we could try to minimise harm to others.
*/ */
if (flags & PIN_NONBLOCK && if (flags & PIN_NONBLOCK &&
fence_size > dev_priv->ggtt.mappable_end / 2) vma->fence_size > dev_priv->ggtt.mappable_end / 2)
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }

View File

@ -79,11 +79,11 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence,
if (vma) { if (vma) {
unsigned int stride = i915_gem_object_get_stride(vma->obj); unsigned int stride = i915_gem_object_get_stride(vma->obj);
u32 row_size = i915_gem_object_get_tile_row_size(vma->obj); u32 row_size = i915_gem_object_get_tile_row_size(vma->obj);
u32 size = rounddown((u32)vma->node.size, row_size); u32 size = rounddown((u32)vma->fence_size, row_size);
GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma));
GEM_BUG_ON(vma->node.start & 4095); GEM_BUG_ON(vma->node.start & 4095);
GEM_BUG_ON(vma->node.size & 4095); GEM_BUG_ON(vma->fence_size & 4095);
GEM_BUG_ON(stride & 127); GEM_BUG_ON(stride & 127);
val = (vma->node.start + size - 4096) << 32; val = (vma->node.start + size - 4096) << 32;
@ -128,8 +128,8 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *fence,
GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma));
GEM_BUG_ON(vma->node.start & ~I915_FENCE_START_MASK); GEM_BUG_ON(vma->node.start & ~I915_FENCE_START_MASK);
GEM_BUG_ON(!is_power_of_2(vma->node.size)); GEM_BUG_ON(!is_power_of_2(vma->fence_size));
GEM_BUG_ON(vma->node.start & (vma->node.size - 1)); GEM_BUG_ON(vma->node.start & (vma->fence_size - 1));
if (is_y_tiled && HAS_128_BYTE_Y_TILING(fence->i915)) if (is_y_tiled && HAS_128_BYTE_Y_TILING(fence->i915))
stride /= 128; stride /= 128;
@ -140,7 +140,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *fence,
val = vma->node.start; val = vma->node.start;
if (is_y_tiled) if (is_y_tiled)
val |= BIT(I830_FENCE_TILING_Y_SHIFT); val |= BIT(I830_FENCE_TILING_Y_SHIFT);
val |= I915_FENCE_SIZE_BITS(vma->node.size); val |= I915_FENCE_SIZE_BITS(vma->fence_size);
val |= ilog2(stride) << I830_FENCE_PITCH_SHIFT; val |= ilog2(stride) << I830_FENCE_PITCH_SHIFT;
val |= I830_FENCE_REG_VALID; val |= I830_FENCE_REG_VALID;
@ -162,20 +162,18 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *fence,
val = 0; val = 0;
if (vma) { if (vma) {
unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
bool is_y_tiled = tiling == I915_TILING_Y;
unsigned int stride = i915_gem_object_get_stride(vma->obj); unsigned int stride = i915_gem_object_get_stride(vma->obj);
GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma));
GEM_BUG_ON(vma->node.start & ~I830_FENCE_START_MASK); GEM_BUG_ON(vma->node.start & ~I830_FENCE_START_MASK);
GEM_BUG_ON(!is_power_of_2(vma->node.size)); GEM_BUG_ON(!is_power_of_2(vma->fence_size));
GEM_BUG_ON(!is_power_of_2(stride / 128)); GEM_BUG_ON(!is_power_of_2(stride / 128));
GEM_BUG_ON(vma->node.start & (vma->node.size - 1)); GEM_BUG_ON(vma->node.start & (vma->fence_size - 1));
val = vma->node.start; val = vma->node.start;
if (is_y_tiled) if (i915_gem_object_get_tiling(vma->obj) == I915_TILING_Y)
val |= BIT(I830_FENCE_TILING_Y_SHIFT); val |= BIT(I830_FENCE_TILING_Y_SHIFT);
val |= I830_FENCE_SIZE_BITS(vma->node.size); val |= I830_FENCE_SIZE_BITS(vma->fence_size);
val |= ilog2(stride / 128) << I830_FENCE_PITCH_SHIFT; val |= ilog2(stride / 128) << I830_FENCE_PITCH_SHIFT;
val |= I830_FENCE_REG_VALID; val |= I830_FENCE_REG_VALID;
} }

View File

@ -120,25 +120,18 @@ i915_tiling_ok(struct drm_i915_private *dev_priv,
static bool i915_vma_fence_prepare(struct i915_vma *vma, static bool i915_vma_fence_prepare(struct i915_vma *vma,
int tiling_mode, unsigned int stride) int tiling_mode, unsigned int stride)
{ {
struct drm_i915_private *dev_priv = vma->vm->i915; struct drm_i915_private *i915 = vma->vm->i915;
u32 size; u32 size, alignment;
if (!i915_vma_is_map_and_fenceable(vma)) if (!i915_vma_is_map_and_fenceable(vma))
return true; return true;
if (INTEL_GEN(dev_priv) == 3) { size = i915_gem_get_ggtt_size(i915, vma->size, tiling_mode, stride);
if (vma->node.start & ~I915_FENCE_START_MASK)
return false;
} else {
if (vma->node.start & ~I830_FENCE_START_MASK)
return false;
}
size = i915_gem_get_ggtt_size(dev_priv, vma->size, tiling_mode, stride);
if (vma->node.size < size) if (vma->node.size < size)
return false; return false;
if (vma->node.start & (size - 1)) alignment = i915_gem_get_ggtt_alignment(i915, vma->size, tiling_mode, stride);
if (vma->node.start & (alignment - 1))
return false; return false;
return true; return true;
@ -156,6 +149,9 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj,
return 0; return 0;
list_for_each_entry(vma, &obj->vma_list, obj_link) { list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (!i915_vma_is_ggtt(vma))
break;
if (i915_vma_fence_prepare(vma, tiling_mode, stride)) if (i915_vma_fence_prepare(vma, tiling_mode, stride))
continue; continue;
@ -277,10 +273,18 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
mutex_unlock(&obj->mm.lock); mutex_unlock(&obj->mm.lock);
list_for_each_entry(vma, &obj->vma_list, obj_link) { list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (!vma->fence) if (!i915_vma_is_ggtt(vma))
continue; break;
vma->fence->dirty = true; vma->fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
args->tiling_mode,
args->stride);
vma->fence_alignment = i915_gem_get_ggtt_alignment(dev_priv, vma->size,
args->tiling_mode,
args->stride);
if (vma->fence)
vma->fence->dirty = true;
} }
obj->tiling_and_stride = obj->tiling_and_stride =
args->stride | args->tiling_mode; args->stride | args->tiling_mode;

View File

@ -91,6 +91,7 @@ __i915_vma_create(struct drm_i915_gem_object *obj,
vma->vm = vm; vma->vm = vm;
vma->obj = obj; vma->obj = obj;
vma->size = obj->base.size; vma->size = obj->base.size;
vma->display_alignment = 4096;
if (view) { if (view) {
vma->ggtt_view = *view; vma->ggtt_view = *view;
@ -110,6 +111,17 @@ __i915_vma_create(struct drm_i915_gem_object *obj,
} }
if (i915_is_ggtt(vm)) { if (i915_is_ggtt(vm)) {
GEM_BUG_ON(overflows_type(vma->size, u32));
vma->fence_size = i915_gem_get_ggtt_size(vm->i915, vma->size,
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj));
GEM_BUG_ON(vma->fence_size & 4095);
vma->fence_alignment = i915_gem_get_ggtt_alignment(vm->i915, vma->size,
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj));
GEM_BUG_ON(!is_power_of_2(vma->fence_alignment));
vma->flags |= I915_VMA_GGTT; vma->flags |= I915_VMA_GGTT;
list_add(&vma->obj_link, &obj->vma_list); list_add(&vma->obj_link, &obj->vma_list);
} else { } else {
@ -277,34 +289,24 @@ i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma) void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
{ {
struct drm_i915_gem_object *obj = vma->obj;
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
bool mappable, fenceable; bool mappable, fenceable;
u32 fence_size, fence_alignment;
fence_size = i915_gem_get_ggtt_size(dev_priv, GEM_BUG_ON(!i915_vma_is_ggtt(vma));
vma->size, GEM_BUG_ON(!vma->fence_size);
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj));
fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
vma->size,
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj),
true);
GEM_BUG_ON(!is_power_of_2(fence_alignment));
fenceable = (vma->node.size == fence_size &&
(vma->node.start & (fence_alignment - 1)) == 0);
mappable = (vma->node.start + fence_size <=
dev_priv->ggtt.mappable_end);
/* /*
* Explicitly disable for rotated VMA since the display does not * Explicitly disable for rotated VMA since the display does not
* need the fence and the VMA is not accessible to other users. * need the fence and the VMA is not accessible to other users.
*/ */
if (mappable && fenceable && if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED) return;
fenceable = (vma->node.size >= vma->fence_size &&
(vma->node.start & (vma->fence_alignment - 1)) == 0);
mappable = vma->node.start + vma->fence_size <= i915_vm_to_ggtt(vma->vm)->mappable_end;
if (mappable && fenceable)
vma->flags |= I915_VMA_CAN_FENCE; vma->flags |= I915_VMA_CAN_FENCE;
else else
vma->flags &= ~I915_VMA_CAN_FENCE; vma->flags &= ~I915_VMA_CAN_FENCE;
@ -371,17 +373,12 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
size = max(size, vma->size); size = max(size, vma->size);
if (flags & PIN_MAPPABLE) alignment = max(alignment, vma->display_alignment);
size = i915_gem_get_ggtt_size(dev_priv, size, if (flags & PIN_MAPPABLE) {
i915_gem_object_get_tiling(obj), size = max_t(typeof(size), size, vma->fence_size);
i915_gem_object_get_stride(obj)); alignment = max_t(typeof(alignment),
alignment, vma->fence_alignment);
alignment = max(max(alignment, vma->display_alignment), }
i915_gem_get_ggtt_alignment(dev_priv, size,
i915_gem_object_get_tiling(obj),
i915_gem_object_get_stride(obj),
flags & PIN_MAPPABLE));
GEM_BUG_ON(!is_power_of_2(alignment));
start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;

View File

@ -55,6 +55,9 @@ struct i915_vma {
u64 size; u64 size;
u64 display_alignment; u64 display_alignment;
u32 fence_size;
u32 fence_alignment;
unsigned int flags; unsigned int flags;
/** /**
* How many users have pinned this object in GTT space. The following * How many users have pinned this object in GTT space. The following