From ed39ec4738724ea1a1722109c40e343c61493591 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 23 Nov 2025 21:16:43 +0100 Subject: [PATCH] Revert "[vk] Fix 20xx flipped screen (#3058)" (#3075) NOTES: regs.window_origin.flip_y MUST flip the y coordinate of any given FragCoord, we don't emulate this, this is the root cause of the error, but I'll just revert for now since it's easier DON'T MERGE unless it's near 0.0.4 and I (or someone else) hasn't tackled this yet properly This reverts commit 17fe74ef11a1777abae4fe198a0d84f3085056f6. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3075 Reviewed-by: MaranBr Reviewed-by: CamilleLaVey Co-authored-by: lizzie Co-committed-by: lizzie --- .../renderer_vulkan/vk_rasterizer.cpp | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 7bd8c57118..b66f5a0502 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -62,29 +62,41 @@ struct DrawParams { VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { const auto& src = regs.viewport_transform[index]; const auto conv = [scale](float value) { - float const new_value = value * scale; - return scale < 1.0f - ? std::round(std::abs(new_value)) * (std::signbit(new_value) ? -1.f : 1.f) - : new_value; + float new_value = value * scale; + if (scale < 1.0f) { + const bool sign = std::signbit(value); + new_value = std::round(std::abs(new_value)); + new_value = sign ? -new_value : new_value; + } + return new_value; }; - float const w = src.scale_x; - float h = src.scale_y; - if (regs.window_origin.mode == Maxwell::WindowOrigin::Mode::LowerLeft) // Flip by surface clip height - h = -h; - if (!device.IsNvViewportSwizzleSupported() && src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY) // Flip by viewport height - h = -h; - // In theory, a raster flip is equivalent to a texture flip for a whole square viewport - // TODO: one day implement this properly and raster flip the triangles, not the whole viewport... guh - if(regs.viewport_transform[1].scale_y == 0 && regs.window_origin.flip_y != 0) - h = -h; - float const x = src.translate_x - w; - float const y = src.translate_y - h; - float const reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; + const float x = conv(src.translate_x - src.scale_x); + const float width = conv(src.scale_x * 2.0f); + float y = conv(src.translate_y - src.scale_y); + float height = conv(src.scale_y * 2.0f); + + const bool lower_left = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft; + const bool y_negate = !device.IsNvViewportSwizzleSupported() && + src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY; + + if (lower_left) { + // Flip by surface clip height + y += conv(static_cast(regs.surface_clip.height)); + height = -height; + } + + if (y_negate) { + // Flip by viewport height + y += height; + height = -height; + } + + const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; VkViewport viewport{ - .x = conv(x), - .y = conv(y), - .width = w != 0.0f ? conv(w * 2.f) : 1.0f, - .height = h != 0.0f ? conv(h * 2.f) : 1.0f, + .x = x, + .y = y, + .width = width != 0.0f ? width : 1.0f, + .height = height != 0.0f ? height : 1.0f, .minDepth = src.translate_z - src.scale_z * reduce_z, .maxDepth = src.translate_z + src.scale_z, }; @@ -1014,10 +1026,10 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg return; } if (!regs.viewport_scale_offset_enabled) { - float x = float(regs.surface_clip.x); - float y = float(regs.surface_clip.y); - float width = (std::max)(1.0f, float(regs.surface_clip.width)); - float height = (std::max)(1.0f, float(regs.surface_clip.height)); + float x = static_cast(regs.surface_clip.x); + float y = static_cast(regs.surface_clip.y); + float width = (std::max)(1.0f, static_cast(regs.surface_clip.width)); + float height = (std::max)(1.0f, static_cast(regs.surface_clip.height)); if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { y += height; height = -height;