summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/dma_pusher.cpp104
-rw-r--r--src/video_core/dma_pusher.h2
2 files changed, 58 insertions, 48 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index eb9bf1878..654e4d9aa 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -38,59 +38,67 @@ bool DmaPusher::Step() {
const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
ASSERT_MSG(address, "Invalid GPU address");
- const CommandHeader command_header{Memory::Read32(*address)};
+ GPUVAddr size = dma_put - dma_get;
+ ASSERT_MSG(size % sizeof(CommandHeader) == 0, "Invalid aligned GPU addresses");
+ command_headers.resize(size / sizeof(CommandHeader));
+
+ Memory::ReadBlock(*address, command_headers.data(), size);
+
+ for (const CommandHeader& command_header : command_headers) {
+
+ // now, see if we're in the middle of a command
+ if (dma_state.length_pending) {
+ // Second word of long non-inc methods command - method count
+ dma_state.length_pending = 0;
+ dma_state.method_count = command_header.method_count_;
+ } else if (dma_state.method_count) {
+ // Data word of methods command
+ CallMethod(command_header.argument);
+
+ if (!dma_state.non_incrementing) {
+ dma_state.method++;
+ }
+
+ if (dma_increment_once) {
+ dma_state.non_incrementing = true;
+ }
+
+ dma_state.method_count--;
+ } else {
+ // No command active - this is the first word of a new one
+ switch (command_header.mode) {
+ case SubmissionMode::Increasing:
+ SetState(command_header);
+ dma_state.non_incrementing = false;
+ dma_increment_once = false;
+ break;
+ case SubmissionMode::NonIncreasing:
+ SetState(command_header);
+ dma_state.non_incrementing = true;
+ dma_increment_once = false;
+ break;
+ case SubmissionMode::Inline:
+ dma_state.method = command_header.method;
+ dma_state.subchannel = command_header.subchannel;
+ CallMethod(command_header.arg_count);
+ dma_state.non_incrementing = true;
+ dma_increment_once = false;
+ break;
+ case SubmissionMode::IncreaseOnce:
+ SetState(command_header);
+ dma_state.non_incrementing = false;
+ dma_increment_once = true;
+ break;
+ }
+ }
+ }
- dma_get += sizeof(u32);
+ dma_get = dma_put;
if (!non_main) {
+ // TODO (degasus): This is dead code, as dma_mget is never read.
dma_mget = dma_get;
}
-
- // now, see if we're in the middle of a command
- if (dma_state.length_pending) {
- // Second word of long non-inc methods command - method count
- dma_state.length_pending = 0;
- dma_state.method_count = command_header.method_count_;
- } else if (dma_state.method_count) {
- // Data word of methods command
- CallMethod(command_header.argument);
-
- if (!dma_state.non_incrementing) {
- dma_state.method++;
- }
-
- if (dma_increment_once) {
- dma_state.non_incrementing = true;
- }
-
- dma_state.method_count--;
- } else {
- // No command active - this is the first word of a new one
- switch (command_header.mode) {
- case SubmissionMode::Increasing:
- SetState(command_header);
- dma_state.non_incrementing = false;
- dma_increment_once = false;
- break;
- case SubmissionMode::NonIncreasing:
- SetState(command_header);
- dma_state.non_incrementing = true;
- dma_increment_once = false;
- break;
- case SubmissionMode::Inline:
- dma_state.method = command_header.method;
- dma_state.subchannel = command_header.subchannel;
- CallMethod(command_header.arg_count);
- dma_state.non_incrementing = true;
- dma_increment_once = false;
- break;
- case SubmissionMode::IncreaseOnce:
- SetState(command_header);
- dma_state.non_incrementing = false;
- dma_increment_once = true;
- break;
- }
- }
} else if (ib_enable && !dma_pushbuffer.empty()) {
// Current pushbuffer empty, but we have more IB entries to read
const CommandList& command_list{dma_pushbuffer.front()};
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index 1097e5c49..14b23b1d7 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -75,6 +75,8 @@ private:
GPU& gpu;
+ std::vector<CommandHeader> command_headers; ///< Buffer for list of commands fetched at once
+
std::queue<CommandList> dma_pushbuffer; ///< Queue of command lists to be processed
std::size_t dma_pushbuffer_subindex{}; ///< Index within a command list within the pushbuffer