diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 2 | ||||
| -rw-r--r-- | src/core/settings.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_dma.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 41 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 223 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_stream_buffer.cpp | 2 |
10 files changed, 220 insertions, 103 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 0d31abe8b..a8e0c869f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 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 <atomic> | ||
| 6 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 6 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| @@ -78,7 +77,7 @@ private: | |||
| 78 | SharedMemory mem{}; | 77 | SharedMemory mem{}; |
| 79 | std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); | 78 | std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); |
| 80 | 79 | ||
| 81 | if (is_device_reload_pending.exchange(false)) | 80 | if (Settings::values.is_device_reload_pending.exchange(false)) |
| 82 | LoadInputDevices(); | 81 | LoadInputDevices(); |
| 83 | 82 | ||
| 84 | // Set up controllers as neon red+blue Joy-Con attached to console | 83 | // Set up controllers as neon red+blue Joy-Con attached to console |
| @@ -267,7 +266,6 @@ private: | |||
| 267 | CoreTiming::EventType* pad_update_event; | 266 | CoreTiming::EventType* pad_update_event; |
| 268 | 267 | ||
| 269 | // Stored input state info | 268 | // Stored input state info |
| 270 | std::atomic<bool> is_device_reload_pending{true}; | ||
| 271 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> | 269 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> |
| 272 | buttons; | 270 | buttons; |
| 273 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks; | 271 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks; |
| @@ -797,7 +795,9 @@ public: | |||
| 797 | } | 795 | } |
| 798 | }; | 796 | }; |
| 799 | 797 | ||
| 800 | void ReloadInputDevices() {} | 798 | void ReloadInputDevices() { |
| 799 | Settings::values.is_device_reload_pending.store(true); | ||
| 800 | } | ||
| 801 | 801 | ||
| 802 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 802 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
| 803 | std::make_shared<Hid>()->InstallAsService(service_manager); | 803 | std::make_shared<Hid>()->InstallAsService(service_manager); |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 9d804652e..9bb7c7b26 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -74,8 +74,6 @@ using Kernel::SharedPtr; | |||
| 74 | 74 | ||
| 75 | namespace Service { | 75 | namespace Service { |
| 76 | 76 | ||
| 77 | std::unordered_map<std::string, SharedPtr<ClientPort>> g_kernel_named_ports; | ||
| 78 | |||
| 79 | /** | 77 | /** |
| 80 | * Creates a function string for logging, complete with the name (or header code, depending | 78 | * Creates a function string for logging, complete with the name (or header code, depending |
| 81 | * on what's passed in) the port name, and all the cmd_buff arguments. | 79 | * on what's passed in) the port name, and all the cmd_buff arguments. |
diff --git a/src/core/settings.h b/src/core/settings.h index 5bf1863e6..08a16ef2c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <atomic> | ||
| 8 | #include <string> | 9 | #include <string> |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | 11 | ||
| @@ -120,6 +121,7 @@ struct Values { | |||
| 120 | std::array<std::string, NativeAnalog::NumAnalogs> analogs; | 121 | std::array<std::string, NativeAnalog::NumAnalogs> analogs; |
| 121 | std::string motion_device; | 122 | std::string motion_device; |
| 122 | std::string touch_device; | 123 | std::string touch_device; |
| 124 | std::atomic_bool is_device_reload_pending{true}; | ||
| 123 | 125 | ||
| 124 | // Core | 126 | // Core |
| 125 | bool use_cpu_jit; | 127 | bool use_cpu_jit; |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 6e740713f..c24d33d5c 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -41,7 +41,6 @@ void MaxwellDMA::HandleCopy() { | |||
| 41 | 41 | ||
| 42 | // TODO(Subv): Perform more research and implement all features of this engine. | 42 | // TODO(Subv): Perform more research and implement all features of this engine. |
| 43 | ASSERT(regs.exec.enable_swizzle == 0); | 43 | ASSERT(regs.exec.enable_swizzle == 0); |
| 44 | ASSERT(regs.exec.enable_2d == 1); | ||
| 45 | ASSERT(regs.exec.query_mode == Regs::QueryMode::None); | 44 | ASSERT(regs.exec.query_mode == Regs::QueryMode::None); |
| 46 | ASSERT(regs.exec.query_intr == Regs::QueryIntr::None); | 45 | ASSERT(regs.exec.query_intr == Regs::QueryIntr::None); |
| 47 | ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2); | 46 | ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2); |
| @@ -51,10 +50,19 @@ void MaxwellDMA::HandleCopy() { | |||
| 51 | ASSERT(regs.dst_params.pos_y == 0); | 50 | ASSERT(regs.dst_params.pos_y == 0); |
| 52 | 51 | ||
| 53 | if (regs.exec.is_dst_linear == regs.exec.is_src_linear) { | 52 | if (regs.exec.is_dst_linear == regs.exec.is_src_linear) { |
| 54 | Memory::CopyBlock(dest_cpu, source_cpu, regs.x_count * regs.y_count); | 53 | size_t copy_size = regs.x_count; |
| 54 | |||
| 55 | // When the enable_2d bit is disabled, the copy is performed as if we were copying a 1D | ||
| 56 | // buffer of length `x_count`, otherwise we copy a 2D buffer of size (x_count, y_count). | ||
| 57 | if (regs.exec.enable_2d) { | ||
| 58 | copy_size = copy_size * regs.y_count; | ||
| 59 | } | ||
| 60 | |||
| 61 | Memory::CopyBlock(dest_cpu, source_cpu, copy_size); | ||
| 55 | return; | 62 | return; |
| 56 | } | 63 | } |
| 57 | 64 | ||
| 65 | ASSERT(regs.exec.enable_2d == 1); | ||
| 58 | u8* src_buffer = Memory::GetPointer(source_cpu); | 66 | u8* src_buffer = Memory::GetPointer(source_cpu); |
| 59 | u8* dst_buffer = Memory::GetPointer(dest_cpu); | 67 | u8* dst_buffer = Memory::GetPointer(dest_cpu); |
| 60 | 68 | ||
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index d2388673e..9176a8dbc 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -244,6 +244,16 @@ enum class TextureType : u64 { | |||
| 244 | TextureCube = 3, | 244 | TextureCube = 3, |
| 245 | }; | 245 | }; |
| 246 | 246 | ||
| 247 | enum class TextureQueryType : u64 { | ||
| 248 | Dimension = 1, | ||
| 249 | TextureType = 2, | ||
| 250 | SamplePosition = 5, | ||
| 251 | Filter = 16, | ||
| 252 | LevelOfDetail = 18, | ||
| 253 | Wrap = 20, | ||
| 254 | BorderColor = 22, | ||
| 255 | }; | ||
| 256 | |||
| 247 | enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; | 257 | enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; |
| 248 | enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; | 258 | enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; |
| 249 | 259 | ||
| @@ -519,6 +529,21 @@ union Instruction { | |||
| 519 | } tex; | 529 | } tex; |
| 520 | 530 | ||
| 521 | union { | 531 | union { |
| 532 | BitField<22, 6, TextureQueryType> query_type; | ||
| 533 | BitField<31, 4, u64> component_mask; | ||
| 534 | } txq; | ||
| 535 | |||
| 536 | union { | ||
| 537 | BitField<28, 1, u64> array; | ||
| 538 | BitField<29, 2, TextureType> texture_type; | ||
| 539 | BitField<31, 4, u64> component_mask; | ||
| 540 | |||
| 541 | bool IsComponentEnabled(size_t component) const { | ||
| 542 | return ((1ull << component) & component_mask) != 0; | ||
| 543 | } | ||
| 544 | } tmml; | ||
| 545 | |||
| 546 | union { | ||
| 522 | BitField<28, 1, u64> array; | 547 | BitField<28, 1, u64> array; |
| 523 | BitField<29, 2, TextureType> texture_type; | 548 | BitField<29, 2, TextureType> texture_type; |
| 524 | BitField<56, 2, u64> component; | 549 | BitField<56, 2, u64> component; |
| @@ -670,11 +695,13 @@ public: | |||
| 670 | LDG, // Load from global memory | 695 | LDG, // Load from global memory |
| 671 | STG, // Store in global memory | 696 | STG, // Store in global memory |
| 672 | TEX, | 697 | TEX, |
| 673 | TEXQ, // Texture Query | 698 | TXQ, // Texture Query |
| 674 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations | 699 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations |
| 675 | TLDS, // Texture Load with scalar/non-vec4 source/destinations | 700 | TLDS, // Texture Load with scalar/non-vec4 source/destinations |
| 676 | TLD4, // Texture Load 4 | 701 | TLD4, // Texture Load 4 |
| 677 | TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations | 702 | TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations |
| 703 | TMML_B, // Texture Mip Map Level | ||
| 704 | TMML, // Texture Mip Map Level | ||
| 678 | EXIT, | 705 | EXIT, |
| 679 | IPA, | 706 | IPA, |
| 680 | FFMA_IMM, // Fused Multiply and Add | 707 | FFMA_IMM, // Fused Multiply and Add |
| @@ -894,11 +921,13 @@ private: | |||
| 894 | INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), | 921 | INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), |
| 895 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), | 922 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), |
| 896 | INST("110000----111---", Id::TEX, Type::Memory, "TEX"), | 923 | INST("110000----111---", Id::TEX, Type::Memory, "TEX"), |
| 897 | INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"), | 924 | INST("1101111101001---", Id::TXQ, Type::Memory, "TXQ"), |
| 898 | INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), | 925 | INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), |
| 899 | INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), | 926 | INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), |
| 900 | INST("110010----111---", Id::TLD4, Type::Memory, "TLD4"), | 927 | INST("110010----111---", Id::TLD4, Type::Memory, "TLD4"), |
| 901 | INST("1101111100------", Id::TLD4S, Type::Memory, "TLD4S"), | 928 | INST("1101111100------", Id::TLD4S, Type::Memory, "TLD4S"), |
| 929 | INST("110111110110----", Id::TMML_B, Type::Memory, "TMML_B"), | ||
| 930 | INST("1101111101011---", Id::TMML, Type::Memory, "TMML"), | ||
| 902 | INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), | 931 | INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), |
| 903 | INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), | 932 | INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), |
| 904 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), | 933 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 360fb0cd5..fa730b9e6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -505,7 +505,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { | |||
| 505 | 505 | ||
| 506 | S8Z24 input_pixel{}; | 506 | S8Z24 input_pixel{}; |
| 507 | Z24S8 output_pixel{}; | 507 | Z24S8 output_pixel{}; |
| 508 | const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)}; | 508 | constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)}; |
| 509 | for (size_t y = 0; y < height; ++y) { | 509 | for (size_t y = 0; y < height; ++y) { |
| 510 | for (size_t x = 0; x < width; ++x) { | 510 | for (size_t x = 0; x < width; ++x) { |
| 511 | const size_t offset{bpp * (y * width + x)}; | 511 | const size_t offset{bpp * (y * width + x)}; |
| @@ -518,7 +518,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { | |||
| 518 | } | 518 | } |
| 519 | 519 | ||
| 520 | static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { | 520 | static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { |
| 521 | const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)}; | 521 | constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)}; |
| 522 | for (size_t y = 0; y < height; ++y) { | 522 | for (size_t y = 0; y < height; ++y) { |
| 523 | for (size_t x = 0; x < width; ++x) { | 523 | for (size_t x = 0; x < width; ++x) { |
| 524 | const size_t offset{bpp * (y * width + x)}; | 524 | const size_t offset{bpp * (y * width + x)}; |
| @@ -584,12 +584,13 @@ void CachedSurface::LoadGLBuffer() { | |||
| 584 | UNREACHABLE(); | 584 | UNREACHABLE(); |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | gl_buffer.resize(params.depth * copy_size); | 587 | gl_buffer.resize(static_cast<size_t>(params.depth) * copy_size); |
| 588 | morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( | 588 | morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( |
| 589 | params.width, params.block_height, params.height, gl_buffer.data(), copy_size, | 589 | params.width, params.block_height, params.height, gl_buffer.data(), copy_size, |
| 590 | params.addr); | 590 | params.addr); |
| 591 | } else { | 591 | } else { |
| 592 | const u8* const texture_src_data_end{texture_src_data + (params.depth * copy_size)}; | 592 | const u8* const texture_src_data_end{texture_src_data + |
| 593 | (static_cast<size_t>(params.depth) * copy_size)}; | ||
| 593 | gl_buffer.assign(texture_src_data, texture_src_data_end); | 594 | gl_buffer.assign(texture_src_data, texture_src_data_end); |
| 594 | } | 595 | } |
| 595 | 596 | ||
| @@ -608,18 +609,20 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle | |||
| 608 | 609 | ||
| 609 | MICROPROFILE_SCOPE(OpenGL_TextureUL); | 610 | MICROPROFILE_SCOPE(OpenGL_TextureUL); |
| 610 | 611 | ||
| 611 | ASSERT(gl_buffer.size() == | 612 | ASSERT(gl_buffer.size() == static_cast<size_t>(params.width) * params.height * |
| 612 | params.width * params.height * GetGLBytesPerPixel(params.pixel_format) * params.depth); | 613 | GetGLBytesPerPixel(params.pixel_format) * params.depth); |
| 613 | 614 | ||
| 614 | const auto& rect{params.GetRect()}; | 615 | const auto& rect{params.GetRect()}; |
| 615 | 616 | ||
| 616 | // Load data from memory to the surface | 617 | // Load data from memory to the surface |
| 617 | GLint x0 = static_cast<GLint>(rect.left); | 618 | const GLint x0 = static_cast<GLint>(rect.left); |
| 618 | GLint y0 = static_cast<GLint>(rect.bottom); | 619 | const GLint y0 = static_cast<GLint>(rect.bottom); |
| 619 | size_t buffer_offset = (y0 * params.width + x0) * GetGLBytesPerPixel(params.pixel_format); | 620 | const size_t buffer_offset = |
| 621 | static_cast<size_t>(static_cast<size_t>(y0) * params.width + static_cast<size_t>(x0)) * | ||
| 622 | GetGLBytesPerPixel(params.pixel_format); | ||
| 620 | 623 | ||
| 621 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); | 624 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); |
| 622 | GLuint target_tex = texture.handle; | 625 | const GLuint target_tex = texture.handle; |
| 623 | OpenGLState cur_state = OpenGLState::GetCurState(); | 626 | OpenGLState cur_state = OpenGLState::GetCurState(); |
| 624 | 627 | ||
| 625 | const auto& old_tex = cur_state.texture_units[0]; | 628 | const auto& old_tex = cur_state.texture_units[0]; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7e4b85ac3..61080f5cc 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -13,8 +13,8 @@ namespace OpenGL { | |||
| 13 | 13 | ||
| 14 | /// Gets the address for the specified shader stage program | 14 | /// Gets the address for the specified shader stage program |
| 15 | static VAddr GetShaderAddress(Maxwell::ShaderProgram program) { | 15 | static VAddr GetShaderAddress(Maxwell::ShaderProgram program) { |
| 16 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 16 | const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); |
| 17 | auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)]; | 17 | const auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)]; |
| 18 | return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() + | 18 | return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() + |
| 19 | shader_config.offset); | 19 | shader_config.offset); |
| 20 | } | 20 | } |
| @@ -86,7 +86,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { | 88 | GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { |
| 89 | auto search{resource_cache.find(buffer.GetHash())}; | 89 | const auto search{resource_cache.find(buffer.GetHash())}; |
| 90 | if (search == resource_cache.end()) { | 90 | if (search == resource_cache.end()) { |
| 91 | const GLuint index{ | 91 | const GLuint index{ |
| 92 | glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; | 92 | glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; |
| @@ -98,7 +98,7 @@ GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& b | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { | 100 | GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { |
| 101 | auto search{uniform_cache.find(sampler.GetHash())}; | 101 | const auto search{uniform_cache.find(sampler.GetHash())}; |
| 102 | if (search == uniform_cache.end()) { | 102 | if (search == uniform_cache.end()) { |
| 103 | const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())}; | 103 | const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())}; |
| 104 | uniform_cache[sampler.GetHash()] = index; | 104 | uniform_cache[sampler.GetHash()] = index; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 172ba8335..762e58aad 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -113,7 +113,7 @@ private: | |||
| 113 | 113 | ||
| 114 | /// Scans a range of code for labels and determines the exit method. | 114 | /// Scans a range of code for labels and determines the exit method. |
| 115 | ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) { | 115 | ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) { |
| 116 | auto [iter, inserted] = | 116 | const auto [iter, inserted] = |
| 117 | exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); | 117 | exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); |
| 118 | ExitMethod& exit_method = iter->second; | 118 | ExitMethod& exit_method = iter->second; |
| 119 | if (!inserted) | 119 | if (!inserted) |
| @@ -131,22 +131,22 @@ private: | |||
| 131 | if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { | 131 | if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { |
| 132 | return exit_method = ExitMethod::AlwaysEnd; | 132 | return exit_method = ExitMethod::AlwaysEnd; |
| 133 | } else { | 133 | } else { |
| 134 | ExitMethod not_met = Scan(offset + 1, end, labels); | 134 | const ExitMethod not_met = Scan(offset + 1, end, labels); |
| 135 | return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); | 135 | return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); |
| 136 | } | 136 | } |
| 137 | } | 137 | } |
| 138 | case OpCode::Id::BRA: { | 138 | case OpCode::Id::BRA: { |
| 139 | u32 target = offset + instr.bra.GetBranchTarget(); | 139 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 140 | labels.insert(target); | 140 | labels.insert(target); |
| 141 | ExitMethod no_jmp = Scan(offset + 1, end, labels); | 141 | const ExitMethod no_jmp = Scan(offset + 1, end, labels); |
| 142 | ExitMethod jmp = Scan(target, end, labels); | 142 | const ExitMethod jmp = Scan(target, end, labels); |
| 143 | return exit_method = ParallelExit(no_jmp, jmp); | 143 | return exit_method = ParallelExit(no_jmp, jmp); |
| 144 | } | 144 | } |
| 145 | case OpCode::Id::SSY: { | 145 | case OpCode::Id::SSY: { |
| 146 | // The SSY instruction uses a similar encoding as the BRA instruction. | 146 | // The SSY instruction uses a similar encoding as the BRA instruction. |
| 147 | ASSERT_MSG(instr.bra.constant_buffer == 0, | 147 | ASSERT_MSG(instr.bra.constant_buffer == 0, |
| 148 | "Constant buffer SSY is not supported"); | 148 | "Constant buffer SSY is not supported"); |
| 149 | u32 target = offset + instr.bra.GetBranchTarget(); | 149 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 150 | labels.insert(target); | 150 | labels.insert(target); |
| 151 | // Continue scanning for an exit method. | 151 | // Continue scanning for an exit method. |
| 152 | break; | 152 | break; |
| @@ -346,8 +346,8 @@ public: | |||
| 346 | */ | 346 | */ |
| 347 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, | 347 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, |
| 348 | const Tegra::Shader::IpaMode& input_mode) { | 348 | const Tegra::Shader::IpaMode& input_mode) { |
| 349 | std::string dest = GetRegisterAsFloat(reg); | 349 | const std::string dest = GetRegisterAsFloat(reg); |
| 350 | std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem); | 350 | const std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem); |
| 351 | shader.AddLine(dest + " = " + src + ';'); | 351 | shader.AddLine(dest + " = " + src + ';'); |
| 352 | } | 352 | } |
| 353 | 353 | ||
| @@ -359,8 +359,8 @@ public: | |||
| 359 | * @param reg The register to use as the source value. | 359 | * @param reg The register to use as the source value. |
| 360 | */ | 360 | */ |
| 361 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { | 361 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { |
| 362 | std::string dest = GetOutputAttribute(attribute); | 362 | const std::string dest = GetOutputAttribute(attribute); |
| 363 | std::string src = GetRegisterAsFloat(reg); | 363 | const std::string src = GetRegisterAsFloat(reg); |
| 364 | 364 | ||
| 365 | if (!dest.empty()) { | 365 | if (!dest.empty()) { |
| 366 | // Can happen with unknown/unimplemented output attributes, in which case we ignore the | 366 | // Can happen with unknown/unimplemented output attributes, in which case we ignore the |
| @@ -393,9 +393,9 @@ public: | |||
| 393 | GLSLRegister::Type type) { | 393 | GLSLRegister::Type type) { |
| 394 | declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage); | 394 | declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage); |
| 395 | 395 | ||
| 396 | std::string final_offset = fmt::format("({} + {})", index_str, offset / 4); | 396 | const std::string final_offset = fmt::format("({} + {})", index_str, offset / 4); |
| 397 | std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" + | 397 | const std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" + |
| 398 | final_offset + " % 4]"; | 398 | final_offset + " % 4]"; |
| 399 | 399 | ||
| 400 | if (type == GLSLRegister::Type::Float) { | 400 | if (type == GLSLRegister::Type::Float) { |
| 401 | return value; | 401 | return value; |
| @@ -468,10 +468,10 @@ public: | |||
| 468 | /// necessary. | 468 | /// necessary. |
| 469 | std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, | 469 | std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, |
| 470 | bool is_array) { | 470 | bool is_array) { |
| 471 | size_t offset = static_cast<size_t>(sampler.index.Value()); | 471 | const size_t offset = static_cast<size_t>(sampler.index.Value()); |
| 472 | 472 | ||
| 473 | // If this sampler has already been used, return the existing mapping. | 473 | // If this sampler has already been used, return the existing mapping. |
| 474 | auto itr = | 474 | const auto itr = |
| 475 | std::find_if(used_samplers.begin(), used_samplers.end(), | 475 | std::find_if(used_samplers.begin(), used_samplers.end(), |
| 476 | [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); | 476 | [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); |
| 477 | 477 | ||
| @@ -481,8 +481,8 @@ public: | |||
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | // Otherwise create a new mapping for this sampler | 483 | // Otherwise create a new mapping for this sampler |
| 484 | size_t next_index = used_samplers.size(); | 484 | const size_t next_index = used_samplers.size(); |
| 485 | SamplerEntry entry{stage, offset, next_index, type, is_array}; | 485 | const SamplerEntry entry{stage, offset, next_index, type, is_array}; |
| 486 | used_samplers.emplace_back(entry); | 486 | used_samplers.emplace_back(entry); |
| 487 | return entry.GetName(); | 487 | return entry.GetName(); |
| 488 | } | 488 | } |
| @@ -699,7 +699,7 @@ private: | |||
| 699 | }; | 699 | }; |
| 700 | 700 | ||
| 701 | bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const { | 701 | bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const { |
| 702 | u32 bit = render_target * 4 + component; | 702 | const u32 bit = render_target * 4 + component; |
| 703 | return enabled_color_outputs & (1 << bit); | 703 | return enabled_color_outputs & (1 << bit); |
| 704 | } | 704 | } |
| 705 | }; | 705 | }; |
| @@ -707,7 +707,7 @@ private: | |||
| 707 | 707 | ||
| 708 | /// Gets the Subroutine object corresponding to the specified address. | 708 | /// Gets the Subroutine object corresponding to the specified address. |
| 709 | const Subroutine& GetSubroutine(u32 begin, u32 end) const { | 709 | const Subroutine& GetSubroutine(u32 begin, u32 end) const { |
| 710 | auto iter = subroutines.find(Subroutine{begin, end, suffix}); | 710 | const auto iter = subroutines.find(Subroutine{begin, end, suffix}); |
| 711 | ASSERT(iter != subroutines.end()); | 711 | ASSERT(iter != subroutines.end()); |
| 712 | return *iter; | 712 | return *iter; |
| 713 | } | 713 | } |
| @@ -752,7 +752,7 @@ private: | |||
| 752 | // Can't assign to the constant predicate. | 752 | // Can't assign to the constant predicate. |
| 753 | ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); | 753 | ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); |
| 754 | 754 | ||
| 755 | std::string variable = 'p' + std::to_string(pred) + '_' + suffix; | 755 | const std::string variable = 'p' + std::to_string(pred) + '_' + suffix; |
| 756 | shader.AddLine(variable + " = " + value + ';'); | 756 | shader.AddLine(variable + " = " + value + ';'); |
| 757 | declr_predicates.insert(std::move(variable)); | 757 | declr_predicates.insert(std::move(variable)); |
| 758 | } | 758 | } |
| @@ -1033,7 +1033,11 @@ private: | |||
| 1033 | if (header.writes_depth) { | 1033 | if (header.writes_depth) { |
| 1034 | // The depth output is always 2 registers after the last color output, and current_reg | 1034 | // The depth output is always 2 registers after the last color output, and current_reg |
| 1035 | // already contains one past the last color register. | 1035 | // already contains one past the last color register. |
| 1036 | shader.AddLine("gl_FragDepth = " + regs.GetRegisterAsFloat(current_reg + 1) + ';'); | 1036 | |
| 1037 | shader.AddLine( | ||
| 1038 | "gl_FragDepth = " + | ||
| 1039 | regs.GetRegisterAsFloat(static_cast<Tegra::Shader::Register>(current_reg) + 1) + | ||
| 1040 | ';'); | ||
| 1037 | } | 1041 | } |
| 1038 | } | 1042 | } |
| 1039 | 1043 | ||
| @@ -1435,7 +1439,7 @@ private: | |||
| 1435 | if (instr.alu_integer.negate_b) | 1439 | if (instr.alu_integer.negate_b) |
| 1436 | op_b = "-(" + op_b + ')'; | 1440 | op_b = "-(" + op_b + ')'; |
| 1437 | 1441 | ||
| 1438 | std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); | 1442 | const std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); |
| 1439 | 1443 | ||
| 1440 | regs.SetRegisterToInteger(instr.gpr0, true, 0, | 1444 | regs.SetRegisterToInteger(instr.gpr0, true, 0, |
| 1441 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | 1445 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); |
| @@ -1453,7 +1457,7 @@ private: | |||
| 1453 | case OpCode::Id::SEL_C: | 1457 | case OpCode::Id::SEL_C: |
| 1454 | case OpCode::Id::SEL_R: | 1458 | case OpCode::Id::SEL_R: |
| 1455 | case OpCode::Id::SEL_IMM: { | 1459 | case OpCode::Id::SEL_IMM: { |
| 1456 | std::string condition = | 1460 | const std::string condition = |
| 1457 | GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0); | 1461 | GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0); |
| 1458 | regs.SetRegisterToInteger(instr.gpr0, true, 0, | 1462 | regs.SetRegisterToInteger(instr.gpr0, true, 0, |
| 1459 | '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1); | 1463 | '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1); |
| @@ -1475,8 +1479,9 @@ private: | |||
| 1475 | case OpCode::Id::LOP3_C: | 1479 | case OpCode::Id::LOP3_C: |
| 1476 | case OpCode::Id::LOP3_R: | 1480 | case OpCode::Id::LOP3_R: |
| 1477 | case OpCode::Id::LOP3_IMM: { | 1481 | case OpCode::Id::LOP3_IMM: { |
| 1478 | std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); | 1482 | const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); |
| 1479 | std::string lut; | 1483 | std::string lut; |
| 1484 | |||
| 1480 | if (opcode->GetId() == OpCode::Id::LOP3_R) { | 1485 | if (opcode->GetId() == OpCode::Id::LOP3_R) { |
| 1481 | lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')'; | 1486 | lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')'; |
| 1482 | } else { | 1487 | } else { |
| @@ -1491,9 +1496,9 @@ private: | |||
| 1491 | case OpCode::Id::IMNMX_IMM: { | 1496 | case OpCode::Id::IMNMX_IMM: { |
| 1492 | ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None, | 1497 | ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None, |
| 1493 | "Unimplemented"); | 1498 | "Unimplemented"); |
| 1494 | std::string condition = | 1499 | const std::string condition = |
| 1495 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); | 1500 | GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); |
| 1496 | std::string parameters = op_a + ',' + op_b; | 1501 | const std::string parameters = op_a + ',' + op_b; |
| 1497 | regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0, | 1502 | regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0, |
| 1498 | '(' + condition + ") ? min(" + parameters + ") : max(" + | 1503 | '(' + condition + ") ? min(" + parameters + ") : max(" + |
| 1499 | parameters + ')', | 1504 | parameters + ')', |
| @@ -1510,7 +1515,7 @@ private: | |||
| 1510 | break; | 1515 | break; |
| 1511 | } | 1516 | } |
| 1512 | case OpCode::Type::Ffma: { | 1517 | case OpCode::Type::Ffma: { |
| 1513 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1518 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 1514 | std::string op_b = instr.ffma.negate_b ? "-" : ""; | 1519 | std::string op_b = instr.ffma.negate_b ? "-" : ""; |
| 1515 | std::string op_c = instr.ffma.negate_c ? "-" : ""; | 1520 | std::string op_c = instr.ffma.negate_c ? "-" : ""; |
| 1516 | 1521 | ||
| @@ -1720,7 +1725,7 @@ private: | |||
| 1720 | shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + | 1725 | shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + |
| 1721 | " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); | 1726 | " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); |
| 1722 | 1727 | ||
| 1723 | std::string op_a = | 1728 | const std::string op_a = |
| 1724 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index", | 1729 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index", |
| 1725 | GLSLRegister::Type::Float); | 1730 | GLSLRegister::Type::Float); |
| 1726 | 1731 | ||
| @@ -1730,7 +1735,7 @@ private: | |||
| 1730 | break; | 1735 | break; |
| 1731 | 1736 | ||
| 1732 | case Tegra::Shader::UniformType::Double: { | 1737 | case Tegra::Shader::UniformType::Double: { |
| 1733 | std::string op_b = | 1738 | const std::string op_b = |
| 1734 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, | 1739 | regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, |
| 1735 | "index", GLSLRegister::Type::Float); | 1740 | "index", GLSLRegister::Type::Float); |
| 1736 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 1741 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| @@ -1760,13 +1765,13 @@ private: | |||
| 1760 | 1765 | ||
| 1761 | switch (texture_type) { | 1766 | switch (texture_type) { |
| 1762 | case Tegra::Shader::TextureType::Texture1D: { | 1767 | case Tegra::Shader::TextureType::Texture1D: { |
| 1763 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1768 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1764 | coord = "float coords = " + x + ';'; | 1769 | coord = "float coords = " + x + ';'; |
| 1765 | break; | 1770 | break; |
| 1766 | } | 1771 | } |
| 1767 | case Tegra::Shader::TextureType::Texture2D: { | 1772 | case Tegra::Shader::TextureType::Texture2D: { |
| 1768 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1773 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1769 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1774 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 1770 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 1775 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| 1771 | break; | 1776 | break; |
| 1772 | } | 1777 | } |
| @@ -1776,8 +1781,8 @@ private: | |||
| 1776 | UNREACHABLE(); | 1781 | UNREACHABLE(); |
| 1777 | 1782 | ||
| 1778 | // Fallback to interpreting as a 2D texture for now | 1783 | // Fallback to interpreting as a 2D texture for now |
| 1779 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1784 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1780 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1785 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 1781 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 1786 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| 1782 | texture_type = Tegra::Shader::TextureType::Texture2D; | 1787 | texture_type = Tegra::Shader::TextureType::Texture2D; |
| 1783 | } | 1788 | } |
| @@ -1811,13 +1816,13 @@ private: | |||
| 1811 | switch (texture_type) { | 1816 | switch (texture_type) { |
| 1812 | case Tegra::Shader::TextureType::Texture2D: { | 1817 | case Tegra::Shader::TextureType::Texture2D: { |
| 1813 | if (is_array) { | 1818 | if (is_array) { |
| 1814 | std::string index = regs.GetRegisterAsInteger(instr.gpr8); | 1819 | const std::string index = regs.GetRegisterAsInteger(instr.gpr8); |
| 1815 | std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1820 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 1816 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | 1821 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); |
| 1817 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; | 1822 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; |
| 1818 | } else { | 1823 | } else { |
| 1819 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1824 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1820 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | 1825 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); |
| 1821 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 1826 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| 1822 | } | 1827 | } |
| 1823 | break; | 1828 | break; |
| @@ -1828,8 +1833,8 @@ private: | |||
| 1828 | UNREACHABLE(); | 1833 | UNREACHABLE(); |
| 1829 | 1834 | ||
| 1830 | // Fallback to interpreting as a 2D texture for now | 1835 | // Fallback to interpreting as a 2D texture for now |
| 1831 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1836 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1832 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | 1837 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); |
| 1833 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 1838 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| 1834 | texture_type = Tegra::Shader::TextureType::Texture2D; | 1839 | texture_type = Tegra::Shader::TextureType::Texture2D; |
| 1835 | is_array = false; | 1840 | is_array = false; |
| @@ -1850,8 +1855,8 @@ private: | |||
| 1850 | LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); | 1855 | LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); |
| 1851 | UNREACHABLE(); | 1856 | UNREACHABLE(); |
| 1852 | } else { | 1857 | } else { |
| 1853 | std::string x = regs.GetRegisterAsInteger(instr.gpr8); | 1858 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); |
| 1854 | std::string y = regs.GetRegisterAsInteger(instr.gpr20); | 1859 | const std::string y = regs.GetRegisterAsInteger(instr.gpr20); |
| 1855 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; | 1860 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; |
| 1856 | } | 1861 | } |
| 1857 | break; | 1862 | break; |
| @@ -1874,8 +1879,8 @@ private: | |||
| 1874 | 1879 | ||
| 1875 | switch (instr.tld4.texture_type) { | 1880 | switch (instr.tld4.texture_type) { |
| 1876 | case Tegra::Shader::TextureType::Texture2D: { | 1881 | case Tegra::Shader::TextureType::Texture2D: { |
| 1877 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | 1882 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); |
| 1878 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1883 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 1879 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 1884 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; |
| 1880 | break; | 1885 | break; |
| 1881 | } | 1886 | } |
| @@ -1920,6 +1925,74 @@ private: | |||
| 1920 | WriteTexsInstruction(instr, coord, texture); | 1925 | WriteTexsInstruction(instr, coord, texture); |
| 1921 | break; | 1926 | break; |
| 1922 | } | 1927 | } |
| 1928 | case OpCode::Id::TXQ: { | ||
| 1929 | // TODO: the new commits on the texture refactor, change the way samplers work. | ||
| 1930 | // Sadly, not all texture instructions specify the type of texture their sampler | ||
| 1931 | // uses. This must be fixed at a later instance. | ||
| 1932 | const std::string sampler = | ||
| 1933 | GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); | ||
| 1934 | switch (instr.txq.query_type) { | ||
| 1935 | case Tegra::Shader::TextureQueryType::Dimension: { | ||
| 1936 | const std::string texture = "textureQueryLevels(" + sampler + ')'; | ||
| 1937 | regs.SetRegisterToInteger(instr.gpr0, true, 0, texture, 1, 1); | ||
| 1938 | break; | ||
| 1939 | } | ||
| 1940 | default: { | ||
| 1941 | LOG_CRITICAL(HW_GPU, "Unhandled texture query type: {}", | ||
| 1942 | static_cast<u32>(instr.txq.query_type.Value())); | ||
| 1943 | UNREACHABLE(); | ||
| 1944 | } | ||
| 1945 | } | ||
| 1946 | break; | ||
| 1947 | } | ||
| 1948 | case OpCode::Id::TMML: { | ||
| 1949 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1950 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1951 | const bool is_array = instr.tmml.array != 0; | ||
| 1952 | auto texture_type = instr.tmml.texture_type.Value(); | ||
| 1953 | const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); | ||
| 1954 | |||
| 1955 | // TODO: add coordinates for different samplers once other texture types are | ||
| 1956 | // implemented. | ||
| 1957 | std::string coord; | ||
| 1958 | switch (texture_type) { | ||
| 1959 | case Tegra::Shader::TextureType::Texture1D: { | ||
| 1960 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1961 | coord = "float coords = " + x + ';'; | ||
| 1962 | break; | ||
| 1963 | } | ||
| 1964 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1965 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1966 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1967 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1968 | break; | ||
| 1969 | } | ||
| 1970 | default: | ||
| 1971 | LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | ||
| 1972 | static_cast<u32>(texture_type)); | ||
| 1973 | UNREACHABLE(); | ||
| 1974 | |||
| 1975 | // Fallback to interpreting as a 2D texture for now | ||
| 1976 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1977 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1978 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1979 | texture_type = Tegra::Shader::TextureType::Texture2D; | ||
| 1980 | } | ||
| 1981 | // Add an extra scope and declare the texture coords inside to prevent | ||
| 1982 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 1983 | shader.AddLine('{'); | ||
| 1984 | ++shader.scope; | ||
| 1985 | shader.AddLine(coord); | ||
| 1986 | const std::string texture = "textureQueryLod(" + sampler + ", coords)"; | ||
| 1987 | const std::string tmp = "vec2 tmp = " + texture + "*vec2(256.0, 256.0);"; | ||
| 1988 | shader.AddLine(tmp); | ||
| 1989 | |||
| 1990 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(tmp.y)", 1, 1); | ||
| 1991 | regs.SetRegisterToInteger(instr.gpr0.Value() + 1, false, 0, "uint(tmp.x)", 1, 1); | ||
| 1992 | --shader.scope; | ||
| 1993 | shader.AddLine('}'); | ||
| 1994 | break; | ||
| 1995 | } | ||
| 1923 | default: { | 1996 | default: { |
| 1924 | LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName()); | 1997 | LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName()); |
| 1925 | UNREACHABLE(); | 1998 | UNREACHABLE(); |
| @@ -1959,12 +2032,12 @@ private: | |||
| 1959 | // We can't use the constant predicate as destination. | 2032 | // We can't use the constant predicate as destination. |
| 1960 | ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | 2033 | ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); |
| 1961 | 2034 | ||
| 1962 | std::string second_pred = | 2035 | const std::string second_pred = |
| 1963 | GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); | 2036 | GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); |
| 1964 | 2037 | ||
| 1965 | std::string combiner = GetPredicateCombiner(instr.fsetp.op); | 2038 | const std::string combiner = GetPredicateCombiner(instr.fsetp.op); |
| 1966 | 2039 | ||
| 1967 | std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b); | 2040 | const std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b); |
| 1968 | // Set the primary predicate to the result of Predicate OP SecondPredicate | 2041 | // Set the primary predicate to the result of Predicate OP SecondPredicate |
| 1969 | SetPredicate(instr.fsetp.pred3, | 2042 | SetPredicate(instr.fsetp.pred3, |
| 1970 | '(' + predicate + ") " + combiner + " (" + second_pred + ')'); | 2043 | '(' + predicate + ") " + combiner + " (" + second_pred + ')'); |
| @@ -1978,7 +2051,8 @@ private: | |||
| 1978 | break; | 2051 | break; |
| 1979 | } | 2052 | } |
| 1980 | case OpCode::Type::IntegerSetPredicate: { | 2053 | case OpCode::Type::IntegerSetPredicate: { |
| 1981 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); | 2054 | const std::string op_a = |
| 2055 | regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); | ||
| 1982 | std::string op_b; | 2056 | std::string op_b; |
| 1983 | 2057 | ||
| 1984 | if (instr.is_b_imm) { | 2058 | if (instr.is_b_imm) { |
| @@ -1995,12 +2069,12 @@ private: | |||
| 1995 | // We can't use the constant predicate as destination. | 2069 | // We can't use the constant predicate as destination. |
| 1996 | ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | 2070 | ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); |
| 1997 | 2071 | ||
| 1998 | std::string second_pred = | 2072 | const std::string second_pred = |
| 1999 | GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0); | 2073 | GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0); |
| 2000 | 2074 | ||
| 2001 | std::string combiner = GetPredicateCombiner(instr.isetp.op); | 2075 | const std::string combiner = GetPredicateCombiner(instr.isetp.op); |
| 2002 | 2076 | ||
| 2003 | std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b); | 2077 | const std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b); |
| 2004 | // Set the primary predicate to the result of Predicate OP SecondPredicate | 2078 | // Set the primary predicate to the result of Predicate OP SecondPredicate |
| 2005 | SetPredicate(instr.isetp.pred3, | 2079 | SetPredicate(instr.isetp.pred3, |
| 2006 | '(' + predicate + ") " + combiner + " (" + second_pred + ')'); | 2080 | '(' + predicate + ") " + combiner + " (" + second_pred + ')'); |
| @@ -2014,20 +2088,20 @@ private: | |||
| 2014 | break; | 2088 | break; |
| 2015 | } | 2089 | } |
| 2016 | case OpCode::Type::PredicateSetPredicate: { | 2090 | case OpCode::Type::PredicateSetPredicate: { |
| 2017 | std::string op_a = | 2091 | const std::string op_a = |
| 2018 | GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); | 2092 | GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); |
| 2019 | std::string op_b = | 2093 | const std::string op_b = |
| 2020 | GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); | 2094 | GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); |
| 2021 | 2095 | ||
| 2022 | // We can't use the constant predicate as destination. | 2096 | // We can't use the constant predicate as destination. |
| 2023 | ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | 2097 | ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); |
| 2024 | 2098 | ||
| 2025 | std::string second_pred = | 2099 | const std::string second_pred = |
| 2026 | GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); | 2100 | GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); |
| 2027 | 2101 | ||
| 2028 | std::string combiner = GetPredicateCombiner(instr.psetp.op); | 2102 | const std::string combiner = GetPredicateCombiner(instr.psetp.op); |
| 2029 | 2103 | ||
| 2030 | std::string predicate = | 2104 | const std::string predicate = |
| 2031 | '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; | 2105 | '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; |
| 2032 | 2106 | ||
| 2033 | // Set the primary predicate to the result of Predicate OP SecondPredicate | 2107 | // Set the primary predicate to the result of Predicate OP SecondPredicate |
| @@ -2053,7 +2127,7 @@ private: | |||
| 2053 | std::string op_b = instr.fset.neg_b ? "-" : ""; | 2127 | std::string op_b = instr.fset.neg_b ? "-" : ""; |
| 2054 | 2128 | ||
| 2055 | if (instr.is_b_imm) { | 2129 | if (instr.is_b_imm) { |
| 2056 | std::string imm = GetImmediate19(instr); | 2130 | const std::string imm = GetImmediate19(instr); |
| 2057 | if (instr.fset.neg_imm) | 2131 | if (instr.fset.neg_imm) |
| 2058 | op_b += "(-" + imm + ')'; | 2132 | op_b += "(-" + imm + ')'; |
| 2059 | else | 2133 | else |
| @@ -2073,13 +2147,14 @@ private: | |||
| 2073 | 2147 | ||
| 2074 | // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the | 2148 | // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the |
| 2075 | // condition is true, and to 0 otherwise. | 2149 | // condition is true, and to 0 otherwise. |
| 2076 | std::string second_pred = | 2150 | const std::string second_pred = |
| 2077 | GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0); | 2151 | GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0); |
| 2078 | 2152 | ||
| 2079 | std::string combiner = GetPredicateCombiner(instr.fset.op); | 2153 | const std::string combiner = GetPredicateCombiner(instr.fset.op); |
| 2080 | 2154 | ||
| 2081 | std::string predicate = "((" + GetPredicateComparison(instr.fset.cond, op_a, op_b) + | 2155 | const std::string predicate = "((" + |
| 2082 | ") " + combiner + " (" + second_pred + "))"; | 2156 | GetPredicateComparison(instr.fset.cond, op_a, op_b) + |
| 2157 | ") " + combiner + " (" + second_pred + "))"; | ||
| 2083 | 2158 | ||
| 2084 | if (instr.fset.bf) { | 2159 | if (instr.fset.bf) { |
| 2085 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); | 2160 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); |
| @@ -2090,7 +2165,7 @@ private: | |||
| 2090 | break; | 2165 | break; |
| 2091 | } | 2166 | } |
| 2092 | case OpCode::Type::IntegerSet: { | 2167 | case OpCode::Type::IntegerSet: { |
| 2093 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed); | 2168 | const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed); |
| 2094 | 2169 | ||
| 2095 | std::string op_b; | 2170 | std::string op_b; |
| 2096 | 2171 | ||
| @@ -2107,13 +2182,14 @@ private: | |||
| 2107 | 2182 | ||
| 2108 | // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the | 2183 | // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the |
| 2109 | // condition is true, and to 0 otherwise. | 2184 | // condition is true, and to 0 otherwise. |
| 2110 | std::string second_pred = | 2185 | const std::string second_pred = |
| 2111 | GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0); | 2186 | GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0); |
| 2112 | 2187 | ||
| 2113 | std::string combiner = GetPredicateCombiner(instr.iset.op); | 2188 | const std::string combiner = GetPredicateCombiner(instr.iset.op); |
| 2114 | 2189 | ||
| 2115 | std::string predicate = "((" + GetPredicateComparison(instr.iset.cond, op_a, op_b) + | 2190 | const std::string predicate = "((" + |
| 2116 | ") " + combiner + " (" + second_pred + "))"; | 2191 | GetPredicateComparison(instr.iset.cond, op_a, op_b) + |
| 2192 | ") " + combiner + " (" + second_pred + "))"; | ||
| 2117 | 2193 | ||
| 2118 | if (instr.iset.bf) { | 2194 | if (instr.iset.bf) { |
| 2119 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); | 2195 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); |
| @@ -2263,7 +2339,7 @@ private: | |||
| 2263 | case OpCode::Id::BRA: { | 2339 | case OpCode::Id::BRA: { |
| 2264 | ASSERT_MSG(instr.bra.constant_buffer == 0, | 2340 | ASSERT_MSG(instr.bra.constant_buffer == 0, |
| 2265 | "BRA with constant buffers are not implemented"); | 2341 | "BRA with constant buffers are not implemented"); |
| 2266 | u32 target = offset + instr.bra.GetBranchTarget(); | 2342 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 2267 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); | 2343 | shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); |
| 2268 | break; | 2344 | break; |
| 2269 | } | 2345 | } |
| @@ -2287,7 +2363,7 @@ private: | |||
| 2287 | // has a similar structure to the BRA opcode. | 2363 | // has a similar structure to the BRA opcode. |
| 2288 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); | 2364 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); |
| 2289 | 2365 | ||
| 2290 | u32 target = offset + instr.bra.GetBranchTarget(); | 2366 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 2291 | EmitPushToSSYStack(target); | 2367 | EmitPushToSSYStack(target); |
| 2292 | break; | 2368 | break; |
| 2293 | } | 2369 | } |
| @@ -2381,10 +2457,10 @@ private: | |||
| 2381 | shader.AddLine("case " + std::to_string(label) + "u: {"); | 2457 | shader.AddLine("case " + std::to_string(label) + "u: {"); |
| 2382 | ++shader.scope; | 2458 | ++shader.scope; |
| 2383 | 2459 | ||
| 2384 | auto next_it = labels.lower_bound(label + 1); | 2460 | const auto next_it = labels.lower_bound(label + 1); |
| 2385 | u32 next_label = next_it == labels.end() ? subroutine.end : *next_it; | 2461 | const u32 next_label = next_it == labels.end() ? subroutine.end : *next_it; |
| 2386 | 2462 | ||
| 2387 | u32 compile_end = CompileRange(label, next_label); | 2463 | const u32 compile_end = CompileRange(label, next_label); |
| 2388 | if (compile_end > next_label && compile_end != PROGRAM_END) { | 2464 | if (compile_end > next_label && compile_end != PROGRAM_END) { |
| 2389 | // This happens only when there is a label inside a IF/LOOP block | 2465 | // This happens only when there is a label inside a IF/LOOP block |
| 2390 | shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }"); | 2466 | shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }"); |
| @@ -2447,7 +2523,8 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, | |||
| 2447 | Maxwell3D::Regs::ShaderStage stage, | 2523 | Maxwell3D::Regs::ShaderStage stage, |
| 2448 | const std::string& suffix) { | 2524 | const std::string& suffix) { |
| 2449 | try { | 2525 | try { |
| 2450 | auto subroutines = ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines(); | 2526 | const auto subroutines = |
| 2527 | ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines(); | ||
| 2451 | GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix); | 2528 | GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix); |
| 2452 | return ProgramResult{generator.GetShaderCode(), generator.GetEntries()}; | 2529 | return ProgramResult{generator.GetShaderCode(), generator.GetEntries()}; |
| 2453 | } catch (const DecompileFail& exception) { | 2530 | } catch (const DecompileFail& exception) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 5781d9d16..5f3fe067e 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -25,7 +25,7 @@ GLuint LoadShader(const char* source, GLenum type) { | |||
| 25 | default: | 25 | default: |
| 26 | UNREACHABLE(); | 26 | UNREACHABLE(); |
| 27 | } | 27 | } |
| 28 | GLuint shader_id = glCreateShader(type); | 28 | const GLuint shader_id = glCreateShader(type); |
| 29 | glShaderSource(shader_id, 1, &source, nullptr); | 29 | glShaderSource(shader_id, 1, &source, nullptr); |
| 30 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | 30 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); |
| 31 | glCompileShader(shader_id); | 31 | glCompileShader(shader_id); |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp index e565afcee..aadf68f16 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp +++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp | |||
| @@ -29,7 +29,7 @@ OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coh | |||
| 29 | if (GLAD_GL_ARB_buffer_storage) { | 29 | if (GLAD_GL_ARB_buffer_storage) { |
| 30 | persistent = true; | 30 | persistent = true; |
| 31 | coherent = prefer_coherent; | 31 | coherent = prefer_coherent; |
| 32 | GLbitfield flags = | 32 | const GLbitfield flags = |
| 33 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); | 33 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); |
| 34 | glBufferStorage(gl_target, allocate_size, nullptr, flags); | 34 | glBufferStorage(gl_target, allocate_size, nullptr, flags); |
| 35 | mapped_ptr = static_cast<u8*>(glMapBufferRange( | 35 | mapped_ptr = static_cast<u8*>(glMapBufferRange( |