diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index d9d9fc3dde8..2d80cff0d3d 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -1620,6 +1620,9 @@ create_image_surface(struct zink_context *ctx, const struct pipe_image_view *vie break; default: break; } + if (!res->obj->dt && view->resource->format != view->format) + /* mutable not set by default */ + zink_resource_object_init_mutable(ctx, res); VkImageViewCreateInfo ivci = create_ivci(screen, res, &tmpl, target); struct pipe_surface *psurf = zink_get_surface(ctx, view->resource, &tmpl, &ivci); if (!psurf) @@ -1795,6 +1798,9 @@ zink_set_sampler_views(struct pipe_context *pctx, update = true; zink_batch_resource_usage_set(&ctx->batch, res, false, true); } else if (!res->obj->is_buffer) { + if (res->base.b.format != b->image_view->base.format) + /* mutable not set by default */ + zink_resource_object_init_mutable(ctx, res); if (res->obj != b->image_view->obj) { struct pipe_surface *psurf = &b->image_view->base; VkImageView iv = b->image_view->image_view; diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 715af98a70b..69aa9d6d897 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -423,8 +423,10 @@ create_ici(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe /* pNext may already be set */ if (util_format_get_num_planes(templ->format) > 1) ici->flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + else if (bind & ZINK_BIND_MUTABLE) + ici->flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; else - ici->flags = modifiers_count || dmabuf || bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DEPTH_STENCIL) ? 0 : VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + ici->flags = 0; if (ici->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) /* unset VkImageFormatListCreateInfo if mutable */ ici->pNext = NULL; @@ -2164,11 +2166,11 @@ zink_resource_get_separate_stencil(struct pipe_resource *pres) } -bool -zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource *res) +static bool +resource_object_add_bind(struct zink_context *ctx, struct zink_resource *res, unsigned bind) { /* base resource already has the cap */ - if (res->base.b.bind & PIPE_BIND_SHADER_IMAGE) + if (res->base.b.bind & bind) return true; if (res->obj->is_buffer) { unreachable("zink: all buffers should have this bit"); @@ -2176,13 +2178,25 @@ zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource } assert(!res->obj->dt); zink_fb_clears_apply_region(ctx, &res->base.b, (struct u_rect){0, res->base.b.width0, 0, res->base.b.height0}); - bool ret = add_resource_bind(ctx, res, PIPE_BIND_SHADER_IMAGE); + bool ret = add_resource_bind(ctx, res, bind); if (ret) zink_resource_rebind(ctx, res); return ret; } +bool +zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource *res) +{ + return resource_object_add_bind(ctx, res, PIPE_BIND_SHADER_IMAGE); +} + +bool +zink_resource_object_init_mutable(struct zink_context *ctx, struct zink_resource *res) +{ + return resource_object_add_bind(ctx, res, ZINK_BIND_MUTABLE); +} + void zink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resource *src, struct zink_resource *dst) { diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 25ee4541b47..25afa816c68 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -27,6 +27,7 @@ #include "zink_types.h" #define ZINK_MAP_TEMPORARY (PIPE_MAP_DRV_PRV << 0) +#define ZINK_BIND_MUTABLE (1u << 28) #define ZINK_BIND_DMABUF (1u << 29) #define ZINK_BIND_TRANSIENT (1u << 30) //transient fb attachment #define ZINK_BIND_VIDEO (1u << 31) @@ -71,6 +72,8 @@ zink_resource_object_reference(struct zink_screen *screen, bool zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource *res); +bool +zink_resource_object_init_mutable(struct zink_context *ctx, struct zink_resource *res); static inline bool zink_resource_has_binds(const struct zink_resource *res) diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c index a30de9b3f10..837853f9ad2 100644 --- a/src/gallium/drivers/zink/zink_surface.c +++ b/src/gallium/drivers/zink/zink_surface.c @@ -220,8 +220,9 @@ zink_get_surface(struct zink_context *ctx, struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&res->surface_cache, hash, ivci); if (!entry) { - /* create a new surface */ - surface = do_create_surface(&ctx->base, pres, templ, ivci, hash, true); + /* create a new surface, but don't actually create the imageview if mutable isn't set */ + bool actually = pres->format == templ->format || (res->obj->vkflags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT); + surface = do_create_surface(&ctx->base, pres, templ, ivci, hash, actually); entry = _mesa_hash_table_insert_pre_hashed(&res->surface_cache, hash, &surface->ivci, surface); if (!entry) { simple_mtx_unlock(&res->surface_mtx); @@ -258,6 +259,10 @@ zink_create_surface(struct pipe_context *pctx, struct zink_resource *res = zink_resource(pres); bool is_array = templ->u.tex.last_layer != templ->u.tex.first_layer; enum pipe_texture_target target_2d[] = {PIPE_TEXTURE_2D, PIPE_TEXTURE_2D_ARRAY}; + if (!res->obj->dt && pres->format != templ->format) + /* mutable not set by default */ + zink_resource_object_init_mutable(zink_context(pctx), res); + VkImageViewCreateInfo ivci = create_ivci(zink_screen(pctx->screen), res, templ, pres->target == PIPE_TEXTURE_3D ? target_2d[is_array] : pres->target);