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 -#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(!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(1ULL << (32 - 24)) + / (static_cast(0x1.ep+127)); + units = static_cast(static_cast(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(1ULL << (32 - 24)) - / (static_cast(0x1.ep+127)); - units = static_cast(static_cast(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 -#include +#include "yuzu/configuration/configure_profile_manager.h" #include #include #include @@ -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 +#include +#include 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");