From ae1b97a6dd961ca31a032995abbcca24aad5e01f Mon Sep 17 00:00:00 2001 From: Zephyron Date: Mon, 8 Dec 2025 16:20:12 +1000 Subject: [PATCH] fix(vulkan): Fix viewport handling when transformations are disabled When viewport_scale_offset_enabled is false, properly set all viewports using surface_clip dimensions instead of just one. This prevents vertex explosions caused by invalid or zero-sized viewports. - Set all viewports (Maxwell::NumViewports) when transformations disabled - Ensure minimum viewport dimensions (1.0f) to prevent zero-sized viewports - Respect device viewport limits when setting viewports - Use proper viewport array instead of single viewport Signed-off-by: Zephyron --- .../renderer_vulkan/vk_rasterizer.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 82890e4a8..ed8a89a40 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1045,15 +1045,26 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg const auto y = static_cast(regs.surface_clip.y); const auto width = static_cast(regs.surface_clip.width); const auto height = static_cast(regs.surface_clip.height); - VkViewport viewport{ - .x = x, - .y = y, - .width = width != 0.0f ? width : 1.0f, - .height = height != 0.0f ? height : 1.0f, - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; - scheduler.Record([viewport](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewport); }); + // Ensure valid viewport dimensions to prevent vertex explosions + const float viewport_width = width > 0.0f ? width : 1.0f; + const float viewport_height = height > 0.0f ? height : 1.0f; + + std::array viewport_list; + for (size_t i = 0; i < Maxwell::NumViewports; ++i) { + viewport_list[i] = VkViewport{ + .x = x, + .y = y, + .width = viewport_width, + .height = viewport_height, + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + } + scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { + const u32 num_viewports = std::min(device.GetMaxViewports(), Maxwell::NumViewports); + const vk::Span viewports(viewport_list.data(), num_viewports); + cmdbuf.SetViewport(0, viewports); + }); return; } const bool is_rescaling{texture_cache.IsRescaling()};