summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 6d43e23ea..212427b8b 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) {
@@ -285,31 +286,58 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
285 ASSERT_MSG(method < Regs::NUM_REGS, 286 ASSERT_MSG(method < Regs::NUM_REGS,
286 "Invalid Maxwell3D register, increase the size of the Regs structure"); 287 "Invalid Maxwell3D register, increase the size of the Regs structure");
287 288
289 const u32 argument = ProcessShadowRam(method, method_argument);
290 ProcessDirtyRegisters(method, argument);
291
288 if (draw_command[method]) { 292 if (draw_command[method]) {
289 regs.reg_array[method] = method_argument; 293 regs.reg_array[method] = method_argument;
290 deferred_draw_method.push_back(method); 294 deferred_draw_method.push_back(method);
291 auto u32_to_u8 = [&](const u32 argument) { 295 auto update_inline_index = [&](const u32 index) {
292 inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff)); 296 inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff));
293 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8)); 297 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8));
294 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16)); 298 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16));
295 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24)); 299 inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24));
300 draw_mode = DrawMode::InlineIndex;
296 }; 301 };
297 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) { 302 switch (method) {
298 u32_to_u8(method_argument); 303 case MAXWELL3D_REG_INDEX(draw.end):
299 } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) { 304 switch (draw_mode) {
300 u32_to_u8(regs.inline_index_2x16.even); 305 case DrawMode::General:
301 u32_to_u8(regs.inline_index_2x16.odd); 306 ProcessDraw(1);
302 } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { 307 break;
303 u32_to_u8(regs.inline_index_4x8.index0); 308 case DrawMode::InlineIndex:
304 u32_to_u8(regs.inline_index_4x8.index1); 309 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
305 u32_to_u8(regs.inline_index_4x8.index2); 310 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
306 u32_to_u8(regs.inline_index_4x8.index3); 311 ProcessDraw(1);
312 inline_index_draw_indexes.clear();
313 break;
314 case DrawMode::Instance:
315 break;
316 }
317 break;
318 case MAXWELL3D_REG_INDEX(draw_inline_index):
319 update_inline_index(method_argument);
320 break;
321 case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
322 update_inline_index(regs.inline_index_2x16.even);
323 update_inline_index(regs.inline_index_2x16.odd);
324 break;
325 case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
326 update_inline_index(regs.inline_index_4x8.index0);
327 update_inline_index(regs.inline_index_4x8.index1);
328 update_inline_index(regs.inline_index_4x8.index2);
329 update_inline_index(regs.inline_index_4x8.index3);
330 break;
331 case MAXWELL3D_REG_INDEX(draw.instance_id):
332 draw_mode =
333 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
334 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
335 ? DrawMode::Instance
336 : DrawMode::General;
337 break;
307 } 338 }
308 } else { 339 } else {
309 ProcessDeferredDraw(); 340 ProcessDeferredDraw();
310
311 const u32 argument = ProcessShadowRam(method, method_argument);
312 ProcessDirtyRegisters(method, argument);
313 ProcessMethodCall(method, argument, method_argument, is_last_call); 341 ProcessMethodCall(method, argument, method_argument, is_last_call);
314 } 342 }
315} 343}
@@ -620,57 +648,27 @@ void Maxwell3D::ProcessDraw(u32 instance_count) {
620} 648}
621 649
622void Maxwell3D::ProcessDeferredDraw() { 650void Maxwell3D::ProcessDeferredDraw() {
623 if (deferred_draw_method.empty()) { 651 if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) {
624 return; 652 return;
625 } 653 }
626 654
627 enum class DrawMode {
628 Undefined,
629 General,
630 Instance,
631 };
632 DrawMode draw_mode{DrawMode::Undefined};
633 u32 method_count = static_cast<u32>(deferred_draw_method.size()); 655 u32 method_count = static_cast<u32>(deferred_draw_method.size());
634 u32 method = deferred_draw_method[method_count - 1]; 656 u32 instance_count = 1;
635 if (MAXWELL3D_REG_INDEX(draw.end) != method) { 657 u32 vertex_buffer_count = 0;
636 return; 658 u32 index_buffer_count = 0;
637 } 659 for (u32 index = 0; index < method_count; ++index) {
638 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || 660 u32 method = deferred_draw_method[index];
639 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) 661 if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
640 ? DrawMode::Instance 662 instance_count = ++vertex_buffer_count;
641 : DrawMode::General; 663 } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
642 u32 instance_count = 0; 664 instance_count = ++index_buffer_count;
643 if (draw_mode == DrawMode::Instance) {
644 u32 vertex_buffer_count = 0;
645 u32 index_buffer_count = 0;
646 for (u32 index = 0; index < method_count; ++index) {
647 method = deferred_draw_method[index];
648 if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
649 instance_count = ++vertex_buffer_count;
650 } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
651 instance_count = ++index_buffer_count;
652 }
653 }
654 ASSERT_MSG(!(vertex_buffer_count && index_buffer_count),
655 "Instance both indexed and direct?");
656 } else {
657 instance_count = 1;
658 for (u32 index = 0; index < method_count; ++index) {
659 method = deferred_draw_method[index];
660 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
661 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
662 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
663 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
664 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
665 break;
666 }
667 } 665 }
668 } 666 }
667 ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?");
669 668
670 ProcessDraw(instance_count); 669 ProcessDraw(instance_count);
671 670
672 deferred_draw_method.clear(); 671 deferred_draw_method.clear();
673 inline_index_draw_indexes.clear();
674} 672}
675 673
676} // namespace Tegra::Engines 674} // 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) \