X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_resource.c;h=3ea45ba080b31f16dffd24c921f3b1c1e005d60a;hb=ad1a4cb563f483a5767431adcc6a1a8f973326fd;hp=f13b1da9311409a13bb9c4fa8d946ab5c1e47424;hpb=2aec62a45b1c907a8fff511b8eca21fa52538acb;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index f13b1da9311..3ea45ba080b 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -22,6 +22,7 @@ * IN THE SOFTWARE. */ +#include "pipe/p_defines.h" #include "util/u_blit.h" #include "util/u_memory.h" #include "util/u_format.h" @@ -29,13 +30,13 @@ #include "util/u_surface.h" #include "util/u_upload_mgr.h" +#include "drm_fourcc.h" +#include "vc4_drm.h" #include "vc4_screen.h" #include "vc4_context.h" #include "vc4_resource.h" #include "vc4_tiling.h" -static bool miptree_debug = false; - static bool vc4_resource_bo_alloc(struct vc4_resource *rsc) { @@ -43,7 +44,7 @@ vc4_resource_bo_alloc(struct vc4_resource *rsc) struct pipe_screen *pscreen = prsc->screen; struct vc4_bo *bo; - if (miptree_debug) { + if (vc4_debug & VC4_DEBUG_SURFACE) { fprintf(stderr, "alloc %p: size %d + offset %d -> %d\n", rsc, rsc->slices[0].size, @@ -369,7 +370,6 @@ vc4_resource_destroy(struct pipe_screen *pscreen, { struct vc4_screen *screen = vc4_screen(pscreen); struct vc4_resource *rsc = vc4_resource(prsc); - pipe_resource_reference(&rsc->shadow_parent, NULL); vc4_bo_unreference(&rsc->bo); if (rsc->scanout) @@ -389,6 +389,7 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, struct vc4_resource *rsc = vc4_resource(prsc); whandle->stride = rsc->slices[0].stride; + whandle->offset = 0; /* If we're passing some reference to our BO out to some other part of * the system, then we can't do any optimizations about only us being @@ -396,8 +397,13 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, */ rsc->bo->private = false; + if (rsc->tiled) + whandle->modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED; + else + whandle->modifier = DRM_FORMAT_MOD_LINEAR; + switch (whandle->type) { - case DRM_API_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_SHARED: if (screen->ro) { /* This could probably be supported, assuming that a * control node was used for pl111. @@ -407,12 +413,12 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, } return vc4_bo_flink(rsc->bo, &whandle->handle); - case DRM_API_HANDLE_TYPE_KMS: + case WINSYS_HANDLE_TYPE_KMS: if (screen->ro && renderonly_get_handle(rsc->scanout, whandle)) return TRUE; whandle->handle = rsc->bo->handle; return TRUE; - case DRM_API_HANDLE_TYPE_FD: + case WINSYS_HANDLE_TYPE_FD: /* FDs are cross-device, so we can export directly from vc4. */ whandle->handle = vc4_bo_get_dmabuf(rsc->bo); @@ -423,7 +429,7 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, } static void -vc4_setup_slices(struct vc4_resource *rsc) +vc4_setup_slices(struct vc4_resource *rsc, const char *caller) { struct pipe_resource *prsc = &rsc->base; uint32_t width = prsc->width0; @@ -482,16 +488,16 @@ vc4_setup_slices(struct vc4_resource *rsc) offset += slice->size; - if (miptree_debug) { + if (vc4_debug & VC4_DEBUG_SURFACE) { static const char tiling_chars[] = { [VC4_TILING_FORMAT_LINEAR] = 'R', [VC4_TILING_FORMAT_LT] = 'L', [VC4_TILING_FORMAT_T] = 'T' }; fprintf(stderr, - "rsc setup %p (format %s: vc4 %d), %dx%d: " + "rsc %s %p (format %s: vc4 %d), %dx%d: " "level %d (%c) -> %dx%d, stride %d@0x%08x\n", - rsc, + caller, rsc, util_format_short_name(prsc->format), rsc->vc4_format, prsc->width0, prsc->height0, @@ -555,56 +561,138 @@ get_resource_texture_format(struct pipe_resource *prsc) if (prsc->nr_samples > 1) { return ~0; } else { - assert(format == VC4_TEXTURE_TYPE_RGBA8888); - return VC4_TEXTURE_TYPE_RGBA32R; + if (format == VC4_TEXTURE_TYPE_RGBA8888) + return VC4_TEXTURE_TYPE_RGBA32R; + else + return ~0; } } return format; } -struct pipe_resource * -vc4_resource_create(struct pipe_screen *pscreen, - const struct pipe_resource *tmpl) +static bool +find_modifier(uint64_t needle, const uint64_t *haystack, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (haystack[i] == needle) + return true; + } + + return false; +} + +static struct pipe_resource * +vc4_resource_create_with_modifiers(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl, + const uint64_t *modifiers, + int count) { struct vc4_screen *screen = vc4_screen(pscreen); struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl); struct pipe_resource *prsc = &rsc->base; + bool linear_ok = find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count); + /* Use a tiled layout if we can, for better 3D performance. */ + bool should_tile = true; + + /* VBOs/PBOs are untiled (and 1 height). */ + if (tmpl->target == PIPE_BUFFER) + should_tile = false; + + /* MSAA buffers are linear. */ + if (tmpl->nr_samples > 1) + should_tile = false; + + /* No tiling when we're sharing with another device (pl111). */ + if (screen->ro && (tmpl->bind & PIPE_BIND_SCANOUT)) + should_tile = false; + + /* Cursors are always linear, and the user can request linear as well. + */ + if (tmpl->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR)) + should_tile = false; + + /* No shared objects with LT format -- the kernel only has T-format + * metadata. LT objects are small enough it's not worth the trouble to + * give them metadata to tile. + */ + if ((tmpl->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT)) && + vc4_size_is_lt(prsc->width0, prsc->height0, rsc->cpp)) + should_tile = false; - /* We have to make shared be untiled, since we don't have any way to - * communicate metadata about tiling currently. + /* If we're sharing or scanning out, we need the ioctl present to + * inform the kernel or the other side. */ - if (tmpl->target == PIPE_BUFFER || - tmpl->nr_samples > 1 || - (tmpl->bind & (PIPE_BIND_SCANOUT | - PIPE_BIND_LINEAR | - PIPE_BIND_SHARED | - PIPE_BIND_CURSOR))) { + if ((tmpl->bind & (PIPE_BIND_SHARED | + PIPE_BIND_SCANOUT)) && !screen->has_tiling_ioctl) + should_tile = false; + + /* No user-specified modifier; determine our own. */ + if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { + linear_ok = true; + rsc->tiled = should_tile; + } else if (should_tile && + find_modifier(DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, + modifiers, count)) { + rsc->tiled = true; + } else if (linear_ok) { rsc->tiled = false; } else { - rsc->tiled = true; + fprintf(stderr, "Unsupported modifier requested\n"); + return NULL; } if (tmpl->target != PIPE_BUFFER) rsc->vc4_format = get_resource_texture_format(prsc); - vc4_setup_slices(rsc); + vc4_setup_slices(rsc, "create"); if (!vc4_resource_bo_alloc(rsc)) goto fail; + if (screen->has_tiling_ioctl) { + uint64_t modifier; + if (rsc->tiled) + modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED; + else + modifier = DRM_FORMAT_MOD_LINEAR; + struct drm_vc4_set_tiling set_tiling = { + .handle = rsc->bo->handle, + .modifier = modifier, + }; + int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_SET_TILING, + &set_tiling); + if (ret != 0) + goto fail; + } + if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) { rsc->scanout = - renderonly_scanout_for_resource(prsc, screen->ro); + renderonly_scanout_for_resource(prsc, screen->ro, NULL); if (!rsc->scanout) goto fail; } + vc4_bo_label(screen, rsc->bo, "%sresource %dx%d@%d/%d", + (tmpl->bind & PIPE_BIND_SCANOUT) ? "scanout " : "", + tmpl->width0, tmpl->height0, + rsc->cpp * 8, prsc->last_level); + return prsc; fail: vc4_resource_destroy(pscreen, prsc); return NULL; } +struct pipe_resource * +vc4_resource_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl) +{ + const uint64_t mod = DRM_FORMAT_MOD_INVALID; + return vc4_resource_create_with_modifiers(pscreen, tmpl, &mod, 1); +} + static struct pipe_resource * vc4_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *tmpl, @@ -615,42 +703,16 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl); struct pipe_resource *prsc = &rsc->base; struct vc4_resource_slice *slice = &rsc->slices[0]; - uint32_t expected_stride = - align(prsc->width0, vc4_utile_width(rsc->cpp)) * rsc->cpp; if (!rsc) return NULL; - if (whandle->stride != expected_stride) { - static bool warned = false; - if (!warned) { - warned = true; - fprintf(stderr, - "Attempting to import %dx%d %s with " - "unsupported stride %d instead of %d\n", - prsc->width0, prsc->height0, - util_format_short_name(prsc->format), - whandle->stride, - expected_stride); - } - goto fail; - } - - rsc->tiled = false; - - if (whandle->offset != 0) { - fprintf(stderr, - "Attempt to import unsupported winsys offset %u\n", - whandle->offset); - return NULL; - } - switch (whandle->type) { - case DRM_API_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_SHARED: rsc->bo = vc4_bo_open_name(screen, whandle->handle, whandle->stride); break; - case DRM_API_HANDLE_TYPE_FD: + case WINSYS_HANDLE_TYPE_FD: rsc->bo = vc4_bo_open_dmabuf(screen, whandle->handle, whandle->stride); break; @@ -663,10 +725,60 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, if (!rsc->bo) goto fail; - slice->stride = whandle->stride; - slice->tiling = VC4_TILING_FORMAT_LINEAR; + struct drm_vc4_get_tiling get_tiling = { + .handle = rsc->bo->handle, + }; + int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling); + + if (ret != 0) { + whandle->modifier = DRM_FORMAT_MOD_LINEAR; + } else if (whandle->modifier == DRM_FORMAT_MOD_INVALID) { + whandle->modifier = get_tiling.modifier; + } else if (whandle->modifier != get_tiling.modifier) { + fprintf(stderr, + "Modifier 0x%llx vs. tiling (0x%llx) mismatch\n", + (long long)whandle->modifier, get_tiling.modifier); + goto fail; + } + + switch (whandle->modifier) { + case DRM_FORMAT_MOD_LINEAR: + rsc->tiled = false; + break; + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: + rsc->tiled = true; + break; + default: + fprintf(stderr, + "Attempt to import unsupported modifier 0x%llx\n", + (long long)whandle->modifier); + goto fail; + } rsc->vc4_format = get_resource_texture_format(prsc); + vc4_setup_slices(rsc, "import"); + + if (whandle->offset != 0) { + if (rsc->tiled) { + fprintf(stderr, + "Attempt to import unsupported " + "winsys offset %u\n", + whandle->offset); + goto fail; + } + + rsc->slices[0].offset += whandle->offset; + + if (rsc->slices[0].offset + rsc->slices[0].size > + rsc->bo->size) { + fprintf(stderr, "Attempt to import " + "with overflowing offset (%d + %d > %d)\n", + whandle->offset, + rsc->slices[0].size, + rsc->bo->size); + goto fail; + } + } if (screen->ro) { /* Make sure that renderonly has a handle to our buffer in the @@ -675,18 +787,27 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, */ rsc->scanout = renderonly_create_gpu_import_for_resource(prsc, - screen->ro); + screen->ro, + NULL); if (!rsc->scanout) goto fail; } - if (miptree_debug) { - fprintf(stderr, - "rsc import %p (format %d), %dx%d: " - "level 0 (R) -> stride %d@0x%08x\n", - rsc, rsc->vc4_format, - prsc->width0, prsc->height0, - slice->stride, slice->offset); + if (rsc->tiled && whandle->stride != slice->stride) { + static bool warned = false; + if (!warned) { + warned = true; + fprintf(stderr, + "Attempting to import %dx%d %s with " + "unsupported stride %d instead of %d\n", + prsc->width0, prsc->height0, + util_format_short_name(prsc->format), + whandle->stride, + slice->stride); + } + goto fail; + } else if (!rsc->tiled) { + slice->stride = whandle->stride; } return prsc; @@ -977,19 +1098,21 @@ vc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource) void vc4_update_shadow_baselevel_texture(struct pipe_context *pctx, - struct pipe_sampler_view *view) + struct pipe_sampler_view *pview) { + struct vc4_sampler_view *view = vc4_sampler_view(pview); struct vc4_resource *shadow = vc4_resource(view->texture); - struct vc4_resource *orig = vc4_resource(shadow->shadow_parent); - assert(orig); + struct vc4_resource *orig = vc4_resource(pview->texture); + + assert(view->texture != pview->texture); if (shadow->writes == orig->writes && orig->bo->private) return; perf_debug("Updating %dx%d@%d shadow texture due to %s\n", orig->base.width0, orig->base.height0, - view->u.tex.first_level, - view->u.tex.first_level ? "base level" : "raster layout"); + pview->u.tex.first_level, + pview->u.tex.first_level ? "base level" : "raster layout"); for (int i = 0; i <= shadow->base.last_level; i++) { unsigned width = u_minify(shadow->base.width0, i); @@ -1010,7 +1133,7 @@ vc4_update_shadow_baselevel_texture(struct pipe_context *pctx, }, .src = { .resource = &orig->base, - .level = view->u.tex.first_level + i, + .level = pview->u.tex.first_level + i, .box = { .x = 0, .y = 0, @@ -1083,11 +1206,26 @@ vc4_get_shadow_index_buffer(struct pipe_context *pctx, void vc4_resource_screen_init(struct pipe_screen *pscreen) { + struct vc4_screen *screen = vc4_screen(pscreen); + pscreen->resource_create = vc4_resource_create; + pscreen->resource_create_with_modifiers = + vc4_resource_create_with_modifiers; pscreen->resource_from_handle = vc4_resource_from_handle; pscreen->resource_destroy = u_resource_destroy_vtbl; pscreen->resource_get_handle = vc4_resource_get_handle; pscreen->resource_destroy = vc4_resource_destroy; + + /* Test if the kernel has GET_TILING; it will return -EINVAL if the + * ioctl does not exist, but -ENOENT if we pass an impossible handle. + * 0 cannot be a valid GEM object, so use that. + */ + struct drm_vc4_get_tiling get_tiling = { + .handle = 0x0, + }; + int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling); + if (ret == -1 && errno == ENOENT) + screen->has_tiling_ioctl = true; } void