summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/skyeye_common/armstate.cpp7
-rw-r--r--src/core/file_sys/archive_extsavedata.h3
-rw-r--r--src/core/hle/kernel/session.h12
-rw-r--r--src/core/hle/service/soc_u.cpp13
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/video_core/command_processor.cpp46
-rw-r--r--src/video_core/pica.cpp15
-rw-r--r--src/video_core/pica.h15
-rw-r--r--src/video_core/pica_state.h15
-rw-r--r--src/video_core/primitive_assembly.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp3
-rw-r--r--src/video_core/shader/shader.cpp18
12 files changed, 95 insertions, 56 deletions
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp
index 2d814345a..5550c112e 100644
--- a/src/core/arm/skyeye_common/armstate.cpp
+++ b/src/core/arm/skyeye_common/armstate.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 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 <algorithm>
5#include "common/swap.h" 6#include "common/swap.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/memory.h" 8#include "core/memory.h"
@@ -48,8 +49,7 @@ void ARMul_State::ChangePrivilegeMode(u32 new_mode)
48 Spsr[UNDEFBANK] = Spsr_copy; 49 Spsr[UNDEFBANK] = Spsr_copy;
49 break; 50 break;
50 case FIQ32MODE: 51 case FIQ32MODE:
51 Reg_firq[0] = Reg[13]; 52 std::copy(Reg.begin() + 8, Reg.end() - 1, Reg_firq.begin());
52 Reg_firq[1] = Reg[14];
53 Spsr[FIQBANK] = Spsr_copy; 53 Spsr[FIQBANK] = Spsr_copy;
54 break; 54 break;
55 } 55 }
@@ -85,8 +85,7 @@ void ARMul_State::ChangePrivilegeMode(u32 new_mode)
85 Bank = UNDEFBANK; 85 Bank = UNDEFBANK;
86 break; 86 break;
87 case FIQ32MODE: 87 case FIQ32MODE:
88 Reg[13] = Reg_firq[0]; 88 std::copy(Reg_firq.begin(), Reg_firq.end(), Reg.begin() + 8);
89 Reg[14] = Reg_firq[1];
90 Spsr_copy = Spsr[FIQBANK]; 89 Spsr_copy = Spsr[FIQBANK];
91 Bank = FIQBANK; 90 Bank = FIQBANK;
92 break; 91 break;
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h
index 287a6fee1..e9a72850d 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -45,13 +45,14 @@ public:
45 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); 45 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size);
46 46
47private: 47private:
48 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive
49
48 /** 50 /**
49 * This holds the full directory path for this archive, it is only set after a successful call 51 * This holds the full directory path for this archive, it is only set after a successful call
50 * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>. 52 * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>.
51 * See GetExtSaveDataPath for the code that extracts this data from an archive path. 53 * See GetExtSaveDataPath for the code that extracts this data from an archive path.
52 */ 54 */
53 std::string mount_point; 55 std::string mount_point;
54 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive
55}; 56};
56 57
57/** 58/**
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index adaffcafe..6ddaf970e 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -16,23 +16,23 @@
16 16
17namespace IPC { 17namespace IPC {
18 18
19inline u32 MakeHeader(u16 command_id, unsigned int regular_params, unsigned int translate_params) { 19constexpr u32 MakeHeader(u16 command_id, unsigned int regular_params, unsigned int translate_params) {
20 return ((u32)command_id << 16) | (((u32)regular_params & 0x3F) << 6) | (((u32)translate_params & 0x3F) << 0); 20 return ((u32)command_id << 16) | (((u32)regular_params & 0x3F) << 6) | (((u32)translate_params & 0x3F) << 0);
21} 21}
22 22
23inline u32 MoveHandleDesc(unsigned int num_handles = 1) { 23constexpr u32 MoveHandleDesc(unsigned int num_handles = 1) {
24 return 0x0 | ((num_handles - 1) << 26); 24 return 0x0 | ((num_handles - 1) << 26);
25} 25}
26 26
27inline u32 CopyHandleDesc(unsigned int num_handles = 1) { 27constexpr u32 CopyHandleDesc(unsigned int num_handles = 1) {
28 return 0x10 | ((num_handles - 1) << 26); 28 return 0x10 | ((num_handles - 1) << 26);
29} 29}
30 30
31inline u32 CallingPidDesc() { 31constexpr u32 CallingPidDesc() {
32 return 0x20; 32 return 0x20;
33} 33}
34 34
35inline u32 StaticBufferDesc(u32 size, unsigned int buffer_id) { 35constexpr u32 StaticBufferDesc(u32 size, unsigned int buffer_id) {
36 return 0x2 | (size << 14) | ((buffer_id & 0xF) << 10); 36 return 0x2 | (size << 14) | ((buffer_id & 0xF) << 10);
37} 37}
38 38
@@ -42,7 +42,7 @@ enum MappedBufferPermissions {
42 RW = R | W, 42 RW = R | W,
43}; 43};
44 44
45inline u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { 45constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
46 return 0x8 | (size << 4) | (u32)perms; 46 return 0x8 | (size << 4) | (u32)perms;
47} 47}
48 48
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index b52e52d4a..ff0af8f12 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include <unordered_map> 7#include <unordered_map>
8#include <vector>
8 9
9#include "common/assert.h" 10#include "common/assert.h"
10#include "common/bit_field.h" 11#include "common/bit_field.h"
@@ -593,17 +594,13 @@ static void Poll(Service::Interface* self) {
593 594
594 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) 595 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes)
595 // so we have to copy the data 596 // so we have to copy the data
596 pollfd* platform_pollfd = new pollfd[nfds]; 597 std::vector<pollfd> platform_pollfd(nfds);
597 for (unsigned current_fds = 0; current_fds < nfds; ++current_fds) 598 std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform);
598 platform_pollfd[current_fds] = CTRPollFD::ToPlatform(input_fds[current_fds]);
599 599
600 int ret = ::poll(platform_pollfd, nfds, timeout); 600 const int ret = ::poll(platform_pollfd.data(), nfds, timeout);
601 601
602 // Now update the output pollfd structure 602 // Now update the output pollfd structure
603 for (unsigned current_fds = 0; current_fds < nfds; ++current_fds) 603 std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform);
604 output_fds[current_fds] = CTRPollFD::FromPlatform(platform_pollfd[current_fds]);
605
606 delete[] platform_pollfd;
607 604
608 int result = 0; 605 int result = 0;
609 if (ret == SOCKET_ERROR_VALUE) 606 if (ret == SOCKET_ERROR_VALUE)
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index a7f2715ba..84a4ce5fc 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -74,7 +74,7 @@ enum class ResultStatus {
74 ErrorEncrypted, 74 ErrorEncrypted,
75}; 75};
76 76
77static inline u32 MakeMagic(char a, char b, char c, char d) { 77constexpr u32 MakeMagic(char a, char b, char c, char d) {
78 return a | b << 8 | c << 16 | d << 24; 78 return a | b << 8 | c << 16 | d << 24;
79} 79}
80 80
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 4b59984ad..028b59348 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -75,12 +75,17 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
75 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); 75 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D);
76 break; 76 break;
77 77
78 case PICA_REG_INDEX_WORKAROUND(triangle_topology, 0x25E):
79 g_state.primitive_assembler.Reconfigure(regs.triangle_topology);
80 break;
81
82 case PICA_REG_INDEX_WORKAROUND(restart_primitive, 0x25F):
83 g_state.primitive_assembler.Reset();
84 break;
85
78 case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232): 86 case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232):
79 if (regs.vs_default_attributes_setup.index == 15) { 87 g_state.immediate.current_attribute = 0;
80 // Reset immediate primitive state 88 default_attr_counter = 0;
81 g_state.immediate.primitive_assembler.Reconfigure(regs.triangle_topology);
82 g_state.immediate.attribute_id = 0;
83 }
84 break; 89 break;
85 90
86 // Load default vertex input attributes 91 // Load default vertex input attributes
@@ -105,7 +110,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
105 break; 110 break;
106 } 111 }
107 112
108 Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; 113 Math::Vec4<float24> attribute;
109 114
110 // NOTE: The destination component order indeed is "backwards" 115 // NOTE: The destination component order indeed is "backwards"
111 attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8); 116 attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8);
@@ -119,26 +124,29 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
119 124
120 // TODO: Verify that this actually modifies the register! 125 // TODO: Verify that this actually modifies the register!
121 if (setup.index < 15) { 126 if (setup.index < 15) {
127 g_state.vs.default_attributes[setup.index] = attribute;
122 setup.index++; 128 setup.index++;
123 } else { 129 } else {
124 // Put each attribute into an immediate input buffer. 130 // Put each attribute into an immediate input buffer.
125 // When all specified immediate attributes are present, the Vertex Shader is invoked and everything is 131 // When all specified immediate attributes are present, the Vertex Shader is invoked and everything is
126 // sent to the primitive assembler. 132 // sent to the primitive assembler.
127 133
128 auto& immediate_input = g_state.immediate.input; 134 auto& immediate_input = g_state.immediate.input_vertex;
129 auto& immediate_attribute_id = g_state.immediate.attribute_id; 135 auto& immediate_attribute_id = g_state.immediate.current_attribute;
130 const auto& attribute_config = regs.vertex_attributes;
131 136
132 immediate_input.attr[immediate_attribute_id++] = attribute; 137 immediate_input.attr[immediate_attribute_id++] = attribute;
133 138
134 if (immediate_attribute_id >= attribute_config.GetNumTotalAttributes()) { 139 if (immediate_attribute_id >= regs.vs.num_input_attributes+1) {
135 immediate_attribute_id = 0; 140 immediate_attribute_id = 0;
136 141
137 Shader::UnitState<false> shader_unit; 142 Shader::UnitState<false> shader_unit;
138 Shader::Setup(shader_unit); 143 Shader::Setup(shader_unit);
139 144
145 if (g_debug_context)
146 g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, static_cast<void*>(&immediate_input));
147
140 // Send to vertex shader 148 // Send to vertex shader
141 Shader::OutputVertex output = Shader::Run(shader_unit, immediate_input, attribute_config.GetNumTotalAttributes()); 149 Shader::OutputVertex output = Shader::Run(shader_unit, immediate_input, regs.vs.num_input_attributes+1);
142 150
143 // Send to renderer 151 // Send to renderer
144 using Pica::Shader::OutputVertex; 152 using Pica::Shader::OutputVertex;
@@ -146,7 +154,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
146 VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); 154 VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2);
147 }; 155 };
148 156
149 g_state.immediate.primitive_assembler.SubmitVertex(output, AddTriangle); 157 g_state.primitive_assembler.SubmitVertex(output, AddTriangle);
150 } 158 }
151 } 159 }
152 } 160 }
@@ -154,9 +162,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
154 } 162 }
155 163
156 case PICA_REG_INDEX(gpu_mode): 164 case PICA_REG_INDEX(gpu_mode):
157 if (regs.gpu_mode == Regs::GPUMode::Configuring && regs.vs_default_attributes_setup.index == 15) { 165 if (regs.gpu_mode == Regs::GPUMode::Configuring) {
158 // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring 166 // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring
159 VideoCore::g_renderer->Rasterizer()->DrawTriangles(); 167 VideoCore::g_renderer->Rasterizer()->DrawTriangles();
168
169 if (g_debug_context) {
170 g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
171 }
160 } 172 }
161 break; 173 break;
162 174
@@ -241,7 +253,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
241 DebugUtils::GeometryDumper geometry_dumper; 253 DebugUtils::GeometryDumper geometry_dumper;
242 PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); 254 PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value());
243#endif 255#endif
244 PrimitiveAssembler<Shader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); 256 PrimitiveAssembler<Shader::OutputVertex>& primitive_assembler = g_state.primitive_assembler;
245 257
246 if (g_debug_context) { 258 if (g_debug_context) {
247 for (int i = 0; i < 3; ++i) { 259 for (int i = 0; i < 3; ++i) {
@@ -412,16 +424,10 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
412 range.second, range.first); 424 range.second, range.first);
413 } 425 }
414 426
415 VideoCore::g_renderer->Rasterizer()->DrawTriangles();
416
417#if PICA_DUMP_GEOMETRY 427#if PICA_DUMP_GEOMETRY
418 geometry_dumper.Dump(); 428 geometry_dumper.Dump();
419#endif 429#endif
420 430
421 if (g_debug_context) {
422 g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
423 }
424
425 break; 431 break;
426 } 432 }
427 433
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp
index 32ad72674..ccbaf071b 100644
--- a/src/video_core/pica.cpp
+++ b/src/video_core/pica.cpp
@@ -493,12 +493,25 @@ std::string Regs::GetCommandName(int index) {
493} 493}
494 494
495void Init() { 495void Init() {
496 g_state.Reset();
496} 497}
497 498
498void Shutdown() { 499void Shutdown() {
499 Shader::Shutdown(); 500 Shader::Shutdown();
501}
502
503template <typename T>
504void Zero(T& o) {
505 memset(&o, 0, sizeof(o));
506}
500 507
501 memset(&g_state, 0, sizeof(State)); 508void State::Reset() {
509 Zero(regs);
510 Zero(vs);
511 Zero(gs);
512 Zero(cmd_list);
513 Zero(immediate);
514 primitive_assembler.Reconfigure(Regs::TriangleTopology::List);
502} 515}
503 516
504} 517}
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 337cff8ce..16f9e4006 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -71,7 +71,7 @@ struct Regs {
71 BitField<0, 24, u32> viewport_depth_range; // float24 71 BitField<0, 24, u32> viewport_depth_range; // float24
72 BitField<0, 24, u32> viewport_depth_far_plane; // float24 72 BitField<0, 24, u32> viewport_depth_far_plane; // float24
73 73
74 INSERT_PADDING_WORDS(0x1); 74 BitField<0, 3, u32> vs_output_total;
75 75
76 union VSOutputAttributes { 76 union VSOutputAttributes {
77 // Maps components of output vertex attributes to semantics 77 // Maps components of output vertex attributes to semantics
@@ -1123,7 +1123,12 @@ struct Regs {
1123 BitField<24, 8, u32> w; 1123 BitField<24, 8, u32> w;
1124 } int_uniforms[4]; 1124 } int_uniforms[4];
1125 1125
1126 INSERT_PADDING_WORDS(0x5); 1126 INSERT_PADDING_WORDS(0x4);
1127
1128 union {
1129 // Number of input attributes to shader unit - 1
1130 BitField<0, 4, u32> num_input_attributes;
1131 };
1127 1132
1128 // Offset to shader program entry point (in words) 1133 // Offset to shader program entry point (in words)
1129 BitField<0, 16, u32> main_offset; 1134 BitField<0, 16, u32> main_offset;
@@ -1157,8 +1162,10 @@ struct Regs {
1157 } 1162 }
1158 } input_register_map; 1163 } input_register_map;
1159 1164
1160 // OUTMAP_MASK, 0x28E, CODETRANSFER_END 1165 BitField<0, 16, u32> output_mask;
1161 INSERT_PADDING_WORDS(0x3); 1166
1167 // 0x28E, CODETRANSFER_END
1168 INSERT_PADDING_WORDS(0x2);
1162 1169
1163 struct { 1170 struct {
1164 enum Format : u32 1171 enum Format : u32
diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h
index c7616bc55..323290054 100644
--- a/src/video_core/pica_state.h
+++ b/src/video_core/pica_state.h
@@ -12,6 +12,8 @@ namespace Pica {
12 12
13/// Struct used to describe current Pica state 13/// Struct used to describe current Pica state
14struct State { 14struct State {
15 void Reset();
16
15 /// Pica registers 17 /// Pica registers
16 Regs regs; 18 Regs regs;
17 19
@@ -46,13 +48,14 @@ struct State {
46 48
47 /// Struct used to describe immediate mode rendering state 49 /// Struct used to describe immediate mode rendering state
48 struct ImmediateModeState { 50 struct ImmediateModeState {
49 Shader::InputVertex input; 51 // Used to buffer partial vertices for immediate-mode rendering.
50 // This is constructed with a dummy triangle topology 52 Shader::InputVertex input_vertex;
51 PrimitiveAssembler<Shader::OutputVertex> primitive_assembler; 53 // Index of the next attribute to be loaded into `input_vertex`.
52 int attribute_id = 0; 54 int current_attribute = 0;
53
54 ImmediateModeState() : primitive_assembler(Regs::TriangleTopology::List) {}
55 } immediate; 55 } immediate;
56
57 // This is constructed with a dummy triangle topology
58 PrimitiveAssembler<Shader::OutputVertex> primitive_assembler;
56}; 59};
57 60
58extern State g_state; ///< Current Pica state 61extern State g_state; ///< Current Pica state
diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h
index cc6e5fde5..9396b4c85 100644
--- a/src/video_core/primitive_assembly.h
+++ b/src/video_core/primitive_assembly.h
@@ -20,7 +20,7 @@ struct PrimitiveAssembler {
20 VertexType& v1, 20 VertexType& v1,
21 VertexType& v2)>; 21 VertexType& v2)>;
22 22
23 PrimitiveAssembler(Regs::TriangleTopology topology); 23 PrimitiveAssembler(Regs::TriangleTopology topology = Regs::TriangleTopology::List);
24 24
25 /* 25 /*
26 * Queues a vertex, builds primitives from the vertex queue according to the given 26 * Queues a vertex, builds primitives from the vertex queue according to the given
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index b3dc6aa19..1fadcf5ae 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -190,6 +190,9 @@ void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
190} 190}
191 191
192void RasterizerOpenGL::DrawTriangles() { 192void RasterizerOpenGL::DrawTriangles() {
193 if (vertex_batch.empty())
194 return;
195
193 SyncFramebuffer(); 196 SyncFramebuffer();
194 SyncDrawState(); 197 SyncDrawState();
195 198
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index 509558fc0..eb1db0778 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -121,15 +121,23 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr
121 OutputVertex ret; 121 OutputVertex ret;
122 // TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to 122 // TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to
123 // figure out what those circumstances are and enable the remaining outputs then. 123 // figure out what those circumstances are and enable the remaining outputs then.
124 for (int i = 0; i < 7; ++i) { 124 unsigned index = 0;
125 const auto& output_register_map = g_state.regs.vs_output_attributes[i]; // TODO: Don't hardcode VS here 125 for (unsigned i = 0; i < 7; ++i) {
126
127 if (index >= g_state.regs.vs_output_total)
128 break;
129
130 if ((g_state.regs.vs.output_mask & (1 << i)) == 0)
131 continue;
132
133 const auto& output_register_map = g_state.regs.vs_output_attributes[index]; // TODO: Don't hardcode VS here
126 134
127 u32 semantics[4] = { 135 u32 semantics[4] = {
128 output_register_map.map_x, output_register_map.map_y, 136 output_register_map.map_x, output_register_map.map_y,
129 output_register_map.map_z, output_register_map.map_w 137 output_register_map.map_z, output_register_map.map_w
130 }; 138 };
131 139
132 for (int comp = 0; comp < 4; ++comp) { 140 for (unsigned comp = 0; comp < 4; ++comp) {
133 float24* out = ((float24*)&ret) + semantics[comp]; 141 float24* out = ((float24*)&ret) + semantics[comp];
134 if (semantics[comp] != Regs::VSOutputAttributes::INVALID) { 142 if (semantics[comp] != Regs::VSOutputAttributes::INVALID) {
135 *out = state.registers.output[i][comp]; 143 *out = state.registers.output[i][comp];
@@ -139,10 +147,12 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr
139 memset(out, 0, sizeof(*out)); 147 memset(out, 0, sizeof(*out));
140 } 148 }
141 } 149 }
150
151 index++;
142 } 152 }
143 153
144 // The hardware takes the absolute and saturates vertex colors like this, *before* doing interpolation 154 // The hardware takes the absolute and saturates vertex colors like this, *before* doing interpolation
145 for (int i = 0; i < 4; ++i) { 155 for (unsigned i = 0; i < 4; ++i) {
146 ret.color[i] = float24::FromFloat32( 156 ret.color[i] = float24::FromFloat32(
147 std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); 157 std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f));
148 } 158 }