summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-03-13 16:30:23 +1000
committerMike Lothian <mike@fireburn.co.uk>2025-05-12 12:46:19 +0100
commit70b38c0ce83aa0628472ef960aab38b0cf54b95d (patch)
treee35dbe69800c730880ca5c0980a29385b202ec9c /src
parent6656c60bca91091573f729387bfcf7d5d98b6ce5 (diff)
vulkan: Implement AMD driver workaround for logic operations
- Added conditional check for AMD graphics drivers - Automatically disable logic operations when float vertex attributes are present to work around driver quirks - Maintain original logic op state to preserve emulator behavior - Prepare dynamic state management infrastructure for future OpenGL implementation changes OpenGL implementation will follow in subsequent commits. Signed-off-by: Zephyron <zephyron@citron-emu.org>
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp45
1 files changed, 29 insertions, 16 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index fac631fb8..cd0b255a0 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -928,6 +929,8 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
void RasterizerVulkan::UpdateDynamicStates() {
auto& regs = maxwell3d->regs;
+
+ // Always update base dynamic states.
UpdateViewportsState(regs);
UpdateScissorsState(regs);
UpdateDepthBias(regs);
@@ -935,7 +938,9 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
+
if (device.IsExtExtendedDynamicStateSupported()) {
+ // Update extended dynamic states.
UpdateCullMode(regs);
UpdateDepthCompareOp(regs);
UpdateFrontFace(regs);
@@ -946,37 +951,44 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthTestEnable(regs);
UpdateDepthWriteEnable(regs);
UpdateStencilTestEnable(regs);
+
if (device.IsExtExtendedDynamicState2Supported()) {
UpdatePrimitiveRestartEnable(regs);
UpdateRasterizerDiscardEnable(regs);
UpdateDepthBiasEnable(regs);
}
+
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
- const auto old = regs.logic_op.enable;
-
- if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
- device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR) {
- struct In {
- const Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type d;
- In(Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type n) : d(n) {}
- bool operator()(Tegra::Engines::Maxwell3D::Regs::VertexAttribute n) const {
- return n.type == d;
- }
- };
-
- auto has_float = std::any_of(
+ // Store the original logic_op.enable state.
+ const auto oldLogicOpEnable = regs.logic_op.enable;
+
+ // Determine if the current driver is an AMD driver.
+ bool isAmdDriver = (device.GetDriverID() == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
+ device.GetDriverID() == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR ||
+ device.GetDriverID() == VK_DRIVER_ID_AMD_PROPRIETARY ||
+ device.GetDriverID() == VK_DRIVER_ID_AMD_PROPRIETARY_KHR ||
+ device.GetDriverID() == VK_DRIVER_ID_MESA_RADV);
+
+ if (isAmdDriver) {
+ // Check if any vertex attribute is of type Float.
+ bool hasFloat = std::any_of(
regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(),
- In(Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::Float));
+ [](const auto& attrib) {
+ return attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::Float;
+ });
- regs.logic_op.enable = static_cast<u32>(!has_float);
+ // For AMD drivers, disable logic_op if a float attribute is present.
+ regs.logic_op.enable = static_cast<u32>(!hasFloat);
UpdateLogicOpEnable(regs);
- regs.logic_op.enable = old;
+ // Restore the original value.
+ regs.logic_op.enable = oldLogicOpEnable;
} else {
UpdateLogicOpEnable(regs);
}
UpdateDepthClampEnable(regs);
}
}
+
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
UpdateLogicOp(regs);
}
@@ -984,6 +996,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateBlending(regs);
}
}
+
if (device.IsExtVertexInputDynamicStateSupported()) {
UpdateVertexInput(regs);
}