[intel] Minor kludge -- wait for the ring to be nearly empty before queuing
No need to fill the ring that much; wait for it to become nearly empty before adding the execbuffer request. A better fix will involve scheduling ring insertion in the irq handler.main
parent
7e7ea313c4
commit
17e8000ac0
|
@ -821,14 +821,43 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Kludge -- wait for almost all rendering to complete
|
||||
* before queuing more. This uses interrupts, so the wakeup
|
||||
* occurs without any delay.
|
||||
*/
|
||||
static int
|
||||
i915_gem_wait_space(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
struct drm_i915_gem_object *obj_priv, *last_priv = NULL;
|
||||
int ret = 0;
|
||||
|
||||
while (ring->space + 1024 < dev_priv->ring.Size &&
|
||||
!list_empty(&dev_priv->mm.execution_list)) {
|
||||
obj_priv = list_first_entry(&dev_priv->mm.execution_list,
|
||||
struct drm_i915_gem_object,
|
||||
gtt_lru_entry);
|
||||
if (obj_priv == last_priv)
|
||||
break;
|
||||
ret = i915_gem_object_wait_rendering(obj_priv->obj);
|
||||
if (ret)
|
||||
break;
|
||||
last_priv = obj_priv;
|
||||
i915_kernel_lost_context(dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_execbuffer *args = data;
|
||||
struct drm_i915_gem_exec_object *validate_list;
|
||||
struct drm_gem_object **object_list;
|
||||
struct drm_i915_gem_exec_object *validate_list = NULL;
|
||||
struct drm_gem_object **object_list = NULL;
|
||||
struct drm_gem_object *batch_obj;
|
||||
int ret, i;
|
||||
uint64_t exec_offset;
|
||||
|
@ -842,6 +871,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
|||
#endif
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
ret = i915_gem_wait_space(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Copy in the validate list from userland */
|
||||
validate_list = drm_calloc(sizeof(*validate_list), args->buffer_count,
|
||||
DRM_MEM_DRIVER);
|
||||
|
@ -975,7 +1008,6 @@ err:
|
|||
for (i = 0; i < args->buffer_count; i++)
|
||||
drm_gem_object_unreference(object_list[i]);
|
||||
}
|
||||
|
||||
drm_free(object_list, sizeof(*object_list) * args->buffer_count,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(validate_list, sizeof(*validate_list) * args->buffer_count,
|
||||
|
@ -1078,22 +1110,21 @@ i915_gem_flush_pwrite(struct drm_gem_object *obj,
|
|||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
|
||||
/*
|
||||
* As far as I can tell, writes of > 64 bytes will use non-temporal
|
||||
* stores which should obviate the need for this clflush.
|
||||
* It doesn't work for me though...
|
||||
* For writes much less than the size of the object and
|
||||
* which are already pinned in memory, do the flush right now
|
||||
*/
|
||||
/* if (size <= 64) */{
|
||||
if (obj_priv->gtt_space == NULL) {
|
||||
int ret = i915_gem_object_get_page_list (obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
i915_gem_clflush_object(obj);
|
||||
if (obj_priv->gtt_space == NULL)
|
||||
i915_gem_object_free_page_list (obj);
|
||||
}
|
||||
|
||||
if ((size < obj->size >> 1) && obj_priv->page_list != NULL) {
|
||||
unsigned long first_page = offset / PAGE_SIZE;
|
||||
unsigned long beyond_page = roundup(offset + size, PAGE_SIZE);
|
||||
|
||||
drm_ttm_cache_flush(obj_priv->page_list + first_page,
|
||||
beyond_page - first_page);
|
||||
drm_agp_chipset_flush(dev);
|
||||
obj->write_domain = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue