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(); +        }      }  } | 
