aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-01-10 12:35:37 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-11 17:55:48 -0500
commit6fe4f14044f181e146cdc15485428f95fa541ce8 (patch)
treec063724f6c4fc109a7af0c5f0799113e7527b2ae /drivers
parent809b63349ce6eb6603e7dab482c642f28135a2db (diff)
drm/i915/execbuffer: Reorder binding of objects to favour restrictions
As the mappable portion of the aperture is always a small subset at the start of the GTT, it is allocated preferentially by drm_mm. This is useful in case we ever need to map an object later. However, if you have a large object that can consume the entire mappable region of the GTT this prevents the batchbuffer from fitting and so causing an error. Instead allocate all those that require a mapping up front in order to improve the likelihood of finding sufficient space to bind them. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c72
2 files changed, 47 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6130f77c26b..385fc7ec39d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -796,6 +796,7 @@ struct drm_i915_gem_object {
796 */ 796 */
797 struct hlist_node exec_node; 797 struct hlist_node exec_node;
798 unsigned long exec_handle; 798 unsigned long exec_handle;
799 struct drm_i915_gem_exec_object2 *exec_entry;
799 800
800 /** 801 /**
801 * Current offset of the object in GTT space. 802 * Current offset of the object in GTT space.
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 0445770cc23..e69834341ef 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -268,7 +268,6 @@ eb_destroy(struct eb_objects *eb)
268static int 268static int
269i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, 269i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
270 struct eb_objects *eb, 270 struct eb_objects *eb,
271 struct drm_i915_gem_exec_object2 *entry,
272 struct drm_i915_gem_relocation_entry *reloc) 271 struct drm_i915_gem_relocation_entry *reloc)
273{ 272{
274 struct drm_device *dev = obj->base.dev; 273 struct drm_device *dev = obj->base.dev;
@@ -411,10 +410,10 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
411 410
412static int 411static int
413i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, 412i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
414 struct eb_objects *eb, 413 struct eb_objects *eb)
415 struct drm_i915_gem_exec_object2 *entry)
416{ 414{
417 struct drm_i915_gem_relocation_entry __user *user_relocs; 415 struct drm_i915_gem_relocation_entry __user *user_relocs;
416 struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
418 int i, ret; 417 int i, ret;
419 418
420 user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; 419 user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
@@ -426,7 +425,7 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
426 sizeof(reloc))) 425 sizeof(reloc)))
427 return -EFAULT; 426 return -EFAULT;
428 427
429 ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &reloc); 428 ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc);
430 if (ret) 429 if (ret)
431 return ret; 430 return ret;
432 431
@@ -442,13 +441,13 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
442static int 441static int
443i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, 442i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
444 struct eb_objects *eb, 443 struct eb_objects *eb,
445 struct drm_i915_gem_exec_object2 *entry,
446 struct drm_i915_gem_relocation_entry *relocs) 444 struct drm_i915_gem_relocation_entry *relocs)
447{ 445{
446 const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
448 int i, ret; 447 int i, ret;
449 448
450 for (i = 0; i < entry->relocation_count; i++) { 449 for (i = 0; i < entry->relocation_count; i++) {
451 ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &relocs[i]); 450 ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i]);
452 if (ret) 451 if (ret)
453 return ret; 452 return ret;
454 } 453 }
@@ -459,8 +458,7 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
459static int 458static int
460i915_gem_execbuffer_relocate(struct drm_device *dev, 459i915_gem_execbuffer_relocate(struct drm_device *dev,
461 struct eb_objects *eb, 460 struct eb_objects *eb,
462 struct list_head *objects, 461 struct list_head *objects)
463 struct drm_i915_gem_exec_object2 *exec)
464{ 462{
465 struct drm_i915_gem_object *obj; 463 struct drm_i915_gem_object *obj;
466 int ret; 464 int ret;
@@ -468,7 +466,7 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,
468 list_for_each_entry(obj, objects, exec_list) { 466 list_for_each_entry(obj, objects, exec_list) {
469 obj->base.pending_read_domains = 0; 467 obj->base.pending_read_domains = 0;
470 obj->base.pending_write_domain = 0; 468 obj->base.pending_write_domain = 0;
471 ret = i915_gem_execbuffer_relocate_object(obj, eb, exec++); 469 ret = i915_gem_execbuffer_relocate_object(obj, eb);
472 if (ret) 470 if (ret)
473 return ret; 471 return ret;
474 } 472 }
@@ -479,13 +477,36 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,
479static int 477static int
480i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, 478i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
481 struct drm_file *file, 479 struct drm_file *file,
482 struct list_head *objects, 480 struct list_head *objects)
483 struct drm_i915_gem_exec_object2 *exec)
484{ 481{
485 struct drm_i915_gem_object *obj; 482 struct drm_i915_gem_object *obj;
486 struct drm_i915_gem_exec_object2 *entry;
487 int ret, retry; 483 int ret, retry;
488 bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; 484 bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
485 struct list_head ordered_objects;
486
487 INIT_LIST_HEAD(&ordered_objects);
488 while (!list_empty(objects)) {
489 struct drm_i915_gem_exec_object2 *entry;
490 bool need_fence, need_mappable;
491
492 obj = list_first_entry(objects,
493 struct drm_i915_gem_object,
494 exec_list);
495 entry = obj->exec_entry;
496
497 need_fence =
498 has_fenced_gpu_access &&
499 entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
500 obj->tiling_mode != I915_TILING_NONE;
501 need_mappable =
502 entry->relocation_count ? true : need_fence;
503
504 if (need_mappable)
505 list_move(&obj->exec_list, &ordered_objects);
506 else
507 list_move_tail(&obj->exec_list, &ordered_objects);
508 }
509 list_splice(&ordered_objects, objects);
489 510
490 /* Attempt to pin all of the buffers into the GTT. 511 /* Attempt to pin all of the buffers into the GTT.
491 * This is done in 3 phases: 512 * This is done in 3 phases:
@@ -504,14 +525,11 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
504 ret = 0; 525 ret = 0;
505 526
506 /* Unbind any ill-fitting objects or pin. */ 527 /* Unbind any ill-fitting objects or pin. */
507 entry = exec;
508 list_for_each_entry(obj, objects, exec_list) { 528 list_for_each_entry(obj, objects, exec_list) {
529 struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
509 bool need_fence, need_mappable; 530 bool need_fence, need_mappable;
510 531 if (!obj->gtt_space)
511 if (!obj->gtt_space) {
512 entry++;
513 continue; 532 continue;
514 }
515 533
516 need_fence = 534 need_fence =
517 has_fenced_gpu_access && 535 has_fenced_gpu_access &&
@@ -534,8 +552,8 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
534 } 552 }
535 553
536 /* Bind fresh objects */ 554 /* Bind fresh objects */
537 entry = exec;
538 list_for_each_entry(obj, objects, exec_list) { 555 list_for_each_entry(obj, objects, exec_list) {
556 struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
539 bool need_fence; 557 bool need_fence;
540 558
541 need_fence = 559 need_fence =
@@ -570,7 +588,6 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
570 } 588 }
571 589
572 entry->offset = obj->gtt_offset; 590 entry->offset = obj->gtt_offset;
573 entry++;
574 } 591 }
575 592
576 /* Decrement pin count for bound objects */ 593 /* Decrement pin count for bound objects */
@@ -680,10 +697,11 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
680 697
681 list_add_tail(&obj->exec_list, objects); 698 list_add_tail(&obj->exec_list, objects);
682 obj->exec_handle = exec[i].handle; 699 obj->exec_handle = exec[i].handle;
700 obj->exec_entry = &exec[i];
683 eb_add_object(eb, obj); 701 eb_add_object(eb, obj);
684 } 702 }
685 703
686 ret = i915_gem_execbuffer_reserve(ring, file, objects, exec); 704 ret = i915_gem_execbuffer_reserve(ring, file, objects);
687 if (ret) 705 if (ret)
688 goto err; 706 goto err;
689 707
@@ -692,7 +710,6 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
692 obj->base.pending_read_domains = 0; 710 obj->base.pending_read_domains = 0;
693 obj->base.pending_write_domain = 0; 711 obj->base.pending_write_domain = 0;
694 ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, 712 ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
695 exec,
696 reloc + total); 713 reloc + total);
697 if (ret) 714 if (ret)
698 goto err; 715 goto err;
@@ -1110,16 +1127,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
1110 1127
1111 list_add_tail(&obj->exec_list, &objects); 1128 list_add_tail(&obj->exec_list, &objects);
1112 obj->exec_handle = exec[i].handle; 1129 obj->exec_handle = exec[i].handle;
1130 obj->exec_entry = &exec[i];
1113 eb_add_object(eb, obj); 1131 eb_add_object(eb, obj);
1114 } 1132 }
1115 1133
1134 /* take note of the batch buffer before we might reorder the lists */
1135 batch_obj = list_entry(objects.prev,
1136 struct drm_i915_gem_object,
1137 exec_list);
1138
1116 /* Move the objects en-masse into the GTT, evicting if necessary. */ 1139 /* Move the objects en-masse into the GTT, evicting if necessary. */
1117 ret = i915_gem_execbuffer_reserve(ring, file, &objects, exec); 1140 ret = i915_gem_execbuffer_reserve(ring, file, &objects);
1118 if (ret) 1141 if (ret)
1119 goto err; 1142 goto err;
1120 1143
1121 /* The objects are in their final locations, apply the relocations. */ 1144 /* The objects are in their final locations, apply the relocations. */
1122 ret = i915_gem_execbuffer_relocate(dev, eb, &objects, exec); 1145 ret = i915_gem_execbuffer_relocate(dev, eb, &objects);
1123 if (ret) { 1146 if (ret) {
1124 if (ret == -EFAULT) { 1147 if (ret == -EFAULT) {
1125 ret = i915_gem_execbuffer_relocate_slow(dev, file, ring, 1148 ret = i915_gem_execbuffer_relocate_slow(dev, file, ring,
@@ -1133,9 +1156,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
1133 } 1156 }
1134 1157
1135 /* Set the pending read domains for the batch buffer to COMMAND */ 1158 /* Set the pending read domains for the batch buffer to COMMAND */
1136 batch_obj = list_entry(objects.prev,
1137 struct drm_i915_gem_object,
1138 exec_list);
1139 if (batch_obj->base.pending_write_domain) { 1159 if (batch_obj->base.pending_write_domain) {
1140 DRM_ERROR("Attempting to use self-modifying batch buffer\n"); 1160 DRM_ERROR("Attempting to use self-modifying batch buffer\n");
1141 ret = -EINVAL; 1161 ret = -EINVAL;