From 0642f2326d25e5d7a1e4f450cca122a31f6368a3 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Mon, 24 Nov 2025 20:42:56 -0400 Subject: [PATCH] [vk, rasterizer] Clamping Render-Area out of limits --- .../renderer_vulkan/vk_rasterizer.cpp | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 2950654347..5297e0abb4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -440,13 +440,48 @@ void RasterizerVulkan::Clear(u32 layer_count) { .baseArrayLayer = regs.clear_surface.layer, .layerCount = layer_count, }; - if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) { + const auto clamp_rect_to_render_area = [render_area](VkRect2D& rect) -> bool { + const auto clamp_axis = [](s32& offset, u32& extent, u32 limit) { + auto clamp_offset = [&offset, limit]() { + if (limit == 0) { + offset = 0; + return; + } + offset = std::clamp(offset, 0, static_cast(limit)); + }; + + if (extent == 0) { + clamp_offset(); + return; + } + if (offset < 0) { + const u32 shrink = (std::min)(extent, static_cast(-offset)); + extent -= shrink; + offset = 0; + } + if (limit == 0) { + extent = 0; + offset = 0; + return; + } + if (offset >= static_cast(limit)) { + offset = static_cast(limit); + extent = 0; + return; + } + const u64 end_coord = static_cast(offset) + extent; + if (end_coord > limit) { + extent = limit - static_cast(offset); + } + }; + + clamp_axis(rect.offset.x, rect.extent.width, render_area.width); + clamp_axis(rect.offset.y, rect.extent.height, render_area.height); + return rect.extent.width != 0 && rect.extent.height != 0; + }; + if (!clamp_rect_to_render_area(clear_rect.rect)) { return; } - clear_rect.rect.extent = VkExtent2D{ - .width = (std::min)(clear_rect.rect.extent.width, render_area.width), - .height = (std::min)(clear_rect.rect.extent.height, render_area.height), - }; const u32 color_attachment = regs.clear_surface.RT; if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {