diff options
| author | 2019-02-19 09:44:33 +0100 | |
|---|---|---|
| committer | 2019-02-19 09:58:38 +0100 | |
| commit | 717394c980509ee68608e6378cf58162adb5edaa (patch) | |
| tree | e3b8edbc830b10f80dd3efa8e4d1d4e14f577e6b /src/video_core/dma_pusher.cpp | |
| parent | Merge pull request #2122 from ReinUsesLisp/vulkan-resource-manager (diff) | |
| download | yuzu-717394c980509ee68608e6378cf58162adb5edaa.tar.gz yuzu-717394c980509ee68608e6378cf58162adb5edaa.tar.xz yuzu-717394c980509ee68608e6378cf58162adb5edaa.zip | |
video_core/dma_pusher: The full list of headers at once.
Fetching every u32 from memory leads to a big overhead. So let's fetch all of them as a block if possible.
This reduces the Memory::* calls by the dma_pusher by a factor of 10.
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
| -rw-r--r-- | src/video_core/dma_pusher.cpp | 104 |
1 files changed, 56 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() { | |||
| 38 | const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get); | 38 | const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get); |
| 39 | ASSERT_MSG(address, "Invalid GPU address"); | 39 | ASSERT_MSG(address, "Invalid GPU address"); |
| 40 | 40 | ||
| 41 | const CommandHeader command_header{Memory::Read32(*address)}; | 41 | GPUVAddr size = dma_put - dma_get; |
| 42 | ASSERT_MSG(size % sizeof(CommandHeader) == 0, "Invalid aligned GPU addresses"); | ||
| 43 | command_headers.resize(size / sizeof(CommandHeader)); | ||
| 44 | |||
| 45 | Memory::ReadBlock(*address, command_headers.data(), size); | ||
| 46 | |||
| 47 | for (const CommandHeader& command_header : command_headers) { | ||
| 48 | |||
| 49 | // now, see if we're in the middle of a command | ||
| 50 | if (dma_state.length_pending) { | ||
| 51 | // Second word of long non-inc methods command - method count | ||
| 52 | dma_state.length_pending = 0; | ||
| 53 | dma_state.method_count = command_header.method_count_; | ||
| 54 | } else if (dma_state.method_count) { | ||
| 55 | // Data word of methods command | ||
| 56 | CallMethod(command_header.argument); | ||
| 57 | |||
| 58 | if (!dma_state.non_incrementing) { | ||
| 59 | dma_state.method++; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (dma_increment_once) { | ||
| 63 | dma_state.non_incrementing = true; | ||
| 64 | } | ||
| 65 | |||
| 66 | dma_state.method_count--; | ||
| 67 | } else { | ||
| 68 | // No command active - this is the first word of a new one | ||
| 69 | switch (command_header.mode) { | ||
| 70 | case SubmissionMode::Increasing: | ||
| 71 | SetState(command_header); | ||
| 72 | dma_state.non_incrementing = false; | ||
| 73 | dma_increment_once = false; | ||
| 74 | break; | ||
| 75 | case SubmissionMode::NonIncreasing: | ||
| 76 | SetState(command_header); | ||
| 77 | dma_state.non_incrementing = true; | ||
| 78 | dma_increment_once = false; | ||
| 79 | break; | ||
| 80 | case SubmissionMode::Inline: | ||
| 81 | dma_state.method = command_header.method; | ||
| 82 | dma_state.subchannel = command_header.subchannel; | ||
| 83 | CallMethod(command_header.arg_count); | ||
| 84 | dma_state.non_incrementing = true; | ||
| 85 | dma_increment_once = false; | ||
| 86 | break; | ||
| 87 | case SubmissionMode::IncreaseOnce: | ||
| 88 | SetState(command_header); | ||
| 89 | dma_state.non_incrementing = false; | ||
| 90 | dma_increment_once = true; | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 42 | 95 | ||
| 43 | dma_get += sizeof(u32); | 96 | dma_get = dma_put; |
| 44 | 97 | ||
| 45 | if (!non_main) { | 98 | if (!non_main) { |
| 99 | // TODO (degasus): This is dead code, as dma_mget is never read. | ||
| 46 | dma_mget = dma_get; | 100 | dma_mget = dma_get; |
| 47 | } | 101 | } |
| 48 | |||
| 49 | // now, see if we're in the middle of a command | ||
| 50 | if (dma_state.length_pending) { | ||
| 51 | // Second word of long non-inc methods command - method count | ||
| 52 | dma_state.length_pending = 0; | ||
| 53 | dma_state.method_count = command_header.method_count_; | ||
| 54 | } else if (dma_state.method_count) { | ||
| 55 | // Data word of methods command | ||
| 56 | CallMethod(command_header.argument); | ||
| 57 | |||
| 58 | if (!dma_state.non_incrementing) { | ||
| 59 | dma_state.method++; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (dma_increment_once) { | ||
| 63 | dma_state.non_incrementing = true; | ||
| 64 | } | ||
| 65 | |||
| 66 | dma_state.method_count--; | ||
| 67 | } else { | ||
| 68 | // No command active - this is the first word of a new one | ||
| 69 | switch (command_header.mode) { | ||
| 70 | case SubmissionMode::Increasing: | ||
| 71 | SetState(command_header); | ||
| 72 | dma_state.non_incrementing = false; | ||
| 73 | dma_increment_once = false; | ||
| 74 | break; | ||
| 75 | case SubmissionMode::NonIncreasing: | ||
| 76 | SetState(command_header); | ||
| 77 | dma_state.non_incrementing = true; | ||
| 78 | dma_increment_once = false; | ||
| 79 | break; | ||
| 80 | case SubmissionMode::Inline: | ||
| 81 | dma_state.method = command_header.method; | ||
| 82 | dma_state.subchannel = command_header.subchannel; | ||
| 83 | CallMethod(command_header.arg_count); | ||
| 84 | dma_state.non_incrementing = true; | ||
| 85 | dma_increment_once = false; | ||
| 86 | break; | ||
| 87 | case SubmissionMode::IncreaseOnce: | ||
| 88 | SetState(command_header); | ||
| 89 | dma_state.non_incrementing = false; | ||
| 90 | dma_increment_once = true; | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } else if (ib_enable && !dma_pushbuffer.empty()) { | 102 | } else if (ib_enable && !dma_pushbuffer.empty()) { |
| 95 | // Current pushbuffer empty, but we have more IB entries to read | 103 | // Current pushbuffer empty, but we have more IB entries to read |
| 96 | const CommandList& command_list{dma_pushbuffer.front()}; | 104 | const CommandList& command_list{dma_pushbuffer.front()}; |