aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/dma_pusher.cpp
diff options
context:
space:
mode:
authorMaranBr <maranbr@outlook.com>2025-08-20 00:21:25 +0200
committercrueter <crueter@eden-emu.dev>2025-08-20 00:21:25 +0200
commit7bfa2404a63d26a0da657e20b11c5c72cbba27ef (patch)
tree8fb8d33d130b8e6f640227a2a23695b2c85d77c3 /src/video_core/dma_pusher.cpp
parentbf7f3e25fca8b73178622dfe2aaaae45f845a923 (diff)
[video_core] Improve DMA logic and add an option to sync memory operations (#276)
This improves DMA logic and add an option to sync memory operations. Thanks to Higgs for the new DMA logic. Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com> Co-authored-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/276 Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: MaranBr <maranbr@outlook.com> Co-committed-by: MaranBr <maranbr@outlook.com>
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
-rw-r--r--src/video_core/dma_pusher.cpp65
1 files changed, 38 insertions, 27 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index c2c07deb9b..8ea4cbd43a 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -1,10 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "common/cityhash.h"
#include "common/settings.h"
#include "core/core.h"
#include "video_core/dma_pusher.h"
@@ -12,26 +11,22 @@
#include "video_core/gpu.h"
#include "video_core/guest_memory.h"
#include "video_core/memory_manager.h"
+#include "video_core/rasterizer_interface.h"
namespace Tegra {
constexpr u32 MacroRegistersStart = 0xE00;
-constexpr u32 ComputeInline = 0x6D;
-//start on PR#76 of Eden this is a unused variable in android (need to investigate)
-
-// Dummy function that uses ComputeInline
-constexpr void UseComputeInline() {
- static_cast<void>(ComputeInline); // Suppress unused variable error
-}
+[[maybe_unused]] constexpr u32 ComputeInline = 0x6D;
DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_,
Control::ChannelState& channel_state_)
: gpu{gpu_}, system{system_}, memory_manager{memory_manager_}, puller{gpu_, memory_manager_,
- *this, channel_state_} {}
+ *this, channel_state_}, signal_sync{false}, synced{false} {}
DmaPusher::~DmaPusher() = default;
void DmaPusher::DispatchCalls() {
+
dma_pushbuffer_subindex = 0;
dma_state.is_last_call = true;
@@ -69,14 +64,16 @@ bool DmaPusher::Step() {
} else {
const CommandListHeader command_list_header{
command_list.command_lists[dma_pushbuffer_subindex++]};
- dma_state.dma_get = command_list_header.addr;
- if (dma_pushbuffer_subindex >= command_list.command_lists.size()) {
- // We've gone through the current list, remove it from the queue
- dma_pushbuffer.pop();
- dma_pushbuffer_subindex = 0;
+ if (signal_sync) {
+ std::unique_lock lk(sync_mutex);
+ sync_cv.wait(lk, [this]() { return synced; });
+ signal_sync = false;
+ synced = false;
}
+ dma_state.dma_get = command_list_header.addr;
+
if (command_list_header.size == 0) {
return true;
}
@@ -88,6 +85,7 @@ bool DmaPusher::Step() {
dma_state.dma_get, command_list_header.size * sizeof(u32));
}
}
+
const auto safe_process = [&] {
Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader,
Tegra::Memory::GuestMemoryFlags::SafeRead>
@@ -95,6 +93,7 @@ bool DmaPusher::Step() {
&command_headers);
ProcessCommands(headers);
};
+
const auto unsafe_process = [&] {
Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader,
Tegra::Memory::GuestMemoryFlags::UnsafeRead>
@@ -103,22 +102,33 @@ bool DmaPusher::Step() {
ProcessCommands(headers);
};
- // Only use unsafe reads for non-compute macro operations
- if (Settings::IsGPULevelHigh()) {
- const bool is_compute = (subchannel_type[dma_state.subchannel] ==
- Engines::EngineTypes::KeplerCompute);
-
- if (dma_state.method >= MacroRegistersStart && !is_compute) {
+ if (Settings::IsGPULevelExtreme()) {
+ safe_process();
+ } else if (Settings::IsGPULevelHigh()) {
+ if (dma_state.method >= MacroRegistersStart) {
unsafe_process();
- return true;
+ } else {
+ safe_process();
}
+ } else {
+ unsafe_process();
+ }
- // Always use safe reads for compute operations
- safe_process();
- return true;
+ if (dma_pushbuffer_subindex >= command_list.command_lists.size()) {
+ // We've gone through the current list, remove it from the queue
+ dma_pushbuffer.pop();
+ dma_pushbuffer_subindex = 0;
+ } else if (command_list.command_lists[dma_pushbuffer_subindex].sync && Settings::values.sync_memory_operations.GetValue()) {
+ signal_sync = true;
}
- unsafe_process();
+ if (signal_sync) {
+ rasterizer->SignalFence([this]() {
+ std::scoped_lock lk(sync_mutex);
+ synced = true;
+ sync_cv.notify_all();
+ });
+ }
}
return true;
}
@@ -226,7 +236,8 @@ void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) const {
}
}
-void DmaPusher::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) {
+void DmaPusher::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
+ rasterizer = rasterizer_;
puller.BindRasterizer(rasterizer);
}