summaryrefslogtreecommitdiff
path: root/src/video_core/dma_pusher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
-rw-r--r--src/video_core/dma_pusher.cpp42
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