diff options
-rw-r--r-- | src/common/nvidia_flags.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.h | 2 | ||||
-rw-r--r-- | src/core/settings.h | 1 | ||||
-rw-r--r-- | src/video_core/engines/engine_interface.h | 3 | ||||
-rw-r--r-- | src/video_core/engines/fermi_2d.h | 2 | ||||
-rw-r--r-- | src/video_core/engines/kepler_memory.h | 2 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_dma.h | 2 | ||||
-rw-r--r-- | src/video_core/query_cache.h | 9 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_master_semaphore.h | 4 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 11 | ||||
-rw-r--r-- | src/video_core/texture_cache/util.cpp | 21 | ||||
-rw-r--r-- | src/video_core/texture_cache/util.h | 5 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 14 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_graphics.cpp | 19 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_graphics.ui | 41 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 54 |
16 files changed, 155 insertions, 37 deletions
diff --git a/src/common/nvidia_flags.h b/src/common/nvidia_flags.h index 75a0233ac..8930efcec 100644 --- a/src/common/nvidia_flags.h +++ b/src/common/nvidia_flags.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + namespace Common { /// Configure platform specific flags for Nvidia's driver diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 1c86fdd20..b442dfe57 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -402,7 +402,7 @@ public: return wait_cancelled; } - [[nodiscard]] void ClearWaitCancelled() { + void ClearWaitCancelled() { wait_cancelled = false; } diff --git a/src/core/settings.h b/src/core/settings.h index a81016b23..6c03a6ea9 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -139,6 +139,7 @@ struct Values { Setting<int> vulkan_device; Setting<u16> resolution_factor{1}; + Setting<int> fullscreen_mode; Setting<int> aspect_ratio; Setting<int> max_anisotropy; Setting<bool> use_frame_limit; diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index 18a9db7e6..c7ffd68c5 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h @@ -4,13 +4,14 @@ #pragma once -#include <type_traits> #include "common/common_types.h" namespace Tegra::Engines { class EngineInterface { public: + virtual ~EngineInterface() = default; + /// Write the value to the register identified by method. virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index c808a577d..a4170ffff 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -35,7 +35,7 @@ namespace Tegra::Engines { class Fermi2D final : public EngineInterface { public: explicit Fermi2D(); - ~Fermi2D(); + ~Fermi2D() override; /// Binds a rasterizer to this engine. void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index 19808a5c6..0d8ea09a9 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h @@ -36,7 +36,7 @@ namespace Tegra::Engines { class KeplerMemory final : public EngineInterface { public: explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); - ~KeplerMemory(); + ~KeplerMemory() override; /// Write the value to the register identified by method. void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 3c59eeb13..c77f02a22 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -188,7 +188,7 @@ public: static_assert(sizeof(RemapConst) == 12); explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); - ~MaxwellDMA(); + ~MaxwellDMA() override; /// Write the value to the register identified by method. void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 203f2af05..639d7ce7e 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h @@ -208,9 +208,9 @@ public: private: /// Flushes a memory range to guest memory and removes it from the cache. void FlushAndRemoveRegion(VAddr addr, std::size_t size) { - const u64 addr_begin = static_cast<u64>(addr); - const u64 addr_end = addr_begin + static_cast<u64>(size); - const auto in_range = [addr_begin, addr_end](CachedQuery& query) { + const u64 addr_begin = addr; + const u64 addr_end = addr_begin + size; + const auto in_range = [addr_begin, addr_end](const CachedQuery& query) { const u64 cache_begin = query.GetCpuAddr(); const u64 cache_end = cache_begin + query.SizeInBytes(); return cache_begin < addr_end && addr_begin < cache_end; @@ -230,8 +230,7 @@ private: rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); query.Flush(); } - contents.erase(std::remove_if(std::begin(contents), std::end(contents), in_range), - std::end(contents)); + std::erase_if(contents, in_range); } } diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 2c7ed654d..4b6d64daa 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h @@ -35,8 +35,8 @@ public: } /// Returns true when a tick has been hit by the GPU. - [[nodiscard]] bool IsFree(u64 tick) { - return gpu_tick.load(std::memory_order_relaxed) >= tick; + [[nodiscard]] bool IsFree(u64 tick) const noexcept { + return KnownGpuTick() >= tick; } /// Advance to the logical tick. diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 18155e449..bc2a53841 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -7,6 +7,8 @@ #include <span> #include <vector> +#include "common/bit_cast.h" + #include "video_core/engines/fermi_2d.h" #include "video_core/renderer_vulkan/blit_image.h" #include "video_core/renderer_vulkan/maxwell_to_vk.h" @@ -1062,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) { Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { const auto& device = runtime.device; const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); - const std::array<float, 4> color = tsc.BorderColor(); - // C++20 bit_cast - VkClearColorValue border_color; - std::memcpy(&border_color, &color, sizeof(color)); + const auto color = tsc.BorderColor(); + const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, .pNext = nullptr, - .customBorderColor = border_color, + // TODO: Make use of std::bit_cast once libc++ supports it. + .customBorderColor = Common::BitCast<VkClearColorValue>(color), .format = VK_FORMAT_UNDEFINED, }; const void* pnext = nullptr; diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index c22dd0148..0ab297413 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -268,16 +268,19 @@ template <u32 GOB_EXTENT> return num_tiles << shift; } -[[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info, - u32 num_levels) { +[[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) { ASSERT(num_levels <= MAX_MIP_LEVELS); - std::array<u32, MAX_MIP_LEVELS> sizes{}; + LevelArray sizes{}; for (u32 level = 0; level < num_levels; ++level) { sizes[level] = CalculateLevelSize(info, level); } return sizes; } +[[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) { + return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U); +} + [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, u32 num_samples, u32 tile_width_spacing) { const auto [samples_x, samples_y] = Samples(num_samples); @@ -566,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr const u32 num_levels = info.resources.levels; const std::array sizes = CalculateLevelSizes(level_info, num_levels); - size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0); + size_t guest_offset = CalculateLevelBytes(sizes, level); const size_t layer_stride = - AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size, - level_info.block, tile_size.height, info.tile_width_spacing); + AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block, + tile_size.height, info.tile_width_spacing); const size_t subresource_size = sizes[level]; const auto dst_data = std::make_unique<u8[]>(subresource_size); @@ -643,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept { info.tile_width_spacing, info.resources.levels); } -std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { +LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept { ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); const LevelInfo level_info = MakeLevelInfo(info); - std::array<u32, MAX_MIP_LEVELS> offsets{}; + LevelArray offsets{}; u32 offset = 0; for (s32 level = 0; level < info.resources.levels; ++level) { offsets[level] = offset; @@ -812,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP const Extent2D tile_size = DefaultBlockSize(info.format); const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); - const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0); + const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels); const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, info.tile_width_spacing); size_t guest_offset = 0; diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h index 4d0072867..cdc5cbc75 100644 --- a/src/video_core/texture_cache/util.h +++ b/src/video_core/texture_cache/util.h @@ -20,6 +20,8 @@ namespace VideoCommon { using Tegra::Texture::TICEntry; +using LevelArray = std::array<u32, MAX_MIP_LEVELS>; + struct OverlapResult { GPUVAddr gpu_addr; VAddr cpu_addr; @@ -36,8 +38,7 @@ struct OverlapResult { [[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; -[[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets( - const ImageInfo& info) noexcept; +[[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept; [[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 1d6155999..50ea15e2a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -771,6 +771,13 @@ void Config::ReadRendererValues() { ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); +#ifdef _WIN32 + ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 0); +#else + // *nix platforms may have issues with the borderless windowed fullscreen mode. + // Default to exclusive fullscreen on these platforms for now. + ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 1); +#endif ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); @@ -1334,6 +1341,13 @@ void Config::SaveRendererValues() { Settings::values.renderer_backend.UsingGlobal(), 0); WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); +#ifdef _WIN32 + WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 0); +#else + // *nix platforms may have issues with the borderless windowed fullscreen mode. + // Default to exclusive fullscreen on these platforms for now. + WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 1); +#endif WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 49acc48b2..8a2008b2a 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -77,18 +77,25 @@ void ConfigureGraphics::SetConfiguration() { if (Settings::IsConfiguringGlobal()) { ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); + ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue()); ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); } else { ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); ConfigurationShared::SetHighlight(ui->api_layout, !Settings::values.renderer_backend.UsingGlobal()); + + ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox, + &Settings::values.fullscreen_mode); + ConfigurationShared::SetHighlight(ui->fullscreen_mode_label, + !Settings::values.fullscreen_mode.UsingGlobal()); + ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, &Settings::values.aspect_ratio); + ConfigurationShared::SetHighlight(ui->ar_label, + !Settings::values.aspect_ratio.UsingGlobal()); ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); - ConfigurationShared::SetHighlight(ui->ar_label, - !Settings::values.aspect_ratio.UsingGlobal()); ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); } @@ -107,6 +114,9 @@ void ConfigureGraphics::ApplyConfiguration() { if (Settings::values.vulkan_device.UsingGlobal()) { Settings::values.vulkan_device.SetValue(vulkan_device); } + if (Settings::values.fullscreen_mode.UsingGlobal()) { + Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex()); + } if (Settings::values.aspect_ratio.UsingGlobal()) { Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); } @@ -140,6 +150,8 @@ void ConfigureGraphics::ApplyConfiguration() { } } + ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, + ui->fullscreen_mode_combobox); ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, ui->aspect_ratio_combobox); @@ -253,6 +265,7 @@ void ConfigureGraphics::SetupPerGameUI() { if (Settings::IsConfiguringGlobal()) { ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); + ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal()); ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); ui->use_asynchronous_gpu_emulation->setEnabled( Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); @@ -278,6 +291,8 @@ void ConfigureGraphics::SetupPerGameUI() { ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, Settings::values.aspect_ratio.GetValue(true)); + ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, + Settings::values.fullscreen_mode.GetValue(true)); ConfigurationShared::InsertGlobalItem( ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); } diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 58486eb1e..ab0bd4d77 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -105,8 +105,47 @@ </widget> </item> <item> + <widget class="QWidget" name="fullscreen_mode_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_1"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="fullscreen_mode_label"> + <property name="text"> + <string>Fullscreen Mode:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="fullscreen_mode_combobox"> + <item> + <property name="text"> + <string>Borderless Windowed</string> + </property> + </item> + <item> + <property name="text"> + <string>Exclusive Fullscreen</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + <item> <widget class="QWidget" name="aspect_ratio_layout" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <property name="leftMargin"> <number>0</number> </property> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 06445b993..23ea4983d 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2295,24 +2295,66 @@ void GMainWindow::ToggleFullscreen() { void GMainWindow::ShowFullscreen() { if (ui.action_Single_Window_Mode->isChecked()) { UISettings::values.geometry = saveGeometry(); + ui.menubar->hide(); statusBar()->hide(); - showFullScreen(); + + if (Settings::values.fullscreen_mode.GetValue() == 1) { + showFullScreen(); + return; + } + + hide(); + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + const auto screen_geometry = QApplication::desktop()->screenGeometry(this); + setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(), + screen_geometry.height() + 1); + raise(); + showNormal(); } else { UISettings::values.renderwindow_geometry = render_window->saveGeometry(); - render_window->showFullScreen(); + + if (Settings::values.fullscreen_mode.GetValue() == 1) { + render_window->showFullScreen(); + return; + } + + render_window->hide(); + render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + const auto screen_geometry = QApplication::desktop()->screenGeometry(this); + render_window->setGeometry(screen_geometry.x(), screen_geometry.y(), + screen_geometry.width(), screen_geometry.height() + 1); + render_window->raise(); + render_window->showNormal(); } } void GMainWindow::HideFullscreen() { if (ui.action_Single_Window_Mode->isChecked()) { + if (Settings::values.fullscreen_mode.GetValue() == 1) { + showNormal(); + restoreGeometry(UISettings::values.geometry); + } else { + hide(); + setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); + restoreGeometry(UISettings::values.geometry); + raise(); + show(); + } + statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); ui.menubar->show(); - showNormal(); - restoreGeometry(UISettings::values.geometry); } else { - render_window->showNormal(); - render_window->restoreGeometry(UISettings::values.renderwindow_geometry); + if (Settings::values.fullscreen_mode.GetValue() == 1) { + render_window->showNormal(); + render_window->restoreGeometry(UISettings::values.renderwindow_geometry); + } else { + render_window->hide(); + render_window->setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); + render_window->restoreGeometry(UISettings::values.renderwindow_geometry); + render_window->raise(); + render_window->show(); + } } } |