From 0bfde1fcde657ca5f98487ba28486b07738670bb Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sat, 13 Sep 2025 06:32:24 -0500 Subject: [PATCH] video_core: Check DB_SHADER_CONTROL register before performing depth exports (#3588) The DB_SHADER_CONTROL register has several enable flags which must be set before certain depth exports are enabled. This commit adds logic to respect the values in this register when performing depth exports, which fixes the regression in earlier versions of KNACK. I've also renamed DepthBufferControl to DepthShaderControl, since that's closer to the official name for the register. --- src/shader_recompiler/frontend/translate/export.cpp | 3 ++- src/shader_recompiler/runtime_info.h | 3 ++- src/video_core/amdgpu/liverpool.h | 4 ++-- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 6 ++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index e1e39105f..1290c59c2 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -145,7 +145,8 @@ void Translator::ExportDepth(const GcnInst& inst) { } } else { // Components are float32 into separate VGPRS - u32 mask = MaskFromExportFormat(exp.en, runtime_info.fs_info.z_export_format); + u32 mask = MaskFromExportFormat(exp.en & runtime_info.fs_info.mrtz_mask, + runtime_info.fs_info.z_export_format); for (u32 i = 0; i < 4; i++, mask >>= 1) { if ((mask & 1) == 0) { continue; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 53e4ecd11..13de0f381 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -206,13 +206,14 @@ struct FragmentRuntimeInfo { std::array inputs; std::array color_buffers; AmdGpu::Liverpool::ShaderExportFormat z_export_format; + u8 mrtz_mask; bool dual_source_blending; bool operator==(const FragmentRuntimeInfo& other) const noexcept { return std::ranges::equal(color_buffers, other.color_buffers) && en_flags.raw == other.en_flags.raw && addr_flags.raw == other.addr_flags.raw && num_inputs == other.num_inputs && z_export_format == other.z_export_format && - dual_source_blending == other.dual_source_blending && + mrtz_mask == other.mrtz_mask && dual_source_blending == other.dual_source_blending && std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(), other.inputs.begin() + num_inputs); } diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 43c40d2b5..52bbd277b 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -338,7 +338,7 @@ struct Liverpool { GreaterThanZ = 2, }; - union DepthBufferControl { + union DepthShaderControl { u32 raw; BitField<0, 1, u32> z_export_enable; BitField<1, 1, u32> stencil_test_val_export_enable; @@ -1410,7 +1410,7 @@ struct Liverpool { DepthControl depth_control; INSERT_PADDING_WORDS(1); ColorControl color_control; - DepthBufferControl depth_buffer_control; + DepthShaderControl depth_shader_control; ClipperControl clipper_control; PolygonControl polygon_control; ViewportControl viewport_control; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index c250f4d13..37623bb32 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -169,6 +169,12 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS info.fs_info.addr_flags = regs.ps_input_addr; info.fs_info.num_inputs = regs.num_interp; info.fs_info.z_export_format = regs.z_export_format; + u8 stencil_ref_export_enable = regs.depth_shader_control.stencil_op_val_export_enable | + regs.depth_shader_control.stencil_test_val_export_enable; + info.fs_info.mrtz_mask = regs.depth_shader_control.z_export_enable | + (stencil_ref_export_enable << 1) | + (regs.depth_shader_control.mask_export_enable << 2) | + (regs.depth_shader_control.coverage_to_mask_enable << 3); const auto& cb0_blend = regs.blend_control[0]; if (cb0_blend.enable) { info.fs_info.dual_source_blending =