summaryrefslogtreecommitdiff
path: root/src/video_core/dma_pusher.cpp
diff options
context:
space:
mode:
authorGravatar Markus Wick2019-02-19 09:44:33 +0100
committerGravatar Markus Wick2019-02-19 09:58:38 +0100
commit717394c980509ee68608e6378cf58162adb5edaa (patch)
treee3b8edbc830b10f80dd3efa8e4d1d4e14f577e6b /src/video_core/dma_pusher.cpp
parentMerge pull request #2122 from ReinUsesLisp/vulkan-resource-manager (diff)
downloadyuzu-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.cpp104
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()};