diff options
| author | 2022-02-09 15:00:05 +0100 | |
|---|---|---|
| committer | 2023-01-01 16:43:57 -0500 | |
| commit | a5a94f52ffcbf3119d272a9369021a213ea6dad2 (patch) | |
| tree | ba6d42b142894d0f3f0ac34fb6ce491442bae8fd /src/video_core/macro | |
| parent | Merge pull request #9538 from merryhime/char-concat (diff) | |
| download | yuzu-a5a94f52ffcbf3119d272a9369021a213ea6dad2.tar.gz yuzu-a5a94f52ffcbf3119d272a9369021a213ea6dad2.tar.xz yuzu-a5a94f52ffcbf3119d272a9369021a213ea6dad2.zip | |
MacroHLE: Add MultidrawIndirect HLE Macro.
Diffstat (limited to 'src/video_core/macro')
| -rw-r--r-- | src/video_core/macro/macro_hle.cpp | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 8549db2e4..1cc202cc7 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -53,42 +53,43 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 53 | 53 | ||
| 54 | // Multidraw Indirect | 54 | // Multidraw Indirect |
| 55 | void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 55 | void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { |
| 56 | SCOPE_EXIT({ | ||
| 57 | // Clean everything. | ||
| 58 | maxwell3d.regs.vertex_id_base = 0x0; | ||
| 59 | maxwell3d.CallMethod(0x8e3, 0x640, true); | ||
| 60 | maxwell3d.CallMethod(0x8e4, 0x0, true); | ||
| 61 | maxwell3d.CallMethod(0x8e5, 0x0, true); | ||
| 62 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 63 | }); | ||
| 64 | const u32 start_indirect = parameters[0]; | 56 | const u32 start_indirect = parameters[0]; |
| 65 | const u32 end_indirect = parameters[1]; | 57 | const u32 end_indirect = parameters[1]; |
| 66 | if (start_indirect >= end_indirect) { | 58 | if (start_indirect >= end_indirect) { |
| 67 | // Nothing to do. | 59 | // Nothing to do. |
| 68 | return; | 60 | return; |
| 69 | } | 61 | } |
| 70 | const u32 padding = parameters[3]; | 62 | const auto topology = |
| 71 | const std::size_t max_draws = parameters[4]; | 63 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]); |
| 64 | const u32 padding = parameters[3]; // padding is in words | ||
| 72 | 65 | ||
| 66 | // size of each indirect segment | ||
| 73 | const u32 indirect_words = 5 + padding; | 67 | const u32 indirect_words = 5 + padding; |
| 74 | const std::size_t first_draw = start_indirect; | 68 | const u32 stride = indirect_words * sizeof(u32); |
| 75 | const std::size_t effective_draws = end_indirect - start_indirect; | 69 | const GPUVAddr start_address = maxwell3d.current_dma_segment + 4 * sizeof(u32); |
| 76 | const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws); | 70 | const std::size_t draw_count = end_indirect - start_indirect; |
| 77 | 71 | u32 lowest_first = std::numeric_limits<u32>::max(); | |
| 78 | for (std::size_t index = first_draw; index < last_draw; index++) { | 72 | u32 highest_limit = std::numeric_limits<u32>::min(); |
| 73 | for (std::size_t index = 0; index < draw_count; index++) { | ||
| 79 | const std::size_t base = index * indirect_words + 5; | 74 | const std::size_t base = index * indirect_words + 5; |
| 80 | const u32 base_vertex = parameters[base + 3]; | 75 | const u32 count = parameters[base]; |
| 81 | const u32 base_instance = parameters[base + 4]; | 76 | const u32 first_index = parameters[base + 2]; |
| 82 | maxwell3d.regs.vertex_id_base = base_vertex; | 77 | lowest_first = std::min(lowest_first, first_index); |
| 83 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 78 | highest_limit = std::max(highest_limit, first_index + count); |
| 84 | maxwell3d.CallMethod(0x8e4, base_vertex, true); | ||
| 85 | maxwell3d.CallMethod(0x8e5, base_instance, true); | ||
| 86 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 87 | maxwell3d.draw_manager->DrawIndex( | ||
| 88 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]), | ||
| 89 | parameters[base + 2], parameters[base], base_vertex, base_instance, | ||
| 90 | parameters[base + 1]); | ||
| 91 | } | 79 | } |
| 80 | |||
| 81 | const u32 base_vertex = parameters[8]; | ||
| 82 | const u32 base_instance = parameters[9]; | ||
| 83 | maxwell3d.CallMethod(0x8e3, 0x640, true); | ||
| 84 | maxwell3d.CallMethod(0x8e4, base_vertex, true); | ||
| 85 | maxwell3d.CallMethod(0x8e5, base_instance, true); | ||
| 86 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | ||
| 87 | params.start_address = start_address; | ||
| 88 | params.buffer_size = sizeof(u32) + stride * draw_count; | ||
| 89 | params.max_draw_counts = draw_count; | ||
| 90 | params.stride = stride; | ||
| 91 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 92 | maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, highest_limit); | ||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | // Multi-layer Clear | 95 | // Multi-layer Clear |