From 16e1eb8e28a2935b75c36707b585a4f5e174ad43 Mon Sep 17 00:00:00 2001 From: goldislead <69987043+goldislead@users.noreply.github.com> Date: Fri, 17 Jul 2026 03:10:29 +0000 Subject: [PATCH] [GPU] Clarify 64bpp clear register order This resolves the TODO in GetColorClearShaderConstants about which 32 bit portion is in which register. For 64bpp formats, RB_COLOR_CLEAR_LO holds the lower 32 bits of the packed clear value, and RB_COLOR_CLEAR holds the upper 32 bits. --- src/xenia/gpu/d3d12/d3d12_render_target_cache.cc | 10 ++++++++-- src/xenia/gpu/draw_util.h | 16 +++++++++++++--- .../gpu/vulkan/vulkan_render_target_cache.cc | 10 ++++++++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc index 3cc4c4bbe..6b96f4cdb 100644 --- a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc +++ b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc @@ -1441,8 +1441,14 @@ bool D3D12RenderTargetCache::Resolve(const Memory& memory, clear_transfers_[1])) { uint64_t clear_values[2]; clear_values[0] = resolve_info.rb_depth_clear; - clear_values[1] = resolve_info.rb_color_clear | - (uint64_t(resolve_info.rb_color_clear_lo) << 32); + // For 64bpp formats, RB_COLOR_CLEAR_LO is the lower 32 bits of the + // packed clear value. RB_COLOR_CLEAR is the upper 32 bits and, for + // 32bpp formats, the whole value. + clear_values[1] = + resolve_info.color_edram_info.format_is_64bpp + ? resolve_info.rb_color_clear_lo | + (uint64_t(resolve_info.rb_color_clear) << 32) + : resolve_info.rb_color_clear; PerformTransfersAndResolveClears(2, clear_render_targets, clear_transfers_, clear_values, &clear_rectangle); diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h index cf2301f6a..8c68e0da2 100644 --- a/src/xenia/gpu/draw_util.h +++ b/src/xenia/gpu/draw_util.h @@ -713,9 +713,19 @@ struct ResolveInfo { // Not doing -32...32 to -1...1 clamping here as a hack for k_16_16 and // k_16_16_16_16 blending emulation when using host render targets as it // would be inconsistent with the usual way of clearing with a depth quad. - // TODO(Triang3l): Check which 32-bit portion is in which register. - constants_out.rt_specific.clear_value[0] = rb_color_clear; - constants_out.rt_specific.clear_value[1] = rb_color_clear_lo; + if (color_edram_info.format_is_64bpp) { + // RB_COLOR_CLEAR_LO holds the lower 32 bits. + // Red | green << 16 for 16_16_16_16, red for 32_32_FLOAT. + // RB_COLOR_CLEAR holds the upper 32 bits. + // D3D builds the low dword as R | G << 16 and the high as B | A << 16, + // and writes to the _LO and base register respectively. + constants_out.rt_specific.clear_value[0] = rb_color_clear_lo; + constants_out.rt_specific.clear_value[1] = rb_color_clear; + } else { + // 32bpp clear values are only taken from RB_COLOR_CLEAR. + constants_out.rt_specific.clear_value[0] = rb_color_clear; + constants_out.rt_specific.clear_value[1] = rb_color_clear; + } constants_out.rt_specific.edram_info = color_edram_info; constants_out.coordinate_info = coordinate_info; } diff --git a/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc b/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc index 67f6d2d32..55724adb7 100644 --- a/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc @@ -1316,8 +1316,14 @@ bool VulkanRenderTargetCache::Resolve(const Memory& memory, clear_transfers_[1])) { uint64_t clear_values[2]; clear_values[0] = resolve_info.rb_depth_clear; - clear_values[1] = resolve_info.rb_color_clear | - (uint64_t(resolve_info.rb_color_clear_lo) << 32); + // For 64bpp formats, RB_COLOR_CLEAR_LO is the lower 32 bits of the + // packed clear value. RB_COLOR_CLEAR is the upper 32 bits and, for + // 32bpp formats, the whole value. + clear_values[1] = + resolve_info.color_edram_info.format_is_64bpp + ? resolve_info.rb_color_clear_lo | + (uint64_t(resolve_info.rb_color_clear) << 32) + : resolve_info.rb_color_clear; PerformTransfersAndResolveClears(2, clear_render_targets, clear_transfers_, clear_values, &clear_rectangle);