diff options
| author | MaranBr <maranbr@outlook.com> | 2025-08-20 00:21:25 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2025-08-20 00:21:25 +0200 |
| commit | 7bfa2404a63d26a0da657e20b11c5c72cbba27ef (patch) | |
| tree | 8fb8d33d130b8e6f640227a2a23695b2c85d77c3 /src/video_core/dma_pusher.cpp | |
| parent | bf7f3e25fca8b73178622dfe2aaaae45f845a923 (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.cpp | 65 |
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); } |
