zink: use smaller keys for surface/bufferview caching and switch to sets

this should be a bit more efficient

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35722>
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index a24184c..cac9fac 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -947,10 +947,9 @@
 }
 
 static uint32_t
-hash_bufferview(void *bvci)
+hash_bufferview_key(void *key)
 {
-   size_t offset = offsetof(VkBufferViewCreateInfo, flags);
-   return _mesa_hash_data((char*)bvci + offset, sizeof(VkBufferViewCreateInfo) - offset);
+   return _mesa_hash_data(key, sizeof(struct zink_bufferview_key));
 }
 
 static VkBufferViewCreateInfo
@@ -990,30 +989,37 @@
 {
    struct zink_screen *screen = zink_screen(ctx->base.screen);
    struct zink_buffer_view *buffer_view = NULL;
+   struct zink_bufferview_key key = {
+      format,
+      offset,
+      size
+   };
    VkBufferViewCreateInfo bvci = create_bvci(ctx, res, format, offset, size);
 
-   uint32_t hash = hash_bufferview(&bvci);
+   uint32_t hash = hash_bufferview_key(&key);
    simple_mtx_lock(&res->obj->surface_mtx);
-   struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&res->obj->surface_cache, hash, &bvci);
-   if (he) {
-      buffer_view = he->data;
+   bool found = false;
+   struct set_entry *he = _mesa_set_search_or_add_pre_hashed(&res->obj->surface_cache, hash, &key, &found);
+   if (found) {
+      buffer_view = (void*)he->key;
    } else {
       VkBufferView view;
       VkResult result = VKSCR(CreateBufferView)(screen->dev, &bvci, NULL, &view);
       if (result != VK_SUCCESS) {
+         _mesa_set_remove(&res->obj->surface_cache, he);
          mesa_loge("ZINK: vkCreateBufferView failed (%s)", vk_Result_to_str(result));
          goto out;
       }
       buffer_view = CALLOC_STRUCT(zink_buffer_view);
       if (!buffer_view) {
+         _mesa_set_remove(&res->obj->surface_cache, he);
          VKSCR(DestroyBufferView)(screen->dev, view, NULL);
          goto out;
       }
       buffer_view->pres = &res->base.b;
-      buffer_view->bvci = bvci;
+      buffer_view->key = key;
       buffer_view->buffer_view = view;
-      buffer_view->hash = hash;
-      _mesa_hash_table_insert_pre_hashed(&res->obj->surface_cache, hash, &buffer_view->bvci, buffer_view);
+      he->key = buffer_view;
    }
 out:
    simple_mtx_unlock(&res->obj->surface_mtx);
diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c
index 5bd44ae..3523382 100644
--- a/src/gallium/drivers/zink/zink_kopper.c
+++ b/src/gallium/drivers/zink/zink_kopper.c
@@ -370,7 +370,7 @@
    if (zink_screen_handle_vkresult(screen, error)) {
       for (unsigned i = 0; i < cswap->num_images; i++) {
          cswap->images[i].image = images[i];
-         _mesa_hash_table_init(&cswap->images[i].surface_cache, NULL, NULL, equals_ivci);
+         _mesa_set_init(&cswap->images[i].surface_cache, NULL, NULL, equals_surface_key);
       }
    }
    cswap->max_acquires = cswap->num_images - cswap->scci.minImageCount + 1;
diff --git a/src/gallium/drivers/zink/zink_kopper.h b/src/gallium/drivers/zink/zink_kopper.h
index 9e52f51..fba05a0 100644
--- a/src/gallium/drivers/zink/zink_kopper.h
+++ b/src/gallium/drivers/zink/zink_kopper.h
@@ -29,7 +29,7 @@
 
 #include "kopper_interface.h"
 #include "util/u_queue.h"
-#include "util/hash_table.h"
+#include "util/set.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -51,7 +51,7 @@
    VkSemaphore acquire;
    VkImageLayout layout;
 
-   struct hash_table surface_cache;
+   struct set surface_cache;
 };
 
 struct kopper_swapchain {
diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c
index 47436c6..70d5463 100644
--- a/src/gallium/drivers/zink/zink_resource.c
+++ b/src/gallium/drivers/zink/zink_resource.c
@@ -180,12 +180,9 @@
 }
 
 static bool
