kosmickrisp/zink: fix gray screen on Metal by forcing alpha=1 in blit shaders

Minecraft and other applications can render with alpha=0 in the backbuffer,
which causes the content to appear transparent/gray when blitted to the
Metal swapchain (CAMetalLayer). This is because Metal's compositor respects
the alpha channel of the swapchain content.

Fix this by forcing the alpha channel to 1.0 in both blit shader paths:
- vk_meta_blit_resolve.c: For the meta blit path (vk_meta_blit_image2)
- u_simple_shaders.c: For the util_blitter path

Additionally, force format conversion blits (RGBA->BGRA) to use util_blitter
instead of vk_meta_blit, as the meta path has intermittent black flashing
issues on Metal that still need investigation.

Also removes debug fprintf statements added during debugging.
This commit is contained in:
Luca Mignatti
2025-12-30 13:30:36 -06:00
parent fc578131ad
commit eb364234f9
6 changed files with 10 additions and 62 deletions
@@ -300,6 +300,12 @@ util_make_fragment_tex_shader(struct pipe_context *pipe,
}
}
/* Force alpha to 1.0 for float blits - fixes gray screen on Metal where
* source FBO may have alpha=0 causing transparent/gray appearance */
if (stype == TGSI_RETURN_TYPE_FLOAT) {
ureg_MOV(ureg, ureg_writemask(temp, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
}
ureg_MOV(ureg, out, ureg_src(temp));
ureg_END( ureg );
+3 -43
View File
@@ -162,25 +162,21 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *n
info->scissor_enable ||
info->swizzle_enable ||
info->alpha_blend) {
fprintf(stderr, "DEBUG: blit_native rejected: mask/scissor/swizzle/alpha_blend\n");
return false;
}
if (info->render_condition_enable &&
ctx->render_condition_active) {
fprintf(stderr, "DEBUG: blit_native rejected: render_condition\n");
return false;
}
if (util_format_is_depth_or_stencil(info->dst.format) &&
(dst_format != info->src.format || info->filter == PIPE_TEX_FILTER_LINEAR)) {
fprintf(stderr, "DEBUG: blit_native rejected: depth/stencil format mismatch\n");
return false;
}
/* vkCmdBlitImage must not be used for multisampled source or destination images. */
if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1) {
fprintf(stderr, "DEBUG: blit_native rejected: multisampled\n");
return false;
}
@@ -197,27 +193,19 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *n
dst_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ? dst_vkformat :
vk_format_get_aspect_format(dst_vkformat, dst_aspects);
if (src->format != zink_get_format(screen, info->src.format) || dst_aspect_fmt != dst_vkformat) {
fprintf(stderr, "DEBUG: blit_native rejected: format aspect mismatch src_format=%u vs expected=%u, dst_aspect_fmt=%u vs dst_vkformat=%u\n",
src->format, zink_get_format(screen, info->src.format), dst_aspect_fmt, dst_vkformat);
return false;
}
/* TODO: remove this in the future when spec permits to allow single-aspected blits */
if (src->format != zink_get_format(screen, info->src.format) ||
dst->format != zink_get_format(screen, info->dst.format)) {
fprintf(stderr, "DEBUG: blit_native rejected: format mismatch src->format=%u vs info->src.format=%s, dst->format=%u vs info->dst.format=%s\n",
src->format, util_format_short_name(info->src.format),
dst->format, util_format_short_name(info->dst.format));
return false;
}
if (src->format != VK_FORMAT_A8_UNORM_KHR && zink_format_is_emulated_alpha(info->src.format)) {
fprintf(stderr, "DEBUG: blit_native rejected: emulated alpha\n");
return false;
}
if (!(src->obj->vkfeats & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
!(dst->obj->vkfeats & VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
fprintf(stderr, "DEBUG: blit_native rejected: missing blit feature bits src=0x%x dst=0x%x\n",
src->obj->vkfeats, dst->obj->vkfeats);
return false;
}
@@ -225,26 +213,20 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *n
util_format_is_pure_sint(info->dst.format)) ||
(util_format_is_pure_uint(info->src.format) !=
util_format_is_pure_uint(info->dst.format))) {
fprintf(stderr, "DEBUG: blit_native rejected: sint/uint mismatch\n");
return false;
}
if (info->filter == PIPE_TEX_FILTER_LINEAR &&
!(src->obj->vkfeats & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
fprintf(stderr, "DEBUG: blit_native rejected: linear filter not supported\n");
return false;
}
/* TESTING: Allow format conversion to test alpha=1 fix
* Reject blits that require format conversion - kosmickrisp's meta blit
* texture sampling via argument buffers has issues
/* Reject blits requiring format conversion - use util_blitter instead.
* kosmickrisp's vk_meta_blit has intermittent black flashing issues on Metal.
* util_blitter goes through the regular Gallium draw path which works. */
if (info->src.format != info->dst.format) {
fprintf(stderr, "DEBUG: blit_native rejected: format conversion needed %s -> %s\n",
util_format_short_name(info->src.format),
util_format_short_name(info->dst.format));
return false;
}
*/
VkImageBlit region = {0};
@@ -356,12 +338,6 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *n
info->src.box.width, info->src.box.height,
info->dst.box.width, info->dst.box.height);
fprintf(stderr, "DEBUG: blit_native VkImages: src=%p dst=%p dst_dt_idx=%u dst_is_swapchain=%d\n",
(void*)use_src->obj->image,
(void*)dst->obj->image,
dst->obj->dt_idx,
dst->swapchain ? 1 : 0);
VKCTX(CmdBlitImage)(cmdbuf, use_src->obj->image, src->layout,
dst->obj->image, dst->layout,
1, &region,
@@ -404,13 +380,6 @@ zink_blit(struct pipe_context *pctx,
struct zink_resource *dst = zink_resource(info->dst.resource);
bool needs_present_readback = false;
fprintf(stderr, "DEBUG: zink_blit: src=%s %dx%d -> dst=%s %dx%d mask=0x%x\n",
util_format_short_name(info->src.format),
info->src.box.width, info->src.box.height,
util_format_short_name(info->dst.format),
info->dst.box.width, info->dst.box.height,
info->mask);
if (ctx->awaiting_resolve && ctx->in_rp && ctx->dynamic_fb.tc_info.has_resolve) {
bool is_depth = util_format_is_depth_or_stencil(info->src.format);
struct pipe_resource *resolve = ctx->fb_state.resolve;
@@ -437,20 +406,16 @@ zink_blit(struct pipe_context *pctx,
if (info->src.resource->nr_samples > 1 &&
info->dst.resource->nr_samples <= 1) {
if (blit_resolve(ctx, info, &needs_present_readback)) {
fprintf(stderr, "DEBUG: blit_resolve succeeded\n");
goto end;
}
} else {
if (try_copy_region(pctx, info)) {
fprintf(stderr, "DEBUG: try_copy_region succeeded\n");
goto end;
}
if (blit_native(ctx, info, &needs_present_readback)) {
fprintf(stderr, "DEBUG: blit_native succeeded\n");
goto end;
}
}
fprintf(stderr, "DEBUG: using util_blitter fallback\n");
}
@@ -606,17 +571,12 @@ zink_blit(struct pipe_context *pctx,
struct pipe_blit_info new_info = *info;
new_info.src.resource = &use_src->base.b;
fprintf(stderr, "DEBUG: zink_blit util_blitter path - srcbox y=%d height=%d\n",
new_info.src.box.y, new_info.src.box.height);
/* Fix Y-flip coordinates: when srcbox has y=0 and negative height (Y-flip),
* the source region would span from y=0 to y=-height which is invalid.
* Instead, adjust to y=abs(height) with negative height to read from the
* valid texture region in reverse order (0 to height, flipped). */
if (new_info.src.box.height < 0 && new_info.src.box.y == 0) {
new_info.src.box.y = -new_info.src.box.height;
fprintf(stderr, "DEBUG: zink_blit fixed Y-flip: src.box.y now %d, height %d\n",
new_info.src.box.y, new_info.src.box.height);
}
util_blitter_blit(ctx->blitter, &new_info, NULL);
-14
View File
@@ -136,9 +136,7 @@ kopper_CreateSurface(struct zink_screen *screen, struct kopper_displaytarget *cd
PFN_vkCreateMetalSurfaceEXT createMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)VKSCR(GetInstanceProcAddr)(screen->instance, "vkCreateMetalSurfaceEXT");
if (createMetalSurfaceEXT) {
error = createMetalSurfaceEXT(screen->instance, metal, NULL, &surface);
fprintf(stderr, "DEBUG: vkCreateMetalSurfaceEXT returned %d, surface=%p, pLayer=%p\n", error, (void*)surface, metal->pLayer);
} else {
fprintf(stderr, "DEBUG: vkCreateMetalSurfaceEXT not found!\n");
error = VK_ERROR_EXTENSION_NOT_PRESENT;
}
break;
@@ -153,7 +151,6 @@ kopper_CreateSurface(struct zink_screen *screen, struct kopper_displaytarget *cd
VkBool32 supported;
error = VKSCR(GetPhysicalDeviceSurfaceSupportKHR)(screen->pdev, screen->gfx_queue, surface, &supported);
fprintf(stderr, "DEBUG: GetPhysicalDeviceSurfaceSupportKHR error=%d supported=%d\n", error, supported);
if (!zink_screen_handle_vkresult(screen, error) || !supported)
goto fail;
@@ -440,14 +437,10 @@ update_caps(struct zink_screen *screen, struct kopper_displaytarget *cdt)
static VkResult
update_swapchain(struct zink_screen *screen, struct kopper_displaytarget *cdt, unsigned w, unsigned h)
{
fprintf(stderr, "DEBUG: update_swapchain ENTER w=%u h=%u\n", w, h);
VkResult error = update_caps(screen, cdt);
fprintf(stderr, "DEBUG: update_caps returned %d\n", error);
if (error != VK_SUCCESS)
return error;
fprintf(stderr, "DEBUG: calling kopper_CreateSwapchain\n");
struct kopper_swapchain *cswap = kopper_CreateSwapchain(screen, cdt, w, h, &error);
fprintf(stderr, "DEBUG: kopper_CreateSwapchain returned cswap=%p error=%d\n", (void*)cswap, error);
if (!cswap)
return error;
prune_old_swapchains(screen, cdt, false);
@@ -457,9 +450,7 @@ update_swapchain(struct zink_screen *screen, struct kopper_displaytarget *cdt, u
*pswap = cdt->swapchain;
cdt->swapchain = cswap;
fprintf(stderr, "DEBUG: calling kopper_GetSwapchainImages\n");
VkResult ret = kopper_GetSwapchainImages(screen, cdt->swapchain);
fprintf(stderr, "DEBUG: kopper_GetSwapchainImages returned %d\n", ret);
return ret;
}
@@ -471,7 +462,6 @@ zink_kopper_displaytarget_create(struct zink_screen *screen, unsigned tex_usage,
{
if (!width) width = 1;
if (!height) height = 1;
fprintf(stderr, "DEBUG: ENTERING zink_kopper_displaytarget_create w=%u h=%u\n", width, height);
struct kopper_displaytarget *cdt;
const struct kopper_loader_info *info = loader_private;
@@ -532,9 +522,7 @@ zink_kopper_displaytarget_create(struct zink_screen *screen, unsigned tex_usage,
cdt->formats[1] = zink_get_format(screen, srgb);
}
fprintf(stderr, "DEBUG: zink_kopper_displaytarget_create calling kopper_CreateSurface w=%u h=%u sType=%u\n", width, height, cdt->info.bos.sType);
cdt->surface = kopper_CreateSurface(screen, cdt);
fprintf(stderr, "DEBUG: kopper_CreateSurface returned surface=%p\n", (void*)cdt->surface);
if (!cdt->surface)
goto out;
@@ -839,9 +827,7 @@ kopper_present(void *data, void *gdata, int thread_idx)
cpi->info.pWaitSemaphores = NULL;
cpi->info.waitSemaphoreCount = 0;
}
fprintf(stderr, "DEBUG: kopper_present calling QueuePresentKHR image=%u swapchain=%p\n", cpi->image, (void*)swapchain);
VkResult error2 = VKSCR(QueuePresentKHR)(screen->queue, &cpi->info);
fprintf(stderr, "DEBUG: QueuePresentKHR returned %d\n", error2);
zink_screen_debug_marker_end(screen, screen->frame_marker_emitted);
zink_screen_debug_marker_begin(screen, "frame");
simple_mtx_unlock(screen->queue_lock);
-3
View File
@@ -826,9 +826,6 @@ kk_flush_draw_state(struct kk_cmd_buffer *cmd)
mtl_set_depth_stencil_state(enc, gfx->depth_stencil_state);
}
fprintf(stderr, "DEBUG: kk_flush_draw_state push_dirty=0x%x root_dirty=%d\n",
desc->push_dirty, desc->root_dirty);
if (desc->push_dirty)
kk_cmd_buffer_flush_push_descriptors(cmd, desc);
if (desc->root_dirty)
-1
View File
@@ -252,7 +252,6 @@ kk_CmdBlitImage2(VkCommandBuffer commandBuffer,
vk_meta_blit_image2(&cmd->vk, &dev->meta, pBlitImageInfo);
kk_meta_end(cmd, &save, VK_PIPELINE_BIND_POINT_GRAPHICS);
fprintf(stderr, "DEBUG: kk_CmdBlitImage2 completed\n");
}
VKAPI_ATTR void VKAPI_CALL
+1 -1
View File
@@ -648,7 +648,7 @@ do_blit(struct vk_command_buffer *cmd,
.imageView = dst_view,
.imageLayout = dst_image_layout,
.loadOp = key->stencil_as_discard ? VK_ATTACHMENT_LOAD_OP_CLEAR :
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
VkRenderingInfo vk_render = {