mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-22 23:02:47 +01:00
video_core/dma_pusher: Simplyfy Step() logic.
As fetching command list headers and and the list of command headers is a fixed 1:1 relation now, they can be implemented within a single call. This cleans up the Step() logic quite a bit.
This commit is contained in:
parent
717394c980
commit
6dd40976d0
2 changed files with 71 additions and 75 deletions
|
@ -33,88 +33,87 @@ void DmaPusher::DispatchCalls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DmaPusher::Step() {
|
bool DmaPusher::Step() {
|
||||||
if (dma_get != dma_put) {
|
if (!ib_enable || dma_pushbuffer.empty()) {
|
||||||
// Push buffer non-empty, read a word
|
// pushbuffer empty and IB empty or nonexistent - nothing to do
|
||||||
const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
|
return false;
|
||||||
ASSERT_MSG(address, "Invalid GPU address");
|
}
|
||||||
|
|
||||||
GPUVAddr size = dma_put - dma_get;
|
const CommandList& command_list{dma_pushbuffer.front()};
|
||||||
ASSERT_MSG(size % sizeof(CommandHeader) == 0, "Invalid aligned GPU addresses");
|
const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]};
|
||||||
command_headers.resize(size / sizeof(CommandHeader));
|
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;
|
||||||
|
|
||||||
Memory::ReadBlock(*address, command_headers.data(), size);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
for (const CommandHeader& command_header : command_headers) {
|
if (command_list_header.size == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// now, see if we're in the middle of a command
|
// Push buffer non-empty, read a word
|
||||||
if (dma_state.length_pending) {
|
const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
|
||||||
// Second word of long non-inc methods command - method count
|
ASSERT_MSG(address, "Invalid GPU address");
|
||||||
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) {
|
command_headers.resize(command_list_header.size);
|
||||||
dma_state.method++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dma_increment_once) {
|
Memory::ReadBlock(*address, command_headers.data(), command_list_header.size * sizeof(u32));
|
||||||
dma_state.non_incrementing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma_state.method_count--;
|
for (const CommandHeader& command_header : command_headers) {
|
||||||
} else {
|
|
||||||
// No command active - this is the first word of a new one
|
// now, see if we're in the middle of a command
|
||||||
switch (command_header.mode) {
|
if (dma_state.length_pending) {
|
||||||
case SubmissionMode::Increasing:
|
// Second word of long non-inc methods command - method count
|
||||||
SetState(command_header);
|
dma_state.length_pending = 0;
|
||||||
dma_state.non_incrementing = false;
|
dma_state.method_count = command_header.method_count_;
|
||||||
dma_increment_once = false;
|
} else if (dma_state.method_count) {
|
||||||
break;
|
// Data word of methods command
|
||||||
case SubmissionMode::NonIncreasing:
|
CallMethod(command_header.argument);
|
||||||
SetState(command_header);
|
|
||||||
dma_state.non_incrementing = true;
|
if (!dma_state.non_incrementing) {
|
||||||
dma_increment_once = false;
|
dma_state.method++;
|
||||||
break;
|
}
|
||||||
case SubmissionMode::Inline:
|
|
||||||
dma_state.method = command_header.method;
|
if (dma_increment_once) {
|
||||||
dma_state.subchannel = command_header.subchannel;
|
dma_state.non_incrementing = true;
|
||||||
CallMethod(command_header.arg_count);
|
}
|
||||||
dma_state.non_incrementing = true;
|
|
||||||
dma_increment_once = false;
|
dma_state.method_count--;
|
||||||
break;
|
} else {
|
||||||
case SubmissionMode::IncreaseOnce:
|
// No command active - this is the first word of a new one
|
||||||
SetState(command_header);
|
switch (command_header.mode) {
|
||||||
dma_state.non_incrementing = false;
|
case SubmissionMode::Increasing:
|
||||||
dma_increment_once = true;
|
SetState(command_header);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dma_get = dma_put;
|
if (!non_main) {
|
||||||
|
// TODO (degasus): This is dead code, as dma_mget is never read.
|
||||||
if (!non_main) {
|
dma_mget = dma_put;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Otherwise, pushbuffer empty and IB empty or nonexistent - nothing to do
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -91,11 +91,8 @@ private:
|
||||||
DmaState dma_state{};
|
DmaState dma_state{};
|
||||||
bool dma_increment_once{};
|
bool dma_increment_once{};
|
||||||
|
|
||||||
GPUVAddr dma_put{}; ///< pushbuffer current end address
|
|
||||||
GPUVAddr dma_get{}; ///< pushbuffer current read address
|
|
||||||
GPUVAddr dma_mget{}; ///< main pushbuffer last read address
|
GPUVAddr dma_mget{}; ///< main pushbuffer last read address
|
||||||
bool ib_enable{true}; ///< IB mode enabled
|
bool ib_enable{true}; ///< IB mode enabled
|
||||||
bool non_main{}; ///< non-main pushbuffer active
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
Loading…
Reference in a new issue