summaryrefslogtreecommitdiff
path: root/src/video_core/vertex_shader.cpp
diff options
context:
space:
mode:
authorGravatar darkf2014-12-29 19:47:41 -0800
committerGravatar darkf2014-12-29 19:47:41 -0800
commit8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch)
treef1c7c3393fa726435b5b90bf335567c93e528ef1 /src/video_core/vertex_shader.cpp
parentAdd comment regarding __WIN32__ in SkyEye code (diff)
parentMerge pull request #367 from bunnei/usat_ssat (diff)
downloadyuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip
Fix merge conflicts
Diffstat (limited to 'src/video_core/vertex_shader.cpp')
-rw-r--r--src/video_core/vertex_shader.cpp358
1 files changed, 285 insertions, 73 deletions
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 96625791c..bed5081a0 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -1,12 +1,26 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <stack>
6
7#include <boost/range/algorithm.hpp>
8
9#include <common/file_util.h>
10
11#include <core/mem_map.h>
12
13#include <nihstro/shader_bytecode.h>
14
15
5#include "pica.h" 16#include "pica.h"
6#include "vertex_shader.h" 17#include "vertex_shader.h"
7#include "debug_utils/debug_utils.h" 18#include "debug_utils/debug_utils.h"
8#include <core/mem_map.h> 19
9#include <common/file_util.h> 20using nihstro::Instruction;
21using nihstro::RegisterType;
22using nihstro::SourceRegister;
23using nihstro::SwizzlePattern;
10 24
11namespace Pica { 25namespace Pica {
12 26
@@ -14,13 +28,14 @@ namespace VertexShader {
14 28
15static struct { 29static struct {
16 Math::Vec4<float24> f[96]; 30 Math::Vec4<float24> f[96];
17} shader_uniforms;
18 31
32 std::array<bool,16> b;
33} shader_uniforms;
19 34
20// TODO: Not sure where the shader binary and swizzle patterns are supposed to be loaded to! 35// TODO: Not sure where the shader binary and swizzle patterns are supposed to be loaded to!
21// For now, we just keep these local arrays around. 36// For now, we just keep these local arrays around.
22static u32 shader_memory[1024]; 37static std::array<u32, 1024> shader_memory;
23static u32 swizzle_data[1024]; 38static std::array<u32, 1024> swizzle_data;
24 39
25void SubmitShaderMemoryChange(u32 addr, u32 value) 40void SubmitShaderMemoryChange(u32 addr, u32 value)
26{ 41{
@@ -37,6 +52,21 @@ Math::Vec4<float24>& GetFloatUniform(u32 index)
37 return shader_uniforms.f[index]; 52 return shader_uniforms.f[index];
38} 53}
39 54
55bool& GetBoolUniform(u32 index)
56{
57 return shader_uniforms.b[index];
58}
59
60const std::array<u32, 1024>& GetShaderBinary()
61{
62 return shader_memory;
63}
64
65const std::array<u32, 1024>& GetSwizzlePatterns()
66{
67 return swizzle_data;
68}
69
40struct VertexShaderState { 70struct VertexShaderState {
41 u32* program_counter; 71 u32* program_counter;
42 72
@@ -44,13 +74,23 @@ struct VertexShaderState {
44 float24* output_register_table[7*4]; 74 float24* output_register_table[7*4];
45 75
46 Math::Vec4<float24> temporary_registers[16]; 76 Math::Vec4<float24> temporary_registers[16];
47 bool status_registers[2]; 77 bool conditional_code[2];
78
79 // Two Address registers and one loop counter
80 // TODO: How many bits do these actually have?
81 s32 address_registers[3];
48 82
49 enum { 83 enum {
50 INVALID_ADDRESS = 0xFFFFFFFF 84 INVALID_ADDRESS = 0xFFFFFFFF
51 }; 85 };
52 u32 call_stack[8]; // TODO: What is the maximal call stack depth? 86
53 u32* call_stack_pointer; 87 struct CallStackElement {
88 u32 final_address;
89 u32 return_address;
90 };
91
92 // TODO: Is there a maximal size for this?
93 std::stack<CallStackElement> call_stack;
54 94
55 struct { 95 struct {
56 u32 max_offset; // maximum program counter ever reached 96 u32 max_offset; // maximum program counter ever reached
@@ -59,49 +99,105 @@ struct VertexShaderState {
59}; 99};
60 100
61static void ProcessShaderCode(VertexShaderState& state) { 101static void ProcessShaderCode(VertexShaderState& state) {
102
103 // Placeholder for invalid inputs
104 static float24 dummy_vec4_float24[4];
105
62 while (true) { 106 while (true) {
63 bool increment_pc = true; 107 if (!state.call_stack.empty()) {
108 if (state.program_counter - shader_memory.data() == state.call_stack.top().final_address) {
109 state.program_counter = &shader_memory[state.call_stack.top().return_address];
110 state.call_stack.pop();
111
112 // TODO: Is "trying again" accurate to hardware?
113 continue;
114 }
115 }
116
64 bool exit_loop = false; 117 bool exit_loop = false;
65 const Instruction& instr = *(const Instruction*)state.program_counter; 118 const Instruction& instr = *(const Instruction*)state.program_counter;
66 state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + (state.program_counter - shader_memory));
67
68 const float24* src1_ = (instr.common.src1 < 0x10) ? state.input_register_table[instr.common.src1.GetIndex()]
69 : (instr.common.src1 < 0x20) ? &state.temporary_registers[instr.common.src1.GetIndex()].x
70 : (instr.common.src1 < 0x80) ? &shader_uniforms.f[instr.common.src1.GetIndex()].x
71 : nullptr;
72 const float24* src2_ = (instr.common.src2 < 0x10) ? state.input_register_table[instr.common.src2.GetIndex()]
73 : &state.temporary_registers[instr.common.src2.GetIndex()].x;
74 float24* dest = (instr.common.dest < 0x08) ? state.output_register_table[4*instr.common.dest.GetIndex()]
75 : (instr.common.dest < 0x10) ? nullptr
76 : (instr.common.dest < 0x20) ? &state.temporary_registers[instr.common.dest.GetIndex()][0]
77 : nullptr;
78
79 const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; 119 const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id];
80 const bool negate_src1 = (swizzle.negate != 0);
81 120
82 float24 src1[4] = { 121 auto call = [&](VertexShaderState& state, u32 offset, u32 num_instructions, u32 return_offset) {
83 src1_[(int)swizzle.GetSelectorSrc1(0)], 122 state.program_counter = &shader_memory[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset
84 src1_[(int)swizzle.GetSelectorSrc1(1)], 123 state.call_stack.push({ offset + num_instructions, return_offset });
85 src1_[(int)swizzle.GetSelectorSrc1(2)],
86 src1_[(int)swizzle.GetSelectorSrc1(3)],
87 }; 124 };
88 if (negate_src1) { 125 u32 binary_offset = state.program_counter - shader_memory.data();
89 src1[0] = src1[0] * float24::FromFloat32(-1); 126
90 src1[1] = src1[1] * float24::FromFloat32(-1); 127 state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset);
91 src1[2] = src1[2] * float24::FromFloat32(-1); 128
92 src1[3] = src1[3] * float24::FromFloat32(-1); 129 auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* {
93 } 130 switch (source_reg.GetRegisterType()) {
94 const float24 src2[4] = { 131 case RegisterType::Input:
95 src2_[(int)swizzle.GetSelectorSrc2(0)], 132 return state.input_register_table[source_reg.GetIndex()];
96 src2_[(int)swizzle.GetSelectorSrc2(1)], 133
97 src2_[(int)swizzle.GetSelectorSrc2(2)], 134 case RegisterType::Temporary:
98 src2_[(int)swizzle.GetSelectorSrc2(3)], 135 return &state.temporary_registers[source_reg.GetIndex()].x;
136
137 case RegisterType::FloatUniform:
138 return &shader_uniforms.f[source_reg.GetIndex()].x;
139
140 default:
141 return dummy_vec4_float24;
142 }
99 }; 143 };
100 144
101 switch (instr.opcode) { 145 switch (instr.opcode.GetInfo().type) {
146 case Instruction::OpCodeType::Arithmetic:
147 {
148 bool is_inverted = 0 != (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::SrcInversed);
149 if (is_inverted) {
150 // TODO: We don't really support this properly: For instance, the address register
151 // offset needs to be applied to SRC2 instead, etc.
152 // For now, we just abort in this situation.
153 LOG_CRITICAL(HW_GPU, "Bad condition...");
154 exit(0);
155 }
156
157 const int address_offset = (instr.common.address_register_index == 0)
158 ? 0 : state.address_registers[instr.common.address_register_index - 1];
159
160 const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset);
161 const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted));
162
163 const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
164 const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
165
166 float24 src1[4] = {
167 src1_[(int)swizzle.GetSelectorSrc1(0)],
168 src1_[(int)swizzle.GetSelectorSrc1(1)],
169 src1_[(int)swizzle.GetSelectorSrc1(2)],
170 src1_[(int)swizzle.GetSelectorSrc1(3)],
171 };
172 if (negate_src1) {
173 src1[0] = src1[0] * float24::FromFloat32(-1);
174 src1[1] = src1[1] * float24::FromFloat32(-1);
175 src1[2] = src1[2] * float24::FromFloat32(-1);
176 src1[3] = src1[3] * float24::FromFloat32(-1);
177 }
178 float24 src2[4] = {
179 src2_[(int)swizzle.GetSelectorSrc2(0)],
180 src2_[(int)swizzle.GetSelectorSrc2(1)],
181 src2_[(int)swizzle.GetSelectorSrc2(2)],
182 src2_[(int)swizzle.GetSelectorSrc2(3)],
183 };
184 if (negate_src2) {
185 src2[0] = src2[0] * float24::FromFloat32(-1);
186 src2[1] = src2[1] * float24::FromFloat32(-1);
187 src2[2] = src2[2] * float24::FromFloat32(-1);
188 src2[3] = src2[3] * float24::FromFloat32(-1);
189 }
190
191 float24* dest = (instr.common.dest < 0x08) ? state.output_register_table[4*instr.common.dest.GetIndex()]
192 : (instr.common.dest < 0x10) ? dummy_vec4_float24
193 : (instr.common.dest < 0x20) ? &state.temporary_registers[instr.common.dest.GetIndex()][0]
194 : dummy_vec4_float24;
195
196 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
197
198 switch (instr.opcode.EffectiveOpCode()) {
102 case Instruction::OpCode::ADD: 199 case Instruction::OpCode::ADD:
103 { 200 {
104 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
105 for (int i = 0; i < 4; ++i) { 201 for (int i = 0; i < 4; ++i) {
106 if (!swizzle.DestComponentEnabled(i)) 202 if (!swizzle.DestComponentEnabled(i))
107 continue; 203 continue;
@@ -114,7 +210,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
114 210
115 case Instruction::OpCode::MUL: 211 case Instruction::OpCode::MUL:
116 { 212 {
117 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
118 for (int i = 0; i < 4; ++i) { 213 for (int i = 0; i < 4; ++i) {
119 if (!swizzle.DestComponentEnabled(i)) 214 if (!swizzle.DestComponentEnabled(i))
120 continue; 215 continue;
@@ -125,10 +220,18 @@ static void ProcessShaderCode(VertexShaderState& state) {
125 break; 220 break;
126 } 221 }
127 222
223 case Instruction::OpCode::MAX:
224 for (int i = 0; i < 4; ++i) {
225 if (!swizzle.DestComponentEnabled(i))
226 continue;
227
228 dest[i] = std::max(src1[i], src2[i]);
229 }
230 break;
231
128 case Instruction::OpCode::DP3: 232 case Instruction::OpCode::DP3:
129 case Instruction::OpCode::DP4: 233 case Instruction::OpCode::DP4:
130 { 234 {
131 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
132 float24 dot = float24::FromFloat32(0.f); 235 float24 dot = float24::FromFloat32(0.f);
133 int num_components = (instr.opcode == Instruction::OpCode::DP3) ? 3 : 4; 236 int num_components = (instr.opcode == Instruction::OpCode::DP3) ? 3 : 4;
134 for (int i = 0; i < num_components; ++i) 237 for (int i = 0; i < num_components; ++i)
@@ -146,7 +249,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
146 // Reciprocal 249 // Reciprocal
147 case Instruction::OpCode::RCP: 250 case Instruction::OpCode::RCP:
148 { 251 {
149 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
150 for (int i = 0; i < 4; ++i) { 252 for (int i = 0; i < 4; ++i) {
151 if (!swizzle.DestComponentEnabled(i)) 253 if (!swizzle.DestComponentEnabled(i))
152 continue; 254 continue;
@@ -162,7 +264,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
162 // Reciprocal Square Root 264 // Reciprocal Square Root
163 case Instruction::OpCode::RSQ: 265 case Instruction::OpCode::RSQ:
164 { 266 {
165 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
166 for (int i = 0; i < 4; ++i) { 267 for (int i = 0; i < 4; ++i) {
167 if (!swizzle.DestComponentEnabled(i)) 268 if (!swizzle.DestComponentEnabled(i))
168 continue; 269 continue;
@@ -175,9 +276,21 @@ static void ProcessShaderCode(VertexShaderState& state) {
175 break; 276 break;
176 } 277 }
177 278
279 case Instruction::OpCode::MOVA:
280 {
281 for (int i = 0; i < 2; ++i) {
282 if (!swizzle.DestComponentEnabled(i))
283 continue;
284
285 // TODO: Figure out how the rounding is done on hardware
286 state.address_registers[i] = static_cast<s32>(src1[i].ToFloat32());
287 }
288
289 break;
290 }
291
178 case Instruction::OpCode::MOV: 292 case Instruction::OpCode::MOV:
179 { 293 {
180 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
181 for (int i = 0; i < 4; ++i) { 294 for (int i = 0; i < 4; ++i) {
182 if (!swizzle.DestComponentEnabled(i)) 295 if (!swizzle.DestComponentEnabled(i))
183 continue; 296 continue;
@@ -187,39 +300,137 @@ static void ProcessShaderCode(VertexShaderState& state) {
187 break; 300 break;
188 } 301 }
189 302
190 case Instruction::OpCode::RET: 303 case Instruction::OpCode::CMP:
191 if (*state.call_stack_pointer == VertexShaderState::INVALID_ADDRESS) { 304 for (int i = 0; i < 2; ++i) {
192 exit_loop = true; 305 // TODO: Can you restrict to one compare via dest masking?
193 } else { 306
194 // Jump back to call stack position, invalidate call stack entry, move up call stack pointer 307 auto compare_op = instr.common.compare_op;
195 state.program_counter = &shader_memory[*state.call_stack_pointer]; 308 auto op = (i == 0) ? compare_op.x.Value() : compare_op.y.Value();
196 *state.call_stack_pointer-- = VertexShaderState::INVALID_ADDRESS; 309
310 switch (op) {
311 case compare_op.Equal:
312 state.conditional_code[i] = (src1[i] == src2[i]);
313 break;
314
315 case compare_op.NotEqual:
316 state.conditional_code[i] = (src1[i] != src2[i]);
317 break;
318
319 case compare_op.LessThan:
320 state.conditional_code[i] = (src1[i] < src2[i]);
321 break;
322
323 case compare_op.LessEqual:
324 state.conditional_code[i] = (src1[i] <= src2[i]);
325 break;
326
327 case compare_op.GreaterThan:
328 state.conditional_code[i] = (src1[i] > src2[i]);
329 break;
330
331 case compare_op.GreaterEqual:
332 state.conditional_code[i] = (src1[i] >= src2[i]);
333 break;
334
335 default:
336 LOG_ERROR(HW_GPU, "Unknown compare mode %x", static_cast<int>(op));
337 break;
338 }
197 } 339 }
340 break;
341
342 default:
343 LOG_ERROR(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x",
344 (int)instr.opcode.Value(), instr.opcode.GetInfo().name, instr.hex);
345 _dbg_assert_(HW_GPU, 0);
346 break;
347 }
198 348
349 break;
350 }
351 default:
352 // Handle each instruction on its own
353 switch (instr.opcode) {
354 case Instruction::OpCode::END:
355 exit_loop = true;
199 break; 356 break;
200 357
201 case Instruction::OpCode::CALL: 358 case Instruction::OpCode::CALL:
202 increment_pc = false; 359 call(state,
360 instr.flow_control.dest_offset,
361 instr.flow_control.num_instructions,
362 binary_offset + 1);
363 break;
203 364
204 _dbg_assert_(GPU, state.call_stack_pointer - state.call_stack < sizeof(state.call_stack)); 365 case Instruction::OpCode::NOP:
366 break;
367
368 case Instruction::OpCode::IFU:
369 if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
370 call(state,
371 binary_offset + 1,
372 instr.flow_control.dest_offset - binary_offset - 1,
373 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
374 } else {
375 call(state,
376 instr.flow_control.dest_offset,
377 instr.flow_control.num_instructions,
378 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
379 }
205 380
206 *++state.call_stack_pointer = state.program_counter - shader_memory;
207 // TODO: Does this offset refer to the beginning of shader memory?
208 state.program_counter = &shader_memory[instr.flow_control.offset_words];
209 break; 381 break;
210 382
211 case Instruction::OpCode::FLS: 383 case Instruction::OpCode::IFC:
212 // TODO: Do whatever needs to be done here? 384 {
385 // TODO: Do we need to consider swizzlers here?
386
387 auto flow_control = instr.flow_control;
388 bool results[3] = { (bool)flow_control.refx == state.conditional_code[0],
389 (bool)flow_control.refy == state.conditional_code[1] };
390
391 switch (flow_control.op) {
392 case flow_control.Or:
393 results[2] = results[0] || results[1];
394 break;
395
396 case flow_control.And:
397 results[2] = results[0] && results[1];
398 break;
399
400 case flow_control.JustX:
401 results[2] = results[0];
402 break;
403
404 case flow_control.JustY:
405 results[2] = results[1];
406 break;
407 }
408
409 if (results[2]) {
410 call(state,
411 binary_offset + 1,
412 instr.flow_control.dest_offset - binary_offset - 1,
413 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
414 } else {
415 call(state,
416 instr.flow_control.dest_offset,
417 instr.flow_control.num_instructions,
418 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
419 }
420
213 break; 421 break;
422 }
214 423
215 default: 424 default:
216 ERROR_LOG(GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x", 425 LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
217 (int)instr.opcode.Value(), instr.GetOpCodeName().c_str(), instr.hex); 426 (int)instr.opcode.Value(), instr.opcode.GetInfo().name, instr.hex);
218 break; 427 break;
428 }
429
430 break;
219 } 431 }
220 432
221 if (increment_pc) 433 ++state.program_counter;
222 ++state.program_counter;
223 434
224 if (exit_loop) 435 if (exit_loop)
225 break; 436 break;
@@ -238,7 +449,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
238 // Setup input register table 449 // Setup input register table
239 const auto& attribute_register_map = registers.vs_input_register_map; 450 const auto& attribute_register_map = registers.vs_input_register_map;
240 float24 dummy_register; 451 float24 dummy_register;
241 std::fill(&state.input_register_table[0], &state.input_register_table[16], &dummy_register); 452 boost::fill(state.input_register_table, &dummy_register);
242 if(num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x; 453 if(num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x;
243 if(num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x; 454 if(num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x;
244 if(num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x; 455 if(num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x;
@@ -258,6 +469,10 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
258 469
259 // Setup output register table 470 // Setup output register table
260 OutputVertex ret; 471 OutputVertex ret;
472 // Zero output so that attributes which aren't output won't have denormals in them, which will
473 // slow us down later.
474 memset(&ret, 0, sizeof(ret));
475
261 for (int i = 0; i < 7; ++i) { 476 for (int i = 0; i < 7; ++i) {
262 const auto& output_register_map = registers.vs_output_attributes[i]; 477 const auto& output_register_map = registers.vs_output_attributes[i];
263 478
@@ -270,18 +485,15 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
270 state.output_register_table[4*i+comp] = ((float24*)&ret) + semantics[comp]; 485 state.output_register_table[4*i+comp] = ((float24*)&ret) + semantics[comp];
271 } 486 }
272 487
273 state.status_registers[0] = false; 488 state.conditional_code[0] = false;
274 state.status_registers[1] = false; 489 state.conditional_code[1] = false;
275 std::fill(state.call_stack, state.call_stack + sizeof(state.call_stack) / sizeof(state.call_stack[0]),
276 VertexShaderState::INVALID_ADDRESS);
277 state.call_stack_pointer = &state.call_stack[0];
278 490
279 ProcessShaderCode(state); 491 ProcessShaderCode(state);
280 DebugUtils::DumpShader(shader_memory, state.debug.max_offset, swizzle_data, 492 DebugUtils::DumpShader(shader_memory.data(), state.debug.max_offset, swizzle_data.data(),
281 state.debug.max_opdesc_id, registers.vs_main_offset, 493 state.debug.max_opdesc_id, registers.vs_main_offset,
282 registers.vs_output_attributes); 494 registers.vs_output_attributes);
283 495
284 DEBUG_LOG(GPU, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)", 496 LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)",
285 ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), 497 ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(),
286 ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), 498 ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(),
287 ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32()); 499 ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32());