mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
drm/i915: Use the reloc.handle as an index into the execbuffer array
Using copywinwin10 as an example that is dependent upon emitting a lot of relocations (2 per operation), we see improvements of: c2d/gm45: 618000.0/sec to 623000.0/sec. i3-330m: 748000.0/sec to 789000.0/sec. (measured relative to a baseline with neither optimisations applied). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
ed5982e6ce
commit
eef90ccb8a
3 changed files with 70 additions and 39 deletions
|
@ -995,6 +995,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||||
case I915_PARAM_HAS_EXEC_NO_RELOC:
|
case I915_PARAM_HAS_EXEC_NO_RELOC:
|
||||||
value = 1;
|
value = 1;
|
||||||
break;
|
break;
|
||||||
|
case I915_PARAM_HAS_EXEC_HANDLE_LUT:
|
||||||
|
value = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
||||||
param->param);
|
param->param);
|
||||||
|
|
|
@ -36,24 +36,40 @@
|
||||||
struct eb_objects {
|
struct eb_objects {
|
||||||
struct list_head objects;
|
struct list_head objects;
|
||||||
int and;
|
int and;
|
||||||
|
union {
|
||||||
|
struct drm_i915_gem_object *lut[0];
|
||||||
struct hlist_head buckets[0];
|
struct hlist_head buckets[0];
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static struct eb_objects *
|
static struct eb_objects *
|
||||||
eb_create(int size)
|
eb_create(struct drm_i915_gem_execbuffer2 *args)
|
||||||
{
|
{
|
||||||
struct eb_objects *eb;
|
struct eb_objects *eb = NULL;
|
||||||
|
|
||||||
|
if (args->flags & I915_EXEC_HANDLE_LUT) {
|
||||||
|
int size = args->buffer_count;
|
||||||
|
size *= sizeof(struct drm_i915_gem_object *);
|
||||||
|
size += sizeof(struct eb_objects);
|
||||||
|
eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eb == NULL) {
|
||||||
|
int size = args->buffer_count;
|
||||||
int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
|
int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
|
||||||
BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
|
BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
|
||||||
while (count > size)
|
while (count > 2*size)
|
||||||
count >>= 1;
|
count >>= 1;
|
||||||
eb = kzalloc(count*sizeof(struct hlist_head) +
|
eb = kzalloc(count*sizeof(struct hlist_head) +
|
||||||
sizeof(struct eb_objects),
|
sizeof(struct eb_objects),
|
||||||
GFP_KERNEL);
|
GFP_TEMPORARY);
|
||||||
if (eb == NULL)
|
if (eb == NULL)
|
||||||
return eb;
|
return eb;
|
||||||
|
|
||||||
eb->and = count - 1;
|
eb->and = count - 1;
|
||||||
|
} else
|
||||||
|
eb->and = -args->buffer_count;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&eb->objects);
|
INIT_LIST_HEAD(&eb->objects);
|
||||||
return eb;
|
return eb;
|
||||||
}
|
}
|
||||||
|
@ -61,26 +77,20 @@ eb_create(int size)
|
||||||
static void
|
static void
|
||||||
eb_reset(struct eb_objects *eb)
|
eb_reset(struct eb_objects *eb)
|
||||||
{
|
{
|
||||||
|
if (eb->and >= 0)
|
||||||
memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
|
memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
eb_add_object(struct eb_objects *eb, struct drm_i915_gem_object *obj)
|
|
||||||
{
|
|
||||||
hlist_add_head(&obj->exec_node,
|
|
||||||
&eb->buckets[obj->exec_handle & eb->and]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eb_lookup_objects(struct eb_objects *eb,
|
eb_lookup_objects(struct eb_objects *eb,
|
||||||
struct drm_i915_gem_exec_object2 *exec,
|
struct drm_i915_gem_exec_object2 *exec,
|
||||||
int count,
|
const struct drm_i915_gem_execbuffer2 *args,
|
||||||
struct drm_file *file)
|
struct drm_file *file)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
spin_lock(&file->table_lock);
|
spin_lock(&file->table_lock);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < args->buffer_count; i++) {
|
||||||
struct drm_i915_gem_object *obj;
|
struct drm_i915_gem_object *obj;
|
||||||
|
|
||||||
obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle));
|
obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle));
|
||||||
|
@ -101,9 +111,15 @@ eb_lookup_objects(struct eb_objects *eb,
|
||||||
drm_gem_object_reference(&obj->base);
|
drm_gem_object_reference(&obj->base);
|
||||||
list_add_tail(&obj->exec_list, &eb->objects);
|
list_add_tail(&obj->exec_list, &eb->objects);
|
||||||
|
|
||||||
obj->exec_handle = exec[i].handle;
|
|
||||||
obj->exec_entry = &exec[i];
|
obj->exec_entry = &exec[i];
|
||||||
eb_add_object(eb, obj);
|
if (eb->and < 0) {
|
||||||
|
eb->lut[i] = obj;
|
||||||
|
} else {
|
||||||
|
uint32_t handle = args->flags & I915_EXEC_HANDLE_LUT ? i : exec[i].handle;
|
||||||
|
obj->exec_handle = handle;
|
||||||
|
hlist_add_head(&obj->exec_node,
|
||||||
|
&eb->buckets[handle & eb->and]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&file->table_lock);
|
spin_unlock(&file->table_lock);
|
||||||
|
|
||||||
|
@ -113,19 +129,25 @@ eb_lookup_objects(struct eb_objects *eb,
|
||||||
static struct drm_i915_gem_object *
|
static struct drm_i915_gem_object *
|
||||||
eb_get_object(struct eb_objects *eb, unsigned long handle)
|
eb_get_object(struct eb_objects *eb, unsigned long handle)
|
||||||
{
|
{
|
||||||
|
if (eb->and < 0) {
|
||||||
|
if (handle >= -eb->and)
|
||||||
|
return NULL;
|
||||||
|
return eb->lut[handle];
|
||||||
|
} else {
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct drm_i915_gem_object *obj;
|
|
||||||
|
|
||||||
head = &eb->buckets[handle & eb->and];
|
head = &eb->buckets[handle & eb->and];
|
||||||
hlist_for_each(node, head) {
|
hlist_for_each(node, head) {
|
||||||
|
struct drm_i915_gem_object *obj;
|
||||||
|
|
||||||
obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
|
obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
|
||||||
if (obj->exec_handle == handle)
|
if (obj->exec_handle == handle)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eb_destroy(struct eb_objects *eb)
|
eb_destroy(struct eb_objects *eb)
|
||||||
|
@ -615,7 +637,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
|
||||||
|
|
||||||
/* reacquire the objects */
|
/* reacquire the objects */
|
||||||
eb_reset(eb);
|
eb_reset(eb);
|
||||||
ret = eb_lookup_objects(eb, exec, count, file);
|
ret = eb_lookup_objects(eb, exec, args, file);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -919,7 +941,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||||
goto pre_mutex_err;
|
goto pre_mutex_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
eb = eb_create(args->buffer_count);
|
eb = eb_create(args);
|
||||||
if (eb == NULL) {
|
if (eb == NULL) {
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -927,7 +949,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look up object handles */
|
/* Look up object handles */
|
||||||
ret = eb_lookup_objects(eb, exec, args->buffer_count, file);
|
ret = eb_lookup_objects(eb, exec, args, file);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,7 @@ typedef struct drm_i915_irq_wait {
|
||||||
#define I915_PARAM_HAS_SECURE_BATCHES 23
|
#define I915_PARAM_HAS_SECURE_BATCHES 23
|
||||||
#define I915_PARAM_HAS_PINNED_BATCHES 24
|
#define I915_PARAM_HAS_PINNED_BATCHES 24
|
||||||
#define I915_PARAM_HAS_EXEC_NO_RELOC 25
|
#define I915_PARAM_HAS_EXEC_NO_RELOC 25
|
||||||
|
#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26
|
||||||
|
|
||||||
typedef struct drm_i915_getparam {
|
typedef struct drm_i915_getparam {
|
||||||
int param;
|
int param;
|
||||||
|
@ -699,7 +700,12 @@ struct drm_i915_gem_execbuffer2 {
|
||||||
*/
|
*/
|
||||||
#define I915_EXEC_NO_RELOC (1<<11)
|
#define I915_EXEC_NO_RELOC (1<<11)
|
||||||
|
|
||||||
#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_NO_RELOC<<1)
|
/** Use the reloc.handle as an index into the exec object array rather
|
||||||
|
* than as the per-file handle.
|
||||||
|
*/
|
||||||
|
#define I915_EXEC_HANDLE_LUT (1<<12)
|
||||||
|
|
||||||
|
#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_HANDLE_LUT<<1)
|
||||||
|
|
||||||
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
|
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
|
||||||
#define i915_execbuffer2_set_context_id(eb2, context) \
|
#define i915_execbuffer2_set_context_id(eb2, context) \
|
||||||
|
|
Loading…
Reference in a new issue