diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.cpp | 44 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.h | 12 | ||||
| -rw-r--r-- | src/video_core/pica.cpp | 72 | ||||
| -rw-r--r-- | src/video_core/pica.h | 65 | ||||
| -rw-r--r-- | src/video_core/rasterizer.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 111 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.h | 110 | ||||
| -rw-r--r-- | src/video_core/vertex_shader.cpp | 59 |
10 files changed, 220 insertions, 272 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5c7f4ae18..162108301 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -2,7 +2,6 @@ set(SRCS | |||
| 2 | renderer_opengl/generated/gl_3_2_core.c | 2 | renderer_opengl/generated/gl_3_2_core.c |
| 3 | renderer_opengl/gl_rasterizer.cpp | 3 | renderer_opengl/gl_rasterizer.cpp |
| 4 | renderer_opengl/gl_rasterizer_cache.cpp | 4 | renderer_opengl/gl_rasterizer_cache.cpp |
| 5 | renderer_opengl/gl_resource_manager.cpp | ||
| 6 | renderer_opengl/gl_shader_util.cpp | 5 | renderer_opengl/gl_shader_util.cpp |
| 7 | renderer_opengl/gl_state.cpp | 6 | renderer_opengl/gl_state.cpp |
| 8 | renderer_opengl/renderer_opengl.cpp | 7 | renderer_opengl/renderer_opengl.cpp |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index bbe7e63dc..36c3b9947 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp | |||
| @@ -50,7 +50,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 50 | regs[id] = (old_value & ~mask) | (value & mask); | 50 | regs[id] = (old_value & ~mask) | (value & mask); |
| 51 | 51 | ||
| 52 | if (g_debug_context) | 52 | if (g_debug_context) |
| 53 | g_debug_context->OnEvent(DebugContext::Event::CommandLoaded, reinterpret_cast<void*>(&id)); | 53 | g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id)); |
| 54 | 54 | ||
| 55 | DebugUtils::OnPicaRegWrite(id, regs[id]); | 55 | DebugUtils::OnPicaRegWrite(id, regs[id]); |
| 56 | 56 | ||
| @@ -103,7 +103,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 103 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): | 103 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): |
| 104 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): | 104 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): |
| 105 | { | 105 | { |
| 106 | unsigned index = id - PICA_REG_INDEX(command_buffer.trigger[0]); | 106 | unsigned index = static_cast<unsigned>(id - PICA_REG_INDEX(command_buffer.trigger[0])); |
| 107 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); | 107 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); |
| 108 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; | 108 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; |
| 109 | g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); | 109 | g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); |
| @@ -116,7 +116,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 116 | { | 116 | { |
| 117 | Common::Profiling::ScopeTimer scope_timer(category_drawing); | 117 | Common::Profiling::ScopeTimer scope_timer(category_drawing); |
| 118 | 118 | ||
| 119 | #if PICA_LOG_TEV | ||
| 119 | DebugUtils::DumpTevStageConfig(regs.GetTevStages()); | 120 | DebugUtils::DumpTevStageConfig(regs.GetTevStages()); |
| 121 | #endif | ||
| 120 | 122 | ||
| 121 | if (g_debug_context) | 123 | if (g_debug_context) |
| 122 | g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); | 124 | g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); |
| @@ -159,9 +161,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 159 | const u16* index_address_16 = (u16*)index_address_8; | 161 | const u16* index_address_16 = (u16*)index_address_8; |
| 160 | bool index_u16 = index_info.format != 0; | 162 | bool index_u16 = index_info.format != 0; |
| 161 | 163 | ||
| 164 | #if PICA_DUMP_GEOMETRY | ||
| 162 | DebugUtils::GeometryDumper geometry_dumper; | 165 | DebugUtils::GeometryDumper geometry_dumper; |
| 163 | PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); | ||
| 164 | PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); | 166 | PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); |
| 167 | #endif | ||
| 168 | PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); | ||
| 165 | 169 | ||
| 166 | if (g_debug_context) { | 170 | if (g_debug_context) { |
| 167 | for (int i = 0; i < 3; ++i) { | 171 | for (int i = 0; i < 3; ++i) { |
| @@ -267,6 +271,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 267 | if (g_debug_context) | 271 | if (g_debug_context) |
| 268 | g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input); | 272 | g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input); |
| 269 | 273 | ||
| 274 | #if PICA_DUMP_GEOMETRY | ||
| 270 | // NOTE: When dumping geometry, we simply assume that the first input attribute | 275 | // NOTE: When dumping geometry, we simply assume that the first input attribute |
| 271 | // corresponds to the position for now. | 276 | // corresponds to the position for now. |
| 272 | DebugUtils::GeometryDumper::Vertex dumped_vertex = { | 277 | DebugUtils::GeometryDumper::Vertex dumped_vertex = { |
| @@ -276,6 +281,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 276 | dumping_primitive_assembler.SubmitVertex(dumped_vertex, | 281 | dumping_primitive_assembler.SubmitVertex(dumped_vertex, |
| 277 | std::bind(&DebugUtils::GeometryDumper::AddTriangle, | 282 | std::bind(&DebugUtils::GeometryDumper::AddTriangle, |
| 278 | &geometry_dumper, _1, _2, _3)); | 283 | &geometry_dumper, _1, _2, _3)); |
| 284 | #endif | ||
| 279 | 285 | ||
| 280 | // Send to vertex shader | 286 | // Send to vertex shader |
| 281 | VertexShader::OutputVertex output = VertexShader::RunShader(input, attribute_config.GetNumTotalAttributes(), g_state.regs.vs, g_state.vs); | 287 | VertexShader::OutputVertex output = VertexShader::RunShader(input, attribute_config.GetNumTotalAttributes(), g_state.regs.vs, g_state.vs); |
| @@ -308,7 +314,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 308 | VideoCore::g_renderer->hw_rasterizer->DrawTriangles(); | 314 | VideoCore::g_renderer->hw_rasterizer->DrawTriangles(); |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | #if PICA_DUMP_GEOMETRY | ||
| 311 | geometry_dumper.Dump(); | 318 | geometry_dumper.Dump(); |
| 319 | #endif | ||
| 312 | 320 | ||
| 313 | if (g_debug_context) { | 321 | if (g_debug_context) { |
| 314 | g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); | 322 | g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); |
| @@ -424,7 +432,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 424 | VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); | 432 | VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); |
| 425 | 433 | ||
| 426 | if (g_debug_context) | 434 | if (g_debug_context) |
| 427 | g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id)); | 435 | g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id)); |
| 428 | } | 436 | } |
| 429 | 437 | ||
| 430 | void ProcessCommandList(const u32* list, u32 size) { | 438 | void ProcessCommandList(const u32* list, u32 size) { |
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index d24c0f11e..e9a858411 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp | |||
| @@ -85,15 +85,11 @@ void GeometryDumper::AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2) { | |||
| 85 | vertices.push_back(v1); | 85 | vertices.push_back(v1); |
| 86 | vertices.push_back(v2); | 86 | vertices.push_back(v2); |
| 87 | 87 | ||
| 88 | int num_vertices = vertices.size(); | 88 | int num_vertices = (int)vertices.size(); |
| 89 | faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); | 89 | faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | void GeometryDumper::Dump() { | 92 | void GeometryDumper::Dump() { |
| 93 | // NOTE: Permanently enabling this just trashes the hard disk for no reason. | ||
| 94 | // Hence, this is currently disabled. | ||
| 95 | return; | ||
| 96 | |||
| 97 | static int index = 0; | 93 | static int index = 0; |
| 98 | std::string filename = std::string("geometry_dump") + std::to_string(++index) + ".obj"; | 94 | std::string filename = std::string("geometry_dump") + std::to_string(++index) + ".obj"; |
| 99 | 95 | ||
| @@ -116,10 +112,6 @@ void GeometryDumper::Dump() { | |||
| 116 | void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, | 112 | void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, |
| 117 | u32 main_offset, const Regs::VSOutputAttributes* output_attributes) | 113 | u32 main_offset, const Regs::VSOutputAttributes* output_attributes) |
| 118 | { | 114 | { |
| 119 | // NOTE: Permanently enabling this just trashes hard disks for no reason. | ||
| 120 | // Hence, this is currently disabled. | ||
| 121 | return; | ||
| 122 | |||
| 123 | struct StuffToWrite { | 115 | struct StuffToWrite { |
| 124 | u8* pointer; | 116 | u8* pointer; |
| 125 | u32 size; | 117 | u32 size; |
| @@ -241,8 +233,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data | |||
| 241 | 233 | ||
| 242 | dvle.main_offset_words = main_offset; | 234 | dvle.main_offset_words = main_offset; |
| 243 | dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; | 235 | dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; |
| 244 | dvle.output_register_table_size = output_info_table.size(); | 236 | dvle.output_register_table_size = static_cast<uint32_t>(output_info_table.size()); |
| 245 | QueueForWriting((u8*)output_info_table.data(), output_info_table.size() * sizeof(OutputRegisterInfo)); | 237 | QueueForWriting((u8*)output_info_table.data(), static_cast<u32>(output_info_table.size() * sizeof(OutputRegisterInfo))); |
| 246 | 238 | ||
| 247 | // TODO: Create a label table for "main" | 239 | // TODO: Create a label table for "main" |
| 248 | 240 | ||
| @@ -497,31 +489,31 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
| 497 | // Lookup base value | 489 | // Lookup base value |
| 498 | Math::Vec3<int> ret; | 490 | Math::Vec3<int> ret; |
| 499 | if (differential_mode) { | 491 | if (differential_mode) { |
| 500 | ret.r() = differential.r; | 492 | ret.r() = static_cast<int>(differential.r); |
| 501 | ret.g() = differential.g; | 493 | ret.g() = static_cast<int>(differential.g); |
| 502 | ret.b() = differential.b; | 494 | ret.b() = static_cast<int>(differential.b); |
| 503 | if (x >= 2) { | 495 | if (x >= 2) { |
| 504 | ret.r() += differential.dr; | 496 | ret.r() += static_cast<int>(differential.dr); |
| 505 | ret.g() += differential.dg; | 497 | ret.g() += static_cast<int>(differential.dg); |
| 506 | ret.b() += differential.db; | 498 | ret.b() += static_cast<int>(differential.db); |
| 507 | } | 499 | } |
| 508 | ret.r() = Color::Convert5To8(ret.r()); | 500 | ret.r() = Color::Convert5To8(ret.r()); |
| 509 | ret.g() = Color::Convert5To8(ret.g()); | 501 | ret.g() = Color::Convert5To8(ret.g()); |
| 510 | ret.b() = Color::Convert5To8(ret.b()); | 502 | ret.b() = Color::Convert5To8(ret.b()); |
| 511 | } else { | 503 | } else { |
| 512 | if (x < 2) { | 504 | if (x < 2) { |
| 513 | ret.r() = Color::Convert4To8(separate.r1); | 505 | ret.r() = Color::Convert4To8(static_cast<u8>(separate.r1)); |
| 514 | ret.g() = Color::Convert4To8(separate.g1); | 506 | ret.g() = Color::Convert4To8(static_cast<u8>(separate.g1)); |
| 515 | ret.b() = Color::Convert4To8(separate.b1); | 507 | ret.b() = Color::Convert4To8(static_cast<u8>(separate.b1)); |
| 516 | } else { | 508 | } else { |
| 517 | ret.r() = Color::Convert4To8(separate.r2); | 509 | ret.r() = Color::Convert4To8(static_cast<u8>(separate.r2)); |
| 518 | ret.g() = Color::Convert4To8(separate.g2); | 510 | ret.g() = Color::Convert4To8(static_cast<u8>(separate.g2)); |
| 519 | ret.b() = Color::Convert4To8(separate.b2); | 511 | ret.b() = Color::Convert4To8(static_cast<u8>(separate.b2)); |
| 520 | } | 512 | } |
| 521 | } | 513 | } |
| 522 | 514 | ||
| 523 | // Add modifier | 515 | // Add modifier |
| 524 | unsigned table_index = (x < 2) ? table_index_1.Value() : table_index_2.Value(); | 516 | unsigned table_index = static_cast<int>((x < 2) ? table_index_1.Value() : table_index_2.Value()); |
| 525 | 517 | ||
| 526 | static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ | 518 | static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ |
| 527 | { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, | 519 | { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, |
| @@ -565,10 +557,6 @@ TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, | |||
| 565 | } | 557 | } |
| 566 | 558 | ||
| 567 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | 559 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { |
| 568 | // NOTE: Permanently enabling this just trashes hard disks for no reason. | ||
| 569 | // Hence, this is currently disabled. | ||
| 570 | return; | ||
| 571 | |||
| 572 | #ifndef HAVE_PNG | 560 | #ifndef HAVE_PNG |
| 573 | return; | 561 | return; |
| 574 | #else | 562 | #else |
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 2573292e2..81eea30a9 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h | |||
| @@ -25,11 +25,14 @@ public: | |||
| 25 | enum class Event { | 25 | enum class Event { |
| 26 | FirstEvent = 0, | 26 | FirstEvent = 0, |
| 27 | 27 | ||
| 28 | CommandLoaded = FirstEvent, | 28 | PicaCommandLoaded = FirstEvent, |
| 29 | CommandProcessed, | 29 | PicaCommandProcessed, |
| 30 | IncomingPrimitiveBatch, | 30 | IncomingPrimitiveBatch, |
| 31 | FinishedPrimitiveBatch, | 31 | FinishedPrimitiveBatch, |
| 32 | VertexLoaded, | 32 | VertexLoaded, |
| 33 | IncomingDisplayTransfer, | ||
| 34 | GSPCommandProcessed, | ||
| 35 | BufferSwapped, | ||
| 33 | 36 | ||
| 34 | NumEvents | 37 | NumEvents |
| 35 | }; | 38 | }; |
| @@ -154,6 +157,11 @@ extern std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this g | |||
| 154 | 157 | ||
| 155 | namespace DebugUtils { | 158 | namespace DebugUtils { |
| 156 | 159 | ||
| 160 | #define PICA_DUMP_GEOMETRY 0 | ||
| 161 | #define PICA_DUMP_SHADERS 0 | ||
| 162 | #define PICA_DUMP_TEXTURES 0 | ||
| 163 | #define PICA_LOG_TEV 0 | ||
| 164 | |||
| 157 | // Simple utility class for dumping geometry data to an OBJ file | 165 | // Simple utility class for dumping geometry data to an OBJ file |
| 158 | class GeometryDumper { | 166 | class GeometryDumper { |
| 159 | public: | 167 | public: |
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp index 543d9c443..17cb66780 100644 --- a/src/video_core/pica.cpp +++ b/src/video_core/pica.cpp | |||
| @@ -2,7 +2,8 @@ | |||
| 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 <string.h> | 5 | #include <cstring> |
| 6 | #include <unordered_map> | ||
| 6 | 7 | ||
| 7 | #include "pica.h" | 8 | #include "pica.h" |
| 8 | 9 | ||
| @@ -10,6 +11,75 @@ namespace Pica { | |||
| 10 | 11 | ||
| 11 | State g_state; | 12 | State g_state; |
| 12 | 13 | ||
| 14 | std::string Regs::GetCommandName(int index) { | ||
| 15 | static std::unordered_map<u32, std::string> map; | ||
| 16 | |||
| 17 | if (map.empty()) { | ||
| 18 | #define ADD_FIELD(name) \ | ||
| 19 | map.insert({static_cast<u32>(PICA_REG_INDEX(name)), #name}); \ | ||
| 20 | /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ | ||
| 21 | for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ | ||
| 22 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ | ||
| 23 | |||
| 24 | ADD_FIELD(trigger_irq); | ||
| 25 | ADD_FIELD(cull_mode); | ||
| 26 | ADD_FIELD(viewport_size_x); | ||
| 27 | ADD_FIELD(viewport_size_y); | ||
| 28 | ADD_FIELD(viewport_depth_range); | ||
| 29 | ADD_FIELD(viewport_depth_far_plane); | ||
| 30 | ADD_FIELD(viewport_corner); | ||
| 31 | ADD_FIELD(texture0_enable); | ||
| 32 | ADD_FIELD(texture0); | ||
| 33 | ADD_FIELD(texture0_format); | ||
| 34 | ADD_FIELD(texture1); | ||
| 35 | ADD_FIELD(texture1_format); | ||
| 36 | ADD_FIELD(texture2); | ||
| 37 | ADD_FIELD(texture2_format); | ||
| 38 | ADD_FIELD(tev_stage0); | ||
| 39 | ADD_FIELD(tev_stage1); | ||
| 40 | ADD_FIELD(tev_stage2); | ||
| 41 | ADD_FIELD(tev_stage3); | ||
| 42 | ADD_FIELD(tev_combiner_buffer_input); | ||
| 43 | ADD_FIELD(tev_stage4); | ||
| 44 | ADD_FIELD(tev_stage5); | ||
| 45 | ADD_FIELD(tev_combiner_buffer_color); | ||
| 46 | ADD_FIELD(output_merger); | ||
| 47 | ADD_FIELD(framebuffer); | ||
| 48 | ADD_FIELD(vertex_attributes); | ||
| 49 | ADD_FIELD(index_array); | ||
| 50 | ADD_FIELD(num_vertices); | ||
| 51 | ADD_FIELD(trigger_draw); | ||
| 52 | ADD_FIELD(trigger_draw_indexed); | ||
| 53 | ADD_FIELD(vs_default_attributes_setup); | ||
| 54 | ADD_FIELD(command_buffer); | ||
| 55 | ADD_FIELD(triangle_topology); | ||
| 56 | ADD_FIELD(gs.bool_uniforms); | ||
| 57 | ADD_FIELD(gs.int_uniforms); | ||
| 58 | ADD_FIELD(gs.main_offset); | ||
| 59 | ADD_FIELD(gs.input_register_map); | ||
| 60 | ADD_FIELD(gs.uniform_setup); | ||
| 61 | ADD_FIELD(gs.program); | ||
| 62 | ADD_FIELD(gs.swizzle_patterns); | ||
| 63 | ADD_FIELD(vs.bool_uniforms); | ||
| 64 | ADD_FIELD(vs.int_uniforms); | ||
| 65 | ADD_FIELD(vs.main_offset); | ||
| 66 | ADD_FIELD(vs.input_register_map); | ||
| 67 | ADD_FIELD(vs.uniform_setup); | ||
| 68 | ADD_FIELD(vs.program); | ||
| 69 | ADD_FIELD(vs.swizzle_patterns); | ||
| 70 | |||
| 71 | #undef ADD_FIELD | ||
| 72 | } | ||
| 73 | |||
| 74 | // Return empty string if no match is found | ||
| 75 | auto it = map.find(index); | ||
| 76 | if (it != map.end()) { | ||
| 77 | return it->second; | ||
| 78 | } else { | ||
| 79 | return std::string(); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 13 | void Init() { | 83 | void Init() { |
| 14 | } | 84 | } |
| 15 | 85 | ||
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index aec6f0660..34b02b2f8 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cmath> | 8 | #include <cmath> |
| 9 | #include <cstddef> | 9 | #include <cstddef> |
| 10 | #include <map> | ||
| 11 | #include <string> | 10 | #include <string> |
| 12 | 11 | ||
| 13 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| @@ -908,69 +907,7 @@ struct Regs { | |||
| 908 | 907 | ||
| 909 | // Map register indices to names readable by humans | 908 | // Map register indices to names readable by humans |
| 910 | // Used for debugging purposes, so performance is not an issue here | 909 | // Used for debugging purposes, so performance is not an issue here |
| 911 | static std::string GetCommandName(int index) { | 910 | static std::string GetCommandName(int index); |
| 912 | std::map<u32, std::string> map; | ||
| 913 | |||
| 914 | #define ADD_FIELD(name) \ | ||
| 915 | do { \ | ||
| 916 | map.insert({PICA_REG_INDEX(name), #name}); \ | ||
| 917 | /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ | ||
| 918 | for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ | ||
| 919 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ | ||
| 920 | } while(false) | ||
| 921 | |||
| 922 | ADD_FIELD(trigger_irq); | ||
| 923 | ADD_FIELD(cull_mode); | ||
| 924 | ADD_FIELD(viewport_size_x); | ||
| 925 | ADD_FIELD(viewport_size_y); | ||
| 926 | ADD_FIELD(viewport_depth_range); | ||
| 927 | ADD_FIELD(viewport_depth_far_plane); | ||
| 928 | ADD_FIELD(viewport_corner); | ||
| 929 | ADD_FIELD(texture0_enable); | ||
| 930 | ADD_FIELD(texture0); | ||
| 931 | ADD_FIELD(texture0_format); | ||
| 932 | ADD_FIELD(texture1); | ||
| 933 | ADD_FIELD(texture1_format); | ||
| 934 | ADD_FIELD(texture2); | ||
| 935 | ADD_FIELD(texture2_format); | ||
| 936 | ADD_FIELD(tev_stage0); | ||
| 937 | ADD_FIELD(tev_stage1); | ||
| 938 | ADD_FIELD(tev_stage2); | ||
| 939 | ADD_FIELD(tev_stage3); | ||
| 940 | ADD_FIELD(tev_combiner_buffer_input); | ||
| 941 | ADD_FIELD(tev_stage4); | ||
| 942 | ADD_FIELD(tev_stage5); | ||
| 943 | ADD_FIELD(tev_combiner_buffer_color); | ||
| 944 | ADD_FIELD(output_merger); | ||
| 945 | ADD_FIELD(framebuffer); | ||
| 946 | ADD_FIELD(vertex_attributes); | ||
| 947 | ADD_FIELD(index_array); | ||
| 948 | ADD_FIELD(num_vertices); | ||
| 949 | ADD_FIELD(trigger_draw); | ||
| 950 | ADD_FIELD(trigger_draw_indexed); | ||
| 951 | ADD_FIELD(vs_default_attributes_setup); | ||
| 952 | ADD_FIELD(command_buffer); | ||
| 953 | ADD_FIELD(triangle_topology); | ||
| 954 | ADD_FIELD(gs.bool_uniforms); | ||
| 955 | ADD_FIELD(gs.int_uniforms); | ||
| 956 | ADD_FIELD(gs.main_offset); | ||
| 957 | ADD_FIELD(gs.input_register_map); | ||
| 958 | ADD_FIELD(gs.uniform_setup); | ||
| 959 | ADD_FIELD(gs.program); | ||
| 960 | ADD_FIELD(gs.swizzle_patterns); | ||
| 961 | ADD_FIELD(vs.bool_uniforms); | ||
| 962 | ADD_FIELD(vs.int_uniforms); | ||
| 963 | ADD_FIELD(vs.main_offset); | ||
| 964 | ADD_FIELD(vs.input_register_map); | ||
| 965 | ADD_FIELD(vs.uniform_setup); | ||
| 966 | ADD_FIELD(vs.program); | ||
| 967 | ADD_FIELD(vs.swizzle_patterns); | ||
| 968 | |||
| 969 | #undef ADD_FIELD | ||
| 970 | |||
| 971 | // Return empty string if no match is found | ||
| 972 | return map[index]; | ||
| 973 | } | ||
| 974 | 911 | ||
| 975 | static inline size_t NumIds() { | 912 | static inline size_t NumIds() { |
| 976 | return sizeof(Regs) / sizeof(u32); | 913 | return sizeof(Regs) / sizeof(u32); |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index e2b90ad1c..68b7cc05d 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -462,7 +462,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 462 | 462 | ||
| 463 | // TODO: Apply the min and mag filters to the texture | 463 | // TODO: Apply the min and mag filters to the texture |
| 464 | texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); | 464 | texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); |
| 465 | #if PICA_DUMP_TEXTURES | ||
| 465 | DebugUtils::DumpTexture(texture.config, texture_data); | 466 | DebugUtils::DumpTexture(texture.config, texture_data); |
| 467 | #endif | ||
| 466 | } | 468 | } |
| 467 | } | 469 | } |
| 468 | 470 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp deleted file mode 100644 index 8f4ae28a4..000000000 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 6 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 7 | |||
| 8 | // Textures | ||
| 9 | OGLTexture::OGLTexture() : handle(0) { | ||
| 10 | } | ||
| 11 | |||
| 12 | OGLTexture::~OGLTexture() { | ||
| 13 | Release(); | ||
| 14 | } | ||
| 15 | |||
| 16 | void OGLTexture::Create() { | ||
| 17 | if (handle != 0) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | |||
| 21 | glGenTextures(1, &handle); | ||
| 22 | } | ||
| 23 | |||
| 24 | void OGLTexture::Release() { | ||
| 25 | glDeleteTextures(1, &handle); | ||
| 26 | handle = 0; | ||
| 27 | } | ||
| 28 | |||
| 29 | // Shaders | ||
| 30 | OGLShader::OGLShader() : handle(0) { | ||
| 31 | } | ||
| 32 | |||
| 33 | OGLShader::~OGLShader() { | ||
| 34 | Release(); | ||
| 35 | } | ||
| 36 | |||
| 37 | void OGLShader::Create(const char* vert_shader, const char* frag_shader) { | ||
| 38 | if (handle != 0) { | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); | ||
| 43 | } | ||
| 44 | |||
| 45 | void OGLShader::Release() { | ||
| 46 | glDeleteProgram(handle); | ||
| 47 | handle = 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | // Buffer objects | ||
| 51 | OGLBuffer::OGLBuffer() : handle(0) { | ||
| 52 | } | ||
| 53 | |||
| 54 | OGLBuffer::~OGLBuffer() { | ||
| 55 | Release(); | ||
| 56 | } | ||
| 57 | |||
| 58 | void OGLBuffer::Create() { | ||
| 59 | if (handle != 0) { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | |||
| 63 | glGenBuffers(1, &handle); | ||
| 64 | } | ||
| 65 | |||
| 66 | void OGLBuffer::Release() { | ||
| 67 | glDeleteBuffers(1, &handle); | ||
| 68 | handle = 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | // Vertex array objects | ||
| 72 | OGLVertexArray::OGLVertexArray() : handle(0) { | ||
| 73 | } | ||
| 74 | |||
| 75 | OGLVertexArray::~OGLVertexArray() { | ||
| 76 | Release(); | ||
| 77 | } | ||
| 78 | |||
| 79 | void OGLVertexArray::Create() { | ||
| 80 | if (handle != 0) { | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | |||
| 84 | glGenVertexArrays(1, &handle); | ||
| 85 | } | ||
| 86 | |||
| 87 | void OGLVertexArray::Release() { | ||
| 88 | glDeleteVertexArrays(1, &handle); | ||
| 89 | handle = 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | // Framebuffers | ||
| 93 | OGLFramebuffer::OGLFramebuffer() : handle(0) { | ||
| 94 | } | ||
| 95 | |||
| 96 | OGLFramebuffer::~OGLFramebuffer() { | ||
| 97 | Release(); | ||
| 98 | } | ||
| 99 | |||
| 100 | void OGLFramebuffer::Create() { | ||
| 101 | if (handle != 0) { | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | glGenFramebuffers(1, &handle); | ||
| 106 | } | ||
| 107 | |||
| 108 | void OGLFramebuffer::Release() { | ||
| 109 | glDeleteFramebuffers(1, &handle); | ||
| 110 | handle = 0; | ||
| 111 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 975720d0a..6f9dc012d 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -4,76 +4,124 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <utility> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | 10 | ||
| 9 | #include "generated/gl_3_2_core.h" | 11 | #include "video_core/renderer_opengl/generated/gl_3_2_core.h" |
| 12 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 10 | 13 | ||
| 11 | class OGLTexture : public NonCopyable { | 14 | class OGLTexture : private NonCopyable { |
| 12 | public: | 15 | public: |
| 13 | OGLTexture(); | 16 | OGLTexture() = default; |
| 14 | ~OGLTexture(); | 17 | OGLTexture(OGLTexture&& o) { std::swap(handle, o.handle); } |
| 18 | ~OGLTexture() { Release(); } | ||
| 19 | OGLTexture& operator=(OGLTexture&& o) { std::swap(handle, o.handle); return *this; } | ||
| 15 | 20 | ||
| 16 | /// Creates a new internal OpenGL resource and stores the handle | 21 | /// Creates a new internal OpenGL resource and stores the handle |
| 17 | void Create(); | 22 | void Create() { |
| 23 | if (handle != 0) return; | ||
| 24 | glGenTextures(1, &handle); | ||
| 25 | } | ||
| 18 | 26 | ||
| 19 | /// Deletes the internal OpenGL resource | 27 | /// Deletes the internal OpenGL resource |
| 20 | void Release(); | 28 | void Release() { |
| 29 | if (handle == 0) return; | ||
| 30 | glDeleteTextures(1, &handle); | ||
| 31 | handle = 0; | ||
| 32 | } | ||
| 21 | 33 | ||
| 22 | GLuint handle; | 34 | GLuint handle = 0; |
| 23 | }; | 35 | }; |
| 24 | 36 | ||
| 25 | class OGLShader : public NonCopyable { | 37 | class OGLShader : private NonCopyable { |
| 26 | public: | 38 | public: |
| 27 | OGLShader(); | 39 | OGLShader() = default; |
| 28 | ~OGLShader(); | 40 | OGLShader(OGLShader&& o) { std::swap(handle, o.handle); } |
| 41 | ~OGLShader() { Release(); } | ||
| 42 | OGLShader& operator=(OGLShader&& o) { std::swap(handle, o.handle); return *this; } | ||
| 29 | 43 | ||
| 30 | /// Creates a new internal OpenGL resource and stores the handle | 44 | /// Creates a new internal OpenGL resource and stores the handle |
| 31 | void Create(const char* vert_shader, const char* frag_shader); | 45 | void Create(const char* vert_shader, const char* frag_shader) { |
| 46 | if (handle != 0) return; | ||
| 47 | handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); | ||
| 48 | } | ||
| 32 | 49 | ||
| 33 | /// Deletes the internal OpenGL resource | 50 | /// Deletes the internal OpenGL resource |
| 34 | void Release(); | 51 | void Release() { |
| 52 | if (handle == 0) return; | ||
| 53 | glDeleteProgram(handle); | ||
| 54 | handle = 0; | ||
| 55 | } | ||
| 35 | 56 | ||
| 36 | GLuint handle; | 57 | GLuint handle = 0; |
| 37 | }; | 58 | }; |
| 38 | 59 | ||
| 39 | class OGLBuffer : public NonCopyable { | 60 | class OGLBuffer : private NonCopyable { |
| 40 | public: | 61 | public: |
| 41 | OGLBuffer(); | 62 | OGLBuffer() = default; |
| 42 | ~OGLBuffer(); | 63 | OGLBuffer(OGLBuffer&& o) { std::swap(handle, o.handle); } |
| 64 | ~OGLBuffer() { Release(); } | ||
| 65 | OGLBuffer& operator=(OGLBuffer&& o) { std::swap(handle, o.handle); return *this; } | ||
| 43 | 66 | ||
| 44 | /// Creates a new internal OpenGL resource and stores the handle | 67 | /// Creates a new internal OpenGL resource and stores the handle |
| 45 | void Create(); | 68 | void Create() { |
| 69 | if (handle != 0) return; | ||
| 70 | glGenBuffers(1, &handle); | ||
| 71 | } | ||
| 46 | 72 | ||
| 47 | /// Deletes the internal OpenGL resource | 73 | /// Deletes the internal OpenGL resource |
| 48 | void Release(); | 74 | void Release() { |
| 75 | if (handle == 0) return; | ||
| 76 | glDeleteBuffers(1, &handle); | ||
| 77 | handle = 0; | ||
| 78 | } | ||
| 49 | 79 | ||
| 50 | GLuint handle; | 80 | GLuint handle = 0; |
| 51 | }; | 81 | }; |
| 52 | 82 | ||
| 53 | class OGLVertexArray : public NonCopyable { | 83 | class OGLVertexArray : private NonCopyable { |
| 54 | public: | 84 | public: |
| 55 | OGLVertexArray(); | 85 | OGLVertexArray() = default; |
| 56 | ~OGLVertexArray(); | 86 | OGLVertexArray(OGLVertexArray&& o) { std::swap(handle, o.handle); } |
| 87 | ~OGLVertexArray() { Release(); } | ||
| 88 | OGLVertexArray& operator=(OGLVertexArray&& o) { std::swap(handle, o.handle); return *this; } | ||
| 57 | 89 | ||
| 58 | /// Creates a new internal OpenGL resource and stores the handle | 90 | /// Creates a new internal OpenGL resource and stores the handle |
| 59 | void Create(); | 91 | void Create() { |
| 92 | if (handle != 0) return; | ||
| 93 | glGenVertexArrays(1, &handle); | ||
| 94 | } | ||
| 60 | 95 | ||
| 61 | /// Deletes the internal OpenGL resource | 96 | /// Deletes the internal OpenGL resource |
| 62 | void Release(); | 97 | void Release() { |
| 98 | if (handle == 0) return; | ||
| 99 | glDeleteVertexArrays(1, &handle); | ||
| 100 | handle = 0; | ||
| 101 | } | ||
| 63 | 102 | ||
| 64 | GLuint handle; | 103 | GLuint handle = 0; |
| 65 | }; | 104 | }; |
| 66 | 105 | ||
| 67 | class OGLFramebuffer : public NonCopyable { | 106 | class OGLFramebuffer : private NonCopyable { |
| 68 | public: | 107 | public: |
| 69 | OGLFramebuffer(); | 108 | OGLFramebuffer() = default; |
| 70 | ~OGLFramebuffer(); | 109 | OGLFramebuffer(OGLFramebuffer&& o) { std::swap(handle, o.handle); } |
| 110 | ~OGLFramebuffer() { Release(); } | ||
| 111 | OGLFramebuffer& operator=(OGLFramebuffer&& o) { std::swap(handle, o.handle); return *this; } | ||
| 71 | 112 | ||
| 72 | /// Creates a new internal OpenGL resource and stores the handle | 113 | /// Creates a new internal OpenGL resource and stores the handle |
| 73 | void Create(); | 114 | void Create() { |
| 115 | if (handle != 0) return; | ||
| 116 | glGenFramebuffers(1, &handle); | ||
| 117 | } | ||
| 74 | 118 | ||
| 75 | /// Deletes the internal OpenGL resource | 119 | /// Deletes the internal OpenGL resource |
| 76 | void Release(); | 120 | void Release() { |
| 121 | if (handle == 0) return; | ||
| 122 | glDeleteFramebuffers(1, &handle); | ||
| 123 | handle = 0; | ||
| 124 | } | ||
| 77 | 125 | ||
| 78 | GLuint handle; | 126 | GLuint handle = 0; |
| 79 | }; | 127 | }; |
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index ff114fc3a..5f66f3455 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp | |||
| @@ -2,8 +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 <stack> | 5 | #include <boost/container/static_vector.hpp> |
| 6 | |||
| 7 | #include <boost/range/algorithm.hpp> | 6 | #include <boost/range/algorithm.hpp> |
| 8 | 7 | ||
| 9 | #include <common/file_util.h> | 8 | #include <common/file_util.h> |
| @@ -27,7 +26,7 @@ namespace Pica { | |||
| 27 | namespace VertexShader { | 26 | namespace VertexShader { |
| 28 | 27 | ||
| 29 | struct VertexShaderState { | 28 | struct VertexShaderState { |
| 30 | const u32* program_counter; | 29 | u32 program_counter; |
| 31 | 30 | ||
| 32 | const float24* input_register_table[16]; | 31 | const float24* input_register_table[16]; |
| 33 | Math::Vec4<float24> output_registers[16]; | 32 | Math::Vec4<float24> output_registers[16]; |
| @@ -53,7 +52,7 @@ struct VertexShaderState { | |||
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | // TODO: Is there a maximal size for this? | 54 | // TODO: Is there a maximal size for this? |
| 56 | std::stack<CallStackElement> call_stack; | 55 | boost::container::static_vector<CallStackElement, 16> call_stack; |
| 57 | 56 | ||
| 58 | struct { | 57 | struct { |
| 59 | u32 max_offset; // maximum program counter ever reached | 58 | u32 max_offset; // maximum program counter ever reached |
| @@ -71,15 +70,15 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 71 | 70 | ||
| 72 | while (true) { | 71 | while (true) { |
| 73 | if (!state.call_stack.empty()) { | 72 | if (!state.call_stack.empty()) { |
| 74 | auto& top = state.call_stack.top(); | 73 | auto& top = state.call_stack.back(); |
| 75 | if (state.program_counter - program_code.data() == top.final_address) { | 74 | if (state.program_counter == top.final_address) { |
| 76 | state.address_registers[2] += top.loop_increment; | 75 | state.address_registers[2] += top.loop_increment; |
| 77 | 76 | ||
| 78 | if (top.repeat_counter-- == 0) { | 77 | if (top.repeat_counter-- == 0) { |
| 79 | state.program_counter = &program_code[top.return_address]; | 78 | state.program_counter = top.return_address; |
| 80 | state.call_stack.pop(); | 79 | state.call_stack.pop_back(); |
| 81 | } else { | 80 | } else { |
| 82 | state.program_counter = &program_code[top.loop_address]; | 81 | state.program_counter = top.loop_address; |
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | // TODO: Is "trying again" accurate to hardware? | 84 | // TODO: Is "trying again" accurate to hardware? |
| @@ -88,17 +87,16 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | bool exit_loop = false; | 89 | bool exit_loop = false; |
| 91 | const Instruction& instr = *(const Instruction*)state.program_counter; | 90 | const Instruction instr = { program_code[state.program_counter] }; |
| 92 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; | 91 | const SwizzlePattern swizzle = { swizzle_data[instr.common.operand_desc_id] }; |
| 93 | 92 | ||
| 94 | static auto call = [&program_code](VertexShaderState& state, u32 offset, u32 num_instructions, | 93 | static auto call = [](VertexShaderState& state, u32 offset, u32 num_instructions, |
| 95 | u32 return_offset, u8 repeat_count, u8 loop_increment) { | 94 | u32 return_offset, u8 repeat_count, u8 loop_increment) { |
| 96 | state.program_counter = &program_code[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset | 95 | state.program_counter = offset - 1; // -1 to make sure when incrementing the PC we end up at the correct offset |
| 97 | state.call_stack.push({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); | 96 | ASSERT(state.call_stack.size() < state.call_stack.capacity()); |
| 97 | state.call_stack.push_back({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); | ||
| 98 | }; | 98 | }; |
| 99 | u32 binary_offset = state.program_counter - program_code.data(); | 99 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + state.program_counter); |
| 100 | |||
| 101 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset); | ||
| 102 | 100 | ||
| 103 | auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { | 101 | auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { |
| 104 | switch (source_reg.GetRegisterType()) { | 102 | switch (source_reg.GetRegisterType()) { |
| @@ -442,13 +440,13 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 442 | 440 | ||
| 443 | case OpCode::Id::JMPC: | 441 | case OpCode::Id::JMPC: |
| 444 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | 442 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { |
| 445 | state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; | 443 | state.program_counter = instr.flow_control.dest_offset - 1; |
| 446 | } | 444 | } |
| 447 | break; | 445 | break; |
| 448 | 446 | ||
| 449 | case OpCode::Id::JMPU: | 447 | case OpCode::Id::JMPU: |
| 450 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { | 448 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { |
| 451 | state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; | 449 | state.program_counter = instr.flow_control.dest_offset - 1; |
| 452 | } | 450 | } |
| 453 | break; | 451 | break; |
| 454 | 452 | ||
| @@ -456,7 +454,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 456 | call(state, | 454 | call(state, |
| 457 | instr.flow_control.dest_offset, | 455 | instr.flow_control.dest_offset, |
| 458 | instr.flow_control.num_instructions, | 456 | instr.flow_control.num_instructions, |
| 459 | binary_offset + 1, 0, 0); | 457 | state.program_counter + 1, 0, 0); |
| 460 | break; | 458 | break; |
| 461 | 459 | ||
| 462 | case OpCode::Id::CALLU: | 460 | case OpCode::Id::CALLU: |
| @@ -464,7 +462,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 464 | call(state, | 462 | call(state, |
| 465 | instr.flow_control.dest_offset, | 463 | instr.flow_control.dest_offset, |
| 466 | instr.flow_control.num_instructions, | 464 | instr.flow_control.num_instructions, |
| 467 | binary_offset + 1, 0, 0); | 465 | state.program_counter + 1, 0, 0); |
| 468 | } | 466 | } |
| 469 | break; | 467 | break; |
| 470 | 468 | ||
| @@ -473,7 +471,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 473 | call(state, | 471 | call(state, |
| 474 | instr.flow_control.dest_offset, | 472 | instr.flow_control.dest_offset, |
| 475 | instr.flow_control.num_instructions, | 473 | instr.flow_control.num_instructions, |
| 476 | binary_offset + 1, 0, 0); | 474 | state.program_counter + 1, 0, 0); |
| 477 | } | 475 | } |
| 478 | break; | 476 | break; |
| 479 | 477 | ||
| @@ -483,8 +481,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 483 | case OpCode::Id::IFU: | 481 | case OpCode::Id::IFU: |
| 484 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { | 482 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { |
| 485 | call(state, | 483 | call(state, |
| 486 | binary_offset + 1, | 484 | state.program_counter + 1, |
| 487 | instr.flow_control.dest_offset - binary_offset - 1, | 485 | instr.flow_control.dest_offset - state.program_counter - 1, |
| 488 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); | 486 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); |
| 489 | } else { | 487 | } else { |
| 490 | call(state, | 488 | call(state, |
| @@ -501,8 +499,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 501 | 499 | ||
| 502 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | 500 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { |
| 503 | call(state, | 501 | call(state, |
| 504 | binary_offset + 1, | 502 | state.program_counter + 1, |
| 505 | instr.flow_control.dest_offset - binary_offset - 1, | 503 | instr.flow_control.dest_offset - state.program_counter - 1, |
| 506 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); | 504 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); |
| 507 | } else { | 505 | } else { |
| 508 | call(state, | 506 | call(state, |
| @@ -519,8 +517,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 519 | state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y; | 517 | state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y; |
| 520 | 518 | ||
| 521 | call(state, | 519 | call(state, |
| 522 | binary_offset + 1, | 520 | state.program_counter + 1, |
| 523 | instr.flow_control.dest_offset - binary_offset + 1, | 521 | instr.flow_control.dest_offset - state.program_counter + 1, |
| 524 | instr.flow_control.dest_offset + 1, | 522 | instr.flow_control.dest_offset + 1, |
| 525 | uniforms.i[instr.flow_control.int_uniform_id].x, | 523 | uniforms.i[instr.flow_control.int_uniform_id].x, |
| 526 | uniforms.i[instr.flow_control.int_uniform_id].z); | 524 | uniforms.i[instr.flow_control.int_uniform_id].z); |
| @@ -551,8 +549,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: | |||
| 551 | 549 | ||
| 552 | VertexShaderState state; | 550 | VertexShaderState state; |
| 553 | 551 | ||
| 554 | const u32* main = &setup.program_code[config.main_offset]; | 552 | state.program_counter = config.main_offset; |
| 555 | state.program_counter = (u32*)main; | ||
| 556 | state.debug.max_offset = 0; | 553 | state.debug.max_offset = 0; |
| 557 | state.debug.max_opdesc_id = 0; | 554 | state.debug.max_opdesc_id = 0; |
| 558 | 555 | ||
| @@ -582,9 +579,11 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: | |||
| 582 | state.conditional_code[1] = false; | 579 | state.conditional_code[1] = false; |
| 583 | 580 | ||
| 584 | ProcessShaderCode(state); | 581 | ProcessShaderCode(state); |
| 582 | #if PICA_DUMP_SHADERS | ||
| 585 | DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), | 583 | DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), |
| 586 | state.debug.max_opdesc_id, config.main_offset, | 584 | state.debug.max_opdesc_id, config.main_offset, |
| 587 | g_state.regs.vs_output_attributes); // TODO: Don't hardcode VS here | 585 | g_state.regs.vs_output_attributes); // TODO: Don't hardcode VS here |
| 586 | #endif | ||
| 588 | 587 | ||
| 589 | // Setup output data | 588 | // Setup output data |
| 590 | OutputVertex ret; | 589 | OutputVertex ret; |