From a23fd087eecc048054d892e0989f14d1c81b341f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 5 Oct 2026 13:31:08 +0000 Subject: [PATCH] Fix native EFB readback blits on BGRA surfaces and their Y clamp The shared blit shader clamps the sampled Y to flags.z..w, but the native readback uniform set flags.w to 0, so every row sampled row 0. The blit pipeline was also built only for the surface format, while the readback draws into an RGBA8 texture; on a BGRA surface (the usual Linux/Vulkan choice) the pipeline and attachment formats disagree, which release builds no longer catch because Dawn validation is skipped. Build blit pipelines for RGBA8, BGRA8 and the surface format, and pick one by destination format. The Quest 1 simple blit path is unchanged. From upstream patchzyy/Wiicompiled 6f14bde (#244, KartPad batch). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Wg7mB8ogCWmp9GH19Uc82B --- aurora-main/lib/gfx/efb_ram_copy.cpp | 3 ++- aurora-main/lib/gfx/tex_copy_conv.cpp | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/aurora-main/lib/gfx/efb_ram_copy.cpp b/aurora-main/lib/gfx/efb_ram_copy.cpp index c4136f4..99de180 100644 --- a/aurora-main/lib/gfx/efb_ram_copy.cpp +++ b/aurora-main/lib/gfx/efb_ram_copy.cpp @@ -109,8 +109,9 @@ void ensure_native_texture(PendingCopy& pending, TextureHandle* cache = nullptr) *cache = pending.nativeTexture; } } + // The shared blit shader clamps Y to flags.z/w; preserve the full source. const std::array nativeBlitUniform{ - 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 64.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 64.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, }; pending.nativeBlitUniform = push_uniform(nativeBlitUniform); } diff --git a/aurora-main/lib/gfx/tex_copy_conv.cpp b/aurora-main/lib/gfx/tex_copy_conv.cpp index 7c7d7cd..a871931 100644 --- a/aurora-main/lib/gfx/tex_copy_conv.cpp +++ b/aurora-main/lib/gfx/tex_copy_conv.cpp @@ -422,7 +422,7 @@ static wgpu::BindGroupLayout g_depthBindGroupLayout; static wgpu::Sampler g_nearestSampler; static wgpu::Sampler g_linearSampler; static absl::flat_hash_map g_pipelines; -static wgpu::RenderPipeline g_blitPipeline; +static absl::flat_hash_map g_blitPipelines; static wgpu::RenderPipeline g_quest1BlitPipeline; static bool quest1_simple_blit() noexcept { @@ -549,9 +549,15 @@ void initialize() { }; g_depthBindGroupLayout = g_device.CreateBindGroupLayout(&depthBindGroupLayoutDescriptor); - g_blitPipeline = create_pipeline( - {GX_TF_RGBA8, FragPassthrough, webgpu::g_graphicsConfig.surfaceConfiguration.format, "TexCopyConv Blit"}, - ShaderPreamble, g_bindGroupLayout); + // Native RAM readback uses RGBA even when the EFB/surface uses BGRA. + // Build both variants here; frame workers only read the completed map. + for (const auto format : {wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::BGRA8Unorm, + webgpu::g_graphicsConfig.surfaceConfiguration.format}) { + if (format != wgpu::TextureFormat::Undefined && !g_blitPipelines.contains(format)) { + g_blitPipelines[format] = create_pipeline({GX_TF_RGBA8, FragPassthrough, format, "TexCopyConv Blit"}, + ShaderPreamble, g_bindGroupLayout); + } + } g_quest1BlitPipeline = create_pipeline( {GX_TF_RGBA8, {}, webgpu::g_graphicsConfig.surfaceConfiguration.format, "Quest 1 Simple TexCopy Blit"}, SimpleBlitShader, g_bindGroupLayout); @@ -585,7 +591,7 @@ void initialize() { void shutdown() { g_pipelines.clear(); - g_blitPipeline = {}; + g_blitPipelines.clear(); g_quest1BlitPipeline = {}; g_bindGroupLayout = {}; g_depthBindGroupLayout = {}; @@ -678,7 +684,15 @@ void run(const wgpu::CommandEncoder& cmd, const ConvRequest& req) { } void blit(const wgpu::CommandEncoder& cmd, const ConvRequest& req) { - execute(cmd, req, quest1_simple_blit() ? g_quest1BlitPipeline : g_blitPipeline); + if (quest1_simple_blit()) { + execute(cmd, req, g_quest1BlitPipeline); + return; + } + const auto it = g_blitPipelines.find(req.dst->format); + if (it == g_blitPipelines.end()) { + Log.fatal("Unsupported blit destination format {}", static_cast(req.dst->format)); + } + execute(cmd, req, it->second); } } // namespace aurora::gfx::tex_copy_conv