mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-13 11:28:56 +02:00
[video_core] Rework GPU Accuracy levels and remove Early Release Fences toggle (#3129)
The GPU Accuracy level is now divided into Performance, Balanced and Accurate. 1. Performance prioritizes speed at all costs. It's faster, but it can be unstable and may have some bugs (which is expected). 2. Balanced maintains excellent performance and is safer against bugs and shader corruption. 3. Accurate is the most precise and the most expensive in terms of hardware. Only a few games still need this level to work properly. The Release Early Fences toggle has also been removed by @PavelBARABANOV, as it's not needed anymore. Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3129 Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com> Reviewed-by: Maufeat <sahyno1996@gmail.com> Co-authored-by: MaranBr <maranbr@outlook.com> Co-committed-by: MaranBr <maranbr@outlook.com>
This commit is contained in:
parent
7157d5167e
commit
9da38715fe
41 changed files with 76 additions and 266 deletions
|
|
@ -103,7 +103,7 @@ bool DmaPusher::Step() {
|
|||
ProcessCommands(headers);
|
||||
};
|
||||
|
||||
const bool use_safe = Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe();
|
||||
const bool use_safe = Settings::IsDMALevelDefault() ? (Settings::IsGPULevelMedium() || Settings::IsGPULevelHigh()) : Settings::IsDMALevelSafe();
|
||||
|
||||
if (use_safe) {
|
||||
safe_process();
|
||||
|
|
|
|||
|
|
@ -72,66 +72,33 @@ public:
|
|||
}
|
||||
|
||||
void SignalFence(std::function<void()>&& func) {
|
||||
const bool delay_fence = Settings::IsGPULevelHigh();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
const bool use_optimized = Settings::values.early_release_fences.GetValue();
|
||||
#else
|
||||
constexpr bool use_optimized = false;
|
||||
#endif
|
||||
|
||||
if constexpr (!can_async_check) {
|
||||
TryReleasePendingFences<false>();
|
||||
}
|
||||
const bool should_flush = ShouldFlush();
|
||||
CommitAsyncFlushes();
|
||||
TFence new_fence = CreateFence(!should_flush);
|
||||
|
||||
if (use_optimized) {
|
||||
if (!delay_fence) {
|
||||
TryReleasePendingFences<false>();
|
||||
}
|
||||
|
||||
if (delay_fence) {
|
||||
guard.lock();
|
||||
uncommitted_operations.emplace_back(std::move(func));
|
||||
}
|
||||
} else {
|
||||
if constexpr (!can_async_check) {
|
||||
TryReleasePendingFences<false>();
|
||||
}
|
||||
|
||||
if constexpr (can_async_check) {
|
||||
guard.lock();
|
||||
}
|
||||
|
||||
if (delay_fence) {
|
||||
uncommitted_operations.emplace_back(std::move(func));
|
||||
}
|
||||
if constexpr (can_async_check) {
|
||||
guard.lock();
|
||||
}
|
||||
|
||||
pending_operations.emplace_back(std::move(uncommitted_operations));
|
||||
QueueFence(new_fence);
|
||||
|
||||
if (!delay_fence) {
|
||||
if (Settings::IsGPULevelLow() || (Settings::IsGPULevelMedium() && !should_flush)) {
|
||||
func();
|
||||
} else {
|
||||
uncommitted_operations.emplace_back(std::move(func));
|
||||
}
|
||||
|
||||
if (!uncommitted_operations.empty()) {
|
||||
pending_operations.emplace_back(std::move(uncommitted_operations));
|
||||
uncommitted_operations.clear();
|
||||
}
|
||||
QueueFence(new_fence);
|
||||
fences.push(std::move(new_fence));
|
||||
|
||||
if (should_flush) {
|
||||
rasterizer.FlushCommands();
|
||||
}
|
||||
|
||||
if (use_optimized) {
|
||||
if (delay_fence) {
|
||||
guard.unlock();
|
||||
cv.notify_all();
|
||||
}
|
||||
} else {
|
||||
if constexpr (can_async_check) {
|
||||
guard.unlock();
|
||||
cv.notify_all();
|
||||
}
|
||||
if constexpr (can_async_check) {
|
||||
guard.unlock();
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
rasterizer.InvalidateGPUCache();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,15 +79,8 @@ void ThreadManager::FlushRegion(DAddr addr, u64 size) {
|
|||
if (!is_async) {
|
||||
// Always flush with synchronous GPU mode
|
||||
PushCommand(FlushRegionCommand(addr, size));
|
||||
return;
|
||||
}
|
||||
if (!Settings::IsGPULevelExtreme()) {
|
||||
return;
|
||||
}
|
||||
auto& gpu = system.GPU();
|
||||
u64 fence = gpu.RequestFlush(addr, size);
|
||||
TickGPU();
|
||||
gpu.WaitForSyncOperation(fence);
|
||||
return;
|
||||
}
|
||||
|
||||
void ThreadManager::TickGPU() {
|
||||
|
|
|
|||
|
|
@ -629,9 +629,6 @@ void RasterizerOpenGL::ReleaseFences(bool force) {
|
|||
|
||||
void RasterizerOpenGL::FlushAndInvalidateRegion(DAddr addr, u64 size,
|
||||
VideoCommon::CacheType which) {
|
||||
if (Settings::IsGPULevelExtreme()) {
|
||||
FlushRegion(addr, size, which);
|
||||
}
|
||||
InvalidateRegion(addr, size, which);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,9 @@ void MasterSemaphore::Wait(u64 tick) {
|
|||
if (!semaphore) {
|
||||
// If we don't support timeline semaphores, wait for the value normally
|
||||
std::unique_lock lk{free_mutex};
|
||||
free_cv.wait(lk, [&] { return gpu_tick.load(std::memory_order_relaxed) >= tick; });
|
||||
free_cv.wait(lk, [&] {
|
||||
return gpu_tick.load(std::memory_order_acquire) >= tick;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -216,15 +218,32 @@ void MasterSemaphore::WaitThread(std::stop_token token) {
|
|||
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.Reset();
|
||||
#endif
|
||||
|
||||
{
|
||||
std::scoped_lock lock{free_mutex};
|
||||
free_queue.push_front(std::move(fence));
|
||||
gpu_tick.store(host_tick);
|
||||
gpu_tick.store(host_tick, std::memory_order_release);
|
||||
}
|
||||
free_cv.notify_one();
|
||||
free_cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1415,14 +1415,10 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
|
|||
return false;
|
||||
}
|
||||
|
||||
const bool is_gpu_high = Settings::IsGPULevelHigh();
|
||||
if (!is_gpu_high && impl->device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto driver_id = impl->device.GetDriverID();
|
||||
if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
|
||||
driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
|
||||
const bool is_gpu_high = Settings::IsGPULevelHigh();
|
||||
|
||||
if ((!is_gpu_high && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) || driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1443,7 +1439,6 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
|
|||
}
|
||||
|
||||
if (!is_in_bc[0] && !is_in_bc[1]) {
|
||||
// Both queries are in query cache, it's best to just flush.
|
||||
return true;
|
||||
}
|
||||
HostConditionalRenderingCompareBCImpl(object_1.address, equal_check);
|
||||
|
|
|
|||
|
|
@ -730,9 +730,6 @@ void RasterizerVulkan::ReleaseFences(bool force) {
|
|||
|
||||
void RasterizerVulkan::FlushAndInvalidateRegion(DAddr addr, u64 size,
|
||||
VideoCommon::CacheType which) {
|
||||
if (Settings::IsGPULevelExtreme()) {
|
||||
FlushRegion(addr, size, which);
|
||||
}
|
||||
InvalidateRegion(addr, size, which);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue