diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/skyeye_common/armstate.cpp | 7 | ||||
| -rw-r--r-- | src/core/file_sys/archive_extsavedata.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/session.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/soc_u.cpp | 13 | ||||
| -rw-r--r-- | src/core/loader/loader.h | 2 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 46 | ||||
| -rw-r--r-- | src/video_core/pica.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/pica.h | 15 | ||||
| -rw-r--r-- | src/video_core/pica_state.h | 15 | ||||
| -rw-r--r-- | src/video_core/primitive_assembly.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/shader/shader.cpp | 18 |
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 | ||
| 47 | private: | 47 | private: |
| 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 | ||
| 17 | namespace IPC { | 17 | namespace IPC { |
| 18 | 18 | ||
| 19 | inline u32 MakeHeader(u16 command_id, unsigned int regular_params, unsigned int translate_params) { | 19 | constexpr 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 | ||
| 23 | inline u32 MoveHandleDesc(unsigned int num_handles = 1) { | 23 | constexpr 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 | ||
| 27 | inline u32 CopyHandleDesc(unsigned int num_handles = 1) { | 27 | constexpr 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 | ||
| 31 | inline u32 CallingPidDesc() { | 31 | constexpr u32 CallingPidDesc() { |
| 32 | return 0x20; | 32 | return 0x20; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | inline u32 StaticBufferDesc(u32 size, unsigned int buffer_id) { | 35 | constexpr 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 | ||
| 45 | inline u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { | 45 | constexpr 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 | ||
| 77 | static inline u32 MakeMagic(char a, char b, char c, char d) { | 77 | constexpr 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 | ||
| 495 | void Init() { | 495 | void Init() { |
| 496 | g_state.Reset(); | ||
| 496 | } | 497 | } |
| 497 | 498 | ||
| 498 | void Shutdown() { | 499 | void Shutdown() { |
| 499 | Shader::Shutdown(); | 500 | Shader::Shutdown(); |
| 501 | } | ||
| 502 | |||
| 503 | template <typename T> | ||
| 504 | void Zero(T& o) { | ||
| 505 | memset(&o, 0, sizeof(o)); | ||
| 506 | } | ||
| 500 | 507 | ||
| 501 | memset(&g_state, 0, sizeof(State)); | 508 | void 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 |
| 14 | struct State { | 14 | struct 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 | ||
| 58 | extern State g_state; ///< Current Pica state | 61 | extern 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 | ||
| 192 | void RasterizerOpenGL::DrawTriangles() { | 192 | void 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 | } |