Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Add MoltenVK Semaphore setting and fix performance regression #11550

Merged
merged 2 commits into from
Feb 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/build-mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export Qt5_DIR="/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5"
export PATH="/usr/local/opt/llvm/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin"
export LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"
export CPPFLAGS="-I/usr/local/opt/llvm/include -msse -msse2 -mcx16 -no-pie"
export CXXFLAGS="-I/usr/local/opt/llvm/include -msse -msse2 -mcx16 -no-pie"
export CPLUS_INCLUDE_PATH="/usr/local/opt/molten-vk/include"
export VULKAN_SDK="/usr/local/opt/molten-vk"
export VK_ICD_FILENAMES="$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json"

Expand Down
31 changes: 31 additions & 0 deletions rpcs3/Emu/RSX/VK/vkutils/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#include "util/logs.hpp"
#include "Emu/system_config.h"

#ifdef __APPLE__
#include <MoltenVK/vk_mvk_moltenvk.h>
#endif

namespace vk
{
// Global shared render device
Expand Down Expand Up @@ -121,6 +125,33 @@ namespace vk
_vkGetPhysicalDeviceProperties2KHR(dev, &properties2);
props = properties2.properties;

#ifdef __APPLE__
if (instance_extensions.is_supported(VK_MVK_MOLTENVK_EXTENSION_NAME))
{
MVKConfiguration mvk_config = {};
size_t mvk_config_size = sizeof(MVKConfiguration);

PFN_vkGetMoltenVKConfigurationMVK _vkGetMoltenVKConfigurationMVK = nullptr;
_vkGetMoltenVKConfigurationMVK = reinterpret_cast<PFN_vkGetMoltenVKConfigurationMVK>(vkGetInstanceProcAddr(parent, "vkGetMoltenVKConfigurationMVK"));
ensure(_vkGetMoltenVKConfigurationMVK);

PFN_vkSetMoltenVKConfigurationMVK _vkSetMoltenVKConfigurationMVK = nullptr;
_vkSetMoltenVKConfigurationMVK = reinterpret_cast<PFN_vkSetMoltenVKConfigurationMVK>(vkGetInstanceProcAddr(parent, "vkSetMoltenVKConfigurationMVK"));
ensure(_vkSetMoltenVKConfigurationMVK);

CHECK_RESULT_EX(_vkGetMoltenVKConfigurationMVK(VK_NULL_HANDLE, &mvk_config, &mvk_config_size), std::string("Could not get MoltenVK configuration."));
nastys marked this conversation as resolved.
Show resolved Hide resolved
nastys marked this conversation as resolved.
Show resolved Hide resolved

mvk_config.semaphoreUseMTLEvent = (g_cfg.video.vk.metal_semaphore == vk_metal_semaphore_mode::mtlevent_preferred || g_cfg.video.vk.metal_semaphore == vk_metal_semaphore_mode::mtlevent);
mvk_config.semaphoreUseMTLFence = (g_cfg.video.vk.metal_semaphore == vk_metal_semaphore_mode::mtlevent_preferred || g_cfg.video.vk.metal_semaphore == vk_metal_semaphore_mode::mtlfence);

CHECK_RESULT_EX(_vkSetMoltenVKConfigurationMVK(VK_NULL_HANDLE, &mvk_config, &mvk_config_size), std::string("Could not set MoltenVK configuration."));
}
else
{
rsx_log.error("Cannot set Metal Semaphore because VK_MVK_moltenvk is not supported.\nIf you're using MoltenVK through libvulkan, manually set the MVK_ALLOW_METAL_EVENTS and/or MVK_ALLOW_METAL_FENCES environment variables instead.");
}
#endif

if (descriptor_indexing_support)
{
if (descriptor_indexing_props.maxUpdateAfterBindDescriptorsInAllPools < 800'000)
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/Emu/RSX/VK/vkutils/instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ namespace vk
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}

#ifdef __APPLE__
#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk"
if (support.is_supported(VK_MVK_MOLTENVK_EXTENSION_NAME))
{
extensions.push_back(VK_MVK_MOLTENVK_EXTENSION_NAME);
}
#endif

if (support.is_supported(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME))
{
extensions.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct cfg_root : cfg::node
cfg::_bool fsr_upscaling{ this, "Enable FidelityFX Super Resolution Upscaling", false, true };
cfg::uint<0, 100> rcas_sharpening_intensity{ this, "FidelityFX CAS Sharpening Intensity", 50, true };
cfg::_enum<vk_gpu_scheduler_mode> asynchronous_scheduler{ this, "Asynchronous Queue Scheduler", vk_gpu_scheduler_mode::safe };
cfg::_enum<vk_metal_semaphore_mode> metal_semaphore{ this, "Metal Semaphore", vk_metal_semaphore_mode::mtlevent_preferred };

} vk{ this };

Expand Down
17 changes: 17 additions & 0 deletions rpcs3/Emu/system_config_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,23 @@ void fmt_class_string<vk_gpu_scheduler_mode>::format(std::string& out, u64 arg)
});
}

