Browse Source

Return Release Fences Early

pull/3528/head
PavelBARABANOV 3 weeks ago
parent
commit
5421837475
  1. 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
  2. 7
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
  3. 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
  4. 2
      src/android/app/src/main/res/values/strings.xml
  5. 10
      src/common/settings.h
  6. 39
      src/video_core/fence_manager.h
  7. 25
      src/video_core/renderer_vulkan/vk_master_semaphore.cpp

1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt

@ -23,6 +23,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"), RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"),
RENDERER_FORCE_MAX_CLOCK("force_max_clock"), RENDERER_FORCE_MAX_CLOCK("force_max_clock"),
RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"), RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"),
RENDERER_EARLY_RELEASE_FENCES("early_release_fences"),
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"), RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
ENABLE_BUFFER_HISTORY("enable_buffer_history"), ENABLE_BUFFER_HISTORY("enable_buffer_history"),
SYNC_MEMORY_OPERATIONS("sync_memory_operations"), SYNC_MEMORY_OPERATIONS("sync_memory_operations"),

7
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt

@ -679,6 +679,13 @@ abstract class SettingsItem(
descriptionId = R.string.renderer_asynchronous_shaders_description descriptionId = R.string.renderer_asynchronous_shaders_description
) )
) )
put(
SwitchSetting(
BooleanSetting.RENDERER_EARLY_RELEASE_FENCES,
titleId = R.string.renderer_early_release_fences,
descriptionId = R.string.renderer_early_release_fences_description
)
)
put( put(
SingleChoiceSetting( SingleChoiceSetting(
IntSetting.FAST_GPU_TIME, IntSetting.FAST_GPU_TIME,

1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt

@ -285,6 +285,7 @@ class SettingsFragmentPresenter(
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key) add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
add(BooleanSetting.FIX_BLOOM_EFFECTS.key) add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key) add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
add(BooleanSetting.RENDERER_EARLY_RELEASE_FENCES.key)
add(SettingsItem.GPU_UNSWIZZLE_COMBINED) add(SettingsItem.GPU_UNSWIZZLE_COMBINED)
add(HeaderSetting(R.string.extensions)) add(HeaderSetting(R.string.extensions))

2
src/android/app/src/main/res/values/strings.xml

@ -510,6 +510,8 @@
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno 700), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string> <string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno 700), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
<string name="renderer_asynchronous_shaders">Use asynchronous shaders</string> <string name="renderer_asynchronous_shaders">Use asynchronous shaders</string>
<string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches.</string> <string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches.</string>
<string name="renderer_early_release_fences">Release Fences Early</string>
<string name="renderer_early_release_fences_description">Fixes crashes and freezes in some games, may cause issues with Unreal Engine games.</string>
<string name="gpu_unswizzle_settings">GPU Unswizzle Settings</string> <string name="gpu_unswizzle_settings">GPU Unswizzle Settings</string>
<string name="gpu_unswizzle_settings_description">Configure GPU-based texture unswizzling parameters or disable it entirely. Adjust these settings to balance performance and texture loading quality.</string> <string name="gpu_unswizzle_settings_description">Configure GPU-based texture unswizzling parameters or disable it entirely. Adjust these settings to balance performance and texture loading quality.</string>
<string name="gpu_unswizzle_enable">Enable GPU Unswizzle</string> <string name="gpu_unswizzle_enable">Enable GPU Unswizzle</string>

10
src/common/settings.h

@ -546,6 +546,16 @@ struct Values {
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
Category::RendererHacks}; Category::RendererHacks};
#ifdef ANDROID
SwitchableSetting<bool> early_release_fences{linkage,
false,
"early_release_fences",
Category::RendererAdvanced,
Specialization::Default,
true,
true};
#endif
SwitchableSetting<GpuUnswizzleSize> gpu_unswizzle_texture_size{linkage, SwitchableSetting<GpuUnswizzleSize> gpu_unswizzle_texture_size{linkage,
GpuUnswizzleSize::Large, GpuUnswizzleSize::Large,
"gpu_unswizzle_texture_size", "gpu_unswizzle_texture_size",

39
src/video_core/fence_manager.h

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -72,32 +72,49 @@ public:
} }
void SignalFence(std::function<void()>&& func) { void SignalFence(std::function<void()>&& func) {
if constexpr (!can_async_check) {
TryReleasePendingFences<false>();
}
const bool delay_fence = Settings::IsGPULevelHigh();
const bool should_flush = ShouldFlush(); const bool should_flush = ShouldFlush();
const bool delay_fence = Settings::IsGPULevelHigh() || (Settings::IsGPULevelMedium() && should_flush);
#ifdef __ANDROID__
const bool early_release_fences = Settings::values.early_release_fences.GetValue();
#else
constexpr bool early_release_fences = false;
#endif
constexpr bool async_supported = can_async_check;
CommitAsyncFlushes(); CommitAsyncFlushes();
TFence new_fence = CreateFence(!should_flush); TFence new_fence = CreateFence(!should_flush);
if constexpr (can_async_check) {
guard.lock();
std::unique_lock lock(guard, std::defer_lock);
const bool needs_lock = (early_release_fences && delay_fence) ||
(!early_release_fences && async_supported);
if (needs_lock) {
lock.lock();
}
if (!delay_fence) {
if (early_release_fences) {
TryReleasePendingFences<false>();
} else if constexpr (!async_supported) {
TryReleasePendingFences<false>();
}
} }
if (delay_fence) { if (delay_fence) {
uncommitted_operations.emplace_back(std::move(func)); uncommitted_operations.emplace_back(std::move(func));
} }
if (!uncommitted_operations.empty()) {
pending_operations.emplace_back(std::move(uncommitted_operations)); pending_operations.emplace_back(std::move(uncommitted_operations));
uncommitted_operations.clear();
}
QueueFence(new_fence); QueueFence(new_fence);
if (!delay_fence) { if (!delay_fence) {
func(); func();
} }
fences.push(std::move(new_fence)); fences.push(std::move(new_fence));
if (needs_lock) {
lock.unlock();
cv.notify_all();
}
if (should_flush) { if (should_flush) {
rasterizer.FlushCommands(); rasterizer.FlushCommands();
} }
if constexpr (can_async_check) {
guard.unlock();
cv.notify_all();
}
rasterizer.InvalidateGPUCache(); rasterizer.InvalidateGPUCache();
} }

