mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-28 15:39:00 +02:00
[fence_manager] fence-only non-stubbed forced delay (up to 70% less delays than gpu>fast)
This commit is contained in:
parent
af9a5af3c0
commit
4d2df72067
9 changed files with 54 additions and 33 deletions
|
|
@ -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
|
||||||
|
|
@ -71,14 +71,15 @@ public:
|
||||||
uncommitted_operations.emplace_back(std::move(func));
|
uncommitted_operations.emplace_back(std::move(func));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalFence(std::function<void()>&& func) {
|
void SignalFence(std::function<void()>&& func, bool force_delay = false) {
|
||||||
if constexpr (!can_async_check) {
|
if constexpr (!can_async_check) {
|
||||||
TryReleasePendingFences<false>();
|
TryReleasePendingFences<false>();
|
||||||
}
|
}
|
||||||
const bool should_flush = ShouldFlush();
|
const bool should_flush = ShouldFlush();
|
||||||
const bool delay_fence = Settings::IsGPULevelHigh() || (Settings::IsGPULevelMedium() && should_flush);
|
const bool delay_fence = force_delay || Settings::IsGPULevelHigh() ||
|
||||||
|
(Settings::IsGPULevelMedium() && should_flush);
|
||||||
CommitAsyncFlushes();
|
CommitAsyncFlushes();
|
||||||
TFence new_fence = CreateFence(!should_flush);
|
TFence new_fence = CreateFence(!should_flush && !force_delay);
|
||||||
if constexpr (can_async_check) {
|
if constexpr (can_async_check) {
|
||||||
guard.lock();
|
guard.lock();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -246,11 +246,24 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DAddr cpu_addr = *cpu_addr_opt;
|
DAddr cpu_addr = *cpu_addr_opt;
|
||||||
|
u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr);
|
||||||
|
if (is_fence) {
|
||||||
|
u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
|
||||||
|
std::function<void()> operation([this, pointer, pointer_timestamp, payload, has_timestamp] {
|
||||||
|
if (has_timestamp) {
|
||||||
|
const u64 timestamp = impl->gpu.GetTicks();
|
||||||
|
const u64 value = static_cast<u64>(payload);
|
||||||
|
std::memcpy(pointer_timestamp, ×tamp, sizeof(timestamp));
|
||||||
|
std::memcpy(pointer, &value, sizeof(value));
|
||||||
|
} else {
|
||||||
|
std::memcpy(pointer, &payload, sizeof(payload));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
impl->rasterizer.SignalFence(std::move(operation), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport);
|
const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport);
|
||||||
auto* query = streamer->GetQuery(new_query_id);
|
auto* query = streamer->GetQuery(new_query_id);
|
||||||
if (is_fence) {
|
|
||||||
query->flags |= QueryFlagBits::IsFence;
|
|
||||||
}
|
|
||||||
QueryLocation query_location{};
|
QueryLocation query_location{};
|
||||||
query_location.stream_id.Assign(static_cast<u32>(streamer_id));
|
query_location.stream_id.Assign(static_cast<u32>(streamer_id));
|
||||||
query_location.query_id.Assign(static_cast<u32>(new_query_id));
|
query_location.query_id.Assign(static_cast<u32>(new_query_id));
|
||||||
|
|
@ -258,9 +271,8 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
|
||||||
return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS,
|
return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS,
|
||||||
static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK));
|
static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK));
|
||||||
};
|
};
|
||||||
u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr);
|
|
||||||
u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
|
u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
|
||||||
bool is_synced = !Settings::IsGPULevelHigh() && is_fence;
|
bool is_synced = false;
|
||||||
std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
|
std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
|
||||||
pointer, pointer_timestamp] {
|
pointer, pointer_timestamp] {
|
||||||
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
|
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
|
||||||
|
|
@ -291,23 +303,19 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
|
||||||
impl->pending_unregister.push_back(query_location);
|
impl->pending_unregister.push_back(query_location);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (is_fence) {
|
if (!Settings::IsGPULevelHigh() && counter_type == QueryType::Payload) {
|
||||||
impl->rasterizer.SignalFence(std::move(operation));
|
if (has_timestamp) {
|
||||||
} else {
|
u64 timestamp = impl->gpu.GetTicks();
|
||||||
if (!Settings::IsGPULevelHigh() && counter_type == QueryType::Payload) {
|
u64 value = static_cast<u64>(payload);
|
||||||
if (has_timestamp) {
|
std::memcpy(pointer_timestamp, ×tamp, sizeof(timestamp));
|
||||||
u64 timestamp = impl->gpu.GetTicks();
|
std::memcpy(pointer, &value, sizeof(value));
|
||||||
u64 value = static_cast<u64>(payload);
|
} else {
|
||||||
std::memcpy(pointer_timestamp, ×tamp, sizeof(timestamp));
|
std::memcpy(pointer, &payload, sizeof(payload));
|
||||||
std::memcpy(pointer, &value, sizeof(value));
|
|
||||||
} else {
|
|
||||||
std::memcpy(pointer, &payload, sizeof(payload));
|
|
||||||
}
|
|
||||||
streamer->Free(new_query_id);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
impl->rasterizer.SyncOperation(std::move(operation));
|
streamer->Free(new_query_id);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
impl->rasterizer.SyncOperation(std::move(operation));
|
||||||
if (is_synced) {
|
if (is_synced) {
|
||||||
streamer->Free(new_query_id);
|
streamer->Free(new_query_id);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -69,7 +72,7 @@ public:
|
||||||
virtual void DisableGraphicsUniformBuffer(size_t stage, u32 index) = 0;
|
virtual void DisableGraphicsUniformBuffer(size_t stage, u32 index) = 0;
|
||||||
|
|
||||||
/// Signal a GPU based semaphore as a fence
|
/// Signal a GPU based semaphore as a fence
|
||||||
virtual void SignalFence(std::function<void()>&& func) = 0;
|
virtual void SignalFence(std::function<void()>&& func, bool force_delay = false) = 0;
|
||||||
|
|
||||||
/// Send an operation to be done after a certain amount of flushes.
|
/// Send an operation to be done after a certain amount of flushes.
|
||||||
virtual void SyncOperation(std::function<void()>&& func) = 0;
|
virtual void SyncOperation(std::function<void()>&& func) = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -63,7 +66,7 @@ VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(PAddr addr, u64 s
|
||||||
void RasterizerNull::InvalidateGPUCache() {}
|
void RasterizerNull::InvalidateGPUCache() {}
|
||||||
void RasterizerNull::UnmapMemory(DAddr addr, u64 size) {}
|
void RasterizerNull::UnmapMemory(DAddr addr, u64 size) {}
|
||||||
void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {}
|
void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {}
|
||||||
void RasterizerNull::SignalFence(std::function<void()>&& func) {
|
void RasterizerNull::SignalFence(std::function<void()>&& func, bool force_delay) {
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
void RasterizerNull::SyncOperation(std::function<void()>&& func) {
|
void RasterizerNull::SyncOperation(std::function<void()>&& func) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -59,7 +62,7 @@ public:
|
||||||
void InvalidateGPUCache() override;
|
void InvalidateGPUCache() override;
|
||||||
void UnmapMemory(DAddr addr, u64 size) override;
|
void UnmapMemory(DAddr addr, u64 size) override;
|
||||||
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
||||||
void SignalFence(std::function<void()>&& func) override;
|
void SignalFence(std::function<void()>&& func, bool force_delay = false) override;
|
||||||
void SyncOperation(std::function<void()>&& func) override;
|
void SyncOperation(std::function<void()>&& func) override;
|
||||||
void SignalSyncPoint(u32 value) override;
|
void SignalSyncPoint(u32 value) override;
|
||||||
void SignalReference() override;
|
void SignalReference() override;
|
||||||
|
|
|
||||||
|
|
@ -607,8 +607,8 @@ void RasterizerOpenGL::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SignalFence(std::function<void()>&& func) {
|
void RasterizerOpenGL::SignalFence(std::function<void()>&& func, bool force_delay) {
|
||||||
fence_manager.SignalFence(std::move(func));
|
fence_manager.SignalFence(std::move(func), force_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncOperation(std::function<void()>&& func) {
|
void RasterizerOpenGL::SyncOperation(std::function<void()>&& func) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -104,7 +107,7 @@ public:
|
||||||
void InvalidateGPUCache() override;
|
void InvalidateGPUCache() override;
|
||||||
void UnmapMemory(DAddr addr, u64 size) override;
|
void UnmapMemory(DAddr addr, u64 size) override;
|
||||||
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
||||||
void SignalFence(std::function<void()>&& func) override;
|
void SignalFence(std::function<void()>&& func, bool force_delay = false) override;
|
||||||
void SyncOperation(std::function<void()>&& func) override;
|
void SyncOperation(std::function<void()>&& func) override;
|
||||||
void SignalSyncPoint(u32 value) override;
|
void SignalSyncPoint(u32 value) override;
|
||||||
void SignalReference() override;
|
void SignalReference() override;
|
||||||
|
|
|
||||||
|
|
@ -774,8 +774,8 @@ void RasterizerVulkan::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SignalFence(std::function<void()>&& func) {
|
void RasterizerVulkan::SignalFence(std::function<void()>&& func, bool force_delay) {
|
||||||
fence_manager.SignalFence(std::move(func));
|
fence_manager.SignalFence(std::move(func), force_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SyncOperation(std::function<void()>&& func) {
|
void RasterizerVulkan::SyncOperation(std::function<void()>&& func) {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ public:
|
||||||
void InvalidateGPUCache() override;
|
void InvalidateGPUCache() override;
|
||||||
void UnmapMemory(DAddr addr, u64 size) override;
|
void UnmapMemory(DAddr addr, u64 size) override;
|
||||||
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
|
||||||
void SignalFence(std::function<void()>&& func) override;
|
void SignalFence(std::function<void()>&& func, bool force_delay = false) override;
|
||||||
void SyncOperation(std::function<void()>&& func) override;
|
void SyncOperation(std::function<void()>&& func) override;
|
||||||
void SignalSyncPoint(u32 value) override;
|
void SignalSyncPoint(u32 value) override;
|
||||||
void SignalReference() override;
|
void SignalReference() override;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue