aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandr Popovich <alekpopo@pm.me>2025-06-16 22:36:30 +0000
committercrueter <crueter@noreply.localhost>2025-06-16 22:36:30 +0000
commit6aeba9de662e05ba3bdfe73a245ac9f7cde62097 (patch)
tree65a490fb2e81abc695dfac09a9c0dad8f8c6ee98
parenteae819f0d6a75c92e8c78c109507054bccf61f56 (diff)
[vk] Add some dynamic handling in the pipeline (#142)
Co-authored-by: crueter <swurl@swurl.xyz> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/142 Co-authored-by: Aleksandr Popovich <alekpopo@pm.me> Co-committed-by: Aleksandr Popovich <alekpopo@pm.me>
-rw-r--r--src/tests/video_core/memory_tracker.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp141
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.h14
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp6
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h21
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp10
-rw-r--r--src/yuzu/main.cpp1
9 files changed, 173 insertions, 36 deletions
diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp
index 45b1a91dc5..fbfcae62dd 100644
--- a/src/tests/video_core/memory_tracker.cpp
+++ b/src/tests/video_core/memory_tracker.cpp
@@ -7,7 +7,6 @@
#include <catch2/catch_test_macros.hpp>
-#include "common/alignment.h"
#include "common/common_types.h"
#include "video_core/buffer_cache/memory_tracker_base.h"
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 3577342e4a..d616201af2 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -928,6 +931,7 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
void RasterizerVulkan::UpdateDynamicStates() {
auto& regs = maxwell3d->regs;
+
UpdateViewportsState(regs);
UpdateScissorsState(regs);
UpdateDepthBias(regs);
@@ -935,7 +939,24 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
- if (device.IsExtExtendedDynamicStateSupported()) {
+
+ const u8 dynamic_state = Settings::values.dyna_state.GetValue();
+
+ auto features = DynamicFeatures{
+ .has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported()
+ && dynamic_state > 0,
+ .has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported()
+ && dynamic_state > 1,
+ .has_extended_dynamic_state_2_extra = device.IsExtExtendedDynamicState2ExtrasSupported()
+ && dynamic_state > 1,
+ .has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported()
+ && dynamic_state > 2,
+ .has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported()
+ && dynamic_state > 2,
+ .has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),
+ };
+
+ if (features.has_extended_dynamic_state) {
UpdateCullMode(regs);
UpdateDepthCompareOp(regs);
UpdateFrontFace(regs);
@@ -946,45 +967,54 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthTestEnable(regs);
UpdateDepthWriteEnable(regs);
UpdateStencilTestEnable(regs);
- if (device.IsExtExtendedDynamicState2Supported()) {
+
+ if (features.has_extended_dynamic_state_2) {
UpdatePrimitiveRestartEnable(regs);
UpdateRasterizerDiscardEnable(regs);
UpdateDepthBiasEnable(regs);
}
- if (device.IsExtExtendedDynamicState3EnablesSupported()) {
+
+ if (features.has_extended_dynamic_state_3_enables) {
using namespace Tegra::Engines;
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE
|| device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
- struct In {
+ struct In
+ {
const Maxwell3D::Regs::VertexAttribute::Type d;
- In(Maxwell3D::Regs::VertexAttribute::Type n) : d(n) {}
- bool operator()(Maxwell3D::Regs::VertexAttribute n) const {
+ In(Maxwell3D::Regs::VertexAttribute::Type n)
+ : d(n)
+ {}
+ bool operator()(Maxwell3D::Regs::VertexAttribute n) const
+ {
return n.type == d;
}
};
- auto has_float = std::any_of(
- regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(),
- In(Maxwell3D::Regs::VertexAttribute::Type::Float));
+ auto has_float = std::any_of(regs.vertex_attrib_format.begin(),
+ regs.vertex_attrib_format.end(),
+ In(Maxwell3D::Regs::VertexAttribute::Type::Float));
if (regs.logic_op.enable)
regs.logic_op.enable = static_cast<u32>(!has_float);
UpdateLogicOpEnable(regs);
- } else
+ } else {
UpdateLogicOpEnable(regs);
+ }
UpdateDepthClampEnable(regs);
}
}
- if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
+ if (features.has_extended_dynamic_state_2_extra) {
UpdateLogicOp(regs);
}
- if (device.IsExtExtendedDynamicState3Supported()) {
+ if (features.has_extended_dynamic_state_3_enables) {
UpdateBlending(regs);
+ UpdateLineStippleEnable(regs);
+ UpdateConservativeRasterizationMode(regs);
}
}
- if (device.IsExtVertexInputDynamicStateSupported()) {
+ if (features.has_dynamic_vertex_input) {
UpdateVertexInput(regs);
}
}
@@ -1104,25 +1134,39 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM ||
regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM;
- size_t length = sizeof(NEEDS_D24) / sizeof(u64);
- bool needs_convert = false;
- for (size_t i = 0; i < length; ++i) {
- if (NEEDS_D24[i] == program_id) {
- needs_convert = true;
- break;
+ if (is_d24 && !device.SupportsD24DepthBuffer()) {
+ static constexpr const size_t length = sizeof(NEEDS_D24) / sizeof(NEEDS_D24[0]);
+
+ static constexpr const u64 *start = NEEDS_D24;
+ static constexpr const u64 *end = NEEDS_D24 + length;
+
+ const size_t *it = std::find(start, end, program_id);
+
+ if (it != end) {
+ // the base formulas can be obtained from here:
+ // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
+ const double rescale_factor = static_cast<double>(1ULL << (32 - 24))
+ / (static_cast<double>(0x1.ep+127));
+ units = static_cast<float>(static_cast<double>(units) * rescale_factor);
}
}
- if (is_d24 && !device.SupportsD24DepthBuffer() && needs_convert) {
- // the base formulas can be obtained from here:
- // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
- const double rescale_factor = static_cast<double>(1ULL << (32 - 24))
- / (static_cast<double>(0x1.ep+127));
- units = static_cast<float>(static_cast<double>(units) * rescale_factor);
- } scheduler.Record([constant = units, clamp = regs.depth_bias_clamp,
- factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) {
- cmdbuf.SetDepthBias(constant, clamp, factor);
- });
+ scheduler.Record(
+ [constant = units, clamp = regs.depth_bias_clamp, factor = regs.slope_scale_depth_bias, this](
+ vk::CommandBuffer cmdbuf) {
+ if (device.IsExtDepthBiasControlSupported()) {
+ static VkDepthBiasRepresentationInfoEXT bias_info{
+ .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT,
+ .pNext = nullptr,
+ .depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT,
+ .depthBiasExact = VK_FALSE,
+ };
+
+ cmdbuf.SetDepthBias(constant, clamp, factor, &bias_info);
+ } else {
+ cmdbuf.SetDepthBias(constant, clamp, factor);
+ }
+ });
}
void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs) {
@@ -1304,6 +1348,45 @@ void RasterizerVulkan::UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::
});
}
+void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs)
+{
+ if (!state_tracker.TouchConservativeRasterizationMode()) {
+ return;
+ }
+
+ scheduler.Record([enable = regs.conservative_raster_enable](vk::CommandBuffer cmdbuf) {
+ cmdbuf.SetConservativeRasterizationModeEXT(
+ enable ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
+ : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT);
+ });
+}
+
+void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs)
+{
+ if (!state_tracker.TouchLineStippleEnable()) {
+ return;
+ }
+
+ scheduler.Record([enable = regs.line_stipple_enable](vk::CommandBuffer cmdbuf) {
+ cmdbuf.SetLineStippleEnableEXT(enable);
+ });
+}
+
+void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs)
+{
+ // if (!state_tracker.TouchLi()) {
+ // return;
+ // }
+
+ // TODO: The maxwell emulator does not capture line rasters
+
+ // scheduler.Record([enable = regs.line](vk::CommandBuffer cmdbuf) {
+ // cmdbuf.SetConservativeRasterizationModeEXT(
+ // enable ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
+ // : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT);
+ // });
+}
+
void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchDepthBiasEnable()) {
return;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 70e889eb16..f562ad1941 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -139,7 +142,7 @@ public:
u32 pixel_stride);
private:
- static constexpr u64 NEEDS_D24[] = {
+ static constexpr const u64 NEEDS_D24[] = {
0x01006A800016E000ULL, // SSBU
0x0100E95004038000ULL, // XC2
0x0100A6301214E000ULL, // FE:Engage
@@ -175,6 +178,9 @@ private:
void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::Regs& regs);
+ void UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs);
+ void UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs);
+ void UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& regs);
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index daaea29798..ff274ede6e 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -50,6 +53,8 @@ Flags MakeInvalidationFlags() {
StateEnable,
PrimitiveRestartEnable,
RasterizerDiscardEnable,
+ ConservativeRasterizationMode,
+ LineStippleEnable,
DepthBiasEnable,
LogicOpEnable,
DepthClampEnable,
@@ -137,6 +142,8 @@ void SetupDirtyStateEnable(Tables& tables) {
setup(OFF(stencil_enable), StencilTestEnable);
setup(OFF(primitive_restart.enabled), PrimitiveRestartEnable);
setup(OFF(rasterize_enable), RasterizerDiscardEnable);
+ setup(OFF(conservative_raster_enable), ConservativeRasterizationMode);
+ setup(OFF(line_stipple_enable), LineStippleEnable);
setup(OFF(polygon_offset_point_enable), DepthBiasEnable);
setup(OFF(polygon_offset_line_enable), DepthBiasEnable);
setup(OFF(polygon_offset_fill_enable), DepthBiasEnable);
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h
index 8010ad26cc..c7e460ce11 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.h
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -50,6 +53,8 @@ enum : u8 {
StencilTestEnable,
PrimitiveRestartEnable,
RasterizerDiscardEnable,
+ ConservativeRasterizationMode,
+ LineStippleEnable,
DepthBiasEnable,
StateEnable,
LogicOp,
@@ -200,10 +205,15 @@ public:
return Exchange(Dirty::RasterizerDiscardEnable, false);
}
- bool TouchDepthBiasEnable() {
- return Exchange(Dirty::DepthBiasEnable, false);
+ bool TouchConservativeRasterizationMode()
+ {
+ return Exchange(Dirty::ConservativeRasterizationMode, false);
}
+ bool TouchLineStippleEnable() { return Exchange(Dirty::ConservativeRasterizationMode, false); }
+
+ bool TouchDepthBiasEnable() { return Exchange(Dirty::DepthBiasEnable, false); }
+
bool TouchLogicOpEnable() {
return Exchange(Dirty::LogicOpEnable, false);
}
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index f1aa455516..0caf415212 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -141,6 +144,9 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetDepthWriteEnableEXT);
X(vkCmdSetPrimitiveRestartEnableEXT);
X(vkCmdSetRasterizerDiscardEnableEXT);
+ X(vkCmdSetConservativeRasterizationModeEXT);
+ X(vkCmdSetLineRasterizationModeEXT);
+ X(vkCmdSetLineStippleEnableEXT);
X(vkCmdSetDepthBiasEnableEXT);
X(vkCmdSetLogicOpEnableEXT);
X(vkCmdSetDepthClampEnableEXT);
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 4607bf516c..d12a1546e5 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -234,6 +237,9 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{};
PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT{};
PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT{};
+ PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT{};
+ PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT{};
+ PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT{};
PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{};
PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT{};
PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT{};
@@ -1431,6 +1437,21 @@ public:
dld->vkCmdSetRasterizerDiscardEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
}
+ void SetConservativeRasterizationModeEXT(VkConservativeRasterizationModeEXT mode) const noexcept
+ {
+ dld->vkCmdSetConservativeRasterizationModeEXT(handle, mode);
+ }
+
+ void SetLineRasterizationModeEXT(VkLineRasterizationModeEXT mode) const noexcept
+ {
+ dld->vkCmdSetLineRasterizationModeEXT(handle, mode);
+ }
+
+ void SetLineStippleEnableEXT(bool enable) const noexcept
+ {
+ dld->vkCmdSetLineStippleEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
+ }
+
void SetDepthBiasEnableEXT(bool enable) const noexcept {
dld->vkCmdSetDepthBiasEnableEXT(handle, enable ? VK_TRUE : VK_FALSE);
}
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index bf3a96b211..7fb335ee77 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -1,8 +1,10 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
-#include <functional>
+#include "yuzu/configuration/configure_profile_manager.h"
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileDialog>
@@ -18,8 +20,10 @@
#include "core/core.h"
#include "core/hle/service/acc/profile_manager.h"
#include "ui_configure_profile_manager.h"
-#include "yuzu/configuration/configure_profile_manager.h"
#include "yuzu/util/limitable_input_dialog.h"
+#include <algorithm>
+#include <functional>
+#include <iostream>
namespace {
// Same backup JPEG used by acc IProfile::GetImage if no jpeg found
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 3dbe2e3243..ae48907274 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2407,6 +2407,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?");
+ // TODO(alekpop): It returns the wrong user
switch (target) {
case GameListOpenTarget::SaveData: {
open_target = tr("Save Data");