zink: use real A8_UNORM when possible

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>
This commit is contained in:
Mike Blumenkrantz 2023-08-10 09:48:01 -04:00 committed by Marge Bot
parent f501f9453a
commit 252bff0f48
7 changed files with 34 additions and 6 deletions

View 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) ||

View 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

View 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) ||

View 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)) {

View 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) &&

View 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,

View 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;