summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/nvidia_flags.h2
-rw-r--r--src/core/hle/kernel/k_thread.h2
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/engines/engine_interface.h3
-rw-r--r--src/video_core/engines/fermi_2d.h2
-rw-r--r--src/video_core/engines/kepler_memory.h2
-rw-r--r--src/video_core/engines/maxwell_dma.h2
-rw-r--r--src/video_core/query_cache.h9
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp11
-rw-r--r--src/video_core/texture_cache/util.cpp21
-rw-r--r--src/video_core/texture_cache/util.h5
-rw-r--r--src/yuzu/configuration/config.cpp14
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp19
-rw-r--r--src/yuzu/configuration/configure_graphics.ui41
-rw-r--r--src/yuzu/main.cpp54
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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
5namespace Common { 7namespace Common {
6 8
7/// Configure platform specific flags for Nvidia's driver 9/// 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:
402 return wait_cancelled; 402 return wait_cancelled;
403 } 403 }
404 404
405 [[nodiscard]] void ClearWaitCancelled() { 405 void ClearWaitCancelled() {
406 wait_cancelled = false; 406 wait_cancelled = false;
407 } 407 }
408 408
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 {
139 Setting<int> vulkan_device; 139 Setting<int> vulkan_device;
140 140
141 Setting<u16> resolution_factor{1}; 141 Setting<u16> resolution_factor{1};
142 Setting<int> fullscreen_mode;
142 Setting<int> aspect_ratio; 143 Setting<int> aspect_ratio;
143 Setting<int> max_anisotropy; 144 Setting<int> max_anisotropy;
144 Setting<bool> use_frame_limit; 145 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <type_traits>
8#include "common/common_types.h" 7#include "common/common_types.h"
9 8
10namespace Tegra::Engines { 9namespace Tegra::Engines {
11 10
12class EngineInterface { 11class EngineInterface {
13public: 12public:
13 virtual ~EngineInterface() = default;
14
14 /// Write the value to the register identified by method. 15 /// Write the value to the register identified by method.
15 virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; 16 virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0;
16 17
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 {
35class Fermi2D final : public EngineInterface { 35class Fermi2D final : public EngineInterface {
36public: 36public:
37 explicit Fermi2D(); 37 explicit Fermi2D();
38 ~Fermi2D(); 38 ~Fermi2D() override;
39 39
40 /// Binds a rasterizer to this engine. 40 /// Binds a rasterizer to this engine.
41 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); 41 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 {
36class KeplerMemory final : public EngineInterface { 36class KeplerMemory final : public EngineInterface {
37public: 37public:
38 explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); 38 explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager);
39 ~KeplerMemory(); 39 ~KeplerMemory() override;
40 40
41 /// Write the value to the register identified by method. 41 /// Write the value to the register identified by method.
42 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; 42 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:
188 static_assert(sizeof(RemapConst) == 12); 188 static_assert(sizeof(RemapConst) == 12);
189 189
190 explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); 190 explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_);
191 ~MaxwellDMA(); 191 ~MaxwellDMA() override;
192 192
193 /// Write the value to the register identified by method. 193 /// Write the value to the register identified by method.
194 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; 194 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:
208private: 208private:
209 /// Flushes a memory range to guest memory and removes it from the cache. 209 /// Flushes a memory range to guest memory and removes it from the cache.
210 void FlushAndRemoveRegion(VAddr addr, std::size_t size) { 210 void FlushAndRemoveRegion(VAddr addr, std::size_t size) {
211 const u64 addr_begin = static_cast<u64>(addr); 211 const u64 addr_begin = addr;
212 const u64 addr_end = addr_begin + static_cast<u64>(size); 212 const u64 addr_end = addr_begin + size;
213 const auto in_range = [addr_begin, addr_end](CachedQuery& query) { 213 const auto in_range = [addr_begin, addr_end](const CachedQuery& query) {
214 const u64 cache_begin = query.GetCpuAddr(); 214 const u64 cache_begin = query.GetCpuAddr();
215 const u64 cache_end = cache_begin + query.SizeInBytes(); 215 const u64 cache_end = cache_begin + query.SizeInBytes();
216 return cache_begin < addr_end && addr_begin < cache_end; 216 return cache_begin < addr_end && addr_begin < cache_end;
@@ -230,8 +230,7 @@ private:
230 rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); 230 rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1);
231 query.Flush(); 231 query.Flush();
232 } 232 }
233 contents.erase(std::remove_if(std::begin(contents), std::end(contents), in_range), 233 std::erase_if(contents, in_range);
234 std::end(contents));
235 } 234 }
236 } 235 }
237 236
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:
35 } 35 }
36 36
37 /// Returns true when a tick has been hit by the GPU. 37 /// Returns true when a tick has been hit by the GPU.
38 [[nodiscard]] bool IsFree(u64 tick) { 38 [[nodiscard]] bool IsFree(u64 tick) const noexcept {
39 return gpu_tick.load(std::memory_order_relaxed) >= tick; 39 return KnownGpuTick() >= tick;
40 } 40 }
41 41
42 /// Advance to the logical tick. 42 /// 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 @@
7#include <span> 7#include <span>
8#include <vector> 8#include <vector>
9 9
10#include "common/bit_cast.h"
11
10#include "video_core/engines/fermi_2d.h" 12#include "video_core/engines/fermi_2d.h"
11#include "video_core/renderer_vulkan/blit_image.h" 13#include "video_core/renderer_vulkan/blit_image.h"
12#include "video_core/renderer_vulkan/maxwell_to_vk.h" 14#include "video_core/renderer_vulkan/maxwell_to_vk.h"
@@ -1062,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) {
1062Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { 1064Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
1063 const auto& device = runtime.device; 1065 const auto& device = runtime.device;
1064 const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); 1066 const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported();
1065 const std::array<float, 4> color = tsc.BorderColor(); 1067 const auto color = tsc.BorderColor();
1066 // C++20 bit_cast 1068
1067 VkClearColorValue border_color;
1068 std::memcpy(&border_color, &color, sizeof(color));
1069 const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ 1069 const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
1070 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, 1070 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
1071 .pNext = nullptr, 1071 .pNext = nullptr,
1072 .customBorderColor = border_color, 1072 // TODO: Make use of std::bit_cast once libc++ supports it.
1073 .customBorderColor = Common::BitCast<VkClearColorValue>(color),
1073 .format = VK_FORMAT_UNDEFINED, 1074 .format = VK_FORMAT_UNDEFINED,
1074 }; 1075 };
1075 const void* pnext = nullptr; 1076 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>
268 return num_tiles << shift; 268 return num_tiles << shift;
269} 269}
270 270
271[[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info, 271[[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) {
272 u32 num_levels) {
273 ASSERT(num_levels <= MAX_MIP_LEVELS); 272 ASSERT(num_levels <= MAX_MIP_LEVELS);
274 std::array<u32, MAX_MIP_LEVELS> sizes{}; 273 LevelArray sizes{};
275 for (u32 level = 0; level < num_levels; ++level) { 274 for (u32 level = 0; level < num_levels; ++level) {
276 sizes[level] = CalculateLevelSize(info, level); 275 sizes[level] = CalculateLevelSize(info, level);
277 } 276 }
278 return sizes; 277 return sizes;
279} 278}
280 279
280[[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) {
281 return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U);
282}
283
281[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, 284[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
282 u32 num_samples, u32 tile_width_spacing) { 285 u32 num_samples, u32 tile_width_spacing) {
283 const auto [samples_x, samples_y] = Samples(num_samples); 286 const auto [samples_x, samples_y] = Samples(num_samples);
@@ -566,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
566 569
567 const u32 num_levels = info.resources.levels; 570 const u32 num_levels = info.resources.levels;
568 const std::array sizes = CalculateLevelSizes(level_info, num_levels); 571 const std::array sizes = CalculateLevelSizes(level_info, num_levels);
569 size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0); 572 size_t guest_offset = CalculateLevelBytes(sizes, level);
570 const size_t layer_stride = 573 const size_t layer_stride =
571 AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size, 574 AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block,
572 level_info.block, tile_size.height, info.tile_width_spacing); 575 tile_size.height, info.tile_width_spacing);
573 const size_t subresource_size = sizes[level]; 576 const size_t subresource_size = sizes[level];
574 577
575 const auto dst_data = std::make_unique<u8[]>(subresource_size); 578 const auto dst_data = std::make_unique<u8[]>(subresource_size);
@@ -643,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept {
643 info.tile_width_spacing, info.resources.levels); 646 info.tile_width_spacing, info.resources.levels);
644} 647}
645 648
646std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { 649LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
647 ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); 650 ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS));
648 const LevelInfo level_info = MakeLevelInfo(info); 651 const LevelInfo level_info = MakeLevelInfo(info);
649 std::array<u32, MAX_MIP_LEVELS> offsets{}; 652 LevelArray offsets{};
650 u32 offset = 0; 653 u32 offset = 0;
651 for (s32 level = 0; level < info.resources.levels; ++level) { 654 for (s32 level = 0; level < info.resources.levels; ++level) {
652 offsets[level] = offset; 655 offsets[level] = offset;
@@ -812,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP
812 const Extent2D tile_size = DefaultBlockSize(info.format); 815 const Extent2D tile_size = DefaultBlockSize(info.format);
813 const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); 816 const std::array level_sizes = CalculateLevelSizes(level_info, num_levels);
814 const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); 817 const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing);
815 const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0); 818 const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels);
816 const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, 819 const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height,
817 info.tile_width_spacing); 820 info.tile_width_spacing);
818 size_t guest_offset = 0; 821 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 {
20 20
21using Tegra::Texture::TICEntry; 21using Tegra::Texture::TICEntry;
22 22
23using LevelArray = std::array<u32, MAX_MIP_LEVELS>;
24
23struct OverlapResult { 25struct OverlapResult {
24 GPUVAddr gpu_addr; 26 GPUVAddr gpu_addr;
25 VAddr cpu_addr; 27 VAddr cpu_addr;
@@ -36,8 +38,7 @@ struct OverlapResult {
36 38
37[[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; 39[[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept;
38 40
39[[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets( 41[[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept;
40 const ImageInfo& info) noexcept;
41 42
42[[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); 43[[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info);
43 44
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() {
771 ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); 771 ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0);
772 ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); 772 ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false);
773 ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); 773 ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0);
774#ifdef _WIN32
775 ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 0);
776#else
777 // *nix platforms may have issues with the borderless windowed fullscreen mode.
778 // Default to exclusive fullscreen on these platforms for now.
779 ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 1);
780#endif
774 ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); 781 ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0);
775 ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); 782 ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0);
776 ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); 783 ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true);
@@ -1334,6 +1341,13 @@ void Config::SaveRendererValues() {
1334 Settings::values.renderer_backend.UsingGlobal(), 0); 1341 Settings::values.renderer_backend.UsingGlobal(), 0);
1335 WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); 1342 WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false);
1336 WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); 1343 WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0);
1344#ifdef _WIN32
1345 WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 0);
1346#else
1347 // *nix platforms may have issues with the borderless windowed fullscreen mode.
1348 // Default to exclusive fullscreen on these platforms for now.
1349 WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 1);
1350#endif
1337 WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); 1351 WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0);
1338 WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); 1352 WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0);
1339 WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); 1353 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() {
77 77
78 if (Settings::IsConfiguringGlobal()) { 78 if (Settings::IsConfiguringGlobal()) {
79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); 79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
80 ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue());
80 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); 81 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
81 } else { 82 } else {
82 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); 83 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
83 ConfigurationShared::SetHighlight(ui->api_layout, 84 ConfigurationShared::SetHighlight(ui->api_layout,
84 !Settings::values.renderer_backend.UsingGlobal()); 85 !Settings::values.renderer_backend.UsingGlobal());
86
87 ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox,
88 &Settings::values.fullscreen_mode);
89 ConfigurationShared::SetHighlight(ui->fullscreen_mode_label,
90 !Settings::values.fullscreen_mode.UsingGlobal());
91
85 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, 92 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
86 &Settings::values.aspect_ratio); 93 &Settings::values.aspect_ratio);
94 ConfigurationShared::SetHighlight(ui->ar_label,
95 !Settings::values.aspect_ratio.UsingGlobal());
87 96
88 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); 97 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
89 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); 98 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
90 ConfigurationShared::SetHighlight(ui->ar_label,
91 !Settings::values.aspect_ratio.UsingGlobal());
92 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); 99 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal());
93 } 100 }
94 101
@@ -107,6 +114,9 @@ void ConfigureGraphics::ApplyConfiguration() {
107 if (Settings::values.vulkan_device.UsingGlobal()) { 114 if (Settings::values.vulkan_device.UsingGlobal()) {
108 Settings::values.vulkan_device.SetValue(vulkan_device); 115 Settings::values.vulkan_device.SetValue(vulkan_device);
109 } 116 }
117 if (Settings::values.fullscreen_mode.UsingGlobal()) {
118 Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex());
119 }
110 if (Settings::values.aspect_ratio.UsingGlobal()) { 120 if (Settings::values.aspect_ratio.UsingGlobal()) {
111 Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); 121 Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex());
112 } 122 }
@@ -140,6 +150,8 @@ void ConfigureGraphics::ApplyConfiguration() {
140 } 150 }
141 } 151 }
142 152
153 ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode,
154 ui->fullscreen_mode_combobox);
143 ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, 155 ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
144 ui->aspect_ratio_combobox); 156 ui->aspect_ratio_combobox);
145 157
@@ -253,6 +265,7 @@ void ConfigureGraphics::SetupPerGameUI() {
253 if (Settings::IsConfiguringGlobal()) { 265 if (Settings::IsConfiguringGlobal()) {
254 ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); 266 ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal());
255 ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); 267 ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal());
268 ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal());
256 ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); 269 ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal());
257 ui->use_asynchronous_gpu_emulation->setEnabled( 270 ui->use_asynchronous_gpu_emulation->setEnabled(
258 Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); 271 Settings::values.use_asynchronous_gpu_emulation.UsingGlobal());
@@ -278,6 +291,8 @@ void ConfigureGraphics::SetupPerGameUI() {
278 291
279 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, 292 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label,
280 Settings::values.aspect_ratio.GetValue(true)); 293 Settings::values.aspect_ratio.GetValue(true));
294 ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label,
295 Settings::values.fullscreen_mode.GetValue(true));
281 ConfigurationShared::InsertGlobalItem( 296 ConfigurationShared::InsertGlobalItem(
282 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); 297 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
283} 298}
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 @@
105 </widget> 105 </widget>
106 </item> 106 </item>
107 <item> 107 <item>
108 <widget class="QWidget" name="fullscreen_mode_layout" native="true">
109 <layout class="QHBoxLayout" name="horizontalLayout_1">
110 <property name="leftMargin">
111 <number>0</number>
112 </property>
113 <property name="topMargin">
114 <number>0</number>
115 </property>
116 <property name="rightMargin">
117 <number>0</number>
118 </property>
119 <property name="bottomMargin">
120 <number>0</number>
121 </property>
122 <item>
123 <widget class="QLabel" name="fullscreen_mode_label">
124 <property name="text">
125 <string>Fullscreen Mode:</string>
126 </property>
127 </widget>
128 </item>
129 <item>
130 <widget class="QComboBox" name="fullscreen_mode_combobox">
131 <item>
132 <property name="text">
133 <string>Borderless Windowed</string>
134 </property>
135 </item>
136 <item>
137 <property name="text">
138 <string>Exclusive Fullscreen</string>
139 </property>
140 </item>
141 </widget>
142 </item>
143 </layout>
144 </widget>
145 </item>
146 <item>
108 <widget class="QWidget" name="aspect_ratio_layout" native="true"> 147 <widget class="QWidget" name="aspect_ratio_layout" native="true">
109 <layout class="QHBoxLayout" name="horizontalLayout_6"> 148 <layout class="QHBoxLayout" name="horizontalLayout_2">
110 <property name="leftMargin"> 149 <property name="leftMargin">
111 <number>0</number> 150 <number>0</number>
112 </property> 151 </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() {
2295void GMainWindow::ShowFullscreen() { 2295void GMainWindow::ShowFullscreen() {
2296 if (ui.action_Single_Window_Mode->isChecked()) { 2296 if (ui.action_Single_Window_Mode->isChecked()) {
2297 UISettings::values.geometry = saveGeometry(); 2297 UISettings::values.geometry = saveGeometry();
2298
2298 ui.menubar->hide(); 2299 ui.menubar->hide();
2299 statusBar()->hide(); 2300 statusBar()->hide();
2300 showFullScreen(); 2301
2302 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2303 showFullScreen();
2304 return;
2305 }
2306
2307 hide();
2308 setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2309 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2310 setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2311 screen_geometry.height() + 1);
2312 raise();
2313 showNormal();
2301 } else { 2314 } else {
2302 UISettings::values.renderwindow_geometry = render_window->saveGeometry(); 2315 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
2303 render_window->showFullScreen(); 2316
2317 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2318 render_window->showFullScreen();
2319 return;
2320 }
2321
2322 render_window->hide();
2323 render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2324 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2325 render_window->setGeometry(screen_geometry.x(), screen_geometry.y(),
2326 screen_geometry.width(), screen_geometry.height() + 1);
2327 render_window->raise();
2328 render_window->showNormal();
2304 } 2329 }
2305} 2330}
2306 2331
2307void GMainWindow::HideFullscreen() { 2332void GMainWindow::HideFullscreen() {
2308 if (ui.action_Single_Window_Mode->isChecked()) { 2333 if (ui.action_Single_Window_Mode->isChecked()) {
2334 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2335 showNormal();
2336 restoreGeometry(UISettings::values.geometry);
2337 } else {
2338 hide();
2339 setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
2340 restoreGeometry(UISettings::values.geometry);
2341 raise();
2342 show();
2343 }
2344
2309 statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); 2345 statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked());
2310 ui.menubar->show(); 2346 ui.menubar->show();
2311 showNormal();
2312 restoreGeometry(UISettings::values.geometry);
2313 } else { 2347 } else {
2314 render_window->showNormal(); 2348 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2315 render_window->restoreGeometry(UISettings::values.renderwindow_geometry); 2349 render_window->showNormal();
2350 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
2351 } else {
2352 render_window->hide();
2353 render_window->setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
2354 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
2355 render_window->raise();
2356 render_window->show();
2357 }
2316 } 2358 }
2317} 2359}
2318 2360