diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9ce5ea60a4..96fea10d63 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1029,10 +1029,18 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg return; } if (!regs.viewport_scale_offset_enabled) { - const auto x = static_cast(regs.surface_clip.x); - 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); + float x = static_cast(regs.surface_clip.x); + float y = static_cast(regs.surface_clip.y); + float width = static_cast(regs.surface_clip.width); + float height = static_cast(regs.surface_clip.height); + + const bool lower_left = + regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft; + if (lower_left) { + // Vulkan viewport space is top-left; emulate lower-left with negative height. + y += height; + height = -height; + } VkViewport viewport{ .x = x, .y = y, @@ -1068,15 +1076,20 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs return; } if (!regs.viewport_scale_offset_enabled) { - const auto x = static_cast(regs.surface_clip.x); - 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); - VkRect2D scissor; - scissor.offset.x = static_cast(x); - scissor.offset.y = static_cast(y); - scissor.extent.width = static_cast(width != 0.0f ? width : 1.0f); - scissor.extent.height = static_cast(height != 0.0f ? height : 1.0f); + u32 x = regs.surface_clip.x; + u32 y = regs.surface_clip.y; + u32 width = regs.surface_clip.width ? regs.surface_clip.width : 1u; + u32 height = regs.surface_clip.height ? regs.surface_clip.height : 1u; + + if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { + // Vulkan scissor is top-left; convert from lower-left coordinates. + y = regs.surface_clip.height - (y + height); + } + VkRect2D scissor{}; + scissor.offset.x = static_cast(x); + scissor.offset.y = static_cast(y); + scissor.extent.width = width; + scissor.extent.height = height; scheduler.Record([scissor](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissor); }); return; } @@ -1586,7 +1599,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) highest_dirty_attr = index; } } - for (size_t index = 0; index < highest_dirty_attr; ++index) { + for (size_t index = 0; index <= highest_dirty_attr; ++index) { const Maxwell::VertexAttribute attribute{regs.vertex_attrib_format[index]}; const u32 binding{attribute.buffer}; dirty[Dirty::VertexAttribute0 + index] = false;