25
src/video_core/renderer_vulkan/vk_master_semaphore.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -80,9 +80,7 @@ void MasterSemaphore::Wait(u64 tick) {
if (!semaphore) { if (!semaphore) {
// If we don't support timeline semaphores, wait for the value normally // If we don't support timeline semaphores, wait for the value normally
std::unique_lock lk{free_mutex}; std::unique_lock lk{free_mutex};
free_cv.wait(lk, [&] {
return gpu_tick.load(std::memory_order_acquire) >= tick;
});
free_cv.wait(lk, [&] { return gpu_tick.load(std::memory_order_relaxed) >= tick; });
return; return;
} }
@ -218,30 +216,13 @@ void MasterSemaphore::WaitThread(std::stop_token token) {
wait_queue.pop(); wait_queue.pop();
} }
#ifdef ANDROID
VkResult status;
do {
status = fence.GetStatus();
if (status == VK_NOT_READY) {
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
} while (status == VK_NOT_READY);
if (status == VK_SUCCESS) {
fence.Reset();
} else {
vk::Check(status);
continue;
}
#else
fence.Wait(); fence.Wait();
fence.Reset(); fence.Reset();
#endif
{ {
std::scoped_lock lock{free_mutex}; std::scoped_lock lock{free_mutex};
free_queue.push_front(std::move(fence)); free_queue.push_front(std::move(fence));
gpu_tick.store(host_tick, std::memory_order_release);
gpu_tick.store(host_tick);
} }
free_cv.notify_all(); free_cv.notify_all();
} }

Loading…
Cancel
Save