diff options
author | Markus Wick <markus@selfnet.de> | 2019-02-19 10:26:58 +0100 |
---|---|---|
committer | Markus Wick <markus@selfnet.de> | 2019-02-19 10:28:42 +0100 |
commit | 6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116 (patch) | |
tree | f13452d784190c570118f6bb22dec6ea91c6012a /src/video_core/dma_pusher.cpp | |
parent | video_core/dma_pusher: The full list of headers at once. (diff) | |
download | yuzu-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.cpp | 155 |
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; |