-equals_bvci(const void *a, const void *b)
+equals_bufferview_key(const void *a, const void *b)
 {
-   const uint8_t *pa = a;
-   const uint8_t *pb = b;
-   size_t offset = offsetof(VkBufferViewCreateInfo, flags);
-   return memcmp(pa + offset, pb + offset, sizeof(VkBufferViewCreateInfo) - offset) == 0;
+   return memcmp(a, b, sizeof(struct zink_bufferview_key)) == 0;
 }
 
 static void
@@ -200,20 +197,19 @@
 }
 
 void
-zink_destroy_resource_surface_cache(struct zink_screen *screen, struct hash_table *ht, bool is_buffer)
+zink_destroy_resource_surface_cache(struct zink_screen *screen, struct set *ht, bool is_buffer)
 {
    if (is_buffer) {
-      hash_table_foreach_remove(ht, he) {
-         struct zink_buffer_view *bv = he->data;
+      set_foreach_remove(ht, he) {
+         struct zink_buffer_view *bv = (void*)he->key;
          VKSCR(DestroyBufferView)(screen->dev, bv->buffer_view, NULL);
          FREE(bv);
       }
       ralloc_free(ht->table);
    } else {
-      hash_table_foreach_remove(ht, he) {
-         struct zink_surface *surf = he->data;
+      set_foreach_remove(ht, he) {
+         struct zink_surface *surf = (void*)he->key;
          VKSCR(DestroyImageView)(screen->dev, surf->image_view, NULL);
-         free((void*)he->key);
          FREE(surf);
       }
       ralloc_free(ht->table);
@@ -1250,7 +1246,7 @@
          return roc_fail_and_cleanup_all;
       }
    }
-   _mesa_hash_table_init(&obj->surface_cache, NULL, NULL, equals_bvci);
+   _mesa_set_init(&obj->surface_cache, NULL, NULL, equals_bufferview_key);
    return roc_success;
 }
 
@@ -1482,7 +1478,7 @@
             return roc_fail_and_cleanup_all;
          }
    }
-   _mesa_hash_table_init(&obj->surface_cache, NULL, NULL, equals_ivci);
+   _mesa_set_init(&obj->surface_cache, NULL, NULL, equals_surface_key);
    return roc_success;
 }
 
diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h
index 3001ff2..157e7a1 100644
--- a/src/gallium/drivers/zink/zink_resource.h
+++ b/src/gallium/drivers/zink/zink_resource.h
@@ -203,7 +203,7 @@
 }
 
 void
-zink_destroy_resource_surface_cache(struct zink_screen *screen, struct hash_table *ht, bool is_buffer);
+zink_destroy_resource_surface_cache(struct zink_screen *screen, struct set *ht, bool is_buffer);
 
 #ifdef __cplusplus
 }
diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c
index bf4334f..c45d278 100644
--- a/src/gallium/drivers/zink/zink_surface.c
+++ b/src/gallium/drivers/zink/zink_surface.c
@@ -32,6 +32,38 @@
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 
+static VkImageViewType
+vkviewtype_from_pipe(enum pipe_texture_target target, bool need_2D)
+{
+   switch (target) {
+   case PIPE_TEXTURE_1D:
+      return need_2D ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D;
+
+   case PIPE_TEXTURE_1D_ARRAY:
+      return need_2D ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+
+   case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
+      return VK_IMAGE_VIEW_TYPE_2D;
+
+   case PIPE_TEXTURE_2D_ARRAY:
+      return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+
+   case PIPE_TEXTURE_CUBE:
+      return VK_IMAGE_VIEW_TYPE_CUBE;
+
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+      break;
+
+   case PIPE_TEXTURE_3D:
+      return VK_IMAGE_VIEW_TYPE_3D;
+
+   default:
+      unreachable("unsupported target");
+   }
+}
+
 VkImageViewCreateInfo
 create_ivci(struct zink_screen *screen,
             struct zink_resource *res,
@@ -43,41 +75,7 @@
    memset(&ivci, 0, sizeof(VkImageViewCreateInfo));
    ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    ivci.image = res->obj->image;
-
-   switch (target) {
-   case PIPE_TEXTURE_1D:
-      ivci.viewType = res->need_2D ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D;
-      break;
-
-   case PIPE_TEXTURE_1D_ARRAY:
-      ivci.viewType = res->need_2D ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_1D_ARRAY;
-      break;
-
-   case PIPE_TEXTURE_2D:
-   case PIPE_TEXTURE_RECT:
-      ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
-      break;
-
-   case PIPE_TEXTURE_2D_ARRAY:
-      ivci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
-      break;
-
-   case PIPE_TEXTURE_CUBE:
-      ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
-      break;
-
-   case PIPE_TEXTURE_CUBE_ARRAY:
-      ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
-      break;
-
-   case PIPE_TEXTURE_3D:
-      ivci.viewType = VK_IMAGE_VIEW_TYPE_3D;
-      break;
-
-   default:
-      unreachable("unsupported target");
-   }
-
+   ivci.viewType = vkviewtype_from_pipe(target, res->need_2D);
    ivci.format = res->base.b.format == PIPE_FORMAT_A8_UNORM ? res->format : zink_get_format(screen, templ->format);
    assert(ivci.format != VK_FORMAT_UNDEFINED);
 
@@ -136,7 +134,7 @@
 static struct zink_surface *
 create_surface(struct pipe_context *pctx,
                struct pipe_resource *pres,
-               const struct pipe_surface *templ,
+               const struct zink_surface_key *templ,
                VkImageViewCreateInfo *ivci)
 {
    struct zink_screen *screen = zink_screen(pctx->screen);
@@ -155,17 +153,18 @@
       FREE(surface);
       return NULL;
    }
+   surface->key = *templ;
 
    return surface;
 }
 
 static uint32_t
