summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Markus Wick2019-02-19 10:26:58 +0100
committerGravatar Markus Wick2019-02-19 10:28:42 +0100
commit6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116 (patch)
treef13452d784190c570118f6bb22dec6ea91c6012a /src
parentvideo_core/dma_pusher: The full list of headers at once. (diff)
downloadyuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.gz
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.tar.xz
yuzu-6dd40976d0eb39e9b4ac2cb7e3b78fe0a4bf0116.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/dma_pusher.cpp155
-rw-r--r--src/video_core/dma_pusher.h3
2 files changed, 77 insertions, 81 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 654e4d9aa..669541b4b 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -33,88 +33,87 @@ void DmaPusher::DispatchCalls() {
33} 33}
34 34
35bool DmaPusher::Step() { 35bool DmaPusher::Step() {
36 if (dma_get != dma_put) { 36 if (!ib_enable || dma_pushbuffer.empty()) {
37 // Push buffer non-empty, read a word 37 // pushbuffer empty and IB empty or nonexistent - nothing to do
38 const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get); 38 return false;
39 ASSERT_MSG(address, "Invalid GPU address"); 39 }
40 40
41 GPUVAddr size = dma_put - dma_get; 41 const CommandList& command_list{dma_pushbuffer.front()};
42 ASSERT_MSG(size % sizeof(CommandHeader) == 0, "Invalid aligned GPU addresses"); 42 const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]};
43 command_headers.resize(size / sizeof(CommandHeader)); 43 GPUVAddr dma_get = command_list_header.addr;
44 44 GPUVAddr dma_put = dma_get + command_list_header.size * sizeof(u32);
45 Memory::ReadBlock(*address, command_headers.data(), size); 45 bool non_main = command_list_header.is_non_main;
46 46
47 for (const CommandHeader& command_header : command_headers) { 47 if (dma_pushbuffer_subindex >= command_list.size()) {
48 48 // We've gone through the current list, remove it from the queue
49 // now, see if we're in the middle of a command 49 dma_pushbuffer.pop();
50 if (dma_state.length_pending) { 50 dma_pushbuffer_subindex = 0;
51 // Second word of long non-inc methods command - method count 51 }
52 dma_state.length_pending = 0; 52
53 dma_state.method_count = command_header.method_count_; 53 if (command_list_header.size == 0) {
54 } else if (dma_state.method_count) { 54 return true;
55 // Data word of methods command 55 }
56 CallMethod(command_header.argument); 56
57 57 // Push buffer non-empty, read a word
58 if (!dma_state.non_incrementing) { 58 const auto address = gpu.MemoryManager().GpuToCpuAddress(dma_get);
59 dma_state.method++; 59 ASSERT_MSG(address, "Invalid GPU address");
60 } 60
61 61 command_headers.resize(command_list_header.size);
62 if (dma_increment_once) { 62
63 dma_state.non_incrementing = true; 63 Memory::ReadBlock(*address, command_headers.data(), command_list_header.size * sizeof(u32));
64 } 64
65 65 for (const CommandHeader& command_header : command_headers) {
66 dma_state.method_count--; 66
67 } else { 67 // now, see if we're in the middle of a command
68 // No command active - this is the first word of a new one 68 if (dma_state.length_pending) {
69 switch (command_header.mode) { 69 // Second word of long non-inc methods command - method count
70 case SubmissionMode::Increasing: 70 dma_state.length_pending = 0;
71 SetState(command_header); 71 dma_state.method_count = command_header.method_count_;
72 dma_state.non_incrementing = false; 72 } else if (dma_state.method_count) {
73 dma_increment_once = false; 73 // Data word of methods command
74 break; 74 CallMethod(command_header.argument);
75 case SubmissionMode::NonIncreasing: 75
76 SetState(command_header); 76 if (!dma_state.non_incrementing) {
77 dma_state.non_incrementing = true; 77 dma_state.method++;
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 } 78 }
94 }
95 79
96 dma_get = dma_put; 80 if (dma_increment_once) {
81 dma_state.non_incrementing = true;
82 }
97 83
98 if (!non_main) { 84 dma_state.method_count--;
99 // TODO (degasus): This is dead code, as dma_mget is never read. 85 } else {
100 dma_mget = dma_get; 86 // No command active - this is the first word of a new one
101 } 87 switch (command_header.mode) {
102 } else if (ib_enable && !dma_pushbuffer.empty()) { 88 case SubmissionMode::Increasing:
103 // Current pushbuffer empty, but we have more IB entries to read 89 SetState(command_header);
104 const CommandList& command_list{dma_pushbuffer.front()}; 90 dma_state.non_incrementing = false;
105 const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]}; 91 dma_increment_once = false;
106 dma_get = command_list_header.addr; 92 break;
107 dma_put = dma_get + command_list_header.size * sizeof(u32); 93 case SubmissionMode::NonIncreasing:
108 non_main = command_list_header.is_non_main; 94 SetState(command_header);
109 95 dma_state.non_incrementing = true;
110 if (dma_pushbuffer_subindex >= command_list.size()) { 96 dma_increment_once = false;
111 // We've gone through the current list, remove it from the queue 97 break;
112 dma_pushbuffer.pop(); 98 case SubmissionMode::Inline:
113 dma_pushbuffer_subindex = 0; 99 dma_state.method = command_header.method;
100 dma_state.subchannel = command_header.subchannel;
101 CallMethod(command_header.arg_count);
102 dma_state.non_incrementing = true;
103 dma_increment_once = false;
104 break;
105 case SubmissionMode::IncreaseOnce:
106 SetState(command_header);
107 dma_state.non_incrementing = false;
108 dma_increment_once = true;
109 break;
110 }
114 } 111 }
115 } else { 112 }
116 // Otherwise, pushbuffer empty and IB empty or nonexistent - nothing to do 113
117 return {}; 114 if (!non_main) {
115 // TODO (degasus): This is dead code, as dma_mget is never read.
116 dma_mget = dma_put;
118 } 117 }
119 118
120 return true; 119 return true;
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index 14b23b1d7..27a36348c 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -91,11 +91,8 @@ private:
91 DmaState dma_state{}; 91 DmaState dma_state{};
92 bool dma_increment_once{}; 92 bool dma_increment_once{};
93 93
94 GPUVAddr dma_put{}; ///< pushbuffer current end address
95 GPUVAddr dma_get{}; ///< pushbuffer current read address
96 GPUVAddr dma_mget{}; ///< main pushbuffer last read address 94 GPUVAddr dma_mget{}; ///< main pushbuffer last read address
97 bool ib_enable{true}; ///< IB mode enabled 95 bool ib_enable{true}; ///< IB mode enabled
98 bool non_main{}; ///< non-main pushbuffer active
99}; 96};
100 97
101} // namespace Tegra 98} // namespace Tegra