17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2018 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "zink_context.h"
257ec681f3Smrg#include "zink_framebuffer.h"
267ec681f3Smrg#include "zink_resource.h"
277ec681f3Smrg#include "zink_screen.h"
287ec681f3Smrg#include "zink_surface.h"
297ec681f3Smrg
307ec681f3Smrg#include "util/format/u_format.h"
317ec681f3Smrg#include "util/u_inlines.h"
327ec681f3Smrg#include "util/u_memory.h"
337ec681f3Smrg
347ec681f3SmrgVkImageViewCreateInfo
357ec681f3Smrgcreate_ivci(struct zink_screen *screen,
367ec681f3Smrg            struct zink_resource *res,
377ec681f3Smrg            const struct pipe_surface *templ,
387ec681f3Smrg            enum pipe_texture_target target)
397ec681f3Smrg{
407ec681f3Smrg   VkImageViewCreateInfo ivci;
417ec681f3Smrg   /* zero holes since this is hashed */
427ec681f3Smrg   memset(&ivci, 0, sizeof(VkImageViewCreateInfo));
437ec681f3Smrg   ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
447ec681f3Smrg   ivci.image = res->obj->image;
457ec681f3Smrg
467ec681f3Smrg   switch (target) {
477ec681f3Smrg   case PIPE_TEXTURE_1D:
487ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_1D;
497ec681f3Smrg      break;
507ec681f3Smrg
517ec681f3Smrg   case PIPE_TEXTURE_1D_ARRAY:
527ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
537ec681f3Smrg      break;
547ec681f3Smrg
557ec681f3Smrg   case PIPE_TEXTURE_2D:
567ec681f3Smrg   case PIPE_TEXTURE_RECT:
577ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
587ec681f3Smrg      break;
597ec681f3Smrg
607ec681f3Smrg   case PIPE_TEXTURE_2D_ARRAY:
617ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
627ec681f3Smrg      break;
637ec681f3Smrg
647ec681f3Smrg   case PIPE_TEXTURE_CUBE:
657ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
667ec681f3Smrg      break;
677ec681f3Smrg
687ec681f3Smrg   case PIPE_TEXTURE_CUBE_ARRAY:
697ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
707ec681f3Smrg      break;
717ec681f3Smrg
727ec681f3Smrg   case PIPE_TEXTURE_3D:
737ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_3D;
747ec681f3Smrg      break;
757ec681f3Smrg
767ec681f3Smrg   default:
777ec681f3Smrg      unreachable("unsupported target");
787ec681f3Smrg   }
797ec681f3Smrg
807ec681f3Smrg   ivci.format = zink_get_format(screen, templ->format);
817ec681f3Smrg   assert(ivci.format != VK_FORMAT_UNDEFINED);
827ec681f3Smrg
837ec681f3Smrg   /* TODO: it's currently illegal to use non-identity swizzles for framebuffer attachments,
847ec681f3Smrg    * but if that ever changes, this will be useful
857ec681f3Smrg   const struct util_format_description *desc = util_format_description(templ->format);
867ec681f3Smrg   ivci.components.r = zink_component_mapping(zink_clamp_void_swizzle(desc, PIPE_SWIZZLE_X));
877ec681f3Smrg   ivci.components.g = zink_component_mapping(zink_clamp_void_swizzle(desc, PIPE_SWIZZLE_Y));
887ec681f3Smrg   ivci.components.b = zink_component_mapping(zink_clamp_void_swizzle(desc, PIPE_SWIZZLE_Z));
897ec681f3Smrg   ivci.components.a = zink_component_mapping(zink_clamp_void_swizzle(desc, PIPE_SWIZZLE_W));
907ec681f3Smrg   */
917ec681f3Smrg   ivci.components.r = VK_COMPONENT_SWIZZLE_R;
927ec681f3Smrg   ivci.components.g = VK_COMPONENT_SWIZZLE_G;
937ec681f3Smrg   ivci.components.b = VK_COMPONENT_SWIZZLE_B;
947ec681f3Smrg   ivci.components.a = VK_COMPONENT_SWIZZLE_A;
957ec681f3Smrg
967ec681f3Smrg   ivci.subresourceRange.aspectMask = res->aspect;
977ec681f3Smrg   ivci.subresourceRange.baseMipLevel = templ->u.tex.level;
987ec681f3Smrg   ivci.subresourceRange.levelCount = 1;
997ec681f3Smrg   ivci.subresourceRange.baseArrayLayer = templ->u.tex.first_layer;
1007ec681f3Smrg   ivci.subresourceRange.layerCount = 1 + templ->u.tex.last_layer - templ->u.tex.first_layer;
1017ec681f3Smrg   ivci.viewType = zink_surface_clamp_viewtype(ivci.viewType, templ->u.tex.first_layer, templ->u.tex.last_layer, res->base.b.array_size);
1027ec681f3Smrg
1037ec681f3Smrg   return ivci;
1047ec681f3Smrg}
1057ec681f3Smrg
1067ec681f3Smrgstatic void
1077ec681f3Smrginit_surface_info(struct zink_surface *surface, struct zink_resource *res, VkImageViewCreateInfo *ivci)
1087ec681f3Smrg{
1097ec681f3Smrg   surface->info.flags = res->obj->vkflags;
1107ec681f3Smrg   surface->info.usage = res->obj->vkusage;
1117ec681f3Smrg   surface->info.width = surface->base.width;
1127ec681f3Smrg   surface->info.height = surface->base.height;
1137ec681f3Smrg   surface->info.layerCount = ivci->subresourceRange.layerCount;
1147ec681f3Smrg   surface->info.format = ivci->format;
1157ec681f3Smrg   surface->info_hash = _mesa_hash_data(&surface->info, sizeof(surface->info));
1167ec681f3Smrg}
1177ec681f3Smrg
1187ec681f3Smrgstatic struct zink_surface *
1197ec681f3Smrgcreate_surface(struct pipe_context *pctx,
1207ec681f3Smrg               struct pipe_resource *pres,
1217ec681f3Smrg               const struct pipe_surface *templ,
1227ec681f3Smrg               VkImageViewCreateInfo *ivci)
1237ec681f3Smrg{
1247ec681f3Smrg   struct zink_screen *screen = zink_screen(pctx->screen);
1257ec681f3Smrg   struct zink_resource *res = zink_resource(pres);
1267ec681f3Smrg   unsigned int level = templ->u.tex.level;
1277ec681f3Smrg
1287ec681f3Smrg   struct zink_surface *surface = CALLOC_STRUCT(zink_surface);
1297ec681f3Smrg   if (!surface)
1307ec681f3Smrg      return NULL;
1317ec681f3Smrg
1327ec681f3Smrg   pipe_resource_reference(&surface->base.texture, pres);
1337ec681f3Smrg   pipe_reference_init(&surface->base.reference, 1);
1347ec681f3Smrg   surface->base.context = pctx;
1357ec681f3Smrg   surface->base.format = templ->format;
1367ec681f3Smrg   surface->base.width = u_minify(pres->width0, level);
1377ec681f3Smrg   assert(surface->base.width);
1387ec681f3Smrg   surface->base.height = u_minify(pres->height0, level);
1397ec681f3Smrg   assert(surface->base.height);
1407ec681f3Smrg   surface->base.nr_samples = templ->nr_samples;
1417ec681f3Smrg   surface->base.u.tex.level = level;
1427ec681f3Smrg   surface->base.u.tex.first_layer = templ->u.tex.first_layer;
1437ec681f3Smrg   surface->base.u.tex.last_layer = templ->u.tex.last_layer;
1447ec681f3Smrg   surface->obj = zink_resource(pres)->obj;
1457ec681f3Smrg   util_dynarray_init(&surface->framebuffer_refs, NULL);
1467ec681f3Smrg   util_dynarray_init(&surface->desc_set_refs.refs, NULL);
1477ec681f3Smrg
1487ec681f3Smrg   init_surface_info(surface, res, ivci);
1497ec681f3Smrg
1507ec681f3Smrg   if (VKSCR(CreateImageView)(screen->dev, ivci, NULL,
1517ec681f3Smrg                         &surface->image_view) != VK_SUCCESS) {
1527ec681f3Smrg      FREE(surface);
1537ec681f3Smrg      return NULL;
1547ec681f3Smrg   }
1557ec681f3Smrg
1567ec681f3Smrg   return surface;
1577ec681f3Smrg}
1587ec681f3Smrg
1597ec681f3Smrgstatic uint32_t
1607ec681f3Smrghash_ivci(const void *key)
1617ec681f3Smrg{
1627ec681f3Smrg   return _mesa_hash_data((char*)key + offsetof(VkImageViewCreateInfo, flags), sizeof(VkImageViewCreateInfo) - offsetof(VkImageViewCreateInfo, flags));
1637ec681f3Smrg}
1647ec681f3Smrg
1657ec681f3Smrgstruct pipe_surface *
1667ec681f3Smrgzink_get_surface(struct zink_context *ctx,
1677ec681f3Smrg            struct pipe_resource *pres,
1687ec681f3Smrg            const struct pipe_surface *templ,
1697ec681f3Smrg            VkImageViewCreateInfo *ivci)
1707ec681f3Smrg{
1717ec681f3Smrg   struct zink_surface *surface = NULL;
1727ec681f3Smrg   struct zink_resource *res = zink_resource(pres);
1737ec681f3Smrg   uint32_t hash = hash_ivci(ivci);
1747ec681f3Smrg
1757ec681f3Smrg   simple_mtx_lock(&res->surface_mtx);
1767ec681f3Smrg   struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&res->surface_cache, hash, ivci);
1777ec681f3Smrg
1787ec681f3Smrg   if (!entry) {
1797ec681f3Smrg      /* create a new surface */
1807ec681f3Smrg      surface = create_surface(&ctx->base, pres, templ, ivci);
1817ec681f3Smrg      surface->base.nr_samples = 0;
1827ec681f3Smrg      surface->hash = hash;
1837ec681f3Smrg      surface->ivci = *ivci;
1847ec681f3Smrg      entry = _mesa_hash_table_insert_pre_hashed(&res->surface_cache, hash, &surface->ivci, surface);
1857ec681f3Smrg      if (!entry) {
1867ec681f3Smrg         simple_mtx_unlock(&res->surface_mtx);
1877ec681f3Smrg         return NULL;
1887ec681f3Smrg      }
1897ec681f3Smrg
1907ec681f3Smrg      surface = entry->data;
1917ec681f3Smrg   } else {
1927ec681f3Smrg      surface = entry->data;
1937ec681f3Smrg      p_atomic_inc(&surface->base.reference.count);
1947ec681f3Smrg   }
1957ec681f3Smrg   simple_mtx_unlock(&res->surface_mtx);
1967ec681f3Smrg
1977ec681f3Smrg   return &surface->base;
1987ec681f3Smrg}
1997ec681f3Smrg
2007ec681f3Smrgstatic struct pipe_surface *
2017ec681f3Smrgwrap_surface(struct pipe_context *pctx, struct pipe_surface *psurf)
2027ec681f3Smrg{
2037ec681f3Smrg   struct zink_ctx_surface *csurf = CALLOC_STRUCT(zink_ctx_surface);
2047ec681f3Smrg   csurf->base = *psurf;
2057ec681f3Smrg   pipe_reference_init(&csurf->base.reference, 1);
2067ec681f3Smrg   csurf->surf = (struct zink_surface*)psurf;
2077ec681f3Smrg   csurf->base.context = pctx;
2087ec681f3Smrg
2097ec681f3Smrg   return &csurf->base;
2107ec681f3Smrg}
2117ec681f3Smrg
2127ec681f3Smrgstatic struct pipe_surface *
2137ec681f3Smrgzink_create_surface(struct pipe_context *pctx,
2147ec681f3Smrg                    struct pipe_resource *pres,
2157ec681f3Smrg                    const struct pipe_surface *templ)
2167ec681f3Smrg{
2177ec681f3Smrg
2187ec681f3Smrg   VkImageViewCreateInfo ivci = create_ivci(zink_screen(pctx->screen),
2197ec681f3Smrg                                            zink_resource(pres), templ, pres->target);
2207ec681f3Smrg   if (pres->target == PIPE_TEXTURE_3D)
2217ec681f3Smrg      ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
2227ec681f3Smrg
2237ec681f3Smrg   struct pipe_surface *psurf = zink_get_surface(zink_context(pctx), pres, templ, &ivci);
2247ec681f3Smrg   if (!psurf)
2257ec681f3Smrg      return NULL;
2267ec681f3Smrg
2277ec681f3Smrg   struct zink_ctx_surface *csurf = (struct zink_ctx_surface*)wrap_surface(pctx, psurf);
2287ec681f3Smrg
2297ec681f3Smrg   if (templ->nr_samples) {
2307ec681f3Smrg      /* transient fb attachment: not cached */
2317ec681f3Smrg      struct pipe_resource rtempl = *pres;
2327ec681f3Smrg      rtempl.nr_samples = templ->nr_samples;
2337ec681f3Smrg      rtempl.bind |= ZINK_BIND_TRANSIENT;
2347ec681f3Smrg      struct zink_resource *transient = zink_resource(pctx->screen->resource_create(pctx->screen, &rtempl));
2357ec681f3Smrg      if (!transient)
2367ec681f3Smrg         return NULL;
2377ec681f3Smrg      ivci.image = transient->obj->image;
2387ec681f3Smrg      csurf->transient = (struct zink_ctx_surface*)wrap_surface(pctx, (struct pipe_surface*)create_surface(pctx, &transient->base.b, templ, &ivci));
2397ec681f3Smrg      if (!csurf->transient) {
2407ec681f3Smrg         pipe_resource_reference((struct pipe_resource**)&transient, NULL);
2417ec681f3Smrg         pipe_surface_release(pctx, &psurf);
2427ec681f3Smrg         return NULL;
2437ec681f3Smrg      }
2447ec681f3Smrg      pipe_resource_reference((struct pipe_resource**)&transient, NULL);
2457ec681f3Smrg   }
2467ec681f3Smrg
2477ec681f3Smrg   return &csurf->base;
2487ec681f3Smrg}
2497ec681f3Smrg
2507ec681f3Smrg/* framebuffers are owned by their surfaces, so each time a surface that's part of a cached fb
2517ec681f3Smrg * is destroyed, it has to unref all the framebuffers it's attached to in order to avoid leaking
2527ec681f3Smrg * all the framebuffers
2537ec681f3Smrg *
2547ec681f3Smrg * surfaces are always batch-tracked, so it is impossible for a framebuffer to be destroyed
2557ec681f3Smrg * while it is in use
2567ec681f3Smrg */
2577ec681f3Smrgstatic void
2587ec681f3Smrgsurface_clear_fb_refs(struct zink_screen *screen, struct pipe_surface *psurface)
2597ec681f3Smrg{
2607ec681f3Smrg   struct zink_surface *surface = zink_surface(psurface);
2617ec681f3Smrg   util_dynarray_foreach(&surface->framebuffer_refs, struct zink_framebuffer*, fb_ref) {
2627ec681f3Smrg      struct zink_framebuffer *fb = *fb_ref;
2637ec681f3Smrg      for (unsigned i = 0; i < fb->state.num_attachments; i++) {
2647ec681f3Smrg         if (fb->surfaces[i] == psurface) {
2657ec681f3Smrg            simple_mtx_lock(&screen->framebuffer_mtx);
2667ec681f3Smrg            fb->surfaces[i] = NULL;
2677ec681f3Smrg            _mesa_hash_table_remove_key(&screen->framebuffer_cache, &fb->state);
2687ec681f3Smrg            zink_framebuffer_reference(screen, &fb, NULL);
2697ec681f3Smrg            simple_mtx_unlock(&screen->framebuffer_mtx);
2707ec681f3Smrg            break;
2717ec681f3Smrg         }
2727ec681f3Smrg      }
2737ec681f3Smrg   }
2747ec681f3Smrg   util_dynarray_fini(&surface->framebuffer_refs);
2757ec681f3Smrg}
2767ec681f3Smrg
2777ec681f3Smrgvoid
2787ec681f3Smrgzink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface)
2797ec681f3Smrg{
2807ec681f3Smrg   struct zink_surface *surface = zink_surface(psurface);
2817ec681f3Smrg   struct zink_resource *res = zink_resource(psurface->texture);
2827ec681f3Smrg   if (!psurface->nr_samples) {
2837ec681f3Smrg      simple_mtx_lock(&res->surface_mtx);
2847ec681f3Smrg      if (psurface->reference.count) {
2857ec681f3Smrg         /* got a cache hit during deletion */
2867ec681f3Smrg         simple_mtx_unlock(&res->surface_mtx);
2877ec681f3Smrg         return;
2887ec681f3Smrg      }
2897ec681f3Smrg      struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&res->surface_cache, surface->hash, &surface->ivci);
2907ec681f3Smrg      assert(he);
2917ec681f3Smrg      assert(he->data == surface);
2927ec681f3Smrg      _mesa_hash_table_remove(&res->surface_cache, he);
2937ec681f3Smrg      simple_mtx_unlock(&res->surface_mtx);
2947ec681f3Smrg   }
2957ec681f3Smrg   if (!screen->info.have_KHR_imageless_framebuffer)
2967ec681f3Smrg      surface_clear_fb_refs(screen, psurface);
2977ec681f3Smrg   zink_descriptor_set_refs_clear(&surface->desc_set_refs, surface);
2987ec681f3Smrg   util_dynarray_fini(&surface->framebuffer_refs);
2997ec681f3Smrg   pipe_resource_reference(&psurface->texture, NULL);
3007ec681f3Smrg   if (surface->simage_view)
3017ec681f3Smrg      VKSCR(DestroyImageView)(screen->dev, surface->simage_view, NULL);
3027ec681f3Smrg   VKSCR(DestroyImageView)(screen->dev, surface->image_view, NULL);
3037ec681f3Smrg   FREE(surface);
3047ec681f3Smrg}
3057ec681f3Smrg
3067ec681f3Smrgstatic void
3077ec681f3Smrgzink_surface_destroy(struct pipe_context *pctx,
3087ec681f3Smrg                     struct pipe_surface *psurface)
3097ec681f3Smrg{
3107ec681f3Smrg   struct zink_ctx_surface *csurf = (struct zink_ctx_surface *)psurface;
3117ec681f3Smrg   zink_surface_reference(zink_screen(pctx->screen), &csurf->surf, NULL);
3127ec681f3Smrg   pipe_surface_release(pctx, (struct pipe_surface**)&csurf->transient);
3137ec681f3Smrg   FREE(csurf);
3147ec681f3Smrg}
3157ec681f3Smrg
3167ec681f3Smrgbool
3177ec681f3Smrgzink_rebind_surface(struct zink_context *ctx, struct pipe_surface **psurface)
3187ec681f3Smrg{
3197ec681f3Smrg   struct zink_surface *surface = zink_surface(*psurface);
3207ec681f3Smrg   struct zink_resource *res = zink_resource((*psurface)->texture);
3217ec681f3Smrg   struct zink_screen *screen = zink_screen(ctx->base.screen);
3227ec681f3Smrg   if (surface->simage_view)
3237ec681f3Smrg      return false;
3247ec681f3Smrg   VkImageViewCreateInfo ivci = create_ivci(screen,
3257ec681f3Smrg                                            zink_resource((*psurface)->texture), (*psurface), surface->base.texture->target);
3267ec681f3Smrg   uint32_t hash = hash_ivci(&ivci);
3277ec681f3Smrg
3287ec681f3Smrg   simple_mtx_lock(&res->surface_mtx);
3297ec681f3Smrg   struct hash_entry *new_entry = _mesa_hash_table_search_pre_hashed(&res->surface_cache, hash, &ivci);
3307ec681f3Smrg   if (zink_batch_usage_exists(surface->batch_uses))
3317ec681f3Smrg      zink_batch_reference_surface(&ctx->batch, surface);
3327ec681f3Smrg   surface_clear_fb_refs(screen, *psurface);
3337ec681f3Smrg   zink_descriptor_set_refs_clear(&surface->desc_set_refs, surface);
3347ec681f3Smrg   if (new_entry) {
3357ec681f3Smrg      /* reuse existing surface; old one will be cleaned up naturally */
3367ec681f3Smrg      struct zink_surface *new_surface = new_entry->data;
3377ec681f3Smrg      simple_mtx_unlock(&res->surface_mtx);
3387ec681f3Smrg      zink_batch_usage_set(&new_surface->batch_uses, ctx->batch.state);
3397ec681f3Smrg      zink_surface_reference(screen, (struct zink_surface**)psurface, new_surface);
3407ec681f3Smrg      return true;
3417ec681f3Smrg   }
3427ec681f3Smrg   struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&res->surface_cache, surface->hash, &surface->ivci);
3437ec681f3Smrg   assert(entry);
3447ec681f3Smrg   _mesa_hash_table_remove(&res->surface_cache, entry);
3457ec681f3Smrg   VkImageView image_view;
3467ec681f3Smrg   if (VKSCR(CreateImageView)(screen->dev, &ivci, NULL, &image_view) != VK_SUCCESS) {
3477ec681f3Smrg      debug_printf("zink: failed to create new imageview");
3487ec681f3Smrg      simple_mtx_unlock(&res->surface_mtx);
3497ec681f3Smrg      return false;
3507ec681f3Smrg   }
3517ec681f3Smrg   surface->hash = hash;
3527ec681f3Smrg   surface->ivci = ivci;
3537ec681f3Smrg   entry = _mesa_hash_table_insert_pre_hashed(&res->surface_cache, surface->hash, &surface->ivci, surface);
3547ec681f3Smrg   assert(entry);
3557ec681f3Smrg   surface->simage_view = surface->image_view;
3567ec681f3Smrg   surface->image_view = image_view;
3577ec681f3Smrg   surface->obj = zink_resource(surface->base.texture)->obj;
3587ec681f3Smrg   /* update for imageless fb */
3597ec681f3Smrg   surface->info.flags = res->obj->vkflags;
3607ec681f3Smrg   surface->info.usage = res->obj->vkusage;
3617ec681f3Smrg   surface->info_hash = _mesa_hash_data(&surface->info, sizeof(surface->info));
3627ec681f3Smrg   zink_batch_usage_set(&surface->batch_uses, ctx->batch.state);
3637ec681f3Smrg   simple_mtx_unlock(&res->surface_mtx);
3647ec681f3Smrg   return true;
3657ec681f3Smrg}
3667ec681f3Smrg
3677ec681f3Smrgstruct pipe_surface *
3687ec681f3Smrgzink_surface_create_null(struct zink_context *ctx, enum pipe_texture_target target, unsigned width, unsigned height, unsigned samples)
3697ec681f3Smrg{
3707ec681f3Smrg   struct pipe_surface surf_templ = {0};
3717ec681f3Smrg
3727ec681f3Smrg   struct pipe_resource *pres;
3737ec681f3Smrg   struct pipe_resource templ = {0};
3747ec681f3Smrg   templ.width0 = width;
3757ec681f3Smrg   templ.height0 = height;
3767ec681f3Smrg   templ.depth0 = 1;
3777ec681f3Smrg   templ.format = PIPE_FORMAT_R8_UINT;
3787ec681f3Smrg   templ.target = target;
3797ec681f3Smrg   templ.bind = PIPE_BIND_RENDER_TARGET;
3807ec681f3Smrg   templ.nr_samples = samples;
3817ec681f3Smrg
3827ec681f3Smrg   pres = ctx->base.screen->resource_create(ctx->base.screen, &templ);
3837ec681f3Smrg   if (!pres)
3847ec681f3Smrg      return NULL;
3857ec681f3Smrg
3867ec681f3Smrg   surf_templ.format = PIPE_FORMAT_R8_UINT;
3877ec681f3Smrg   surf_templ.nr_samples = 0;
3887ec681f3Smrg   struct pipe_surface *psurf = ctx->base.create_surface(&ctx->base, pres, &surf_templ);
3897ec681f3Smrg   pipe_resource_reference(&pres, NULL);
3907ec681f3Smrg   return psurf;
3917ec681f3Smrg}
3927ec681f3Smrg
3937ec681f3Smrgvoid
3947ec681f3Smrgzink_context_surface_init(struct pipe_context *context)
3957ec681f3Smrg{
3967ec681f3Smrg   context->create_surface = zink_create_surface;
3977ec681f3Smrg   context->surface_destroy = zink_surface_destroy;
3987ec681f3Smrg}
399