summaryrefslogtreecommitdiffstats
path: root/src/video_core/dma_pusher.cpp
diff options
context:
space:
mode:
authorMarkus Wick <markus@selfnet.de>2019-02-19 10:26:58 +0100
committerMarkus Wick <markus@selfnet.de>2019-02-19 10:28:42 +0100
commit6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116 (patch)
treef13452d784190c570118f6bb22dec6ea91c6012a /src/video_core/dma_pusher.cpp
parentvideo_core/dma_pusher: The full list of headers at once. (diff)
downloadyuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.gz
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.bz2
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.lz
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.xz
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.zst
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.zip
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
-rw-r--r--src/video_core/dma_pusher.cpp155
1 files changed, 77 insertions, 78 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 654e4d9aa..669541b4b 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -33,88 +33,87 @@ void DmaPusher::DispatchCalls() {
}
bool DmaPusher::Step() {
- if (dma_get != dma_put) {
- // Push buffer non-empty, read a word
- const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
- ASSERT_MSG(address, "Invalid GPU 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;
- }
+ if (!ib_enable || dma_pushbuffer.empty()) {
+ // pushbuffer empty and IB empty or nonexistent - nothing to do
+ return false;
+ }
+
+ const CommandList& command_list{dma_pushbuffer.front()};
+ const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]};
+ GPUVAddr dma_get = command_list_header.addr;
+ GPUVAddr dma_put = dma_get + command_list_header.size * sizeof(u32);
+ bool non_main = command_list_header.is_non_main;
+
+ if (dma_pushbuffer_subindex >= command_list.size()) {
+ // We've gone through the current list, remove it from the queue
+ dma_pushbuffer.pop();
+ dma_pushbuffer_subindex = 0;
+ }
+
+ if (command_list_header.size == 0) {
+ return true;
+ }
+
+ // Push buffer non-empty, read a word
+ const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
+ ASSERT_MSG(address, "Invalid GPU address");
+
+ command_headers.resize(command_list_header.size);
+
+ Memory::ReadBlock(*address, command_headers.data(), command_list_header.size * sizeof(u32));
+
+ 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++;
}
- }
- dma_get = dma_put;
+ if (dma_increment_once) {
+ dma_state.non_incrementing = true;
+ }
- if (!non_main) {
- // TODO (degasus): This is dead code, as dma_mget is never read.
- dma_mget = dma_get;
- }
- } 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()};
- const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]};
- dma_get = command_list_header.addr;
- dma_put = dma_get + command_list_header.size * sizeof(u32);
- non_main = command_list_header.is_non_main;
-
- if (dma_pushbuffer_subindex >= command_list.size()) {
- // We've gone through the current list, remove it from the queue
- dma_pushbuffer.pop();
- dma_pushbuffer_subindex = 0;
+ 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 {
- // Otherwise, pushbuffer empty and IB empty or nonexistent - nothing to do
- return {};
+ }
+
+ if (!non_main) {
+ // TODO (degasus): This is dead code, as dma_mget is never read.
+ dma_mget = dma_put;
}
return true;