summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.cpp116
-rw-r--r--src/video_core/engines/maxwell_3d.h8
2 files changed, 63 insertions, 61 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5bb1427c1..7266cba0d 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -126,6 +126,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
126 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; 126 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
127 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; 127 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
128 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; 128 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
129 draw_command[MAXWELL3D_REG_INDEX(draw.instance_id)] = true;
129} 130}
130 131
131void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { 132void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -288,31 +289,58 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
288 ASSERT_MSG(method < Regs::NUM_REGS, 289 ASSERT_MSG(method < Regs::NUM_REGS,
289 "Invalid Maxwell3D register, increase the size of the Regs structure"); 290 "Invalid Maxwell3D register, increase the size of the Regs structure");
290 291
292 const u32 argument = ProcessShadowRam(method, method_argument);
293 ProcessDirtyRegisters(method, argument);
294
291 if (draw_command[method]) { 295 if (draw_command[method]) {
292 regs.reg_array[method] = method_argument; 296 regs.reg_array[method] = method_argument;
293 deferred_draw_method.push_back(method); 297 deferred_draw_method.push_back(method);
294 auto u32_to_u8 = [&](const u32 argument) { 298 auto update_inline_index = [&](const u32 index) {
295 inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff)); 299 inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff));
296 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8)); 300 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8));
297 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16)); 301 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16));
298 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24)); 302 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24));
303 draw_mode = DrawMode::InlineIndex;
299 }; 304 };
300 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) { 305 switch (method) {
301 u32_to_u8(method_argument); 306 case MAXWELL3D_REG_INDEX(draw.end):
302 } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) { 307 switch (draw_mode) {
303 u32_to_u8(regs.inline_index_2x16.even); 308 case DrawMode::General:
304 u32_to_u8(regs.inline_index_2x16.odd); 309 ProcessDraw(1);
305 } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { 310 break;
306 u32_to_u8(regs.inline_index_4x8.index0); 311 case DrawMode::InlineIndex:
307 u32_to_u8(regs.inline_index_4x8.index1); 312 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
308 u32_to_u8(regs.inline_index_4x8.index2); 313 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
309 u32_to_u8(regs.inline_index_4x8.index3); 314 ProcessDraw(1);
315 inline_index_draw_indexes.clear();
316 break;
317 case DrawMode::Instance:
318 break;
319 }
320 break;
321 case MAXWELL3D_REG_INDEX(draw_inline_index):
322 update_inline_index(method_argument);
323 break;
324 case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
325 update_inline_index(regs.inline_index_2x16.even);
326 update_inline_index(regs.inline_index_2x16.odd);
327 break;
328 case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
329 update_inline_index(regs.inline_index_4x8.index0);
330 update_inline_index(regs.inline_index_4x8.index1);
331 update_inline_index(regs.inline_index_4x8.index2);
332 update_inline_index(regs.inline_index_4x8.index3);
333 break;
334 case MAXWELL3D_REG_INDEX(draw.instance_id):
335 draw_mode =
336 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
337 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
338 ? DrawMode::Instance
339 : DrawMode::General;
340 break;
310 } 341 }
311 } else { 342 } else {
312 ProcessDeferredDraw(); 343 ProcessDeferredDraw();
313
314 const u32 argument = ProcessShadowRam(method, method_argument);
315 ProcessDirtyRegisters(method, argument);
316 ProcessMethodCall(method, argument, method_argument, is_last_call); 344 ProcessMethodCall(method, argument, method_argument, is_last_call);
317 } 345 }
318} 346}
@@ -626,57 +654,27 @@ void Maxwell3D::ProcessDraw(u32 instance_count) {
626} 654}
627 655
628void Maxwell3D::ProcessDeferredDraw() { 656void Maxwell3D::ProcessDeferredDraw() {
629 if (deferred_draw_method.empty()) { 657 if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) {
630 return; 658 return;
631 } 659 }
632 660
633 enum class DrawMode {
634 Undefined,
635 General,
636 Instance,
637 };
638 DrawMode draw_mode{DrawMode::Undefined};
639 u32 method_count = static_cast<u32>(deferred_draw_method.size()); 661 u32 method_count = static_cast<u32>(deferred_draw_method.size());
640 u32 method = deferred_draw_method[method_count - 1]; 662 u32 instance_count = 1;
641 if (MAXWELL3D_REG_INDEX(draw.end) != method) { 663 u32 vertex_buffer_count = 0;
642 return; 664 u32 index_buffer_count = 0;
643 } 665 for (u32 index = 0; index < method_count; ++index) {
644 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || 666 u32 method = deferred_draw_method[index];
645 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) 667 if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
646 ? DrawMode::Instance 668 instance_count = ++vertex_buffer_count;
647 : DrawMode::General; 669 } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
648 u32 instance_count = 0; 670 instance_count = ++index_buffer_count;
649 if (draw_mode == DrawMode::Instance) {
650 u32 vertex_buffer_count = 0;
651 u32 index_buffer_count = 0;
652 for (u32 index = 0; index < method_count; ++index) {
653 method = deferred_draw_method[index];
654 if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
655 instance_count = ++vertex_buffer_count;
656 } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
657 instance_count = ++index_buffer_count;
658 }
659 }
660 ASSERT_MSG(!(vertex_buffer_count && index_buffer_count),
661 "Instance both indexed and direct?");
662 } else {
663 instance_count = 1;
664 for (u32 index = 0; index < method_count; ++index) {
665 method = deferred_draw_method[index];
666 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
667 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
668 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
669 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
670 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
671 break;
672 }
673 } 671 }
674 } 672 }
673 ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?");
675 674
676 ProcessDraw(instance_count); 675 ProcessDraw(instance_count);
677 676
678 deferred_draw_method.clear(); 677 deferred_draw_method.clear();
679 inline_index_draw_indexes.clear();
680} 678}
681 679
682} // namespace Tegra::Engines 680} // namespace Tegra::Engines
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index c3099f9a6..84c497ebd 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -3148,10 +3148,12 @@ private:
3148 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) 3148 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)
3149 void ProcessTopologyOverride(); 3149 void ProcessTopologyOverride();
3150 3150
3151 void ProcessDraw(u32 instance_count = 1); 3151 /// Handles deferred draw(e.g., instance draw).
3152
3153 void ProcessDeferredDraw(); 3152 void ProcessDeferredDraw();
3154 3153
3154 /// Handles a draw.
3155 void ProcessDraw(u32 instance_count = 1);
3156
3155 /// Returns a query's value or an empty object if the value will be deferred through a cache. 3157 /// Returns a query's value or an empty object if the value will be deferred through a cache.
3156 std::optional<u64> GetQueryResult(); 3158 std::optional<u64> GetQueryResult();
3157 3159
@@ -3178,6 +3180,8 @@ private:
3178 3180
3179 std::array<bool, Regs::NUM_REGS> draw_command{}; 3181 std::array<bool, Regs::NUM_REGS> draw_command{};
3180 std::vector<u32> deferred_draw_method; 3182 std::vector<u32> deferred_draw_method;
3183 enum class DrawMode : u32 { General = 0, Instance, InlineIndex };
3184 DrawMode draw_mode{DrawMode::General};
3181}; 3185};
3182 3186
3183#define ASSERT_REG_POSITION(field_name, position) \ 3187#define ASSERT_REG_POSITION(field_name, position) \