template <>
void fmt_class_string<vk_metal_semaphore_mode>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](vk_metal_semaphore_mode value)
{
switch (value)
{
case vk_metal_semaphore_mode::software: return "Software emulation";
case vk_metal_semaphore_mode::mtlevent_preferred: return "MTLEvent preferred";
case vk_metal_semaphore_mode::mtlevent: return "MTLEvent";
case vk_metal_semaphore_mode::mtlfence: return "MTLFence";
}

return unknown;
});
}

template <>
void fmt_class_string<thread_scheduler_mode>::format(std::string& out, u64 arg)
{
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/Emu/system_config_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ enum class vk_gpu_scheduler_mode
fast
};

enum class vk_metal_semaphore_mode
{
software,
mtlevent_preferred,
mtlevent,
mtlfence
};

enum class thread_scheduler_mode
{
os,
Expand Down
9 changes: 9 additions & 0 deletions rpcs3/rpcs3qt/emu_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,15 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case vk_gpu_scheduler_mode::fast: return tr("Fast");
}
break;
case emu_settings_type::MetalSemaphore:
switch (static_cast<vk_metal_semaphore_mode>(index))
{
case vk_metal_semaphore_mode::software: return tr("Software emulation");
case vk_metal_semaphore_mode::mtlevent_preferred: return tr("MTLEvent preferred");
case vk_metal_semaphore_mode::mtlevent: return tr("MTLEvent");
case vk_metal_semaphore_mode::mtlfence: return tr("MTLFence");
}
break;
default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/rpcs3qt/emu_settings_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ enum class emu_settings_type
DriverWakeUpDelay,
VulkanAsyncTextureUploads,
VulkanAsyncSchedulerDriver,
MetalSemaphore,

// Performance Overlay
PerfOverlayEnabled,
Expand Down Expand Up @@ -252,6 +253,7 @@ inline static const QMap<emu_settings_type, cfg_location> settings_location =
{ emu_settings_type::VulkanAsyncSchedulerDriver, { "Video", "Vulkan", "Asynchronous Queue Scheduler"}},
{ emu_settings_type::FsrUpscalingEnable, { "Video", "Vulkan", "Enable FidelityFX Super Resolution Upscaling"}},
{ emu_settings_type::FsrSharpeningStrength, { "Video", "Vulkan", "FidelityFX CAS Sharpening Intensity"}},
{ emu_settings_type::MetalSemaphore, { "Video", "Vulkan", "Metal Semaphore"}},

// Performance Overlay
{ emu_settings_type::PerfOverlayEnabled, { "Video", "Performance Overlay", "Enabled" } },
Expand Down
7 changes: 7 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,13 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceComboBox(ui->vulkansched, emu_settings_type::VulkanAsyncSchedulerDriver);
SubscribeTooltip(ui->gb_vulkansched, tooltips.settings.vulkan_async_scheduler);

m_emu_settings->EnhanceComboBox(ui->metalsemaphore, emu_settings_type::MetalSemaphore);
#ifdef __APPLE__
SubscribeTooltip(ui->gb_metalsemaphore, tooltips.settings.metal_semaphore);
#else
ui->metalsemaphore->setVisible(false);
#endif

// Sliders

EnhanceSlider(emu_settings_type::DriverWakeUpDelay, ui->wakeupDelay, ui->wakeupText, tr(reinterpret_cast<const char*>(u8"%0 µs"), "Driver wake up delay"));
Expand Down
18 changes: 18 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -3904,6 +3904,24 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_metalsemaphore">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Metal Semaphore</string>
</property>
<layout class="QVBoxLayout" name="gb_metalsemaphore_layout">
<item>
<widget class="QComboBox" name="metalsemaphore"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacerDebugMore">
<property name="orientation">
Expand Down
1 change: 1 addition & 0 deletions rpcs3/rpcs3qt/tooltips.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class Tooltips : public QObject
const QString accurate_ppu_128_loop = tr("When enabled, PPU atomic operations will operate on entire cache line data, as opposed to a single 64bit block of memory when disabled.\nNumerical values control whether or not to enable the accurate version based on the atomic operation's length.");
const QString enable_performance_report = tr("Measure certain events and print a chart after the emulator is stopped. Don't enable if not asked to.");
const QString num_ppu_threads = tr("Affects maximum amount of PPU threads running concurrently, the value of 1 has very low compatibility with games.\n2 is the default, if unsure do not modify this setting.");
const QString metal_semaphore = tr("Determines how MoltenVK will simulate vkSemaphore on the Metal API.\nSoftware emulation is the slowest, but most accurate option. However, it can cause tearing.\nMTLEvent is faster, but not available under Rosetta (if MTLEvent preferred is selected, MTLFence is used; otherwise, emulation is used).\nMTLFence is faster than emulation, but can randomly cause synchronization issues.");

// emulator

Expand Down