From bca7e8aea5e53a1a54c475d09332496ee06b0dad Mon Sep 17 00:00:00 2001 From: tuwary <47059291+tuwary@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:19:45 +0800 Subject: [PATCH] Take alpha to coverage out of the dynamic state on AMD's RDNA 2-and-older driver AMD's Windows driver branch for RDNA 2 and older (vk_caps.amd_sc, driverInfo "(AMD proprietary shader compiler)") applies alpha to coverage even while vkCmdSetAlphaToCoverageEnableEXT sets it to false. TotK never turns alpha to coverage on (a TOTK_DUMP frame showed it off in all 1170 pipelines), yet on an RX 590 with driver 24.9.1 the character draws kept their depth and lost their colour in the G-buffer, so Link and the NPCs were black silhouettes, and other surfaces were dithered into checkerboards (issue #67, RX 470/570/580). On that driver branch vk_pipeline.c ensure_init now leaves alpha to coverage out of the dynamic state, so it goes into the pipeline key as on GPUs without EDS3. TOTK_VK_DYN_A2C=0/1 (ini vk_dyn_a2c) forces either behaviour. NVIDIA and RDNA 3/4 are unchanged. Tested on the RX 590 with 1.4.3: characters, the checkerboards and the black blocks all render correctly. Fixes #67. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DcYzeu7eb2txzmu4brvcgh --- runtime/cfg.c | 2 +- runtime/vk_pipeline.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/runtime/cfg.c b/runtime/cfg.c index 25a30f18..d26c5086 100644 --- a/runtime/cfg.c +++ b/runtime/cfg.c @@ -48,7 +48,7 @@ static const char *const known[] = { "REPLAY_CHECK", "RESOLVE_CHECK", "ROMFS", "ROMFS_INDEX", "ROMFS_MMAP", "ROMFS_MODS", "ROMFS_PATCHES", "ROMFS_PROOF_DIR", "ROMFS_VERIFY", "RUMBLE", "RUMBLE_CURVE", "RUMBLE_STRENGTH", "RUMBLE_TRIGGERS", "SHADER_CACHE", "SHADER_MEMO", "SHARED_FONTS", "SHARPNESS", "SHOTS", "SHOTS_DIR", "SHOTS_FULL", "SPEED_PROBE", "SPIN", "SPIN_HANDOFF_US", "SPLIT_DRAWS", "SPLIT_US", "STICK_DEADZONE", "SWKBD_ANSWER", - "SWKBD_TEST", "TEST_PAD", "TEST_PREPARE_SHADERS", "TEX_ALIAS", "TEX_MEMO", "TEX_VRAM_PRESSURE", "TIMER_1MS", "TRACE", "UBO_SNAPSHOT", "UPSCALER", "VK_DYN_VERTEX", "VK_NO_FLOAT64", + "SWKBD_TEST", "TEST_PAD", "TEST_PREPARE_SHADERS", "TEX_ALIAS", "TEX_MEMO", "TEX_VRAM_PRESSURE", "TIMER_1MS", "TRACE", "UBO_SNAPSHOT", "UPSCALER", "VK_DYN_A2C", "VK_DYN_VERTEX", "VK_NO_FLOAT64", "VK_PRESENT", "VK_RECORDER", "VK_SSBO_ALIGN", "VK_SUBGROUP", "VK_SUBGROUP_PIN", "VK_VALIDATION", "VOLUME", "VRAM_HEADROOM", "VS_OUTS", "WB_FENCE_LIMIT", "WINDOW_SIZE", "XLATE", "XLATE_ID", "XLATE_PROCS", "ZSTD_CHECK", "ZSTD_NATIVE", }; diff --git a/runtime/vk_pipeline.c b/runtime/vk_pipeline.c index 15758686..8fdebe1c 100644 --- a/runtime/vk_pipeline.c +++ b/runtime/vk_pipeline.c @@ -278,6 +278,17 @@ static int ensure_init(void) { P.dyn_wmask = e3.extendedDynamicState3ColorWriteMask && PROC(set_wmask, "vkCmdSetColorWriteMaskEXT"); P.dyn_a2c = e3.extendedDynamicState3AlphaToCoverageEnable && PROC(set_a2c, "vkCmdSetAlphaToCoverageEnableEXT"); } + // TOTK_VK_DYN_A2C=0/1 forces dynamic alpha to coverage off or on. Default off on AMD's Windows driver branch for + // RDNA 2 and older (vk_caps.amd_sc), which applies alpha to coverage while the dynamic state says off: on an RX 590 + // (24.9.1) TotK, which never turns it on, drew Link and the NPCs with depth but no colour (black silhouettes) and + // dithered other surfaces into checkerboards (issue #67, RX 470/570/580). Taken out of the dynamic state, it goes + // into the pipeline key and the characters draw. + const char *da = cfg_get("TOTK_VK_DYN_A2C"); // no fixed default: it depends on the driver, see above + int da_on = da && *da ? strcmp(da, "0") != 0 : !vk_caps.amd_sc; + if (!da_on && P.dyn_a2c) { + P.dyn_a2c = 0; + rt_log("vk_pipeline: dynamic alpha to coverage off (%s)", da && *da ? "TOTK_VK_DYN_A2C=0" : "AMD's driver for RDNA 2 and older"); + } #undef PROC static const VkDynamicState core[] = { VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, VK_DYNAMIC_STATE_DEPTH_BIAS,