summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/macro/macro_hle.cpp63
1 files changed, 62 insertions, 1 deletions
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index 58382755b..cabe8dcbf 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -3,6 +3,8 @@
3 3
4#include <array> 4#include <array>
5#include <vector> 5#include <vector>
6#include "common/scope_exit.h"
7#include "video_core/dirty_flags.h"
6#include "video_core/engines/maxwell_3d.h" 8#include "video_core/engines/maxwell_3d.h"
7#include "video_core/macro/macro.h" 9#include "video_core/macro/macro.h"
8#include "video_core/macro/macro_hle.h" 10#include "video_core/macro/macro_hle.h"
@@ -58,6 +60,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
58 maxwell3d.regs.index_array.first = parameters[3]; 60 maxwell3d.regs.index_array.first = parameters[3];
59 maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base? 61 maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
60 maxwell3d.regs.index_array.count = parameters[1]; 62 maxwell3d.regs.index_array.count = parameters[1];
63 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
61 maxwell3d.regs.vb_element_base = element_base; 64 maxwell3d.regs.vb_element_base = element_base;
62 maxwell3d.regs.vb_base_instance = base_instance; 65 maxwell3d.regs.vb_base_instance = base_instance;
63 maxwell3d.mme_draw.instance_count = instance_count; 66 maxwell3d.mme_draw.instance_count = instance_count;
@@ -80,10 +83,67 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
80 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 83 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
81} 84}
82 85
83constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{ 86// Multidraw Indirect
87void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
88 SCOPE_EXIT({
89 // Clean everything.
90 maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
91 maxwell3d.regs.index_array.count = 0;
92 maxwell3d.regs.vb_element_base = 0x0;
93 maxwell3d.regs.vb_base_instance = 0x0;
94 maxwell3d.mme_draw.instance_count = 0;
95 maxwell3d.CallMethodFromMME(0x8e3, 0x640);
96 maxwell3d.CallMethodFromMME(0x8e4, 0x0);
97 maxwell3d.CallMethodFromMME(0x8e5, 0x0);
98 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
99 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
100 });
101 const u32 start_indirect = parameters[0];
102 const u32 end_indirect = parameters[1];
103 if (start_indirect >= end_indirect) {
104 // Nothing to do.
105 return;
106 }
107 const auto topology =
108 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]);
109 maxwell3d.regs.draw.topology.Assign(topology);
110 const u32 padding = parameters[3];
111 const std::size_t max_draws = parameters[4];
112
113 const u32 indirect_words = 5 + padding;
114 const std::size_t first_draw = start_indirect;
115 const std::size_t effective_draws = end_indirect - start_indirect;
116 const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws);
117
118 for (std::size_t index = first_draw; index < last_draw; index++) {
119 const std::size_t base = index * indirect_words + 5;
120 const u32 num_vertices = parameters[base];
121 const u32 instance_count = parameters[base + 1];
122 const u32 first_index = parameters[base + 2];
123 const u32 base_vertex = parameters[base + 3];
124 const u32 base_instance = parameters[base + 4];
125 maxwell3d.regs.index_array.first = first_index;
126 maxwell3d.regs.reg_array[0x446] = base_vertex;
127 maxwell3d.regs.index_array.count = num_vertices;
128 maxwell3d.regs.vb_element_base = base_vertex;
129 maxwell3d.regs.vb_base_instance = base_instance;
130 maxwell3d.mme_draw.instance_count = instance_count;
131 maxwell3d.CallMethodFromMME(0x8e3, 0x640);
132 maxwell3d.CallMethodFromMME(0x8e4, base_vertex);
133 maxwell3d.CallMethodFromMME(0x8e5, base_instance);
134 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
135 if (maxwell3d.ShouldExecute()) {
136 maxwell3d.Rasterizer().Draw(true, true);
137 }
138 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
139 }
140}
141
142constexpr std::array<std::pair<u64, HLEFunction>, 4> hle_funcs{{
84 {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, 143 {0x771BB18C62444DA0, &HLE_771BB18C62444DA0},
85 {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, 144 {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD},
86 {0x0217920100488FF7, &HLE_0217920100488FF7}, 145 {0x0217920100488FF7, &HLE_0217920100488FF7},
146 {0x3F5E74B9C9A50164, &HLE_3F5E74B9C9A50164},
87}}; 147}};
88 148
89class HLEMacroImpl final : public CachedMacro { 149class HLEMacroImpl final : public CachedMacro {
@@ -99,6 +159,7 @@ private:
99 Engines::Maxwell3D& maxwell3d; 159 Engines::Maxwell3D& maxwell3d;
100 HLEFunction func; 160 HLEFunction func;
101}; 161};
162
102} // Anonymous namespace 163} // Anonymous namespace
103 164
104HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} 165HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {}