summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp129
-rw-r--r--src/video_core/engines/maxwell_3d.h2
2 files changed, 70 insertions, 61 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5208bea75..f9794dfe4 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -123,9 +123,6 @@ void Maxwell3D::InitializeRegisterDefaults() {
123 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; 123 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
124 draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; 124 draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true;
125 draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; 125 draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
126 draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true;
127 draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true;
128 draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true;
129 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; 126 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
130 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; 127 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
131 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; 128 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
@@ -216,6 +213,21 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
216 return ProcessCBBind(3); 213 return ProcessCBBind(3);
217 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): 214 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
218 return ProcessCBBind(4); 215 return ProcessCBBind(4);
216 case MAXWELL3D_REG_INDEX(index_buffer32_first):
217 regs.index_buffer.count = regs.index_buffer32_first.count;
218 regs.index_buffer.first = regs.index_buffer32_first.first;
219 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
220 return ProcessDraw();
221 case MAXWELL3D_REG_INDEX(index_buffer16_first):
222 regs.index_buffer.count = regs.index_buffer16_first.count;
223 regs.index_buffer.first = regs.index_buffer16_first.first;
224 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
225 return ProcessDraw();
226 case MAXWELL3D_REG_INDEX(index_buffer8_first):
227 regs.index_buffer.count = regs.index_buffer8_first.count;
228 regs.index_buffer.first = regs.index_buffer8_first.first;
229 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
230 return ProcessDraw();
219 case MAXWELL3D_REG_INDEX(topology_override): 231 case MAXWELL3D_REG_INDEX(topology_override):
220 use_topology_override = true; 232 use_topology_override = true;
221 return; 233 return;
@@ -583,6 +595,31 @@ void Maxwell3D::ProcessClearBuffers() {
583 rasterizer->Clear(); 595 rasterizer->Clear();
584} 596}
585 597
598void Maxwell3D::ProcessDraw(u32 instance_count) {
599 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
600 regs.vertex_buffer.count);
601
602 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
603
604 // Both instance configuration registers can not be set at the same time.
605 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
606 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
607 "Illegal combination of instancing parameters");
608
609 ProcessTopologyOverride();
610
611 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
612 if (ShouldExecute()) {
613 rasterizer->Draw(is_indexed, instance_count);
614 }
615
616 if (is_indexed) {
617 regs.index_buffer.count = 0;
618 } else {
619 regs.vertex_buffer.count = 0;
620 }
621}
622
586void Maxwell3D::ProcessDeferredDraw() { 623void Maxwell3D::ProcessDeferredDraw() {
587 if (deferred_draw_method.empty()) { 624 if (deferred_draw_method.empty()) {
588 return; 625 return;
@@ -596,23 +633,28 @@ void Maxwell3D::ProcessDeferredDraw() {
596 DrawMode draw_mode{DrawMode::Undefined}; 633 DrawMode draw_mode{DrawMode::Undefined};
597 u32 instance_count = 1; 634 u32 instance_count = 1;
598 635
599 auto first_method = deferred_draw_method[0]; 636 u32 index = 0;
600 if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) { 637 u32 method = 0;
601 // The minimum number of methods for drawing must be greater than or equal to 638 u32 method_count = static_cast<u32>(deferred_draw_method.size());
602 // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing 639 for (; index < method_count &&
603 if (deferred_draw_method.size() < 3) { 640 (method = deferred_draw_method[index]) != MAXWELL3D_REG_INDEX(draw.begin);
604 return; 641 ++index)
605 } 642 ;
606 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || 643
607 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) 644 if (MAXWELL3D_REG_INDEX(draw.begin) != method) {
608 ? DrawMode::Instance 645 return;
609 : DrawMode::General;
610 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
611 MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
612 MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
613 draw_mode = DrawMode::General;
614 } 646 }
615 647
648 // The minimum number of methods for drawing must be greater than or equal to
649 // 3[draw.begin->vertex(index)count(first)->draw.end] to avoid errors in index mode drawing
650 if ((method_count - index) < 3) {
651 return;
652 }
653 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
654 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
655 ? DrawMode::Instance
656 : DrawMode::General;
657
616 // Drawing will only begin with draw.begin or index_buffer method, other methods directly 658 // Drawing will only begin with draw.begin or index_buffer method, other methods directly
617 // clear 659 // clear
618 if (draw_mode == DrawMode::Undefined) { 660 if (draw_mode == DrawMode::Undefined) {
@@ -622,53 +664,18 @@ void Maxwell3D::ProcessDeferredDraw() {
622 664
623 if (draw_mode == DrawMode::Instance) { 665 if (draw_mode == DrawMode::Instance) {
624 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error"); 666 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
625 instance_count = static_cast<u32>(deferred_draw_method.size()) / 4; 667 instance_count = static_cast<u32>(method_count - index) / 4;
626 } else { 668 } else {
627 if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 669 method = deferred_draw_method[index + 1];
628 regs.index_buffer.count = regs.index_buffer32_first.count; 670 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
629 regs.index_buffer.first = regs.index_buffer32_first.first; 671 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
630 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 672 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
631 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 673 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
632 regs.index_buffer.count = regs.index_buffer16_first.count; 674 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
633 regs.index_buffer.first = regs.index_buffer16_first.first;
634 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
635 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
636 regs.index_buffer.count = regs.index_buffer8_first.count;
637 regs.index_buffer.first = regs.index_buffer8_first.first;
638 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
639 } else {
640 auto second_method = deferred_draw_method[1];
641 if (MAXWELL3D_REG_INDEX(draw_inline_index) == second_method ||
642 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == second_method ||
643 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == second_method) {
644 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
645 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
646 }
647 } 675 }
648 } 676 }
649 677
650 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), 678 ProcessDraw(instance_count);
651 regs.vertex_buffer.count);
652
653 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
654
655 // Both instance configuration registers can not be set at the same time.
656 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
657 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
658 "Illegal combination of instancing parameters");
659
660 ProcessTopologyOverride();
661
662 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
663 if (ShouldExecute()) {
664 rasterizer->Draw(is_indexed, instance_count);
665 }
666
667 if (is_indexed) {
668 regs.index_buffer.count = 0;
669 } else {
670 regs.vertex_buffer.count = 0;
671 }
672 679
673 deferred_draw_method.clear(); 680 deferred_draw_method.clear();
674 inline_index_draw_indexes.clear(); 681 inline_index_draw_indexes.clear();
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index bd23ebc12..a948fcb14 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -3143,6 +3143,8 @@ private:
3143 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) 3143 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)
3144 void ProcessTopologyOverride(); 3144 void ProcessTopologyOverride();
3145 3145
3146 void ProcessDraw(u32 instance_count = 1);
3147
3146 void ProcessDeferredDraw(); 3148 void ProcessDeferredDraw();
3147 3149
3148 /// Returns a query's value or an empty object if the value will be deferred through a cache. 3150 /// Returns a query's value or an empty object if the value will be deferred through a cache.