From d258b787faaf9b089acd740df26bddbb64c2c630 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 18 Mar 2019 16:07:00 +0000 Subject: [PATCH] panfrost: Properly align stride Handle buffers whose width is not aligned to 16px by padding the stride and storing it accordingly. This does not reject imports for images whose stride is not sufficiently aligned. v2: make sure bo->stride is set on imported buffers, and add missing variable definition. (Tomeu) Tested-by: Tomeu Vizoso Reviewed-by: Alyssa Rosenzweig --- src/gallium/drivers/panfrost/pan_context.c | 2 +- src/gallium/drivers/panfrost/pan_drm.c | 3 ++- src/gallium/drivers/panfrost/pan_mfbd.c | 11 +++------- src/gallium/drivers/panfrost/pan_resource.c | 23 ++++++++++----------- src/gallium/drivers/panfrost/pan_resource.h | 1 + src/gallium/drivers/panfrost/pan_screen.h | 2 +- src/gallium/drivers/panfrost/pan_sfbd.c | 3 +-- 7 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 10eb6795bae..19cdb6c0444 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -70,7 +70,7 @@ panfrost_enable_afbc(struct panfrost_context *ctx, struct panfrost_resource *rsr int tile_w = (rsrc->base.width0 + (MALI_TILE_LENGTH - 1)) >> MALI_TILE_SHIFT; int tile_h = (rsrc->base.height0 + (MALI_TILE_LENGTH - 1)) >> MALI_TILE_SHIFT; int bytes_per_pixel = util_format_get_blocksize(rsrc->base.format); - int stride = bytes_per_pixel * rsrc->base.width0; /* TODO: Alignment? */ + int stride = bytes_per_pixel * ALIGN(rsrc->base.width0, 16); stride *= 2; /* TODO: Should this be carried over? */ int main_size = stride * rsrc->base.height0; diff --git a/src/gallium/drivers/panfrost/pan_drm.c b/src/gallium/drivers/panfrost/pan_drm.c index 71e8c6ac1f9..bc2007e6cce 100644 --- a/src/gallium/drivers/panfrost/pan_drm.c +++ b/src/gallium/drivers/panfrost/pan_drm.c @@ -162,7 +162,7 @@ panfrost_drm_import_bo(struct panfrost_screen *screen, struct winsys_handle *wha } static int -panfrost_drm_export_bo(struct panfrost_screen *screen, int gem_handle, struct winsys_handle *whandle) +panfrost_drm_export_bo(struct panfrost_screen *screen, int gem_handle, unsigned int stride, struct winsys_handle *whandle) { struct panfrost_drm *drm = (struct panfrost_drm *)screen->driver; struct drm_prime_handle args = { @@ -175,6 +175,7 @@ panfrost_drm_export_bo(struct panfrost_screen *screen, int gem_handle, struct wi return FALSE; whandle->handle = args.fd; + whandle->stride = stride; return TRUE; } diff --git a/src/gallium/drivers/panfrost/pan_mfbd.c b/src/gallium/drivers/panfrost/pan_mfbd.c index ac7f9ed665f..6a7cd596744 100644 --- a/src/gallium/drivers/panfrost/pan_mfbd.c +++ b/src/gallium/drivers/panfrost/pan_mfbd.c @@ -81,9 +81,7 @@ panfrost_mfbd_set_cbuf( bool flip_y) { struct panfrost_resource *rsrc = pan_resource(surf->texture); - - signed stride = - util_format_get_stride(surf->format, surf->texture->width0); + int stride = rsrc->bo->stride; rt->format = panfrost_mfbd_format(surf); @@ -148,8 +146,7 @@ panfrost_mfbd_set_zsbuf( fbx->flags |= MALI_EXTRA_PRESENT | MALI_EXTRA_ZS | 0x1; fbx->ds_linear.depth = rsrc->bo->gpu[0]; - fbx->ds_linear.depth_stride = - util_format_get_stride(surf->format, surf->texture->width0); + fbx->ds_linear.depth_stride = rsrc->bo->stride; } else { assert(0); } @@ -273,12 +270,10 @@ panfrost_mfbd_fragment(struct panfrost_context *ctx, bool flip_y) struct panfrost_resource *rsrc = (struct panfrost_resource *) ctx->pipe_framebuffer.cbufs[0]->texture; if (rsrc->bo->has_checksum) { - int stride = util_format_get_stride(rsrc->base.format, rsrc->base.width0); - fb.unk3 |= MALI_MFBD_EXTRA; fbx.flags |= MALI_EXTRA_PRESENT; fbx.checksum_stride = rsrc->bo->checksum_stride; - fbx.checksum = rsrc->bo->gpu[0] + stride * rsrc->base.height0; + fbx.checksum = rsrc->bo->gpu[0] + rsrc->bo->stride * rsrc->base.height0; } } diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 9e83c9bcb51..6fe871594ea 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -68,6 +68,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, prsc->screen = pscreen; rsc->bo = screen->driver->import_bo(screen, whandle); + rsc->bo->stride = whandle->stride; if (screen->ro) { rsc->scanout = @@ -88,10 +89,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, struct panfrost_screen *screen = pan_screen(pscreen); struct panfrost_resource *rsrc = (struct panfrost_resource *) pt; struct renderonly_scanout *scanout = rsrc->scanout; - int bytes_per_pixel = util_format_get_blocksize(rsrc->base.format); - int stride = bytes_per_pixel * rsrc->base.width0; /* TODO: Alignment? */ - handle->stride = stride; handle->modifier = DRM_FORMAT_MOD_INVALID; if (handle->type == WINSYS_HANDLE_TYPE_SHARED) { @@ -101,6 +99,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, return TRUE; handle->handle = rsrc->bo->gem_handle; + handle->stride = rsrc->bo->stride; return TRUE; } else if (handle->type == WINSYS_HANDLE_TYPE_FD) { if (scanout) { @@ -113,11 +112,12 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, if (ret == -1) return FALSE; + handle->stride = scanout->stride; handle->handle = args.fd; return TRUE; } else - return screen->driver->export_bo(screen, rsrc->bo->gem_handle, handle); + return screen->driver->export_bo(screen, rsrc->bo->gem_handle, rsrc->bo->stride, handle); } return FALSE; @@ -191,7 +191,7 @@ panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *t /* Calculate the size of the bo */ int bytes_per_pixel = util_format_get_blocksize(template->format); - int stride = bytes_per_pixel * template->width0; /* TODO: Alignment? */ + int stride = ALIGN(template->width0, 16) * bytes_per_pixel; size_t sz = stride; if (template->height0) sz *= template->height0; @@ -252,6 +252,8 @@ panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *t /* TODO: Mipmap */ } + bo->stride = stride; + return bo; } @@ -287,8 +289,6 @@ panfrost_resource_create(struct pipe_screen *screen, struct renderonly_scanout *scanout; struct winsys_handle handle; - /* TODO: align width0 and height0? */ - scanout = renderonly_scanout_for_resource(&scanout_templat, pscreen->ro, &handle); if (!scanout) @@ -403,14 +403,14 @@ panfrost_transfer_map(struct pipe_context *pctx, { struct panfrost_context *ctx = pan_context(pctx); int bytes_per_pixel = util_format_get_blocksize(resource->format); - int stride = bytes_per_pixel * resource->width0; /* TODO: Alignment? */ + struct panfrost_bo *bo = pan_resource(resource)->bo; uint8_t *cpu; struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); transfer->level = level; transfer->usage = usage; transfer->box = *box; - transfer->stride = stride; + transfer->stride = bo->stride; assert(!transfer->box.z); pipe_resource_reference(&transfer->resource, resource); @@ -431,7 +431,7 @@ panfrost_transfer_map(struct pipe_context *pctx, if (cpu == NULL) return NULL; - return cpu + transfer->box.x * bytes_per_pixel + transfer->box.y * stride; + return cpu + transfer->box.x * bytes_per_pixel + transfer->box.y * bo->stride; } static void @@ -439,7 +439,6 @@ panfrost_tile_texture(struct panfrost_screen *screen, struct panfrost_resource * { struct panfrost_bo *bo = (struct panfrost_bo *)rsrc->bo; int bytes_per_pixel = util_format_get_blocksize(rsrc->base.format); - int stride = bytes_per_pixel * rsrc->base.width0; /* TODO: Alignment? */ int width = rsrc->base.width0 >> level; int height = rsrc->base.height0 >> level; @@ -469,7 +468,7 @@ panfrost_tile_texture(struct panfrost_screen *screen, struct panfrost_resource * /* Run actual texture swizzle, writing directly to the mapped * GPU chunk we allocated */ - panfrost_texture_swizzle(width, height, bytes_per_pixel, stride, bo->cpu[level], swizzled); + panfrost_texture_swizzle(width, height, bytes_per_pixel, bo->stride, bo->cpu[level], swizzled); } static void diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 2e3d72babe6..4b5b9c49c07 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -81,6 +81,7 @@ struct panfrost_bo { int checksum_stride; int gem_handle; + unsigned int stride; }; struct panfrost_resource { diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h index 882611e93e3..cbadf813675 100644 --- a/src/gallium/drivers/panfrost/pan_screen.h +++ b/src/gallium/drivers/panfrost/pan_screen.h @@ -49,7 +49,7 @@ struct panfrost_screen; struct panfrost_driver { struct panfrost_bo * (*import_bo) (struct panfrost_screen *screen, struct winsys_handle *whandle); - int (*export_bo) (struct panfrost_screen *screen, int gem_handle, struct winsys_handle *whandle); + int (*export_bo) (struct panfrost_screen *screen, int gem_handle, unsigned int stride, struct winsys_handle *whandle); int (*submit_vs_fs_job) (struct panfrost_context *ctx, bool has_draws, bool is_scanout); void (*force_flush_fragment) (struct panfrost_context *ctx, diff --git a/src/gallium/drivers/panfrost/pan_sfbd.c b/src/gallium/drivers/panfrost/pan_sfbd.c index 1c08f97fd1d..787fef2c16e 100644 --- a/src/gallium/drivers/panfrost/pan_sfbd.c +++ b/src/gallium/drivers/panfrost/pan_sfbd.c @@ -92,8 +92,7 @@ panfrost_sfbd_set_cbuf( { struct panfrost_resource *rsrc = pan_resource(surf->texture); - signed stride = - util_format_get_stride(surf->format, surf->texture->width0); + signed stride = rsrc->bo->stride; fb->format = panfrost_sfbd_format(surf); -- 2.30.2