[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: #276 Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: MaranBr <maranbr@outlook.com> Co-committed-by: MaranBr <maranbr@outlook.com>
This commit is contained in:
parent
bf7f3e25fc
commit
7bfa2404a6
31 changed files with 114 additions and 33 deletions
|
@ -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) {
|
||||
unsafe_process();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Always use safe reads for compute operations
|
||||
if (Settings::IsGPULevelExtreme()) {
|
||||
safe_process();
|
||||
return true;
|
||||
} else if (Settings::IsGPULevelHigh()) {
|
||||
if (dma_state.method >= MacroRegistersStart) {
|
||||
unsafe_process();
|
||||
} else {
|
||||
safe_process();
|
||||
}
|
||||
} else {
|
||||
unsafe_process();
|
||||
}
|
||||
|
||||
unsafe_process();
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue