summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.cpp267
-rw-r--r--src/video_core/engines/maxwell_3d.h8
2 files changed, 124 insertions, 151 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 57ebc785f..f7fa5fea7 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -124,6 +124,114 @@ void Maxwell3D::InitializeRegisterDefaults() {
124 mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true; 124 mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
125} 125}
126 126
127void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
128 if (executing_macro == 0) {
129 // A macro call must begin by writing the macro method's register, not its argument.
130 ASSERT_MSG((method % 2) == 0,
131 "Can't start macro execution by writing to the ARGS register");
132 executing_macro = method;
133 }
134
135 for (std::size_t i = 0; i < amount; i++) {
136 macro_params.push_back(base_start[i]);
137 }
138
139 // Call the macro when there are no more parameters in the command buffer
140 if (is_last_call) {
141 CallMacroMethod(executing_macro, macro_params);
142 macro_params.clear();
143 }
144}
145
146u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
147 // Keep track of the register value in shadow_state when requested.
148 const auto control = shadow_state.shadow_ram_control;
149 if (control == Regs::ShadowRamControl::Track ||
150 control == Regs::ShadowRamControl::TrackWithFilter) {
151 shadow_state.reg_array[method] = argument;
152 return argument;
153 }
154 if (control == Regs::ShadowRamControl::Replay) {
155 return shadow_state.reg_array[method];
156 }
157 return argument;
158}
159
160void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) {
161 if (regs.reg_array[method] == argument) {
162 return;
163 }
164 regs.reg_array[method] = argument;
165
166 for (const auto& table : dirty.tables) {
167 dirty.flags[table[method]] = true;
168 }
169}
170
171void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument,
172 bool is_last_call) {
173 switch (method) {
174 case MAXWELL3D_REG_INDEX(wait_for_idle):
175 return rasterizer->WaitForIdle();
176 case MAXWELL3D_REG_INDEX(shadow_ram_control):
177 shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
178 return;
179 case MAXWELL3D_REG_INDEX(macros.data):
180 return macro_engine->AddCode(regs.macros.upload_address, argument);
181 case MAXWELL3D_REG_INDEX(macros.bind):
182 return ProcessMacroBind(argument);
183 case MAXWELL3D_REG_INDEX(firmware[4]):
184 return ProcessFirmwareCall4();
185 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
186 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
187 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
188 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]):
189 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]):
190 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]):
191 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]):
192 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]):
193 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]):
194 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]):
195 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]):
196 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]):
197 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
198 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
199 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
200 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]):
201 return StartCBData(method);
202 case MAXWELL3D_REG_INDEX(cb_bind[0]):
203 return ProcessCBBind(0);
204 case MAXWELL3D_REG_INDEX(cb_bind[1]):
205 return ProcessCBBind(1);
206 case MAXWELL3D_REG_INDEX(cb_bind[2]):
207 return ProcessCBBind(2);
208 case MAXWELL3D_REG_INDEX(cb_bind[3]):
209 return ProcessCBBind(3);
210 case MAXWELL3D_REG_INDEX(cb_bind[4]):
211 return ProcessCBBind(4);
212 case MAXWELL3D_REG_INDEX(draw.vertex_end_gl):
213 return DrawArrays();
214 case MAXWELL3D_REG_INDEX(clear_buffers):
215 return ProcessClearBuffers();
216 case MAXWELL3D_REG_INDEX(query.query_get):
217 return ProcessQueryGet();
218 case MAXWELL3D_REG_INDEX(condition.mode):
219 return ProcessQueryCondition();
220 case MAXWELL3D_REG_INDEX(counter_reset):
221 return ProcessCounterReset();
222 case MAXWELL3D_REG_INDEX(sync_info):
223 return ProcessSyncPoint();
224 case MAXWELL3D_REG_INDEX(exec_upload):
225 return upload_state.ProcessExec(regs.exec_upload.linear != 0);
226 case MAXWELL3D_REG_INDEX(data_upload):
227 upload_state.ProcessData(argument, is_last_call);
228 if (is_last_call) {
229 OnMemoryWrite();
230 }
231 return;
232 }
233}
234
127void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) { 235void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) {
128 // Reset the current macro. 236 // Reset the current macro.
129 executing_macro = 0; 237 executing_macro = 0;
@@ -157,142 +265,16 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
157 // Methods after 0xE00 are special, they're actually triggers for some microcode that was 265 // Methods after 0xE00 are special, they're actually triggers for some microcode that was
158 // uploaded to the GPU during initialization. 266 // uploaded to the GPU during initialization.
159 if (method >= MacroRegistersStart) { 267 if (method >= MacroRegistersStart) {
160 // We're trying to execute a macro 268 ProcessMacro(method, &method_argument, 1, is_last_call);
161 if (executing_macro == 0) {
162 // A macro call must begin by writing the macro method's register, not its argument.
163 ASSERT_MSG((method % 2) == 0,
164 "Can't start macro execution by writing to the ARGS register");
165 executing_macro = method;
166 }
167
168 macro_params.push_back(method_argument);
169
170 // Call the macro when there are no more parameters in the command buffer
171 if (is_last_call) {
172 CallMacroMethod(executing_macro, macro_params);
173 macro_params.clear();
174 }
175 return; 269 return;
176 } 270 }
177 271
178 ASSERT_MSG(method < Regs::NUM_REGS, 272 ASSERT_MSG(method < Regs::NUM_REGS,
179 "Invalid Maxwell3D register, increase the size of the Regs structure"); 273 "Invalid Maxwell3D register, increase the size of the Regs structure");
180 274
181 u32 arg = method_argument; 275 const u32 argument = ProcessShadowRam(method, method_argument);
182 // Keep track of the register value in shadow_state when requested. 276 ProcessDirtyRegisters(method, argument);
183 if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track || 277 ProcessMethodCall(method, argument, method_argument, is_last_call);
184 shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) {
185 shadow_state.reg_array[method] = arg;
186 } else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) {
187 arg = shadow_state.reg_array[method];
188 }
189
190 if (regs.reg_array[method] != arg) {
191 regs.reg_array[method] = arg;
192
193 for (const auto& table : dirty.tables) {
194 dirty.flags[table[method]] = true;
195 }
196 }
197
198 switch (method) {
199 case MAXWELL3D_REG_INDEX(wait_for_idle): {
200 rasterizer->WaitForIdle();
201 break;
202 }
203 case MAXWELL3D_REG_INDEX(shadow_ram_control): {
204 shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_argument);
205 break;
206 }
207 case MAXWELL3D_REG_INDEX(macros.data): {
208 macro_engine->AddCode(regs.macros.upload_address, arg);
209 break;
210 }
211 case MAXWELL3D_REG_INDEX(macros.bind): {
212 ProcessMacroBind(arg);
213 break;
214 }
215 case MAXWELL3D_REG_INDEX(firmware[4]): {
216 ProcessFirmwareCall4();
217 break;
218 }
219 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
220 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
221 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
222 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]):
223 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]):
224 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]):
225 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]):
226 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]):
227 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]):
228 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]):
229 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]):
230 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]):
231 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
232 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
233 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
234 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): {
235 StartCBData(method);
236 break;
237 }
238 case MAXWELL3D_REG_INDEX(cb_bind[0]): {
239 ProcessCBBind(0);
240 break;
241 }
242 case MAXWELL3D_REG_INDEX(cb_bind[1]): {
243 ProcessCBBind(1);
244 break;
245 }
246 case MAXWELL3D_REG_INDEX(cb_bind[2]): {
247 ProcessCBBind(2);
248 break;
249 }
250 case MAXWELL3D_REG_INDEX(cb_bind[3]): {
251 ProcessCBBind(3);
252 break;
253 }
254 case MAXWELL3D_REG_INDEX(cb_bind[4]): {
255 ProcessCBBind(4);
256 break;
257 }
258 case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): {
259 DrawArrays();
260 break;
261 }
262 case MAXWELL3D_REG_INDEX(clear_buffers): {
263 ProcessClearBuffers();
264 break;
265 }
266 case MAXWELL3D_REG_INDEX(query.query_get): {
267 ProcessQueryGet();
268 break;
269 }
270 case MAXWELL3D_REG_INDEX(condition.mode): {
271 ProcessQueryCondition();
272 break;
273 }
274 case MAXWELL3D_REG_INDEX(counter_reset): {
275 ProcessCounterReset();
276 break;
277 }
278 case MAXWELL3D_REG_INDEX(sync_info): {
279 ProcessSyncPoint();
280 break;
281 }
282 case MAXWELL3D_REG_INDEX(exec_upload): {
283 upload_state.ProcessExec(regs.exec_upload.linear != 0);
284 break;
285 }
286 case MAXWELL3D_REG_INDEX(data_upload): {
287 upload_state.ProcessData(arg, is_last_call);
288 if (is_last_call) {
289 OnMemoryWrite();
290 }
291 break;
292 }
293 default:
294 break;
295 }
296} 278}
297 279
298void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, 280void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
@@ -300,23 +282,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
300 // Methods after 0xE00 are special, they're actually triggers for some microcode that was 282 // Methods after 0xE00 are special, they're actually triggers for some microcode that was
301 // uploaded to the GPU during initialization. 283 // uploaded to the GPU during initialization.
302 if (method >= MacroRegistersStart) { 284 if (method >= MacroRegistersStart) {
303 // We're trying to execute a macro 285 ProcessMacro(method, base_start, amount, amount == methods_pending);
304 if (executing_macro == 0) {
305 // A macro call must begin by writing the macro method's register, not its argument.
306 ASSERT_MSG((method % 2) == 0,
307 "Can't start macro execution by writing to the ARGS register");
308 executing_macro = method;
309 }
310
311 for (std::size_t i = 0; i < amount; i++) {
312 macro_params.push_back(base_start[i]);
313 }
314
315 // Call the macro when there are no more parameters in the command buffer
316 if (amount == methods_pending) {
317 CallMacroMethod(executing_macro, macro_params);
318 macro_params.clear();
319 }
320 return; 286 return;
321 } 287 }
322 switch (method) { 288 switch (method) {
@@ -335,15 +301,14 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
335 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): 301 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
336 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): 302 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
337 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): 303 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
338 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { 304 case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]):
339 ProcessCBMultiData(method, base_start, amount); 305 ProcessCBMultiData(method, base_start, amount);
340 break; 306 break;
341 } 307 default:
342 default: {
343 for (std::size_t i = 0; i < amount; i++) { 308 for (std::size_t i = 0; i < amount; i++) {
344 CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); 309 CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
345 } 310 }
346 } 311 break;
347 } 312 }
348} 313}
349 314
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index bc289c55d..1cbe8fe67 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1461,6 +1461,14 @@ public:
1461private: 1461private:
1462 void InitializeRegisterDefaults(); 1462 void InitializeRegisterDefaults();
1463 1463
1464 void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call);
1465
1466 u32 ProcessShadowRam(u32 method, u32 argument);
1467
1468 void ProcessDirtyRegisters(u32 method, u32 argument);
1469
1470 void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call);
1471
1464 Core::System& system; 1472 Core::System& system;
1465 MemoryManager& memory_manager; 1473 MemoryManager& memory_manager;
1466 1474