diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 129 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 2 |
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 | ||
| 598 | void 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 | |||
| 586 | void Maxwell3D::ProcessDeferredDraw() { | 623 | void 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. |