index 60174e19b3eb5d2043b0bb56cd3fc0ee3c1f0cd3..187e8ec9ca8684b5c99cbcb50f72fd095fbe2879 100644 (file)
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <stdbool.h>
#include "errno.h"
#include "libdrm_lists.h"
int num_buckets;
time_t time;
+ drmMMListHead named;
+ drmMMListHead vma_cache;
+ int vma_count, vma_open, vma_max;
+
uint64_t gtt_size;
int available_fences;
int pci_device;
int gen;
- char bo_reuse;
- char fenced_relocs;
+ unsigned int has_bsd : 1;
+ unsigned int has_blt : 1;
+ unsigned int has_relaxed_fencing : 1;
+ unsigned int has_llc : 1;
+ unsigned int bo_reuse : 1;
+ bool fenced_relocs;
} drm_intel_bufmgr_gem;
#define DRM_INTEL_RELOC_FENCE (1<<0)
* Kenel-assigned global name for this object
*/
unsigned int global_name;
+ drmMMListHead name_list;
/**
* Index of the buffer within the validation list while preparing a
void *mem_virtual;
/** GTT virtual address for the buffer, saved across map/unmap cycles */
void *gtt_virtual;
+ int map_count;
+ drmMMListHead vma_list;
/** BO cache list */
drmMMListHead head;
* Boolean of whether this BO and its children have been included in
* the current drm_intel_bufmgr_check_aperture_space() total.
*/
- char included_in_check_aperture;
+ bool included_in_check_aperture;
/**
* Boolean of whether this buffer has been used as a relocation
* target and had its size accounted for, and thus can't have any
* further relocations added to it.
*/
- char used_as_reloc_target;
+ bool used_as_reloc_target;
/**
* Boolean of whether we have encountered an error whilst building the relocation tree.
*/
- char has_error;
+ bool has_error;
/**
* Boolean of whether this buffer can be re-used
*/
- char reusable;
+ bool reusable;
/**
* Size in bytes of this buffer and its relocation descendents.
* relocations.
*/
int reloc_tree_fences;
+
+ /** Flags that we may need to do the SW_FINSIH ioctl on unmap. */
+ bool mapped_cpu_write;
};
static unsigned int
@@ -241,6 +256,10 @@ drm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size,
return size;
}
+ /* Do we need to allocate every page for the fence? */
+ if (bufmgr_gem->has_relaxed_fencing)
+ return ROUND_UP_TO(size, 4096);
+
for (i = min_size; i < size; i <<= 1)
;
if (*tiling_mode == I915_TILING_NONE)
return ALIGN(pitch, 64);
- if (*tiling_mode == I915_TILING_X)
+ if (*tiling_mode == I915_TILING_X
+ || (IS_915(bufmgr_gem->pci_device)
+ && *tiling_mode == I915_TILING_Y))
tile_width = 512;
else
tile_width = 128;
{
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
- assert(atomic_read(&bo_gem->refcount) > 0);
atomic_inc(&bo_gem->refcount);
}
* aperture. Optimal packing is for wimps.
*/
size = bo_gem->bo.size;
- if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE)
- size *= 2;
+ if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) {
+ int min_size;
+
+ if (bufmgr_gem->has_relaxed_fencing) {
+ if (bufmgr_gem->gen == 3)
+ min_size = 1024*1024;
+ else
+ min_size = 512*1024;
+
+ while (min_size < size)
+ min_size *= 2;
+ } else
+ min_size = size;
+
+ /* Account for worst-case alignment. */
+ size = 2 * min_size;
+ }
bo_gem->reloc_tree_size = size;
}
bo_gem->reloc_target_info = malloc(max_relocs *
sizeof(drm_intel_reloc_target));
if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) {
- bo_gem->has_error = 1;
+ bo_gem->has_error = true;
free (bo_gem->relocs);
bo_gem->relocs = NULL;
unsigned int page_size = getpagesize();
int ret;
struct drm_intel_gem_bo_bucket *bucket;
- int alloc_from_cache;
+ bool alloc_from_cache;
unsigned long bo_size;
- int for_render = 0;
+ bool for_render = false;
if (flags & BO_ALLOC_FOR_RENDER)
- for_render = 1;
+ for_render = true;
/* Round the allocated size up to a power of two number of pages. */
bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size);
pthread_mutex_lock(&bufmgr_gem->lock);
/* Get a buffer out of the cache if available */
retry:
- alloc_from_cache = 0;
+ alloc_from_cache = false;
if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) {
if (for_render) {
/* Allocate new render-target BOs from the tail (MRU)
bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
bucket->head.prev, head);
DRMLISTDEL(&bo_gem->head);
- alloc_from_cache = 1;
+ alloc_from_cache = true;
} else {
/* For non-render-target BOs (where we're probably
* going to map it first thing in order to fill it
bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
bucket->head.next, head);
if (!drm_intel_gem_bo_busy(&bo_gem->bo)) {
- alloc_from_cache = 1;
+ alloc_from_cache = true;
DRMLISTDEL(&bo_gem->head);
}
}
drm_intel_gem_bo_free(&bo_gem->bo);
return NULL;
}
+
+ DRMINITLISTHEAD(&bo_gem->name_list);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
}
bo_gem->name = name;
atomic_set(&bo_gem->refcount, 1);
bo_gem->validate_index = -1;
bo_gem->reloc_tree_fences = 0;
- bo_gem->used_as_reloc_target = 0;
- bo_gem->has_error = 0;
- bo_gem->reusable = 1;
+ bo_gem->used_as_reloc_target = false;
+ bo_gem->has_error = false;
+ bo_gem->reusable = true;
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
uint32_t tiling;
do {
- unsigned long aligned_y;
+ unsigned long aligned_y, height_alignment;
tiling = *tiling_mode;
* too so we try to be careful.
*/
aligned_y = y;
- if (tiling == I915_TILING_NONE)
- aligned_y = ALIGN(y, 2);
- else if (tiling == I915_TILING_X)
- aligned_y = ALIGN(y, 8);
+ height_alignment = 2;
+
+ if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
+ height_alignment = 16;
+ else if (tiling == I915_TILING_X
+ || (IS_915(bufmgr_gem->pci_device)
+ && tiling == I915_TILING_Y))
+ height_alignment = 8;
else if (tiling == I915_TILING_Y)
- aligned_y = ALIGN(y, 32);
+ height_alignment = 32;
+ aligned_y = ALIGN(y, height_alignment);
stride = x * cpp;
stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode);
int ret;
struct drm_gem_open open_arg;
struct drm_i915_gem_get_tiling get_tiling;
+ drmMMListHead *list;
+
+ /* At the moment most applications only have a few named bo.
+ * For instance, in a DRI client only the render buffers passed
+ * between X and the client are named. And since X returns the
+ * alternating names for the front/back buffer a linear search
+ * provides a sufficiently fast match.
+ */
+ for (list = bufmgr_gem->named.next;
+ list != &bufmgr_gem->named;
+ list = list->next) {
+ bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
+ if (bo_gem->global_name == handle) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ return &bo_gem->bo;
+ }
+ }
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
atomic_set(&bo_gem->refcount, 1);
bo_gem->validate_index = -1;
bo_gem->gem_handle = open_arg.handle;
+ bo_gem->bo.handle = open_arg.handle;
bo_gem->global_name = handle;
- bo_gem->reusable = 0;
+ bo_gem->reusable = false;
memset(&get_tiling, 0, sizeof(get_tiling));
get_tiling.handle = bo_gem->gem_handle;
/* XXX stride is unknown */
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
+ DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
return &bo_gem->bo;
struct drm_gem_close close;
int ret;
- if (bo_gem->mem_virtual)
+ DRMLISTDEL(&bo_gem->vma_list);
+ if (bo_gem->mem_virtual) {
munmap(bo_gem->mem_virtual, bo_gem->bo.size);
- if (bo_gem->gtt_virtual)
+ bufmgr_gem->vma_count--;
+ }
+ if (bo_gem->gtt_virtual) {
munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
+ bufmgr_gem->vma_count--;
+ }
/* Close this object */
memset(&close, 0, sizeof(close));
bufmgr_gem->time = time;
}
+static void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
+{
+ int limit;
+
+ DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
+ bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
+
+ if (bufmgr_gem->vma_max < 0)
+ return;
+
+ /* We may need to evict a few entries in order to create new mmaps */
+ limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
+ if (limit < 0)
+ limit = 0;
+
+ while (bufmgr_gem->vma_count > limit) {
+ drm_intel_bo_gem *bo_gem;
+
+ bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
+ bufmgr_gem->vma_cache.next,
+ vma_list);
+ assert(bo_gem->map_count == 0);
+ DRMLISTDELINIT(&bo_gem->vma_list);
+
+ if (bo_gem->mem_virtual) {
+ munmap(bo_gem->mem_virtual, bo_gem->bo.size);
+ bo_gem->mem_virtual = NULL;
+ bufmgr_gem->vma_count--;
+ }
+ if (bo_gem->gtt_virtual) {
+ munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
+ bo_gem->gtt_virtual = NULL;
+ bufmgr_gem->vma_count--;
+ }
+ }
+}
+
+static void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
+ drm_intel_bo_gem *bo_gem)
+{
+ bufmgr_gem->vma_open--;
+ DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
+ if (bo_gem->mem_virtual)
+ bufmgr_gem->vma_count++;
+ if (bo_gem->gtt_virtual)
+ bufmgr_gem->vma_count++;
+ drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
+}
+
+static void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
+ drm_intel_bo_gem *bo_gem)
+{
+ bufmgr_gem->vma_open++;
+ DRMLISTDEL(&bo_gem->vma_list);
+ if (bo_gem->mem_virtual)
+ bufmgr_gem->vma_count--;
+ if (bo_gem->gtt_virtual)
+ bufmgr_gem->vma_count--;
+ drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
+}
+
static void
drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
{
}
}
bo_gem->reloc_count = 0;
- bo_gem->used_as_reloc_target = 0;
+ bo_gem->used_as_reloc_target = false;
DBG("bo_unreference final: %d (%s)\n",
bo_gem->gem_handle, bo_gem->name);
bo_gem->relocs = NULL;
}
+ /* Clear any left-over mappings */
+ if (bo_gem->map_count) {
+ DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
+ bo_gem->map_count = 0;
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+ }
+
+ DRMLISTDEL(&bo_gem->name_list);
+
bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
/* Put the buffer into our internal cache for reuse if we can. */
if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
pthread_mutex_lock(&bufmgr_gem->lock);
- /* Allow recursive mapping. Mesa may recursively map buffers with
- * nested display loops.
- */
+ if (bo_gem->map_count++ == 0)
+ drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
+
if (!bo_gem->mem_virtual) {
struct drm_i915_gem_mmap mmap_arg;
- DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
+ DBG("bo_map: %d (%s), map_count=%d\n",
+ bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
memset(&mmap_arg, 0, sizeof(mmap_arg));
mmap_arg.handle = bo_gem->gem_handle;
DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
__FILE__, __LINE__, bo_gem->gem_handle,
bo_gem->name, strerror(errno));
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
pthread_mutex_unlock(&bufmgr_gem->lock);
return ret;
}
strerror(errno));
}
+ if (write_enable)
+ bo_gem->mapped_cpu_write = true;
+
pthread_mutex_unlock(&bufmgr_gem->lock);
return 0;
pthread_mutex_lock(&bufmgr_gem->lock);
+ if (bo_gem->map_count++ == 0)
+ drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
+
/* Get a mapping of the buffer if we haven't before. */
if (bo_gem->gtt_virtual == NULL) {
struct drm_i915_gem_mmap_gtt mmap_arg;
- DBG("bo_map_gtt: mmap %d (%s)\n", bo_gem->gem_handle,
- bo_gem->name);
+ DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
+ bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
memset(&mmap_arg, 0, sizeof(mmap_arg));
mmap_arg.handle = bo_gem->gem_handle;
__FILE__, __LINE__,
bo_gem->gem_handle, bo_gem->name,
strerror(errno));
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
pthread_mutex_unlock(&bufmgr_gem->lock);
return ret;
}
__FILE__, __LINE__,
bo_gem->gem_handle, bo_gem->name,
strerror(errno));
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
pthread_mutex_unlock(&bufmgr_gem->lock);
return ret;
}
return 0;
}
-int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
+static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ struct drm_i915_gem_sw_finish sw_finish;
int ret = 0;
if (bo == NULL)
return 0;
- assert(bo_gem->gtt_virtual != NULL);
-
pthread_mutex_lock(&bufmgr_gem->lock);
- bo->virtual = NULL;
- pthread_mutex_unlock(&bufmgr_gem->lock);
-
- return ret;
-}
-
-static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
-{
- drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
- drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
- struct drm_i915_gem_sw_finish sw_finish;
- int ret;
- if (bo == NULL)
+ if (bo_gem->map_count <= 0) {
+ DBG("attempted to unmap an unmapped bo\n");
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+ /* Preserve the old behaviour of just treating this as a
+ * no-op rather than reporting the error.
+ */
return 0;
+ }
- assert(bo_gem->mem_virtual != NULL);
+ if (bo_gem->mapped_cpu_write) {
+ /* Cause a flush to happen if the buffer's pinned for
+ * scanout, so the results show up in a timely manner.
+ * Unlike GTT set domains, this only does work if the
+ * buffer should be scanout-related.
+ */
+ sw_finish.handle = bo_gem->gem_handle;
+ ret = drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_SW_FINISH,
+ &sw_finish);
+ ret = ret == -1 ? -errno : 0;
- pthread_mutex_lock(&bufmgr_gem->lock);
+ bo_gem->mapped_cpu_write = false;
+ }
- /* Cause a flush to happen if the buffer's pinned for scanout, so the
- * results show up in a timely manner.
+ /* We need to unmap after every innovation as we cannot track
+ * an open vma for every bo as that will exhaasut the system
+ * limits and cause later failures.
*/
- sw_finish.handle = bo_gem->gem_handle;
- ret = drmIoctl(bufmgr_gem->fd,
- DRM_IOCTL_I915_GEM_SW_FINISH,
- &sw_finish);
- ret = ret == -1 ? -errno : 0;
-
- bo->virtual = NULL;
+ if (--bo_gem->map_count == 0) {
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+ bo->virtual = NULL;
+ }
pthread_mutex_unlock(&bufmgr_gem->lock);
return ret;
}
+int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
+{
+ return drm_intel_gem_bo_unmap(bo);
+}
+
static int
drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
unsigned long size, const void *data)
return ret;
}
-/** Waits for all GPU rendering to the object to have completed. */
+/** Waits for all GPU rendering with the object to have completed. */
static void
drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
{
- drm_intel_gem_bo_start_gtt_access(bo, 0);
+ drm_intel_gem_bo_start_gtt_access(bo, 1);
}
/**
do_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
drm_intel_bo *target_bo, uint32_t target_offset,
uint32_t read_domains, uint32_t write_domain,
- int need_fence)
+ bool need_fence)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
+ bool fenced_command;
if (bo_gem->has_error)
return -ENOMEM;
if (target_bo_gem->has_error) {
- bo_gem->has_error = 1;
+ bo_gem->has_error = true;
return -ENOMEM;
}
- if (target_bo_gem->tiling_mode == I915_TILING_NONE)
- need_fence = 0;
-
/* We never use HW fences for rendering on 965+ */
if (bufmgr_gem->gen >= 4)
- need_fence = 0;
+ need_fence = false;
+
+ fenced_command = need_fence;
+ if (target_bo_gem->tiling_mode == I915_TILING_NONE)
+ need_fence = false;
/* Create a new relocation list if needed */
if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo))
*/
assert(!bo_gem->used_as_reloc_target);
if (target_bo_gem != bo_gem) {
- target_bo_gem->used_as_reloc_target = 1;
+ target_bo_gem->used_as_reloc_target = true;
bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
}
/* An object needing a fence is a tiled buffer, so it won't have
target_bo_gem->reloc_tree_fences = 1;
bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences;
- /* Flag the target to disallow further relocations in it. */
-
bo_gem->relocs[bo_gem->reloc_count].offset = offset;
bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
bo_gem->relocs[bo_gem->reloc_count].target_handle =
bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo;
if (target_bo != bo)
drm_intel_gem_bo_reference(target_bo);
- if (need_fence)
+ if (fenced_command)
bo_gem->reloc_target_info[bo_gem->reloc_count].flags =
DRM_INTEL_RELOC_FENCE;
else
uint32_t read_domains, uint32_t write_domain)
{
return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
- read_domains, write_domain, 1);
+ read_domains, write_domain, true);
+}
+
+int
+drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ return bo_gem->reloc_count;
+}
+
+/**
+ * Removes existing relocation entries in the BO after "start".
+ *
+ * This allows a user to avoid a two-step process for state setup with
+ * counting up all the buffer objects and doing a
+ * drm_intel_bufmgr_check_aperture_space() before emitting any of the
+ * relocations for the state setup. Instead, save the state of the
+ * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
+ * state, and then check if it still fits in the aperture.
+ *
+ * Any further drm_intel_bufmgr_check_aperture_space() queries
+ * involving this buffer in the tree are undefined after this call.
+ */
+void
+drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ int i;
+ struct timespec time;
+
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ assert(bo_gem->reloc_count >= start);
+ /* Unreference the cleared target buffers */
+ for (i = start; i < bo_gem->reloc_count; i++) {
+ if (bo_gem->reloc_target_info[i].bo != bo) {
+ drm_intel_gem_bo_unreference_locked_timed(bo_gem->
+ reloc_target_info[i].bo,
+ time.tv_sec);
+ }
+ }
+ bo_gem->reloc_count = start;
}
/**
static int
drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
- int ring_flag)
+ unsigned int flags)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
struct drm_i915_gem_execbuffer2 execbuf;
int ret, i;
- if ((ring_flag != I915_EXEC_RENDER) && (ring_flag != I915_EXEC_BSD))
+ switch (flags & 0x7) {
+ default:
return -EINVAL;
+ case I915_EXEC_BLT:
+ if (!bufmgr_gem->has_blt)
+ return -EINVAL;
+ break;
+ case I915_EXEC_BSD:
+ if (!bufmgr_gem->has_bsd)
+ return -EINVAL;
+ break;
+ case I915_EXEC_RENDER:
+ case I915_EXEC_DEFAULT:
+ break;
+ }
pthread_mutex_lock(&bufmgr_gem->lock);
/* Update indices and set up the validate list. */
execbuf.num_cliprects = num_cliprects;
execbuf.DR1 = 0;
execbuf.DR4 = DR4;
- execbuf.flags = ring_flag;
+ execbuf.flags = flags;
execbuf.rsvd1 = 0;
execbuf.rsvd2 = 0;
if (ret != 0)
return -errno;
bo_gem->global_name = flink.name;
- bo_gem->reusable = 0;
+ bo_gem->reusable = false;
+
+ DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
}
*name = bo_gem->global_name;
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
- bufmgr_gem->bo_reuse = 1;
+ bufmgr_gem->bo_reuse = true;
}
/**
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
if (bufmgr_gem->bufmgr.bo_exec == drm_intel_gem_bo_exec2)
- bufmgr_gem->fenced_relocs = 1;
+ bufmgr_gem->fenced_relocs = true;
}
/**
return 0;
total += bo->size;
- bo_gem->included_in_check_aperture = 1;
+ bo_gem->included_in_check_aperture = true;
for (i = 0; i < bo_gem->reloc_count; i++)
total +=
if (bo == NULL || !bo_gem->included_in_check_aperture)
return;
- bo_gem->included_in_check_aperture = 0;
+ bo_gem->included_in_check_aperture = false;
for (i = 0; i < bo_gem->reloc_count; i++)
drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->
{
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
- bo_gem->reusable = 0;
+ bo_gem->reusable = false;
return 0;
}
}
}
+void
+drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+
+ bufmgr_gem->vma_max = limit;
+
+ drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
+}
+
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.
drm_intel_bufmgr_gem *bufmgr_gem;
struct drm_i915_gem_get_aperture aperture;
drm_i915_getparam_t gp;
- int ret;
- int exec2 = 0, has_bsd = 0;
+ int ret, tmp;
+ bool exec2 = false;
bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
if (bufmgr_gem == NULL)
fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
}
- if (IS_GEN2(bufmgr_gem))
+ if (IS_GEN2(bufmgr_gem->pci_device))
bufmgr_gem->gen = 2;
- else if (IS_GEN3(bufmgr_gem))
+ else if (IS_GEN3(bufmgr_gem->pci_device))
bufmgr_gem->gen = 3;
- else if (IS_GEN4(bufmgr_gem))
+ else if (IS_GEN4(bufmgr_gem->pci_device))
bufmgr_gem->gen = 4;
- else
+ else if (IS_GEN5(bufmgr_gem->pci_device))
+ bufmgr_gem->gen = 5;
+ else if (IS_GEN6(bufmgr_gem->pci_device))
bufmgr_gem->gen = 6;
+ else if (IS_GEN7(bufmgr_gem->pci_device))
+ bufmgr_gem->gen = 7;
+ else
+ assert(0);
+
+ if (IS_GEN3(bufmgr_gem->pci_device) &&
+ bufmgr_gem->gtt_size > 256*1024*1024) {
+ /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
+ * be used for tiled blits. To simplify the accounting, just
+ * substract the unmappable part (fixed to 256MB on all known
+ * gen3 devices) if the kernel advertises it. */
+ bufmgr_gem->gtt_size -= 256*1024*1024;
+ }
+
+ gp.value = &tmp;
gp.param = I915_PARAM_HAS_EXECBUF2;
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
if (!ret)
- exec2 = 1;
+ exec2 = true;
gp.param = I915_PARAM_HAS_BSD;
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
- if (!ret)
- has_bsd = 1;
+ bufmgr_gem->has_bsd = ret == 0;
+
+ gp.param = I915_PARAM_HAS_BLT;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ bufmgr_gem->has_blt = ret == 0;
+
+ gp.param = I915_PARAM_HAS_RELAXED_FENCING;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ bufmgr_gem->has_relaxed_fencing = ret == 0;
+
+ gp.param = I915_PARAM_HAS_LLC;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ if (ret == -EINVAL) {
+ /* Kernel does not supports HAS_LLC query, fallback to GPU
+ * generation detection and assume that we have LLC on GEN6/7
+ */
+ bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
+ IS_GEN7(bufmgr_gem->pci_device));
+ } else
+ bufmgr_gem->has_llc = ret == 0;
if (bufmgr_gem->gen < 4) {
gp.param = I915_PARAM_NUM_FENCES_AVAIL;
/* Use the new one if available */
if (exec2) {
bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2;
- if (has_bsd)
- bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
+ bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
} else
bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec;
bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy;
drm_intel_gem_get_pipe_from_crtc_id;
bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references;
+ DRMINITLISTHEAD(&bufmgr_gem->named);
init_cache_buckets(bufmgr_gem);
+ DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
+ bufmgr_gem->vma_max = -1; /* unlimited by default */
+
return &bufmgr_gem->bufmgr;
}