-hash_ivci(const void *key)
+hash_key(const void *key)
 {
-   return _mesa_hash_data((char*)key + offsetof(VkImageViewCreateInfo, flags), sizeof(VkImageViewCreateInfo) - offsetof(VkImageViewCreateInfo, flags));
+   return _mesa_hash_data(key, sizeof(struct zink_surface_key));
 }
 
-static struct hash_table *
+static struct set *
 get_surface_cache(struct zink_resource *res)
 {
    struct kopper_displaytarget *cdt = res->obj->dt;
@@ -173,6 +172,59 @@
    return res->obj->dt ? &cdt->swapchain->images[res->obj->dt_idx].surface_cache : &res->obj->surface_cache;
 }
 
+static unsigned
+componentmapping_to_pipe(VkComponentSwizzle c)
+{
+   switch (c) {
+   case VK_COMPONENT_SWIZZLE_ZERO:
+      return PIPE_SWIZZLE_0;
+   case VK_COMPONENT_SWIZZLE_ONE:
+      return PIPE_SWIZZLE_1;
+   case VK_COMPONENT_SWIZZLE_R:
+      return PIPE_SWIZZLE_X;
+   case VK_COMPONENT_SWIZZLE_G:
+      return PIPE_SWIZZLE_Y;
+   case VK_COMPONENT_SWIZZLE_B:
+      return PIPE_SWIZZLE_Z;
+   case VK_COMPONENT_SWIZZLE_A:
+      return PIPE_SWIZZLE_W;
+   default:
+      unreachable("unknown swizzle");
+   }
+}
+
+static struct zink_surface_key
+templ_to_key(const struct pipe_surface *templ, const VkImageViewCreateInfo *ivci)
+{
+   VkImageViewType baseviewtype = vkviewtype_from_pipe(templ->texture->target, zink_resource(templ->texture)->need_2D);
+   enum zink_surface_type type = ZINK_SURFACE_NORMAL;
+   if (baseviewtype != ivci->viewType) {
+      switch (ivci->viewType) {
+      case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+      case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+         type = ZINK_SURFACE_ARRAYED;
+         break;
+      default:
+         type = ZINK_SURFACE_LAYERED;
+         break;
+      }
+   }
+   struct zink_surface_key key = {
+      .format = templ->format,
+      .viewtype = type,
+      .stencil = ivci->subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT,
+      .swizzle_r = componentmapping_to_pipe(ivci->components.r),
+      .swizzle_g = componentmapping_to_pipe(ivci->components.g),
+      .swizzle_b = componentmapping_to_pipe(ivci->components.b),
+      .swizzle_a = componentmapping_to_pipe(ivci->components.a),
+      .first_level = ivci->subresourceRange.baseMipLevel,
+      .level_count = ivci->subresourceRange.levelCount,
+      .first_layer = templ->first_layer,
+      .last_layer = templ->last_layer,
+   };
+   return key;
+}
+
 /* get a cached surface for a shader descriptor */
 struct zink_surface *
 zink_get_surface(struct zink_context *ctx,
@@ -190,23 +242,24 @@
       zink_resource_object_init_mutable(ctx, res);
    /* reset for mutable obj switch */
    ivci->image = res->obj->image;
-   uint32_t hash = hash_ivci(ivci);
+   struct zink_surface_key key = templ_to_key(templ, ivci);
+   uint32_t hash = hash_key(&key);
 
    simple_mtx_lock(&res->obj->surface_mtx);
-   struct hash_table *ht = get_surface_cache(res);
-   struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ht, hash, ivci);
+   struct set *ht = get_surface_cache(res);
+   bool found = false;
+   struct set_entry *entry = _mesa_set_search_or_add_pre_hashed(ht, hash, &key, &found);
 
