aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/video_core/cdma_pusher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/cdma_pusher.cpp')
-rw-r--r--src/video_core/cdma_pusher.cpp194
1 files changed, 94 insertions, 100 deletions
diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp
index 28a2d2090..3bcf1b066 100644
--- a/src/video_core/cdma_pusher.cpp
+++ b/src/video_core/cdma_pusher.cpp
@@ -2,136 +2,130 @@
// SPDX-License-Identifier: MIT
#include <bit>
+
+#include "common/thread.h"
+#include "core/core.h"
#include "video_core/cdma_pusher.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/host1x/control.h"
#include "video_core/host1x/host1x.h"
#include "video_core/host1x/nvdec.h"
#include "video_core/host1x/nvdec_common.h"
-#include "video_core/host1x/sync_manager.h"
#include "video_core/host1x/vic.h"
#include "video_core/memory_manager.h"
namespace Tegra {
-CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_)
- : host1x{host1x_}, nvdec_processor(std::make_shared<Host1x::Nvdec>(host1x)),
- vic_processor(std::make_unique<Host1x::Vic>(host1x, nvdec_processor)),
- host1x_processor(std::make_unique<Host1x::Control>(host1x)),
- sync_manager(std::make_unique<Host1x::SyncptIncrManager>(host1x)) {}
+
+CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_, s32 id)
+ : host1x{host1x_}, memory_manager{host1x.GMMU()},
+ host_processor{std::make_unique<Host1x::Control>(host1x_)}, current_class{
+ static_cast<ChClassId>(id)} {
+ thread = std::jthread([this](std::stop_token stop_token) { ProcessEntries(stop_token); });
+}
CDmaPusher::~CDmaPusher() = default;
-void CDmaPusher::ProcessEntries(ChCommandHeaderList&& entries) {
- for (const auto& value : entries) {
- if (mask != 0) {
- const auto lbs = static_cast<u32>(std::countr_zero(mask));
- mask &= ~(1U << lbs);
- ExecuteCommand(offset + lbs, value.raw);
- continue;
- } else if (count != 0) {
- --count;
- ExecuteCommand(offset, value.raw);
- if (incrementing) {
- ++offset;
+void CDmaPusher::ProcessEntries(std::stop_token stop_token) {
+ Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
+ ChCommandHeaderList command_list{host1x.System().ApplicationMemory(), 0, 0};
+ u32 count{};
+ u32 method_offset{};
+ u32 mask{};
+ bool incrementing{};
+
+ while (!stop_token.stop_requested()) {
+ {
+ std::unique_lock l{command_mutex};
+ Common::CondvarWait(command_cv, l, stop_token,
+ [this]() { return command_lists.size() > 0; });
+ if (stop_token.stop_requested()) {
+ return;
}
- continue;
- }
- const auto mode = value.submission_mode.Value();
- switch (mode) {
- case ChSubmissionMode::SetClass: {
- mask = value.value & 0x3f;
- offset = value.method_offset;
- current_class = static_cast<ChClassId>((value.value >> 6) & 0x3ff);
- break;
- }
- case ChSubmissionMode::Incrementing:
- case ChSubmissionMode::NonIncrementing:
- count = value.value;
- offset = value.method_offset;
- incrementing = mode == ChSubmissionMode::Incrementing;
- break;
- case ChSubmissionMode::Mask:
- mask = value.value;
- offset = value.method_offset;
- break;
- case ChSubmissionMode::Immediate: {
- const u32 data = value.value & 0xfff;
- offset = value.method_offset;
- ExecuteCommand(offset, data);
- break;
+
+ command_list = std::move(command_lists.front());
+ command_lists.pop_front();
}
- default:
- UNIMPLEMENTED_MSG("ChSubmission mode {} is not implemented!", static_cast<u32>(mode));
- break;
+
+ size_t i = 0;
+ for (const auto value : command_list) {
+ i++;
+ if (mask != 0) {
+ const auto lbs = static_cast<u32>(std::countr_zero(mask));
+ mask &= ~(1U << lbs);
+ ExecuteCommand(method_offset + lbs, value.raw);
+ continue;
+ } else if (count != 0) {
+ --count;
+ ExecuteCommand(method_offset, value.raw);
+ if (incrementing) {
+ ++method_offset;
+ }
+ continue;
+ }
+ const auto mode = value.submission_mode.Value();
+ switch (mode) {
+ case ChSubmissionMode::SetClass: {
+ mask = value.value & 0x3f;
+ method_offset = value.method_offset;
+ current_class = static_cast<ChClassId>((value.value >> 6) & 0x3ff);
+ break;
+ }
+ case ChSubmissionMode::Incrementing:
+ case ChSubmissionMode::NonIncrementing:
+ count = value.value;
+ method_offset = value.method_offset;
+ incrementing = mode == ChSubmissionMode::Incrementing;
+ break;
+ case ChSubmissionMode::Mask:
+ mask = value.value;
+ method_offset = value.method_offset;
+ break;
+ case ChSubmissionMode::Immediate: {
+ const u32 data = value.value & 0xfff;
+ method_offset = value.method_offset;
+ ExecuteCommand(method_offset, data);
+ break;
+ }
+ default:
+ LOG_ERROR(HW_GPU, "Bad command at index {} (bytes 0x{:X}), buffer size {}", i - 1,
+ (i - 1) * sizeof(u32), command_list.size());
+ UNIMPLEMENTED_MSG("ChSubmission mode {} is not implemented!",
+ static_cast<u32>(mode));
+ break;
+ }
}
}
}
-void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
+void CDmaPusher::ExecuteCommand(u32 method, u32 arg) {
switch (current_class) {
- case ChClassId::NvDec:
- ThiStateWrite(nvdec_thi_state, offset, data);
- switch (static_cast<ThiMethod>(offset)) {
- case ThiMethod::IncSyncpt: {
- LOG_DEBUG(Service_NVDRV, "NVDEC Class IncSyncpt Method");
- const auto syncpoint_id = static_cast<u32>(data & 0xFF);
- const auto cond = static_cast<u32>((data >> 8) & 0xFF);
- if (cond == 0) {
- sync_manager->Increment(syncpoint_id);
- } else {
- sync_manager->SignalDone(
- sync_manager->IncrementWhenDone(static_cast<u32>(current_class), syncpoint_id));
- }
- break;
- }
- case ThiMethod::SetMethod1:
- LOG_DEBUG(Service_NVDRV, "NVDEC method 0x{:X}",
- static_cast<u32>(nvdec_thi_state.method_0));
- nvdec_processor->ProcessMethod(nvdec_thi_state.method_0, data);
- break;
- default:
- break;
- }
+ case ChClassId::Control:
+ LOG_TRACE(Service_NVDRV, "Class {} method 0x{:X} arg 0x{:X}",
+ static_cast<u32>(current_class), method, arg);
+ host_processor->ProcessMethod(static_cast<Host1x::Control::Method>(method), arg);
break;
- case ChClassId::GraphicsVic:
- ThiStateWrite(vic_thi_state, static_cast<u32>(state_offset), {data});
- switch (static_cast<ThiMethod>(state_offset)) {
+ default:
+ thi_regs.reg_array[method] = arg;
+ switch (static_cast<ThiMethod>(method)) {
case ThiMethod::IncSyncpt: {
- LOG_DEBUG(Service_NVDRV, "VIC Class IncSyncpt Method");
- const auto syncpoint_id = static_cast<u32>(data & 0xFF);
- const auto cond = static_cast<u32>((data >> 8) & 0xFF);
- if (cond == 0) {
- sync_manager->Increment(syncpoint_id);
- } else {
- sync_manager->SignalDone(
- sync_manager->IncrementWhenDone(static_cast<u32>(current_class), syncpoint_id));
- }
+ const auto syncpoint_id = static_cast<u32>(arg & 0xFF);
+ [[maybe_unused]] const auto cond = static_cast<u32>((arg >> 8) & 0xFF);
+ LOG_TRACE(Service_NVDRV, "Class {} IncSyncpt Method, syncpt {} cond {}",
+ static_cast<u32>(current_class), syncpoint_id, cond);
+ auto& syncpoint_manager = host1x.GetSyncpointManager();
+ syncpoint_manager.IncrementGuest(syncpoint_id);
+ syncpoint_manager.IncrementHost(syncpoint_id);
break;
}
case ThiMethod::SetMethod1:
- LOG_DEBUG(Service_NVDRV, "VIC method 0x{:X}, Args=({})",
- static_cast<u32>(vic_thi_state.method_0), data);
- vic_processor->ProcessMethod(static_cast<Host1x::Vic::Method>(vic_thi_state.method_0),
- data);
+ LOG_TRACE(Service_NVDRV, "Class {} method 0x{:X} arg 0x{:X}",
+ static_cast<u32>(current_class), static_cast<u32>(thi_regs.method_0), arg);
+ ProcessMethod(thi_regs.method_0, arg);
break;
default:
break;
}
- break;
- case ChClassId::Control:
- // This device is mainly for syncpoint synchronization
- LOG_DEBUG(Service_NVDRV, "Host1X Class Method");
- host1x_processor->ProcessMethod(static_cast<Host1x::Control::Method>(offset), data);
- break;
- default:
- UNIMPLEMENTED_MSG("Current class not implemented {:X}", static_cast<u32>(current_class));
- break;
}
}
-void CDmaPusher::ThiStateWrite(ThiRegisters& state, u32 state_offset, u32 argument) {
- u8* const offset_ptr = reinterpret_cast<u8*>(&state) + sizeof(u32) * state_offset;
- std::memcpy(offset_ptr, &argument, sizeof(u32));
-}
-
} // namespace Tegra