Explorar o código

vk_rasterizer: Pack texceptions and color formats on invalid formats

Sometimes for unknown reasons NVN games can bind a render target format
of 0. This may be a yuzu bug.

With the commits before this the formats were specified without being
"packed", assuming all formats and texceptions will be written like in
the color_attachments vector.

To address this issue, iterate all render targets and pack them as they
are valid. This way they will match color_attachments.

- Fixes validation errors and graphical issues on Breath of the Wild.
ReinUsesLisp %!s(int64=6) %!d(string=hai) anos
pai
achega
527a1574c3

+ 18 - 4
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@@ -1252,11 +1252,25 @@ std::size_t RasterizerVulkan::CalculateConstBufferSize(
 
 RenderPassParams RasterizerVulkan::GetRenderPassParams(Texceptions texceptions) const {
     const auto& regs = system.GPU().Maxwell3D().regs;
+    const std::size_t num_attachments = static_cast<std::size_t>(regs.rt_control.count);
+
     RenderPassParams params;
-    params.num_color_attachments = static_cast<u8>(regs.rt_control.count);
-    std::transform(regs.rt.begin(), regs.rt.end(), params.color_formats.begin(),
-                   [](const auto& rt) { return static_cast<u8>(rt.format); });
-    params.texceptions = static_cast<u8>(texceptions.to_ullong());
+    params.color_formats = {};
+    std::size_t color_texceptions = 0;
+
+    std::size_t index = 0;
+    for (std::size_t rt = 0; rt < num_attachments; ++rt) {
+        const auto& rendertarget = regs.rt[rt];
+        if (rendertarget.Address() == 0 || rendertarget.format == Tegra::RenderTargetFormat::NONE) {
+            continue;
+        }
+        params.color_formats[index] = static_cast<u8>(rendertarget.format);
+        color_texceptions |= (texceptions[rt] ? 1ULL : 0ULL) << index;
+        ++index;
+    }
+    params.num_color_attachments = static_cast<u8>(index);
+    params.texceptions = static_cast<u8>(color_texceptions);
+
     params.zeta_format = regs.zeta_enable ? static_cast<u8>(regs.zeta.format) : 0;
     params.zeta_texception = texceptions[ZETA_TEXCEPTION_INDEX];
     return params;

+ 1 - 1
src/video_core/renderer_vulkan/vk_renderpass_cache.h

@@ -19,8 +19,8 @@ namespace Vulkan {
 class VKDevice;
 
 struct RenderPassParams {
-    u8 num_color_attachments;
     std::array<u8, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_formats;
+    u8 num_color_attachments;
     u8 texceptions;
 
     u8 zeta_format;