-   if (!entry) {
-      surface = create_surface(&ctx->base, &res->base.b, templ, ivci);
-      entry = _mesa_hash_table_insert_pre_hashed(ht, hash, mem_dup(ivci, sizeof(*ivci)), surface);
-      if (!entry) {
+   if (!found) {
+      surface = create_surface(&ctx->base, &res->base.b, &key, ivci);
+      if (!surface) {
+         _mesa_set_remove(ht, entry);
          simple_mtx_unlock(&res->obj->surface_mtx);
          return NULL;
       }
-
-      surface = entry->data;
+      entry->key = surface;
    } else {
-      surface = entry->data;
+      surface = (void*)entry->key;
    }
    simple_mtx_unlock(&res->obj->surface_mtx);
 
diff --git a/src/gallium/drivers/zink/zink_surface.h b/src/gallium/drivers/zink/zink_surface.h
index 65d1c36..a6c90ef 100644
--- a/src/gallium/drivers/zink/zink_surface.h
+++ b/src/gallium/drivers/zink/zink_surface.h
@@ -27,12 +27,9 @@
 #include "zink_types.h"
 
 static inline bool
-equals_ivci(const void *a, const void *b)
+equals_surface_key(const void *a, const void *b)
 {
-   const uint8_t *pa = a;
-   const uint8_t *pb = b;
-   size_t offset = offsetof(VkImageViewCreateInfo, flags);
-   return memcmp(pa + offset, pb + offset, sizeof(VkImageViewCreateInfo) - offset) == 0;
+   return memcmp(a, b, sizeof(struct zink_surface_key)) == 0;
 }
 
 VkImageViewCreateInfo
diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h
index e5bdea9..6302f76 100644
--- a/src/gallium/drivers/zink/zink_types.h
+++ b/src/gallium/drivers/zink/zink_types.h
@@ -1199,7 +1199,7 @@
    };
    VkDeviceAddress bda;
 
-   struct hash_table surface_cache;
+   struct set surface_cache;
    simple_mtx_t surface_mtx;
 
    VkSampleLocationsInfoEXT zs_evaluate;
@@ -1519,9 +1519,32 @@
 }
 
 /** surface types */
- 
+
+enum zink_surface_type {
+   ZINK_SURFACE_NORMAL,
+   ZINK_SURFACE_LAYERED,
+   ZINK_SURFACE_ARRAYED,
+};
+
+/* compact hash table key based on pipe_surface */
+struct zink_surface_key {
+   enum pipe_format format:12;      /**< typed PIPE_FORMAT_x */
+   unsigned swizzle_r:3;         /**< PIPE_SWIZZLE_x for red component */
+   unsigned swizzle_g:3;         /**< PIPE_SWIZZLE_x for green component */
+   unsigned swizzle_b:3;         /**< PIPE_SWIZZLE_x for blue component */
+   unsigned swizzle_a:3;         /**< PIPE_SWIZZLE_x for alpha component */
+   unsigned first_level:4;   /**< first mipmap level to use */
+   unsigned level_count:4;
+   enum zink_surface_type viewtype:2;      /**< layered view of an array/3d iamge */
+   unsigned stencil:1;           /**< stencil-only view */
+   unsigned pad:29;
+   unsigned first_layer:16;  /**< first layer to use for array textures */
+   unsigned last_layer:16;   /**< last layer to use for array textures */
+};
+
 /* this type only exists for compat with 32bit builds because vk types are 64bit */
 struct zink_surface {
+   struct zink_surface_key key;
    VkImageView image_view;
 };
 
@@ -1534,11 +1557,16 @@
    bool emulate_nonseamless;
 };
 
+struct zink_bufferview_key {
+   enum pipe_format format:12;
+   unsigned offset;
+   unsigned size;
+};
+
 struct zink_buffer_view {
    struct pipe_resource *pres;
-   VkBufferViewCreateInfo bvci;
+   struct zink_bufferview_key key;
    VkBufferView buffer_view;
-   uint32_t hash;
 };
 
 struct zink_sampler_view {