summaryrefslogtreecommitdiff
path: root/src/video_core/shader/shader.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader/shader.h')
-rw-r--r--src/video_core/shader/shader.h92
1 files changed, 48 insertions, 44 deletions
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h
index fee16df62..830d933a8 100644
--- a/src/video_core/shader/shader.h
+++ b/src/video_core/shader/shader.h
@@ -94,46 +94,46 @@ struct OutputRegisters {
94static_assert(std::is_pod<OutputRegisters>::value, "Structure is not POD"); 94static_assert(std::is_pod<OutputRegisters>::value, "Structure is not POD");
95 95
96// Helper structure used to keep track of data useful for inspection of shader emulation 96// Helper structure used to keep track of data useful for inspection of shader emulation
97template<bool full_debugging> 97template <bool full_debugging>
98struct DebugData; 98struct DebugData;
99 99
100template<> 100template <>
101struct DebugData<false> { 101struct DebugData<false> {
102 // TODO: Hide these behind and interface and move them to DebugData<true> 102 // TODO: Hide these behind and interface and move them to DebugData<true>
103 u32 max_offset; // maximum program counter ever reached 103 u32 max_offset; // maximum program counter ever reached
104 u32 max_opdesc_id; // maximum swizzle pattern index ever used 104 u32 max_opdesc_id; // maximum swizzle pattern index ever used
105}; 105};
106 106
107template<> 107template <>
108struct DebugData<true> { 108struct DebugData<true> {
109 // Records store the input and output operands of a particular instruction. 109 // Records store the input and output operands of a particular instruction.
110 struct Record { 110 struct Record {
111 enum Type { 111 enum Type {
112 // Floating point arithmetic operands 112 // Floating point arithmetic operands
113 SRC1 = 0x1, 113 SRC1 = 0x1,
114 SRC2 = 0x2, 114 SRC2 = 0x2,
115 SRC3 = 0x4, 115 SRC3 = 0x4,
116 116
117 // Initial and final output operand value 117 // Initial and final output operand value
118 DEST_IN = 0x8, 118 DEST_IN = 0x8,
119 DEST_OUT = 0x10, 119 DEST_OUT = 0x10,
120 120
121 // Current and next instruction offset (in words) 121 // Current and next instruction offset (in words)
122 CUR_INSTR = 0x20, 122 CUR_INSTR = 0x20,
123 NEXT_INSTR = 0x40, 123 NEXT_INSTR = 0x40,
124 124
125 // Output address register value 125 // Output address register value
126 ADDR_REG_OUT = 0x80, 126 ADDR_REG_OUT = 0x80,
127 127
128 // Result of a comparison instruction 128 // Result of a comparison instruction
129 CMP_RESULT = 0x100, 129 CMP_RESULT = 0x100,
130 130
131 // Input values for conditional flow control instructions 131 // Input values for conditional flow control instructions
132 COND_BOOL_IN = 0x200, 132 COND_BOOL_IN = 0x200,
133 COND_CMP_IN = 0x400, 133 COND_CMP_IN = 0x400,
134 134
135 // Input values for a loop 135 // Input values for a loop
136 LOOP_INT_IN = 0x800, 136 LOOP_INT_IN = 0x800,
137 }; 137 };
138 138
139 Math::Vec4<float24> src1; 139 Math::Vec4<float24> src1;
@@ -156,7 +156,7 @@ struct DebugData<true> {
156 unsigned mask = 0; 156 unsigned mask = 0;
157 }; 157 };
158 158
159 u32 max_offset; // maximum program counter ever reached 159 u32 max_offset; // maximum program counter ever reached
160 u32 max_opdesc_id; // maximum swizzle pattern index ever used 160 u32 max_opdesc_id; // maximum swizzle pattern index ever used
161 161
162 // List of records for each executed shader instruction 162 // List of records for each executed shader instruction
@@ -167,10 +167,10 @@ struct DebugData<true> {
167using DebugDataRecord = DebugData<true>::Record; 167using DebugDataRecord = DebugData<true>::Record;
168 168
169// Helper function to set a DebugData<true>::Record field based on the template enum parameter. 169// Helper function to set a DebugData<true>::Record field based on the template enum parameter.
170template<DebugDataRecord::Type type, typename ValueType> 170template <DebugDataRecord::Type type, typename ValueType>
171inline void SetField(DebugDataRecord& record, ValueType value); 171inline void SetField(DebugDataRecord& record, ValueType value);
172 172
173template<> 173template <>
174inline void SetField<DebugDataRecord::SRC1>(DebugDataRecord& record, float24* value) { 174inline void SetField<DebugDataRecord::SRC1>(DebugDataRecord& record, float24* value) {
175 record.src1.x = value[0]; 175 record.src1.x = value[0];
176 record.src1.y = value[1]; 176 record.src1.y = value[1];
@@ -178,7 +178,7 @@ inline void SetField<DebugDataRecord::SRC1>(DebugDataRecord& record, float24* va
178 record.src1.w = value[3]; 178 record.src1.w = value[3];
179} 179}
180 180
181template<> 181template <>
182inline void SetField<DebugDataRecord::SRC2>(DebugDataRecord& record, float24* value) { 182inline void SetField<DebugDataRecord::SRC2>(DebugDataRecord& record, float24* value) {
183 record.src2.x = value[0]; 183 record.src2.x = value[0];
184 record.src2.y = value[1]; 184 record.src2.y = value[1];
@@ -186,7 +186,7 @@ inline void SetField<DebugDataRecord::SRC2>(DebugDataRecord& record, float24* va
186 record.src2.w = value[3]; 186 record.src2.w = value[3];
187} 187}
188 188
189template<> 189template <>
190inline void SetField<DebugDataRecord::SRC3>(DebugDataRecord& record, float24* value) { 190inline void SetField<DebugDataRecord::SRC3>(DebugDataRecord& record, float24* value) {
191 record.src3.x = value[0]; 191 record.src3.x = value[0];
192 record.src3.y = value[1]; 192 record.src3.y = value[1];
@@ -194,7 +194,7 @@ inline void SetField<DebugDataRecord::SRC3>(DebugDataRecord& record, float24* va
194 record.src3.w = value[3]; 194 record.src3.w = value[3];
195} 195}
196 196
197template<> 197template <>
198inline void SetField<DebugDataRecord::DEST_IN>(DebugDataRecord& record, float24* value) { 198inline void SetField<DebugDataRecord::DEST_IN>(DebugDataRecord& record, float24* value) {
199 record.dest_in.x = value[0]; 199 record.dest_in.x = value[0];
200 record.dest_in.y = value[1]; 200 record.dest_in.y = value[1];
@@ -202,7 +202,7 @@ inline void SetField<DebugDataRecord::DEST_IN>(DebugDataRecord& record, float24*
202 record.dest_in.w = value[3]; 202 record.dest_in.w = value[3];
203} 203}
204 204
205template<> 205template <>
206inline void SetField<DebugDataRecord::DEST_OUT>(DebugDataRecord& record, float24* value) { 206inline void SetField<DebugDataRecord::DEST_OUT>(DebugDataRecord& record, float24* value) {
207 record.dest_out.x = value[0]; 207 record.dest_out.x = value[0];
208 record.dest_out.y = value[1]; 208 record.dest_out.y = value[1];
@@ -210,67 +210,66 @@ inline void SetField<DebugDataRecord::DEST_OUT>(DebugDataRecord& record, float24
210 record.dest_out.w = value[3]; 210 record.dest_out.w = value[3];
211} 211}
212 212
213template<> 213template <>
214inline void SetField<DebugDataRecord::ADDR_REG_OUT>(DebugDataRecord& record, s32* value) { 214inline void SetField<DebugDataRecord::ADDR_REG_OUT>(DebugDataRecord& record, s32* value) {
215 record.address_registers[0] = value[0]; 215 record.address_registers[0] = value[0];
216 record.address_registers[1] = value[1]; 216 record.address_registers[1] = value[1];
217} 217}
218 218
219template<> 219template <>
220inline void SetField<DebugDataRecord::CMP_RESULT>(DebugDataRecord& record, bool* value) { 220inline void SetField<DebugDataRecord::CMP_RESULT>(DebugDataRecord& record, bool* value) {
221 record.conditional_code[0] = value[0]; 221 record.conditional_code[0] = value[0];
222 record.conditional_code[1] = value[1]; 222 record.conditional_code[1] = value[1];
223} 223}
224 224
225template<> 225template <>
226inline void SetField<DebugDataRecord::COND_BOOL_IN>(DebugDataRecord& record, bool value) { 226inline void SetField<DebugDataRecord::COND_BOOL_IN>(DebugDataRecord& record, bool value) {
227 record.cond_bool = value; 227 record.cond_bool = value;
228} 228}
229 229
230template<> 230template <>
231inline void SetField<DebugDataRecord::COND_CMP_IN>(DebugDataRecord& record, bool* value) { 231inline void SetField<DebugDataRecord::COND_CMP_IN>(DebugDataRecord& record, bool* value) {
232 record.cond_cmp[0] = value[0]; 232 record.cond_cmp[0] = value[0];
233 record.cond_cmp[1] = value[1]; 233 record.cond_cmp[1] = value[1];
234} 234}
235 235
236template<> 236template <>
237inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record, Math::Vec4<u8> value) { 237inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record, Math::Vec4<u8> value) {
238 record.loop_int = value; 238 record.loop_int = value;
239} 239}
240 240
241template<> 241template <>
242inline void SetField<DebugDataRecord::CUR_INSTR>(DebugDataRecord& record, u32 value) { 242inline void SetField<DebugDataRecord::CUR_INSTR>(DebugDataRecord& record, u32 value) {
243 record.instruction_offset = value; 243 record.instruction_offset = value;
244} 244}
245 245
246template<> 246template <>
247inline void SetField<DebugDataRecord::NEXT_INSTR>(DebugDataRecord& record, u32 value) { 247inline void SetField<DebugDataRecord::NEXT_INSTR>(DebugDataRecord& record, u32 value) {
248 record.next_instruction = value; 248 record.next_instruction = value;
249} 249}
250 250
251// Helper function to set debug information on the current shader iteration. 251// Helper function to set debug information on the current shader iteration.
252template<DebugDataRecord::Type type, typename ValueType> 252template <DebugDataRecord::Type type, typename ValueType>
253inline void Record(DebugData<false>& debug_data, u32 offset, ValueType value) { 253inline void Record(DebugData<false>& debug_data, u32 offset, ValueType value) {
254 // Debugging disabled => nothing to do 254 // Debugging disabled => nothing to do
255} 255}
256 256
257template<DebugDataRecord::Type type, typename ValueType> 257template <DebugDataRecord::Type type, typename ValueType>
258inline void Record(DebugData<true>& debug_data, u32 offset, ValueType value) { 258inline void Record(DebugData<true>& debug_data, u32 offset, ValueType value) {
259 if (offset >= debug_data.records.size()) 259 if (offset >= debug_data.records.size())
260 debug_data.records.resize(offset + 1); 260 debug_data.records.resize(offset + 1);
261 261
262 SetField<type, ValueType>(debug_data.records[offset], value); 262 SetField<type, ValueType>(debug_data.records[offset], value);
263 debug_data.records[offset].mask |= type; 263 debug_data.records[offset].mask |= type;
264} 264}
265 265
266
267/** 266/**
268 * This structure contains the state information that needs to be unique for a shader unit. The 3DS 267 * This structure contains the state information that needs to be unique for a shader unit. The 3DS
269 * has four shader units that process shaders in parallel. At the present, Citra only implements a 268 * has four shader units that process shaders in parallel. At the present, Citra only implements a
270 * single shader unit that processes all shaders serially. Putting the state information in a struct 269 * single shader unit that processes all shaders serially. Putting the state information in a struct
271 * here will make it easier for us to parallelize the shader processing later. 270 * here will make it easier for us to parallelize the shader processing later.
272 */ 271 */
273template<bool Debug> 272template <bool Debug>
274struct UnitState { 273struct UnitState {
275 struct Registers { 274 struct Registers {
276 // The registers are accessed by the shader JIT using SSE instructions, and are therefore 275 // The registers are accessed by the shader JIT using SSE instructions, and are therefore
@@ -293,10 +292,12 @@ struct UnitState {
293 static size_t InputOffset(const SourceRegister& reg) { 292 static size_t InputOffset(const SourceRegister& reg) {
294 switch (reg.GetRegisterType()) { 293 switch (reg.GetRegisterType()) {
295 case RegisterType::Input: 294 case RegisterType::Input:
296 return offsetof(UnitState, registers.input) + reg.GetIndex()*sizeof(Math::Vec4<float24>); 295 return offsetof(UnitState, registers.input) +
296 reg.GetIndex() * sizeof(Math::Vec4<float24>);
297 297
298 case RegisterType::Temporary: 298 case RegisterType::Temporary:
299 return offsetof(UnitState, registers.temporary) + reg.GetIndex()*sizeof(Math::Vec4<float24>); 299 return offsetof(UnitState, registers.temporary) +
300 reg.GetIndex() * sizeof(Math::Vec4<float24>);
300 301
301 default: 302 default:
302 UNREACHABLE(); 303 UNREACHABLE();
@@ -307,10 +308,12 @@ struct UnitState {
307 static size_t OutputOffset(const DestRegister& reg) { 308 static size_t OutputOffset(const DestRegister& reg) {
308 switch (reg.GetRegisterType()) { 309 switch (reg.GetRegisterType()) {
309 case RegisterType::Output: 310 case RegisterType::Output:
310 return offsetof(UnitState, output_registers.value) + reg.GetIndex()*sizeof(Math::Vec4<float24>); 311 return offsetof(UnitState, output_registers.value) +
312 reg.GetIndex() * sizeof(Math::Vec4<float24>);
311 313
312 case RegisterType::Temporary: 314 case RegisterType::Temporary:
313 return offsetof(UnitState, registers.temporary) + reg.GetIndex()*sizeof(Math::Vec4<float24>); 315 return offsetof(UnitState, registers.temporary) +
316 reg.GetIndex() * sizeof(Math::Vec4<float24>);
314 317
315 default: 318 default:
316 UNREACHABLE(); 319 UNREACHABLE();
@@ -336,13 +339,13 @@ struct ShaderSetup {
336 static size_t UniformOffset(RegisterType type, unsigned index) { 339 static size_t UniformOffset(RegisterType type, unsigned index) {
337 switch (type) { 340 switch (type) {
338 case RegisterType::FloatUniform: 341 case RegisterType::FloatUniform:
339 return offsetof(ShaderSetup, uniforms.f) + index*sizeof(Math::Vec4<float24>); 342 return offsetof(ShaderSetup, uniforms.f) + index * sizeof(Math::Vec4<float24>);
340 343
341 case RegisterType::BoolUniform: 344 case RegisterType::BoolUniform:
342 return offsetof(ShaderSetup, uniforms.b) + index*sizeof(bool); 345 return offsetof(ShaderSetup, uniforms.b) + index * sizeof(bool);
343 346
344 case RegisterType::IntUniform: 347 case RegisterType::IntUniform:
345 return offsetof(ShaderSetup, uniforms.i) + index*sizeof(Math::Vec4<u8>); 348 return offsetof(ShaderSetup, uniforms.i) + index * sizeof(Math::Vec4<u8>);
346 349
347 default: 350 default:
348 UNREACHABLE(); 351 UNREACHABLE();
@@ -354,7 +357,8 @@ struct ShaderSetup {
354 std::array<u32, 1024> swizzle_data; 357 std::array<u32, 1024> swizzle_data;
355 358
356 /** 359 /**
357 * Performs any shader unit setup that only needs to happen once per shader (as opposed to once per 360 * Performs any shader unit setup that only needs to happen once per shader (as opposed to once
361 * per
358 * vertex, which would happen within the `Run` function). 362 * vertex, which would happen within the `Run` function).
359 */ 363 */
360 void Setup(); 364 void Setup();
@@ -375,8 +379,8 @@ struct ShaderSetup {
375 * @param setup Setup object for the shader pipeline 379 * @param setup Setup object for the shader pipeline
376 * @return Debug information for this shader with regards to the given vertex 380 * @return Debug information for this shader with regards to the given vertex
377 */ 381 */
378 DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const ShaderSetup& setup); 382 DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes,
379 383 const Regs::ShaderConfig& config, const ShaderSetup& setup);
380}; 384};
381 385
382} // namespace Shader 386} // namespace Shader