diff --git a/src/gallium/drivers/iris/iris_bufmgr.c b/src/gallium/drivers/iris/iris_bufmgr.c index 65b2b4838ff..2e22dc8fd79 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.c +++ b/src/gallium/drivers/iris/iris_bufmgr.c @@ -53,6 +53,7 @@ #include "dev/intel_debug.h" #include "common/intel_gem.h" #include "dev/intel_device_info.h" +#include "isl/isl.h" #include "main/macros.h" #include "os/os_mman.h" #include "util/debug.h" @@ -199,9 +200,6 @@ static struct list_head global_bufmgr_list = { .prev = &global_bufmgr_list, }; -static int bo_set_tiling_internal(struct iris_bo *bo, uint32_t tiling_mode, - uint32_t stride); - static void bo_free(struct iris_bo *bo); static struct iris_bo * @@ -501,8 +499,6 @@ alloc_fresh_bo(struct iris_bufmgr *bufmgr, uint64_t bo_size) bo->bufmgr = bufmgr; bo->size = bo_size; bo->idle = true; - bo->tiling_mode = I915_TILING_NONE; - bo->stride = 0; /* Calling set_domain() will allocate pages for the BO outside of the * struct mutex lock in the kernel, which is more efficient than waiting @@ -522,15 +518,13 @@ alloc_fresh_bo(struct iris_bufmgr *bufmgr, uint64_t bo_size) return bo; } -static struct iris_bo * -bo_alloc_internal(struct iris_bufmgr *bufmgr, - const char *name, - uint64_t size, - uint32_t alignment, - enum iris_memory_zone memzone, - unsigned flags, - uint32_t tiling_mode, - uint32_t stride) +struct iris_bo * +iris_bo_alloc(struct iris_bufmgr *bufmgr, + const char *name, + uint64_t size, + uint32_t alignment, + enum iris_memory_zone memzone, + unsigned flags) { struct iris_bo *bo; unsigned int page_size = getpagesize(); @@ -576,9 +570,6 @@ bo_alloc_internal(struct iris_bufmgr *bufmgr, goto err_free; } - if (bo_set_tiling_internal(bo, tiling_mode, stride)) - goto err_free; - bo->name = name; p_atomic_set(&bo->refcount, 1); bo->reusable = bucket && bufmgr->bo_reuse; @@ -618,28 +609,6 @@ err_free: return NULL; } -struct iris_bo * -iris_bo_alloc(struct iris_bufmgr *bufmgr, - const char *name, - uint64_t size, - uint32_t alignment, - enum iris_memory_zone memzone, - unsigned flags) -{ - return bo_alloc_internal(bufmgr, name, size, alignment, memzone, - flags, I915_TILING_NONE, 0); -} - -struct iris_bo * -iris_bo_alloc_tiled(struct iris_bufmgr *bufmgr, const char *name, - uint64_t size, uint32_t alignment, - enum iris_memory_zone memzone, - uint32_t tiling_mode, uint32_t pitch, unsigned flags) -{ - return bo_alloc_internal(bufmgr, name, size, alignment, memzone, - flags, tiling_mode, pitch); -} - struct iris_bo * iris_bo_create_userptr(struct iris_bufmgr *bufmgr, const char *name, void *ptr, size_t size, @@ -758,24 +727,11 @@ iris_bo_gem_create_from_name(struct iris_bufmgr *bufmgr, _mesa_hash_table_insert(bufmgr->handle_table, &bo->gem_handle, bo); _mesa_hash_table_insert(bufmgr->name_table, &bo->global_name, bo); - struct drm_i915_gem_get_tiling get_tiling = { .handle = bo->gem_handle }; - ret = intel_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); - if (ret != 0) - goto err_unref; - - bo->tiling_mode = get_tiling.tiling_mode; - - /* XXX stride is unknown */ DBG("bo_create_from_handle: %d (%s)\n", handle, bo->name); out: mtx_unlock(&bufmgr->lock); return bo; - -err_unref: - bo_free(bo); - mtx_unlock(&bufmgr->lock); - return NULL; } static void @@ -1153,50 +1109,64 @@ iris_bufmgr_destroy(struct iris_bufmgr *bufmgr) free(bufmgr); } -static int -bo_set_tiling_internal(struct iris_bo *bo, uint32_t tiling_mode, - uint32_t stride) +int +iris_gem_get_tiling(struct iris_bo *bo, uint32_t *tiling) { struct iris_bufmgr *bufmgr = bo->bufmgr; - struct drm_i915_gem_set_tiling set_tiling; - int ret; - if (bo->global_name == 0 && - tiling_mode == bo->tiling_mode && stride == bo->stride) + if (!bufmgr->has_tiling_uapi) { + *tiling = I915_TILING_NONE; return 0; + } + + struct drm_i915_gem_get_tiling ti = { .handle = bo->gem_handle }; + int ret = intel_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &ti); + + if (ret) { + DBG("gem_get_tiling failed for BO %u: %s\n", + bo->gem_handle, strerror(ret)); + } + + *tiling = ti.tiling_mode; + + return ret; +} + +int +iris_gem_set_tiling(struct iris_bo *bo, const struct isl_surf *surf) +{ + struct iris_bufmgr *bufmgr = bo->bufmgr; + uint32_t tiling_mode = isl_tiling_to_i915_tiling(surf->tiling); + int ret; /* If we can't do map_gtt, the set/get_tiling API isn't useful. And it's * actually not supported by the kernel in those cases. */ - if (!bufmgr->has_tiling_uapi) { - bo->tiling_mode = tiling_mode; - bo->stride = stride; + if (!bufmgr->has_tiling_uapi) return 0; - } - memset(&set_tiling, 0, sizeof(set_tiling)); + /* GEM_SET_TILING is slightly broken and overwrites the input on the + * error path, so we have to open code intel_ioctl(). + */ do { - /* set_tiling is slightly broken and overwrites the - * input on the error path, so we have to open code - * drm_ioctl. - */ - set_tiling.handle = bo->gem_handle; - set_tiling.tiling_mode = tiling_mode; - set_tiling.stride = stride; - + struct drm_i915_gem_set_tiling set_tiling = { + .handle = bo->gem_handle, + .tiling_mode = tiling_mode, + .stride = surf->row_pitch_B, + }; ret = ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - if (ret == -1) - return -errno; - bo->tiling_mode = set_tiling.tiling_mode; - bo->stride = set_tiling.stride; - return 0; + if (ret) { + DBG("gem_set_tiling failed for BO %u: %s\n", + bo->gem_handle, strerror(ret)); + } + + return ret; } struct iris_bo * -iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd, - uint64_t modifier) +iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd) { uint32_t handle; struct iris_bo *bo; @@ -1257,79 +1227,6 @@ iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd, bo->gem_handle = handle; _mesa_hash_table_insert(bufmgr->handle_table, &bo->gem_handle, bo); - const struct isl_drm_modifier_info *mod_info = - isl_drm_modifier_get_info(modifier); - if (mod_info) { - bo->tiling_mode = isl_tiling_to_i915_tiling(mod_info->tiling); - } else if (bufmgr->has_tiling_uapi) { - struct drm_i915_gem_get_tiling get_tiling = { .handle = bo->gem_handle }; - if (intel_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) - goto err; - bo->tiling_mode = get_tiling.tiling_mode; - } else { - bo->tiling_mode = I915_TILING_NONE; - } - -out: - mtx_unlock(&bufmgr->lock); - return bo; - -err: - bo_free(bo); - mtx_unlock(&bufmgr->lock); - return NULL; -} - -struct iris_bo * -iris_bo_import_dmabuf_no_mods(struct iris_bufmgr *bufmgr, - int prime_fd) -{ - uint32_t handle; - struct iris_bo *bo; - - mtx_lock(&bufmgr->lock); - int ret = drmPrimeFDToHandle(bufmgr->fd, prime_fd, &handle); - if (ret) { - DBG("import_dmabuf: failed to obtain handle from fd: %s\n", - strerror(errno)); - mtx_unlock(&bufmgr->lock); - return NULL; - } - - /* - * See if the kernel has already returned this buffer to us. Just as - * for named buffers, we must not create two bo's pointing at the same - * kernel object - */ - bo = find_and_ref_external_bo(bufmgr->handle_table, handle); - if (bo) - goto out; - - bo = bo_calloc(); - if (!bo) - goto out; - - p_atomic_set(&bo->refcount, 1); - - /* Determine size of bo. The fd-to-handle ioctl really should - * return the size, but it doesn't. If we have kernel 3.12 or - * later, we can lseek on the prime fd to get the size. Older - * kernels will just fail, in which case we fall back to the - * provided (estimated or guess size). */ - ret = lseek(prime_fd, 0, SEEK_END); - if (ret != -1) - bo->size = ret; - - bo->bufmgr = bufmgr; - bo->name = "prime"; - bo->reusable = false; - bo->imported = true; - bo->mmap_mode = IRIS_MMAP_WC; - bo->kflags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | EXEC_OBJECT_PINNED; - bo->gtt_offset = vma_alloc(bufmgr, IRIS_MEMZONE_OTHER, bo->size, 1); - bo->gem_handle = handle; - _mesa_hash_table_insert(bufmgr->handle_table, &bo->gem_handle, bo); - out: mtx_unlock(&bufmgr->lock); return bo; diff --git a/src/gallium/drivers/iris/iris_bufmgr.h b/src/gallium/drivers/iris/iris_bufmgr.h index 528712be602..9c0a243d7d2 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.h +++ b/src/gallium/drivers/iris/iris_bufmgr.h @@ -37,6 +37,7 @@ struct iris_batch; struct intel_device_info; struct pipe_debug_callback; +struct isl_surf; /** * Memory zones. When allocating a buffer, you can request that it is @@ -182,12 +183,6 @@ struct iris_bo { */ unsigned global_name; - /** - * Current tiling mode - */ - uint32_t tiling_mode; - uint32_t stride; - time_t free_time; /** Mapped address for the buffer, saved across map/unmap cycles */ @@ -262,26 +257,6 @@ struct iris_bo *iris_bo_alloc(struct iris_bufmgr *bufmgr, enum iris_memory_zone memzone, unsigned flags); -/** - * Allocate a tiled buffer object. - * - * Alignment for tiled objects is set automatically; the 'flags' - * argument provides a hint about how the object will be used initially. - * - * Valid tiling formats are: - * I915_TILING_NONE - * I915_TILING_X - * I915_TILING_Y - */ -struct iris_bo *iris_bo_alloc_tiled(struct iris_bufmgr *bufmgr, - const char *name, - uint64_t size, - uint32_t alignment, - enum iris_memory_zone memzone, - uint32_t tiling_mode, - uint32_t pitch, - unsigned flags); - struct iris_bo * iris_bo_create_userptr(struct iris_bufmgr *bufmgr, const char *name, void *ptr, size_t size, @@ -409,9 +384,11 @@ int iris_hw_context_set_priority(struct iris_bufmgr *bufmgr, void iris_destroy_hw_context(struct iris_bufmgr *bufmgr, uint32_t ctx_id); +int iris_gem_get_tiling(struct iris_bo *bo, uint32_t *tiling); +int iris_gem_set_tiling(struct iris_bo *bo, const struct isl_surf *surf); + int iris_bo_export_dmabuf(struct iris_bo *bo, int *prime_fd); -struct iris_bo *iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd, - uint64_t modifier); +struct iris_bo *iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd); /** * Exports a bo as a GEM handle into a given DRM file descriptor @@ -425,9 +402,6 @@ struct iris_bo *iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd, int iris_bo_export_gem_handle_for_device(struct iris_bo *bo, int drm_fd, uint32_t *out_handle); -struct iris_bo *iris_bo_import_dmabuf_no_mods(struct iris_bufmgr *bufmgr, - int prime_fd); - uint32_t iris_bo_export_gem_handle(struct iris_bo *bo); int iris_reg_read(struct iris_bufmgr *bufmgr, uint32_t offset, uint64_t *out); diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index 18d04fb7cde..3d28c83c3ad 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -308,7 +308,6 @@ iris_memobj_create_from_handle(struct pipe_screen *pscreen, struct iris_screen *screen = (struct iris_screen *)pscreen; struct iris_memory_object *memobj = CALLOC_STRUCT(iris_memory_object); struct iris_bo *bo; - const struct isl_drm_modifier_info *mod_inf; if (!memobj) return NULL; @@ -319,19 +318,7 @@ iris_memobj_create_from_handle(struct pipe_screen *pscreen, whandle->handle); break; case WINSYS_HANDLE_TYPE_FD: - mod_inf = isl_drm_modifier_get_info(whandle->modifier); - if (mod_inf) { - bo = iris_bo_import_dmabuf(screen->bufmgr, whandle->handle, - whandle->modifier); - } else { - /* If we can't get information about the tiling from the - * kernel we ignore it. We are going to set it when we - * create the resource. - */ - bo = iris_bo_import_dmabuf_no_mods(screen->bufmgr, - whandle->handle); - } - + bo = iris_bo_import_dmabuf(screen->bufmgr, whandle->handle); break; default: unreachable("invalid winsys handle type"); @@ -1048,10 +1035,8 @@ iris_resource_create_with_modifiers(struct pipe_screen *pscreen, } uint32_t alignment = MAX2(4096, res->surf.alignment_B); - res->bo = iris_bo_alloc_tiled(screen->bufmgr, name, bo_size, alignment, - memzone, - isl_tiling_to_i915_tiling(res->surf.tiling), - res->surf.row_pitch_B, flags); + res->bo = + iris_bo_alloc(screen->bufmgr, name, bo_size, alignment, memzone, flags); if (!res->bo) goto fail; @@ -1164,8 +1149,7 @@ iris_resource_from_handle(struct pipe_screen *pscreen, switch (whandle->type) { case WINSYS_HANDLE_TYPE_FD: - res->bo = iris_bo_import_dmabuf(bufmgr, whandle->handle, - whandle->modifier); + res->bo = iris_bo_import_dmabuf(bufmgr, whandle->handle); break; case WINSYS_HANDLE_TYPE_SHARED: res->bo = iris_bo_gem_create_from_name(bufmgr, "winsys image", @@ -1182,17 +1166,19 @@ iris_resource_from_handle(struct pipe_screen *pscreen, /* Create a surface for each plane specified by the external format. */ if (whandle->plane < util_format_get_num_planes(whandle->format)) { + uint64_t modifier = whandle->modifier; - const uint64_t modifier = - whandle->modifier != DRM_FORMAT_MOD_INVALID ? - whandle->modifier : tiling_to_modifier(res->bo->tiling_mode); + if (whandle->modifier == DRM_FORMAT_MOD_INVALID) { + /* We don't have a modifier; match whatever GEM_GET_TILING says */ + uint32_t tiling; + iris_gem_get_tiling(res->bo, &tiling); + modifier = tiling_to_modifier(tiling); + } UNUSED const bool isl_surf_created_successfully = iris_resource_configure_main(screen, res, templ, modifier, whandle->stride); assert(isl_surf_created_successfully); - assert(res->bo->tiling_mode == - isl_tiling_to_i915_tiling(res->surf.tiling)); UNUSED const bool ok = iris_resource_configure_aux(screen, res, true); assert(ok); @@ -1344,14 +1330,20 @@ iris_resource_get_param(struct pipe_screen *pscreen, return true; case PIPE_RESOURCE_PARAM_MODIFIER: *value = res->mod_info ? res->mod_info->modifier : - tiling_to_modifier(res->bo->tiling_mode); + tiling_to_modifier(isl_tiling_to_i915_tiling(res->surf.tiling)); return true; case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED: + if (!wants_aux) + iris_gem_set_tiling(bo, &res->surf); + result = iris_bo_flink(bo, &handle) == 0; if (result) *value = handle; return result; case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: { + if (!wants_aux) + iris_gem_set_tiling(bo, &res->surf); + /* Because we share the same drm file across multiple iris_screen, when * we export a GEM handle we must make sure it is valid in the DRM file * descriptor the caller is using (this is the FD given at screen @@ -1365,6 +1357,9 @@ iris_resource_get_param(struct pipe_screen *pscreen, } case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD: + if (!wants_aux) + iris_gem_set_tiling(bo, &res->surf); + result = iris_bo_export_dmabuf(bo, (int *) &handle) == 0; if (result) *value = handle; @@ -1408,7 +1403,7 @@ iris_resource_get_handle(struct pipe_screen *pscreen, whandle->format = res->external_format; whandle->modifier = res->mod_info ? res->mod_info->modifier - : tiling_to_modifier(res->bo->tiling_mode); + : tiling_to_modifier(isl_tiling_to_i915_tiling(res->surf.tiling)); #ifndef NDEBUG enum isl_aux_usage allowed_usage = @@ -1424,8 +1419,11 @@ iris_resource_get_handle(struct pipe_screen *pscreen, switch (whandle->type) { case WINSYS_HANDLE_TYPE_SHARED: + iris_gem_set_tiling(bo, &res->surf); return iris_bo_flink(bo, &whandle->handle) == 0; case WINSYS_HANDLE_TYPE_KMS: { + iris_gem_set_tiling(bo, &res->surf); + /* Because we share the same drm file across multiple iris_screen, when * we export a GEM handle we must make sure it is valid in the DRM file * descriptor the caller is using (this is the FD given at screen @@ -1438,6 +1436,7 @@ iris_resource_get_handle(struct pipe_screen *pscreen, return true; } case WINSYS_HANDLE_TYPE_FD: + iris_gem_set_tiling(bo, &res->surf); return iris_bo_export_dmabuf(bo, (int *) &whandle->handle) == 0; }