summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-12-15 23:57:10 -0800
committerGravatar Yuri Kunde Schlesner2016-12-16 00:16:25 -0800
commitc135317de106c59b0c326395ce15b901f2d4595d (patch)
tree078b4d8296ed4ef83d4d1ef12dc8a1cadf1ac7c2
parentRemove unnecessary cast (diff)
downloadyuzu-c135317de106c59b0c326395ce15b901f2d4595d.tar.gz
yuzu-c135317de106c59b0c326395ce15b901f2d4595d.tar.xz
yuzu-c135317de106c59b0c326395ce15b901f2d4595d.zip
VideoCore/Shader: Extract DebugData out from UnitState
-rw-r--r--src/video_core/command_processor.cpp4
-rw-r--r--src/video_core/shader/debug_data.h8
-rw-r--r--src/video_core/shader/shader.cpp26
-rw-r--r--src/video_core/shader/shader.h5
-rw-r--r--src/video_core/shader/shader_interpreter.cpp146
-rw-r--r--src/video_core/shader/shader_interpreter.h7
-rw-r--r--src/video_core/shader/shader_jit_x64.cpp4
-rw-r--r--src/video_core/shader/shader_jit_x64.h2
8 files changed, 99 insertions, 103 deletions
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 8a5d8533c..04de3e6b1 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -138,7 +138,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
138 if (immediate_attribute_id >= regs.vs.num_input_attributes + 1) { 138 if (immediate_attribute_id >= regs.vs.num_input_attributes + 1) {
139 immediate_attribute_id = 0; 139 immediate_attribute_id = 0;
140 140
141 Shader::UnitState<false> shader_unit; 141 Shader::UnitState shader_unit;
142 g_state.vs.Setup(); 142 g_state.vs.Setup();
143 143
144 // Send to vertex shader 144 // Send to vertex shader
@@ -237,7 +237,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
237 unsigned int vertex_cache_pos = 0; 237 unsigned int vertex_cache_pos = 0;
238 vertex_cache_ids.fill(-1); 238 vertex_cache_ids.fill(-1);
239 239
240 Shader::UnitState<false> shader_unit; 240 Shader::UnitState shader_unit;
241 g_state.vs.Setup(); 241 g_state.vs.Setup();
242 242
243 for (unsigned int index = 0; index < regs.num_vertices; ++index) { 243 for (unsigned int index = 0; index < regs.num_vertices; ++index) {
diff --git a/src/video_core/shader/debug_data.h b/src/video_core/shader/debug_data.h
index b0ccf437d..9e82122e1 100644
--- a/src/video_core/shader/debug_data.h
+++ b/src/video_core/shader/debug_data.h
@@ -19,8 +19,8 @@ struct DebugData;
19template <> 19template <>
20struct DebugData<false> { 20struct DebugData<false> {
21 // TODO: Hide these behind and interface and move them to DebugData<true> 21 // TODO: Hide these behind and interface and move them to DebugData<true>
22 u32 max_offset; ///< maximum program counter ever reached 22 u32 max_offset = 0; ///< maximum program counter ever reached
23 u32 max_opdesc_id; ///< maximum swizzle pattern index ever used 23 u32 max_opdesc_id = 0; ///< maximum swizzle pattern index ever used
24}; 24};
25 25
26template <> 26template <>
@@ -75,8 +75,8 @@ struct DebugData<true> {
75 unsigned mask = 0; 75 unsigned mask = 0;
76 }; 76 };
77 77
78 u32 max_offset; ///< maximum program counter ever reached 78 u32 max_offset = 0; ///< maximum program counter ever reached
79 u32 max_opdesc_id; ///< maximum swizzle pattern index ever used 79 u32 max_opdesc_id = 0; ///< maximum swizzle pattern index ever used
80 80
81 /// List of records for each executed shader instruction 81 /// List of records for each executed shader instruction
82 std::vector<DebugData<true>::Record> records; 82 std::vector<DebugData<true>::Record> records;
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index c7f23dab9..a4aa3c9e0 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -109,15 +109,12 @@ void ShaderSetup::Setup() {
109 109
110MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240)); 110MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240));
111 111
112void ShaderSetup::Run(UnitState<false>& state, const InputVertex& input, int num_attributes) { 112void ShaderSetup::Run(UnitState& state, const InputVertex& input, int num_attributes) {
113 auto& config = g_state.regs.vs; 113 auto& config = g_state.regs.vs;
114 auto& setup = g_state.vs; 114 auto& setup = g_state.vs;
115 115
116 MICROPROFILE_SCOPE(GPU_Shader); 116 MICROPROFILE_SCOPE(GPU_Shader);
117 117
118 state.debug.max_offset = 0;
119 state.debug.max_opdesc_id = 0;
120
121 // Setup input register table 118 // Setup input register table
122 const auto& attribute_register_map = config.input_register_map; 119 const auto& attribute_register_map = config.input_register_map;
123 120
@@ -128,22 +125,23 @@ void ShaderSetup::Run(UnitState<false>& state, const InputVertex& input, int num
128 state.conditional_code[1] = false; 125 state.conditional_code[1] = false;
129 126
130#ifdef ARCHITECTURE_x86_64 127#ifdef ARCHITECTURE_x86_64
131 if (VideoCore::g_shader_jit_enabled) 128 if (VideoCore::g_shader_jit_enabled) {
132 jit_shader->Run(setup, state, config.main_offset); 129 jit_shader->Run(setup, state, config.main_offset);
133 else 130 } else {
134 RunInterpreter(setup, state, config.main_offset); 131 DebugData<false> dummy_debug_data;
132 RunInterpreter(setup, state, dummy_debug_data, config.main_offset);
133 }
135#else 134#else
136 RunInterpreter(setup, state, config.main_offset); 135 DebugData<false> dummy_debug_data;
136 RunInterpreter(setup, state, dummy_debug_data, config.main_offset);
137#endif // ARCHITECTURE_x86_64 137#endif // ARCHITECTURE_x86_64
138} 138}
139 139
140DebugData<true> ShaderSetup::ProduceDebugInfo(const InputVertex& input, int num_attributes, 140DebugData<true> ShaderSetup::ProduceDebugInfo(const InputVertex& input, int num_attributes,
141 const Regs::ShaderConfig& config, 141 const Regs::ShaderConfig& config,
142 const ShaderSetup& setup) { 142 const ShaderSetup& setup) {
143 UnitState<true> state; 143 UnitState state;
144 144 DebugData<true> debug_data;
145 state.debug.max_offset = 0;
146 state.debug.max_opdesc_id = 0;
147 145
148 // Setup input register table 146 // Setup input register table
149 boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero())); 147 boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero()));
@@ -154,8 +152,8 @@ DebugData<true> ShaderSetup::ProduceDebugInfo(const InputVertex& input, int num_
154 state.conditional_code[0] = false; 152 state.conditional_code[0] = false;
155 state.conditional_code[1] = false; 153 state.conditional_code[1] = false;
156 154
157 RunInterpreter(setup, state, config.main_offset); 155 RunInterpreter(setup, state, debug_data, config.main_offset);
158 return state.debug; 156 return debug_data;
159} 157}
160 158
161} // namespace Shader 159} // namespace Shader
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h
index d96724860..2b07759b9 100644
--- a/src/video_core/shader/shader.h
+++ b/src/video_core/shader/shader.h
@@ -94,7 +94,6 @@ static_assert(std::is_pod<OutputRegisters>::value, "Structure is not POD");
94 * single shader unit that processes all shaders serially. Putting the state information in a struct 94 * single shader unit that processes all shaders serially. Putting the state information in a struct
95 * here will make it easier for us to parallelize the shader processing later. 95 * here will make it easier for us to parallelize the shader processing later.
96 */ 96 */
97template <bool Debug>
98struct UnitState { 97struct UnitState {
99 struct Registers { 98 struct Registers {
100 // The registers are accessed by the shader JIT using SSE instructions, and are therefore 99 // The registers are accessed by the shader JIT using SSE instructions, and are therefore
@@ -112,8 +111,6 @@ struct UnitState {
112 // TODO: How many bits do these actually have? 111 // TODO: How many bits do these actually have?
113 s32 address_registers[3]; 112 s32 address_registers[3];
114 113
115 DebugData<Debug> debug;
116
117 static size_t InputOffset(const SourceRegister& reg) { 114 static size_t InputOffset(const SourceRegister& reg) {
118 switch (reg.GetRegisterType()) { 115 switch (reg.GetRegisterType()) {
119 case RegisterType::Input: 116 case RegisterType::Input:
@@ -188,7 +185,7 @@ struct ShaderSetup {
188 * @param input Input vertex into the shader 185 * @param input Input vertex into the shader
189 * @param num_attributes The number of vertex shader attributes 186 * @param num_attributes The number of vertex shader attributes
190 */ 187 */
191 void Run(UnitState<false>& state, const InputVertex& input, int num_attributes); 188 void Run(UnitState& state, const InputVertex& input, int num_attributes);
192 189
193 /** 190 /**
194 * Produce debug information based on the given shader and input vertex 191 * Produce debug information based on the given shader and input vertex
diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp
index 29f3ff684..70db4167e 100644
--- a/src/video_core/shader/shader_interpreter.cpp
+++ b/src/video_core/shader/shader_interpreter.cpp
@@ -39,7 +39,8 @@ struct CallStackElement {
39}; 39};
40 40
41template <bool Debug> 41template <bool Debug>
42void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned offset) { 42void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data,
43 unsigned offset) {
43 // TODO: Is there a maximal size for this? 44 // TODO: Is there a maximal size for this?
44 boost::container::static_vector<CallStackElement, 16> call_stack; 45 boost::container::static_vector<CallStackElement, 16> call_stack;
45 u32 program_counter = offset; 46 u32 program_counter = offset;
@@ -104,11 +105,11 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
104 const Instruction instr = {program_code[program_counter]}; 105 const Instruction instr = {program_code[program_counter]};
105 const SwizzlePattern swizzle = {swizzle_data[instr.common.operand_desc_id]}; 106 const SwizzlePattern swizzle = {swizzle_data[instr.common.operand_desc_id]};
106 107
107 Record<DebugDataRecord::CUR_INSTR>(state.debug, iteration, program_counter); 108 Record<DebugDataRecord::CUR_INSTR>(debug_data, iteration, program_counter);
108 if (iteration > 0) 109 if (iteration > 0)
109 Record<DebugDataRecord::NEXT_INSTR>(state.debug, iteration - 1, program_counter); 110 Record<DebugDataRecord::NEXT_INSTR>(debug_data, iteration - 1, program_counter);
110 111
111 state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + program_counter); 112 debug_data.max_offset = std::max<u32>(debug_data.max_offset, 1 + program_counter);
112 113
113 auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { 114 auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* {
114 switch (source_reg.GetRegisterType()) { 115 switch (source_reg.GetRegisterType()) {
@@ -176,54 +177,54 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
176 ? &state.registers.temporary[instr.common.dest.Value().GetIndex()][0] 177 ? &state.registers.temporary[instr.common.dest.Value().GetIndex()][0]
177 : dummy_vec4_float24; 178 : dummy_vec4_float24;
178 179
179 state.debug.max_opdesc_id = 180 debug_data.max_opdesc_id =
180 std::max<u32>(state.debug.max_opdesc_id, 1 + instr.common.operand_desc_id); 181 std::max<u32>(debug_data.max_opdesc_id, 1 + instr.common.operand_desc_id);
181 182
182 switch (instr.opcode.Value().EffectiveOpCode()) { 183 switch (instr.opcode.Value().EffectiveOpCode()) {
183 case OpCode::Id::ADD: { 184 case OpCode::Id::ADD: {
184 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 185 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
185 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 186 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
186 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 187 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
187 for (int i = 0; i < 4; ++i) { 188 for (int i = 0; i < 4; ++i) {
188 if (!swizzle.DestComponentEnabled(i)) 189 if (!swizzle.DestComponentEnabled(i))
189 continue; 190 continue;
190 191
191 dest[i] = src1[i] + src2[i]; 192 dest[i] = src1[i] + src2[i];
192 } 193 }
193 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 194 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
194 break; 195 break;
195 } 196 }
196 197
197 case OpCode::Id::MUL: { 198 case OpCode::Id::MUL: {
198 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 199 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
199 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 200 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
200 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 201 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
201 for (int i = 0; i < 4; ++i) { 202 for (int i = 0; i < 4; ++i) {
202 if (!swizzle.DestComponentEnabled(i)) 203 if (!swizzle.DestComponentEnabled(i))
203 continue; 204 continue;
204 205
205 dest[i] = src1[i] * src2[i]; 206 dest[i] = src1[i] * src2[i];
206 } 207 }
207 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 208 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
208 break; 209 break;
209 } 210 }
210 211
211 case OpCode::Id::FLR: 212 case OpCode::Id::FLR:
212 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 213 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
213 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 214 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
214 for (int i = 0; i < 4; ++i) { 215 for (int i = 0; i < 4; ++i) {
215 if (!swizzle.DestComponentEnabled(i)) 216 if (!swizzle.DestComponentEnabled(i))
216 continue; 217 continue;
217 218
218 dest[i] = float24::FromFloat32(std::floor(src1[i].ToFloat32())); 219 dest[i] = float24::FromFloat32(std::floor(src1[i].ToFloat32()));
219 } 220 }
220 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 221 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
221 break; 222 break;
222 223
223 case OpCode::Id::MAX: 224 case OpCode::Id::MAX:
224 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 225 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
225 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 226 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
226 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 227 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
227 for (int i = 0; i < 4; ++i) { 228 for (int i = 0; i < 4; ++i) {
228 if (!swizzle.DestComponentEnabled(i)) 229 if (!swizzle.DestComponentEnabled(i))
229 continue; 230 continue;
@@ -233,13 +234,13 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
233 // max(NaN, 0) -> 0 234 // max(NaN, 0) -> 0
234 dest[i] = (src1[i] > src2[i]) ? src1[i] : src2[i]; 235 dest[i] = (src1[i] > src2[i]) ? src1[i] : src2[i];
235 } 236 }
236 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 237 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
237 break; 238 break;
238 239
239 case OpCode::Id::MIN: 240 case OpCode::Id::MIN:
240 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 241 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
241 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 242 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
242 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 243 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
243 for (int i = 0; i < 4; ++i) { 244 for (int i = 0; i < 4; ++i) {
244 if (!swizzle.DestComponentEnabled(i)) 245 if (!swizzle.DestComponentEnabled(i))
245 continue; 246 continue;
@@ -249,16 +250,16 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
249 // min(NaN, 0) -> 0 250 // min(NaN, 0) -> 0
250 dest[i] = (src1[i] < src2[i]) ? src1[i] : src2[i]; 251 dest[i] = (src1[i] < src2[i]) ? src1[i] : src2[i];
251 } 252 }
252 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 253 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
253 break; 254 break;
254 255
255 case OpCode::Id::DP3: 256 case OpCode::Id::DP3:
256 case OpCode::Id::DP4: 257 case OpCode::Id::DP4:
257 case OpCode::Id::DPH: 258 case OpCode::Id::DPH:
258 case OpCode::Id::DPHI: { 259 case OpCode::Id::DPHI: {
259 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 260 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
260 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 261 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
261 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 262 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
262 263
263 OpCode::Id opcode = instr.opcode.Value().EffectiveOpCode(); 264 OpCode::Id opcode = instr.opcode.Value().EffectiveOpCode();
264 if (opcode == OpCode::Id::DPH || opcode == OpCode::Id::DPHI) 265 if (opcode == OpCode::Id::DPH || opcode == OpCode::Id::DPHI)
@@ -274,14 +275,14 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
274 275
275 dest[i] = dot; 276 dest[i] = dot;
276 } 277 }
277 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 278 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
278 break; 279 break;
279 } 280 }
280 281
281 // Reciprocal 282 // Reciprocal
282 case OpCode::Id::RCP: { 283 case OpCode::Id::RCP: {
283 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 284 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
284 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 285 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
285 float24 rcp_res = float24::FromFloat32(1.0f / src1[0].ToFloat32()); 286 float24 rcp_res = float24::FromFloat32(1.0f / src1[0].ToFloat32());
286 for (int i = 0; i < 4; ++i) { 287 for (int i = 0; i < 4; ++i) {
287 if (!swizzle.DestComponentEnabled(i)) 288 if (!swizzle.DestComponentEnabled(i))
@@ -289,14 +290,14 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
289 290
290 dest[i] = rcp_res; 291 dest[i] = rcp_res;
291 } 292 }
292 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 293 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
293 break; 294 break;
294 } 295 }
295 296
296 // Reciprocal Square Root 297 // Reciprocal Square Root
297 case OpCode::Id::RSQ: { 298 case OpCode::Id::RSQ: {
298 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 299 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
299 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 300 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
300 float24 rsq_res = float24::FromFloat32(1.0f / std::sqrt(src1[0].ToFloat32())); 301 float24 rsq_res = float24::FromFloat32(1.0f / std::sqrt(src1[0].ToFloat32()));
301 for (int i = 0; i < 4; ++i) { 302 for (int i = 0; i < 4; ++i) {
302 if (!swizzle.DestComponentEnabled(i)) 303 if (!swizzle.DestComponentEnabled(i))
@@ -304,12 +305,12 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
304 305
305 dest[i] = rsq_res; 306 dest[i] = rsq_res;
306 } 307 }
307 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 308 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
308 break; 309 break;
309 } 310 }
310 311
311 case OpCode::Id::MOVA: { 312 case OpCode::Id::MOVA: {
312 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 313 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
313 for (int i = 0; i < 2; ++i) { 314 for (int i = 0; i < 2; ++i) {
314 if (!swizzle.DestComponentEnabled(i)) 315 if (!swizzle.DestComponentEnabled(i))
315 continue; 316 continue;
@@ -317,29 +318,29 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
317 // TODO: Figure out how the rounding is done on hardware 318 // TODO: Figure out how the rounding is done on hardware
318 state.address_registers[i] = static_cast<s32>(src1[i].ToFloat32()); 319 state.address_registers[i] = static_cast<s32>(src1[i].ToFloat32());
319 } 320 }
320 Record<DebugDataRecord::ADDR_REG_OUT>(state.debug, iteration, 321 Record<DebugDataRecord::ADDR_REG_OUT>(debug_data, iteration,
321 state.address_registers); 322 state.address_registers);
322 break; 323 break;
323 } 324 }
324 325
325 case OpCode::Id::MOV: { 326 case OpCode::Id::MOV: {
326 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 327 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
327 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 328 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
328 for (int i = 0; i < 4; ++i) { 329 for (int i = 0; i < 4; ++i) {
329 if (!swizzle.DestComponentEnabled(i)) 330 if (!swizzle.DestComponentEnabled(i))
330 continue; 331 continue;
331 332
332 dest[i] = src1[i]; 333 dest[i] = src1[i];
333 } 334 }
334 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 335 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
335 break; 336 break;
336 } 337 }
337 338
338 case OpCode::Id::SGE: 339 case OpCode::Id::SGE:
339 case OpCode::Id::SGEI: 340 case OpCode::Id::SGEI:
340 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 341 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
341 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 342 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
342 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 343 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
343 for (int i = 0; i < 4; ++i) { 344 for (int i = 0; i < 4; ++i) {
344 if (!swizzle.DestComponentEnabled(i)) 345 if (!swizzle.DestComponentEnabled(i))
345 continue; 346 continue;
@@ -347,14 +348,14 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
347 dest[i] = (src1[i] >= src2[i]) ? float24::FromFloat32(1.0f) 348 dest[i] = (src1[i] >= src2[i]) ? float24::FromFloat32(1.0f)
348 : float24::FromFloat32(0.0f); 349 : float24::FromFloat32(0.0f);
349 } 350 }
350 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 351 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
351 break; 352 break;
352 353
353 case OpCode::Id::SLT: 354 case OpCode::Id::SLT:
354 case OpCode::Id::SLTI: 355 case OpCode::Id::SLTI:
355 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 356 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
356 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 357 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
357 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 358 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
358 for (int i = 0; i < 4; ++i) { 359 for (int i = 0; i < 4; ++i) {
359 if (!swizzle.DestComponentEnabled(i)) 360 if (!swizzle.DestComponentEnabled(i))
360 continue; 361 continue;
@@ -362,12 +363,12 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
362 dest[i] = (src1[i] < src2[i]) ? float24::FromFloat32(1.0f) 363 dest[i] = (src1[i] < src2[i]) ? float24::FromFloat32(1.0f)
363 : float24::FromFloat32(0.0f); 364 : float24::FromFloat32(0.0f);
364 } 365 }
365 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 366 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
366 break; 367 break;
367 368
368 case OpCode::Id::CMP: 369 case OpCode::Id::CMP:
369 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 370 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
370 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 371 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
371 for (int i = 0; i < 2; ++i) { 372 for (int i = 0; i < 2; ++i) {
372 // TODO: Can you restrict to one compare via dest masking? 373 // TODO: Can you restrict to one compare via dest masking?
373 374
@@ -404,12 +405,12 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
404 break; 405 break;
405 } 406 }
406 } 407 }
407 Record<DebugDataRecord::CMP_RESULT>(state.debug, iteration, state.conditional_code); 408 Record<DebugDataRecord::CMP_RESULT>(debug_data, iteration, state.conditional_code);
408 break; 409 break;
409 410
410 case OpCode::Id::EX2: { 411 case OpCode::Id::EX2: {
411 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 412 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
412 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 413 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
413 414
414 // EX2 only takes first component exp2 and writes it to all dest components 415 // EX2 only takes first component exp2 and writes it to all dest components
415 float24 ex2_res = float24::FromFloat32(std::exp2(src1[0].ToFloat32())); 416 float24 ex2_res = float24::FromFloat32(std::exp2(src1[0].ToFloat32()));
@@ -420,13 +421,13 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
420 dest[i] = ex2_res; 421 dest[i] = ex2_res;
421 } 422 }
422 423
423 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 424 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
424 break; 425 break;
425 } 426 }
426 427
427 case OpCode::Id::LG2: { 428 case OpCode::Id::LG2: {
428 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 429 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
429 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 430 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
430 431
431 // LG2 only takes the first component log2 and writes it to all dest components 432 // LG2 only takes the first component log2 and writes it to all dest components
432 float24 lg2_res = float24::FromFloat32(std::log2(src1[0].ToFloat32())); 433 float24 lg2_res = float24::FromFloat32(std::log2(src1[0].ToFloat32()));
@@ -437,7 +438,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
437 dest[i] = lg2_res; 438 dest[i] = lg2_res;
438 } 439 }
439 440
440 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 441 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
441 break; 442 break;
442 } 443 }
443 444
@@ -519,17 +520,17 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
519 ? &state.registers.temporary[instr.mad.dest.Value().GetIndex()][0] 520 ? &state.registers.temporary[instr.mad.dest.Value().GetIndex()][0]
520 : dummy_vec4_float24; 521 : dummy_vec4_float24;
521 522
522 Record<DebugDataRecord::SRC1>(state.debug, iteration, src1); 523 Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
523 Record<DebugDataRecord::SRC2>(state.debug, iteration, src2); 524 Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
524 Record<DebugDataRecord::SRC3>(state.debug, iteration, src3); 525 Record<DebugDataRecord::SRC3>(debug_data, iteration, src3);
525 Record<DebugDataRecord::DEST_IN>(state.debug, iteration, dest); 526 Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
526 for (int i = 0; i < 4; ++i) { 527 for (int i = 0; i < 4; ++i) {
527 if (!swizzle.DestComponentEnabled(i)) 528 if (!swizzle.DestComponentEnabled(i))
528 continue; 529 continue;
529 530
530 dest[i] = src1[i] * src2[i] + src3[i]; 531 dest[i] = src1[i] * src2[i] + src3[i];
531 } 532 }
532 Record<DebugDataRecord::DEST_OUT>(state.debug, iteration, dest); 533 Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
533 } else { 534 } else {
534 LOG_ERROR(HW_GPU, "Unhandled multiply-add instruction: 0x%02x (%s): 0x%08x", 535 LOG_ERROR(HW_GPU, "Unhandled multiply-add instruction: 0x%02x (%s): 0x%08x",
535 (int)instr.opcode.Value().EffectiveOpCode(), 536 (int)instr.opcode.Value().EffectiveOpCode(),
@@ -546,8 +547,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
546 break; 547 break;
547 548
548 case OpCode::Id::JMPC: 549 case OpCode::Id::JMPC:
549 Record<DebugDataRecord::COND_CMP_IN>(state.debug, iteration, 550 Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
550 state.conditional_code);
551 if (evaluate_condition(instr.flow_control)) { 551 if (evaluate_condition(instr.flow_control)) {
552 program_counter = instr.flow_control.dest_offset - 1; 552 program_counter = instr.flow_control.dest_offset - 1;
553 } 553 }
@@ -555,7 +555,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
555 555
556 case OpCode::Id::JMPU: 556 case OpCode::Id::JMPU:
557 Record<DebugDataRecord::COND_BOOL_IN>( 557 Record<DebugDataRecord::COND_BOOL_IN>(
558 state.debug, iteration, uniforms.b[instr.flow_control.bool_uniform_id]); 558 debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
559 559
560 if (uniforms.b[instr.flow_control.bool_uniform_id] == 560 if (uniforms.b[instr.flow_control.bool_uniform_id] ==
561 !(instr.flow_control.num_instructions & 1)) { 561 !(instr.flow_control.num_instructions & 1)) {
@@ -570,7 +570,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
570 570
571 case OpCode::Id::CALLU: 571 case OpCode::Id::CALLU:
572 Record<DebugDataRecord::COND_BOOL_IN>( 572 Record<DebugDataRecord::COND_BOOL_IN>(
573 state.debug, iteration, uniforms.b[instr.flow_control.bool_uniform_id]); 573 debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
574 if (uniforms.b[instr.flow_control.bool_uniform_id]) { 574 if (uniforms.b[instr.flow_control.bool_uniform_id]) {
575 call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, 575 call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
576 program_counter + 1, 0, 0); 576 program_counter + 1, 0, 0);
@@ -578,8 +578,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
578 break; 578 break;
579 579
580 case OpCode::Id::CALLC: 580 case OpCode::Id::CALLC:
581 Record<DebugDataRecord::COND_CMP_IN>(state.debug, iteration, 581 Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
582 state.conditional_code);
583 if (evaluate_condition(instr.flow_control)) { 582 if (evaluate_condition(instr.flow_control)) {
584 call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, 583 call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
585 program_counter + 1, 0, 0); 584 program_counter + 1, 0, 0);
@@ -591,7 +590,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
591 590
592 case OpCode::Id::IFU: 591 case OpCode::Id::IFU:
593 Record<DebugDataRecord::COND_BOOL_IN>( 592 Record<DebugDataRecord::COND_BOOL_IN>(
594 state.debug, iteration, uniforms.b[instr.flow_control.bool_uniform_id]); 593 debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
595 if (uniforms.b[instr.flow_control.bool_uniform_id]) { 594 if (uniforms.b[instr.flow_control.bool_uniform_id]) {
596 call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1, 595 call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1,
597 instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 596 instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
@@ -607,8 +606,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
607 case OpCode::Id::IFC: { 606 case OpCode::Id::IFC: {
608 // TODO: Do we need to consider swizzlers here? 607 // TODO: Do we need to consider swizzlers here?
609 608
610 Record<DebugDataRecord::COND_CMP_IN>(state.debug, iteration, 609 Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
611 state.conditional_code);
612 if (evaluate_condition(instr.flow_control)) { 610 if (evaluate_condition(instr.flow_control)) {
613 call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1, 611 call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1,
614 instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 612 instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
@@ -629,7 +627,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
629 uniforms.i[instr.flow_control.int_uniform_id].w); 627 uniforms.i[instr.flow_control.int_uniform_id].w);
630 state.address_registers[2] = loop_param.y; 628 state.address_registers[2] = loop_param.y;
631 629
632 Record<DebugDataRecord::LOOP_INT_IN>(state.debug, iteration, loop_param); 630 Record<DebugDataRecord::LOOP_INT_IN>(debug_data, iteration, loop_param);
633 call(program_counter + 1, instr.flow_control.dest_offset - program_counter + 1, 631 call(program_counter + 1, instr.flow_control.dest_offset - program_counter + 1,
634 instr.flow_control.dest_offset + 1, loop_param.x, loop_param.z); 632 instr.flow_control.dest_offset + 1, loop_param.x, loop_param.z);
635 break; 633 break;
@@ -652,8 +650,8 @@ void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned
652} 650}
653 651
654// Explicit instantiation 652// Explicit instantiation
655template void RunInterpreter(const ShaderSetup& setup, UnitState<false>& state, unsigned offset); 653template void RunInterpreter(const ShaderSetup&, UnitState&, DebugData<false>&, unsigned offset);
656template void RunInterpreter(const ShaderSetup& setup, UnitState<true>& state, unsigned offset); 654template void RunInterpreter(const ShaderSetup&, UnitState&, DebugData<true>&, unsigned offset);
657 655
658} // namespace 656} // namespace
659 657
diff --git a/src/video_core/shader/shader_interpreter.h b/src/video_core/shader/shader_interpreter.h
index 48ede0a2e..d31dcd7a6 100644
--- a/src/video_core/shader/shader_interpreter.h
+++ b/src/video_core/shader/shader_interpreter.h
@@ -8,11 +8,14 @@ namespace Pica {
8 8
9namespace Shader { 9namespace Shader {
10 10
11template <bool Debug>
12struct UnitState; 11struct UnitState;
13 12
14template <bool Debug> 13template <bool Debug>
15void RunInterpreter(const ShaderSetup& setup, UnitState<Debug>& state, unsigned offset); 14struct DebugData;
15
16template <bool Debug>
17void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data,
18 unsigned offset);
16 19
17} // namespace 20} // namespace
18 21
diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp
index 65898035e..c588b778b 100644
--- a/src/video_core/shader/shader_jit_x64.cpp
+++ b/src/video_core/shader/shader_jit_x64.cpp
@@ -188,7 +188,7 @@ void JitShader::Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRe
188 src_offset = ShaderSetup::GetFloatUniformOffset(src_reg.GetIndex()); 188 src_offset = ShaderSetup::GetFloatUniformOffset(src_reg.GetIndex());
189 } else { 189 } else {
190 src_ptr = STATE; 190 src_ptr = STATE;
191 src_offset = UnitState<false>::InputOffset(src_reg); 191 src_offset = UnitState::InputOffset(src_reg);
192 } 192 }
193 193
194 int src_offset_disp = (int)src_offset; 194 int src_offset_disp = (int)src_offset;
@@ -266,7 +266,7 @@ void JitShader::Compile_DestEnable(Instruction instr, Xmm src) {
266 266
267 SwizzlePattern swiz = {g_state.vs.swizzle_data[operand_desc_id]}; 267 SwizzlePattern swiz = {g_state.vs.swizzle_data[operand_desc_id]};
268 268
269 size_t dest_offset_disp = UnitState<false>::OutputOffset(dest); 269 size_t dest_offset_disp = UnitState::OutputOffset(dest);
270 270
271 // If all components are enabled, write the result to the destination register 271 // If all components are enabled, write the result to the destination register
272 if (swiz.dest_mask == NO_DEST_REG_MASK) { 272 if (swiz.dest_mask == NO_DEST_REG_MASK) {
diff --git a/src/video_core/shader/shader_jit_x64.h b/src/video_core/shader/shader_jit_x64.h
index e0ecde3f2..f37548306 100644
--- a/src/video_core/shader/shader_jit_x64.h
+++ b/src/video_core/shader/shader_jit_x64.h
@@ -34,7 +34,7 @@ class JitShader : public Xbyak::CodeGenerator {
34public: 34public:
35 JitShader(); 35 JitShader();
36 36
37 void Run(const ShaderSetup& setup, UnitState<false>& state, unsigned offset) const { 37 void Run(const ShaderSetup& setup, UnitState& state, unsigned offset) const {
38 program(&setup, &state, instruction_labels[offset].getAddress()); 38 program(&setup, &state, instruction_labels[offset].getAddress());
39 } 39 }
40 40