diff options
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
| -rw-r--r-- | src/video_core/dma_pusher.cpp | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 322de2606..551929824 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp | |||
| @@ -61,7 +61,7 @@ bool DmaPusher::Step() { | |||
| 61 | } else { | 61 | } else { |
| 62 | const CommandListHeader command_list_header{ | 62 | const CommandListHeader command_list_header{ |
| 63 | command_list.command_lists[dma_pushbuffer_subindex++]}; | 63 | command_list.command_lists[dma_pushbuffer_subindex++]}; |
| 64 | const GPUVAddr dma_get = command_list_header.addr; | 64 | dma_state.dma_get = command_list_header.addr; |
| 65 | 65 | ||
| 66 | if (dma_pushbuffer_subindex >= command_list.command_lists.size()) { | 66 | if (dma_pushbuffer_subindex >= command_list.command_lists.size()) { |
| 67 | // We've gone through the current list, remove it from the queue | 67 | // We've gone through the current list, remove it from the queue |
| @@ -75,12 +75,22 @@ bool DmaPusher::Step() { | |||
| 75 | 75 | ||
| 76 | // Push buffer non-empty, read a word | 76 | // Push buffer non-empty, read a word |
| 77 | command_headers.resize_destructive(command_list_header.size); | 77 | command_headers.resize_destructive(command_list_header.size); |
| 78 | if (Settings::IsGPULevelHigh()) { | 78 | constexpr u32 MacroRegistersStart = 0xE00; |
| 79 | memory_manager.ReadBlock(dma_get, command_headers.data(), | 79 | if (dma_state.method < MacroRegistersStart) { |
| 80 | command_list_header.size * sizeof(u32)); | 80 | if (Settings::IsGPULevelHigh()) { |
| 81 | memory_manager.ReadBlock(dma_state.dma_get, command_headers.data(), | ||
| 82 | command_list_header.size * sizeof(u32)); | ||
| 83 | } else { | ||
| 84 | memory_manager.ReadBlockUnsafe(dma_state.dma_get, command_headers.data(), | ||
| 85 | command_list_header.size * sizeof(u32)); | ||
| 86 | } | ||
| 81 | } else { | 87 | } else { |
| 82 | memory_manager.ReadBlockUnsafe(dma_get, command_headers.data(), | 88 | const size_t copy_size = command_list_header.size * sizeof(u32); |
| 83 | command_list_header.size * sizeof(u32)); | 89 | if (subchannels[dma_state.subchannel]) { |
| 90 | subchannels[dma_state.subchannel]->current_dirty = | ||
| 91 | memory_manager.IsMemoryDirty(dma_state.dma_get, copy_size); | ||
| 92 | } | ||
| 93 | memory_manager.ReadBlockUnsafe(dma_state.dma_get, command_headers.data(), copy_size); | ||
| 84 | } | 94 | } |
| 85 | ProcessCommands(command_headers); | 95 | ProcessCommands(command_headers); |
| 86 | } | 96 | } |
| @@ -94,6 +104,7 @@ void DmaPusher::ProcessCommands(std::span<const CommandHeader> commands) { | |||
| 94 | 104 | ||
| 95 | if (dma_state.method_count) { | 105 | if (dma_state.method_count) { |
| 96 | // Data word of methods command | 106 | // Data word of methods command |
| 107 | dma_state.dma_word_offset = static_cast<u32>(index * sizeof(u32)); | ||
| 97 | if (dma_state.non_incrementing) { | 108 | if (dma_state.non_incrementing) { |
| 98 | const u32 max_write = static_cast<u32>( | 109 | const u32 max_write = static_cast<u32>( |
| 99 | std::min<std::size_t>(index + dma_state.method_count, commands.size()) - index); | 110 | std::min<std::size_t>(index + dma_state.method_count, commands.size()) - index); |
| @@ -132,6 +143,8 @@ void DmaPusher::ProcessCommands(std::span<const CommandHeader> commands) { | |||
| 132 | case SubmissionMode::Inline: | 143 | case SubmissionMode::Inline: |
| 133 | dma_state.method = command_header.method; | 144 | dma_state.method = command_header.method; |
| 134 | dma_state.subchannel = command_header.subchannel; | 145 | dma_state.subchannel = command_header.subchannel; |
| 146 | dma_state.dma_word_offset = static_cast<u64>( | ||
| 147 | -static_cast<s64>(dma_state.dma_get)); // negate to set address as 0 | ||
| 135 | CallMethod(command_header.arg_count); | 148 | CallMethod(command_header.arg_count); |
| 136 | dma_state.non_incrementing = true; | 149 | dma_state.non_incrementing = true; |
| 137 | dma_increment_once = false; | 150 | dma_increment_once = false; |
| @@ -164,8 +177,14 @@ void DmaPusher::CallMethod(u32 argument) const { | |||
| 164 | dma_state.method_count, | 177 | dma_state.method_count, |
| 165 | }); | 178 | }); |
| 166 | } else { | 179 | } else { |
| 167 | subchannels[dma_state.subchannel]->CallMethod(dma_state.method, argument, | 180 | auto subchannel = subchannels[dma_state.subchannel]; |
| 168 | dma_state.is_last_call); | 181 | if (!subchannel->execution_mask[dma_state.method]) [[likely]] { |
| 182 | subchannel->method_sink.emplace_back(dma_state.method, argument); | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | subchannel->ConsumeSink(); | ||
| 186 | subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; | ||
| 187 | subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call); | ||
| 169 | } | 188 | } |
| 170 | } | 189 | } |
| 171 | 190 | ||
| @@ -174,8 +193,11 @@ void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) const { | |||
| 174 | puller.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods, | 193 | puller.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods, |
| 175 | dma_state.method_count); | 194 | dma_state.method_count); |
| 176 | } else { | 195 | } else { |
| 177 | subchannels[dma_state.subchannel]->CallMultiMethod(dma_state.method, base_start, | 196 | auto subchannel = subchannels[dma_state.subchannel]; |
| 178 | num_methods, dma_state.method_count); | 197 | subchannel->ConsumeSink(); |
| 198 | subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; | ||
| 199 | subchannel->CallMultiMethod(dma_state.method, base_start, num_methods, | ||
| 200 | dma_state.method_count); | ||
| 179 | } | 201 | } |
| 180 | } | 202 | } |
| 181 | 203 | ||