History

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).

Chris Wilson committed 13 years ago

Commit eef90cc1 parent ed5982e3 files · +71 −40Browse files

Unified · Split

3 files
  1. drivers/gpu/drm/i915/i915_dma.c +3 −0
  2. drivers/gpu/drm/i915/i915_gem_execbuffer.c +61 −39
  3. include/uapi/drm/i915_drm.h +7 −1
drivers/gpu/drm/i915/i915_dma.c+3−0
@@ -995,6 +995,9 @@ static int i915_getparam(struct drm_device *dev, void *data, · 994 unmodified lines
995995 case I915_PARAM_HAS_EXEC_NO_RELOC:
996996 value = 1;
997997 break;
998+ case I915_PARAM_HAS_EXEC_HANDLE_LUT:
999+ value = 1;
1000+ break;
9981001 default:
9991002 DRM_DEBUG_DRIVER("Unknown parameter %d\n",
10001003 param->param);
drivers/gpu/drm/i915/i915_gem_execbuffer.c+61−39
@@ -36,24 +36,40 @@ · 35 unmodified lines
3636 struct eb_objects {
3737 struct list_head objects;
3838 int and;
39− struct hlist_head buckets[0];
39+ union {
40+ struct drm_i915_gem_object *lut[0];
41+ struct hlist_head buckets[0];
42+ };
4043 };
4144
4245 static struct eb_objects *
43−eb_create(int size)
46+eb_create(struct drm_i915_gem_execbuffer2 *args)
4447 {
45− struct eb_objects *eb;
46− int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
47− BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
48− while (count > size)
49− count >>= 1;
50− eb = kzalloc(count*sizeof(struct hlist_head) +
51− sizeof(struct eb_objects),
52− GFP_KERNEL);
53− if (eb == NULL)
54− return eb;
55−
56− eb->and = count - 1;
48+ struct eb_objects *eb = NULL;
49+
50+ if (args->flags & I915_EXEC_HANDLE_LUT) {
51+ int size = args->buffer_count;
52+ size *= sizeof(struct drm_i915_gem_object *);
53+ size += sizeof(struct eb_objects);
54+ eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
55+ }
56+
57+ if (eb == NULL) {
58+ int size = args->buffer_count;
59+ int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
60+ BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
61+ while (count > 2*size)
62+ count >>= 1;
63+ eb = kzalloc(count*sizeof(struct hlist_head) +
64+ sizeof(struct eb_objects),
65+ GFP_TEMPORARY);
66+ if (eb == NULL)
67+ return eb;
68+
69+ eb->and = count - 1;
70+ } else
71+ eb->and = -args->buffer_count;
72+
5773 INIT_LIST_HEAD(&eb->objects);
5874 return eb;
5975 }
@@ -61,26 +77,20 @@ eb_create(int size) · 1 unmodified line
6177 static void
6278 eb_reset(struct eb_objects *eb)
6379 {
64− memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
65−}
66−
67−static void
68−eb_add_object(struct eb_objects *eb, struct drm_i915_gem_object *obj)
69−{
70− hlist_add_head(&obj->exec_node,
71− &eb->buckets[obj->exec_handle & eb->and]);
80+ if (eb->and >= 0)
81+ memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
7282 }
7383
7484 static int
7585 eb_lookup_objects(struct eb_objects *eb,
7686 struct drm_i915_gem_exec_object2 *exec,
77− int count,
87+ const struct drm_i915_gem_execbuffer2 *args,
7888 struct drm_file *file)
7989 {
8090 int i;
8191
8292 spin_lock(&file->table_lock);
83− for (i = 0; i < count; i++) {
93+ for (i = 0; i < args->buffer_count; i++) {
8494 struct drm_i915_gem_object *obj;
8595
8696 obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle));
@@ -101,9 +111,15 @@ eb_lookup_objects(struct eb_objects *eb, · 14 unmodified lines
101111 drm_gem_object_reference(&obj->base);
102112 list_add_tail(&obj->exec_list, &eb->objects);
103113
104− obj->exec_handle = exec[i].handle;
105114 obj->exec_entry = &exec[i];
106− eb_add_object(eb, obj);
115+ if (eb->and < 0) {
116+ eb->lut[i] = obj;
117+ } else {
118+ uint32_t handle = args->flags & I915_EXEC_HANDLE_LUT ? i : exec[i].handle;
119+ obj->exec_handle = handle;
120+ hlist_add_head(&obj->exec_node,
121+ &eb->buckets[handle & eb->and]);
122+ }
107123 }
108124 spin_unlock(&file->table_lock);
109125
@@ -113,18 +129,24 @@ eb_lookup_objects(struct eb_objects *eb, · 3 unmodified lines
113129 static struct drm_i915_gem_object *
114130 eb_get_object(struct eb_objects *eb, unsigned long handle)
115131 {
116− struct hlist_head *head;
117− struct hlist_node *node;
118− struct drm_i915_gem_object *obj;
132+ if (eb->and < 0) {
133+ if (handle >= -eb->and)
134+ return NULL;
135+ return eb->lut[handle];
136+ } else {
137+ struct hlist_head *head;
138+ struct hlist_node *node;
119139
120− head = &eb->buckets[handle & eb->and];
121− hlist_for_each(node, head) {
122− obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
123− if (obj->exec_handle == handle)
124− return obj;
125− }
140+ head = &eb->buckets[handle & eb->and];
141+ hlist_for_each(node, head) {
142+ struct drm_i915_gem_object *obj;
126143
127− return NULL;
144+ obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
145+ if (obj->exec_handle == handle)
146+ return obj;
147+ }
148+ return NULL;
149+ }
128150 }
129151
130152 static void
@@ -615,7 +637,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, · 484 unmodified lines
615637
616638 /* reacquire the objects */
617639 eb_reset(eb);
618− ret = eb_lookup_objects(eb, exec, count, file);
640+ ret = eb_lookup_objects(eb, exec, args, file);
619641 if (ret)
620642 goto err;
621643
@@ -919,7 +941,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, · 297 unmodified lines
919941 goto pre_mutex_err;
920942 }
921943
922− eb = eb_create(args->buffer_count);
944+ eb = eb_create(args);
923945 if (eb == NULL) {
924946 mutex_unlock(&dev->struct_mutex);
925947 ret = -ENOMEM;
@@ -927,7 +949,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, · 1 unmodified line
927949 }
928950
929951 /* Look up object handles */
930− ret = eb_lookup_objects(eb, exec, args->buffer_count, file);
952+ ret = eb_lookup_objects(eb, exec, args, file);
931953 if (ret)
932954 goto err;
933955
include/uapi/drm/i915_drm.h+7−1
@@ -309,6 +309,7 @@ typedef struct drm_i915_irq_wait { · 308 unmodified lines
309309 #define I915_PARAM_HAS_SECURE_BATCHES 23
310310 #define I915_PARAM_HAS_PINNED_BATCHES 24
311311 #define I915_PARAM_HAS_EXEC_NO_RELOC 25
312+#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26
312313
313314 typedef struct drm_i915_getparam {
314315 int param;
@@ -699,7 +700,12 @@ struct drm_i915_gem_execbuffer2 { · 384 unmodified lines
699700 */
700701 #define I915_EXEC_NO_RELOC (1<<11)
701702
702−#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_NO_RELOC<<1)
703+/** Use the reloc.handle as an index into the exec object array rather
704+ * than as the per-file handle.
705+ */
706+#define I915_EXEC_HANDLE_LUT (1<<12)
707+
708+#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_HANDLE_LUT<<1)
703709
704710 #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
705711 #define i915_execbuffer2_set_context_id(eb2, context) \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t