zink: use real A8_UNORM when possible
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Thu, 10 Aug 2023 13:48:01 +0000 (09:48 -0400)
committerMarge Bot <emma+marge@anholt.net>
Tue, 15 Aug 2023 16:42:27 +0000 (16:42 +0000)
this is tricky because drivers are exposing their native support, but
that support may not fit the specific needs of the format

as such, (almost) every use of format where alpha emulation workarounds are
present now need to add a second layer of workarounds in order to handle
the case of possibly-genuine A8 (which might also be emulated A8 even if
the driver supports A8 for some things)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24685>

src/gallium/drivers/zink/zink_blit.c
src/gallium/drivers/zink/zink_clear.c
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_resource.c
src/gallium/drivers/zink/zink_screen.c
src/gallium/drivers/zink/zink_surface.c
src/gallium/drivers/zink/zink_types.h

index fa4b891..1c418a9 100644 (file)
@@ -157,7 +157,7 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *n
    if (src->format != zink_get_format(screen, info->src.format) ||
        dst->format != zink_get_format(screen, info->dst.format))
       return false;
-   if (zink_format_is_emulated_alpha(info->src.format))
+   if (src->format != VK_FORMAT_A8_UNORM_KHR && zink_format_is_emulated_alpha(info->src.format))
       return false;
 
    if (!(src->obj->vkfeats & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
index b859181..d9eb20a 100644 (file)
@@ -148,6 +148,7 @@ get_clear_data(struct zink_context *ctx, struct zink_framebuffer_clear *fb_clear
 static void
 convert_color(struct pipe_surface *psurf, union pipe_color_union *color)
 {
+   struct zink_resource *res = zink_resource(psurf->texture);
    const struct util_format_description *desc = util_format_description(psurf->format);
    union pipe_color_union tmp = *color;
 
@@ -174,6 +175,12 @@ convert_color(struct pipe_surface *psurf, union pipe_color_union *color)
    }
    for (unsigned i = 0; i < 4; i++)
       zink_format_clamp_channel_color(desc, color, &tmp, i);
+
+   /* manually swizzle R -> A for true A8 */
+   if (res->format == VK_FORMAT_A8_UNORM_KHR) {
+      color->ui[3] = color->ui[0];
+      color->ui[0] = 0;
+   }
 }
 
 void
index ffe09cd..1af2093 100644 (file)
@@ -1127,7 +1127,7 @@ zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres,
             const struct util_format_description *view_desc = util_format_description(state->format);
             for (int i = 0; i < 4; ++i)
                swizzle[i] = zink_clamp_void_swizzle(view_desc, swizzle[i]);
-         } else if (util_format_is_alpha(state->format)) {
+         } else if (util_format_is_alpha(state->format) && res->format != VK_FORMAT_A8_UNORM_KHR) {
             for (int i = 0; i < 4; ++i)
                swizzle[i] = clamp_alpha_swizzle(swizzle[i]);
          } else if (util_format_is_luminance(pres->format) ||
index b74c9e0..4f6a096 100644 (file)
@@ -27,6 +27,7 @@
 #include "zink_clear.h"
 #include "zink_context.h"
 #include "zink_fence.h"
+#include "zink_format.h"
 #include "zink_program.h"
 #include "zink_screen.h"
 #include "zink_kopper.h"
@@ -884,6 +885,10 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
       }
       init_ici(screen, &ici, templ, templ->bind, ici_modifier_count);
       uint64_t mod = eval_ici(screen, &ici, templ, templ->bind, ici_modifier_count, ici_modifiers, &success);
+      if (ici.format == VK_FORMAT_A8_UNORM_KHR && !success) {
+         ici.format = zink_get_format(screen, zink_format_get_emulated_alpha(templ->format));
+         mod = eval_ici(screen, &ici, templ, templ->bind, ici_modifier_count, ici_modifiers, &success);
+      }
       if (ici.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && srgb &&
           util_format_get_nr_components(srgb) == 4 &&
           !(ici.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
index 53455ef..d73edd2 100644 (file)
@@ -1334,7 +1334,8 @@ zink_is_format_supported(struct pipe_screen *pscreen,
          return false;
    }
 
-   VkFormat vkformat = zink_get_format(screen, format);
+   /* always use superset to determine feature support */
+   VkFormat vkformat = zink_get_format(screen, PIPE_FORMAT_A8_UNORM ? zink_format_get_emulated_alpha(format) : format);
    if (vkformat == VK_FORMAT_UNDEFINED)
       return false;
 
@@ -1772,7 +1773,9 @@ emulate_x8(enum pipe_format format)
 VkFormat
 zink_get_format(struct zink_screen *screen, enum pipe_format format)
 {
-   if (!screen->driver_workarounds.broken_l4a4 || format != PIPE_FORMAT_L4A4_UNORM)
+   if (format == PIPE_FORMAT_A8_UNORM && !screen->driver_workarounds.missing_a8_unorm)
+      return VK_FORMAT_A8_UNORM_KHR;
+   else if (!screen->driver_workarounds.broken_l4a4 || format != PIPE_FORMAT_L4A4_UNORM)
       format = zink_format_get_emulated_alpha(format);
 
    VkFormat ret = zink_pipe_format_to_vk_format(emulate_x8(format));
@@ -2038,7 +2041,9 @@ static void
 populate_format_props(struct zink_screen *screen)
 {
    for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
-      VkFormat format = zink_get_format(screen, i);
+      VkFormat format;
+retry:
+      format = zink_get_format(screen, i);
       if (!format)
          continue;
       if (VKSCR(GetPhysicalDeviceFormatProperties2)) {
@@ -2072,6 +2077,14 @@ populate_format_props(struct zink_screen *screen)
          }
       } else
          VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &screen->format_props[i]);
+      if (i == PIPE_FORMAT_A8_UNORM && !screen->driver_workarounds.missing_a8_unorm) {
+         if (!screen->format_props[i].linearTilingFeatures &&
+             !screen->format_props[i].optimalTilingFeatures &&
+             !screen->format_props[i].bufferFeatures) {
+            screen->driver_workarounds.missing_a8_unorm = true;
+            goto retry;
+         }
+      }
       if (zink_format_is_emulated_alpha(i)) {
          VkFormatFeatureFlags blocked = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
          screen->format_props[i].linearTilingFeatures &= ~blocked;
@@ -2524,6 +2537,8 @@ init_driver_workarounds(struct zink_screen *screen)
       /* performance */
       screen->info.border_color_feats.customBorderColorWithoutFormat = VK_FALSE;
    }
+   if (!screen->info.have_KHR_maintenance5)
+      screen->driver_workarounds.missing_a8_unorm = true;
 
    if ((!screen->info.have_EXT_line_rasterization ||
         !screen->info.line_rast_feats.stippledBresenhamLines) &&
index f126638..0bf7ec2 100644 (file)
@@ -79,7 +79,7 @@ create_ivci(struct zink_screen *screen,
       unreachable("unsupported target");
    }
 
-   ivci.format = zink_get_format(screen, templ->format);
+   ivci.format = res->base.b.format == PIPE_FORMAT_A8_UNORM ? res->format : zink_get_format(screen, templ->format);
    assert(ivci.format != VK_FORMAT_UNDEFINED);
 
    /* TODO: it's currently illegal to use non-identity swizzles for framebuffer attachments,
index 9c86498..8d9901f 100644 (file)
@@ -1508,6 +1508,7 @@ struct zink_screen {
        * HI TURNIP
        */
       bool broken_cache_semantics;
+      bool missing_a8_unorm;
       bool implicit_sync;
       bool disable_optimized_compile;
       bool always_feedback_loop;