diff options
Diffstat (limited to 'src')
23 files changed, 392 insertions, 195 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 6d5218465..5753b871a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | #include <thread> | 12 | #include <thread> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #ifdef _WIN32 | 14 | #ifdef _WIN32 |
| 15 | #include <share.h> // For _SH_DENYWR | 15 | #include <share.h> // For _SH_DENYWR |
| 16 | #include <windows.h> // For OutputDebugStringA | ||
| 16 | #else | 17 | #else |
| 17 | #define _SH_DENYWR 0 | 18 | #define _SH_DENYWR 0 |
| 18 | #endif | 19 | #endif |
| @@ -139,12 +140,18 @@ void FileBackend::Write(const Entry& entry) { | |||
| 139 | if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { | 140 | if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { |
| 140 | return; | 141 | return; |
| 141 | } | 142 | } |
| 142 | bytes_written += file.WriteString(FormatLogMessage(entry) + '\n'); | 143 | bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); |
| 143 | if (entry.log_level >= Level::Error) { | 144 | if (entry.log_level >= Level::Error) { |
| 144 | file.Flush(); | 145 | file.Flush(); |
| 145 | } | 146 | } |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 149 | void DebuggerBackend::Write(const Entry& entry) { | ||
| 150 | #ifdef _WIN32 | ||
| 151 | ::OutputDebugStringA(FormatLogMessage(entry).append(1, '\n').c_str()); | ||
| 152 | #endif | ||
| 153 | } | ||
| 154 | |||
| 148 | /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. | 155 | /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. |
| 149 | #define ALL_LOG_CLASSES() \ | 156 | #define ALL_LOG_CLASSES() \ |
| 150 | CLS(Log) \ | 157 | CLS(Log) \ |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 11edbf1b6..91bb0c309 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -103,6 +103,20 @@ private: | |||
| 103 | std::size_t bytes_written; | 103 | std::size_t bytes_written; |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | /** | ||
| 107 | * Backend that writes to Visual Studio's output window | ||
| 108 | */ | ||
| 109 | class DebuggerBackend : public Backend { | ||
| 110 | public: | ||
| 111 | static const char* Name() { | ||
| 112 | return "debugger"; | ||
| 113 | } | ||
| 114 | const char* GetName() const override { | ||
| 115 | return Name(); | ||
| 116 | } | ||
| 117 | void Write(const Entry& entry) override; | ||
| 118 | }; | ||
| 119 | |||
| 106 | void AddBackend(std::unique_ptr<Backend> backend); | 120 | void AddBackend(std::unique_ptr<Backend> backend); |
| 107 | 121 | ||
| 108 | void RemoveBackend(std::string_view backend_name); | 122 | void RemoveBackend(std::string_view backend_name); |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 7168c6a10..783c39503 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -161,7 +161,7 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) { | |||
| 161 | ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); | 161 | ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); |
| 162 | 162 | ||
| 163 | std::size_t worker_sz = WorkerBufferSize(channel_count); | 163 | std::size_t worker_sz = WorkerBufferSize(channel_count); |
| 164 | ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large"); | 164 | ASSERT_MSG(buffer_sz >= worker_sz, "Worker buffer too large"); |
| 165 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder{ | 165 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder{ |
| 166 | static_cast<OpusDecoder*>(operator new(worker_sz))}; | 166 | static_cast<OpusDecoder*>(operator new(worker_sz))}; |
| 167 | if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) { | 167 | if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) { |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 4b4d1324f..1ef789bd0 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -427,6 +427,9 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const { | 429 | Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const { |
| 430 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should | ||
| 431 | // be signalled at least once, and signaled after a new controller is connected? | ||
| 432 | styleset_changed_event->Signal(); | ||
| 430 | return styleset_changed_event; | 433 | return styleset_changed_event; |
| 431 | } | 434 | } |
| 432 | 435 | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index a9aa9ec78..a45fd4954 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -96,6 +96,8 @@ public: | |||
| 96 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) | 96 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) |
| 97 | 97 | ||
| 98 | CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); | 98 | CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); |
| 99 | |||
| 100 | ReloadInputDevices(); | ||
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | void ActivateController(HidController controller) { | 103 | void ActivateController(HidController controller) { |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 2fe81a560..8cff5eb71 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h | |||
| @@ -58,9 +58,9 @@ public: | |||
| 58 | /// Rotate source image 90 degrees clockwise | 58 | /// Rotate source image 90 degrees clockwise |
| 59 | Rotate90 = 0x04, | 59 | Rotate90 = 0x04, |
| 60 | /// Rotate source image 180 degrees | 60 | /// Rotate source image 180 degrees |
| 61 | Roate180 = 0x03, | 61 | Rotate180 = 0x03, |
| 62 | /// Rotate source image 270 degrees clockwise | 62 | /// Rotate source image 270 degrees clockwise |
| 63 | Roate270 = 0x07, | 63 | Rotate270 = 0x07, |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | struct Buffer { | 66 | struct Buffer { |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index ddb1a1d69..0b1cc1290 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -33,6 +33,7 @@ add_library(video_core STATIC | |||
| 33 | renderer_opengl/gl_rasterizer.h | 33 | renderer_opengl/gl_rasterizer.h |
| 34 | renderer_opengl/gl_rasterizer_cache.cpp | 34 | renderer_opengl/gl_rasterizer_cache.cpp |
| 35 | renderer_opengl/gl_rasterizer_cache.h | 35 | renderer_opengl/gl_rasterizer_cache.h |
| 36 | renderer_opengl/gl_resource_manager.cpp | ||
| 36 | renderer_opengl/gl_resource_manager.h | 37 | renderer_opengl/gl_resource_manager.h |
| 37 | renderer_opengl/gl_shader_cache.cpp | 38 | renderer_opengl/gl_shader_cache.cpp |
| 38 | renderer_opengl/gl_shader_cache.h | 39 | renderer_opengl/gl_shader_cache.h |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 57f501177..091d9f043 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "core/settings.h" | 16 | #include "core/settings.h" |
| 17 | #include "video_core/engines/maxwell_3d.h" | 17 | #include "video_core/engines/maxwell_3d.h" |
| 18 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 18 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| 19 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 19 | #include "video_core/renderer_opengl/utils.h" | 20 | #include "video_core/renderer_opengl/utils.h" |
| 20 | #include "video_core/surface.h" | 21 | #include "video_core/surface.h" |
| 21 | #include "video_core/textures/astc.h" | 22 | #include "video_core/textures/astc.h" |
| @@ -58,16 +59,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) { | |||
| 58 | 59 | ||
| 59 | std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only, | 60 | std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only, |
| 60 | bool uncompressed) const { | 61 | bool uncompressed) const { |
| 61 | const u32 compression_factor{GetCompressionFactor(pixel_format)}; | 62 | const u32 tile_x{GetDefaultBlockWidth(pixel_format)}; |
| 63 | const u32 tile_y{GetDefaultBlockHeight(pixel_format)}; | ||
| 62 | const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; | 64 | const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; |
| 63 | u32 m_depth = (layer_only ? 1U : depth); | 65 | u32 m_depth = (layer_only ? 1U : depth); |
| 64 | u32 m_width = MipWidth(mip_level); | 66 | u32 m_width = MipWidth(mip_level); |
| 65 | u32 m_height = MipHeight(mip_level); | 67 | u32 m_height = MipHeight(mip_level); |
| 66 | m_width = uncompressed ? m_width | 68 | m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x); |
| 67 | : std::max(1U, (m_width + compression_factor - 1) / compression_factor); | 69 | m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y); |
| 68 | m_height = uncompressed | ||
| 69 | ? m_height | ||
| 70 | : std::max(1U, (m_height + compression_factor - 1) / compression_factor); | ||
| 71 | m_depth = std::max(1U, m_depth >> mip_level); | 70 | m_depth = std::max(1U, m_depth >> mip_level); |
| 72 | u32 m_block_height = MipBlockHeight(mip_level); | 71 | u32 m_block_height = MipBlockHeight(mip_level); |
| 73 | u32 m_block_depth = MipBlockDepth(mip_level); | 72 | u32 m_block_depth = MipBlockDepth(mip_level); |
| @@ -128,6 +127,13 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, | |||
| 128 | params.target = SurfaceTarget::Texture2D; | 127 | params.target = SurfaceTarget::Texture2D; |
| 129 | } | 128 | } |
| 130 | break; | 129 | break; |
| 130 | case SurfaceTarget::TextureCubeArray: | ||
| 131 | params.depth = config.tic.Depth() * 6; | ||
| 132 | if (!entry.IsArray()) { | ||
| 133 | ASSERT(params.depth == 6); | ||
| 134 | params.target = SurfaceTarget::TextureCubemap; | ||
| 135 | } | ||
| 136 | break; | ||
| 131 | default: | 137 | default: |
| 132 | LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target)); | 138 | LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target)); |
| 133 | UNREACHABLE(); | 139 | UNREACHABLE(); |
| @@ -305,6 +311,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex | |||
| 305 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB | 311 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB |
| 306 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB | 312 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB |
| 307 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB | 313 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB |
| 314 | {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5 | ||
| 315 | {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB | ||
| 308 | 316 | ||
| 309 | // Depth formats | 317 | // Depth formats |
| 310 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F | 318 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F |
| @@ -334,6 +342,8 @@ static GLenum SurfaceTargetToGL(SurfaceTarget target) { | |||
| 334 | return GL_TEXTURE_2D_ARRAY; | 342 | return GL_TEXTURE_2D_ARRAY; |
| 335 | case SurfaceTarget::TextureCubemap: | 343 | case SurfaceTarget::TextureCubemap: |
| 336 | return GL_TEXTURE_CUBE_MAP; | 344 | return GL_TEXTURE_CUBE_MAP; |
| 345 | case SurfaceTarget::TextureCubeArray: | ||
| 346 | return GL_TEXTURE_CUBE_MAP_ARRAY_ARB; | ||
| 337 | } | 347 | } |
| 338 | LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target)); | 348 | LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target)); |
| 339 | UNREACHABLE(); | 349 | UNREACHABLE(); |
| @@ -364,15 +374,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d | |||
| 364 | 374 | ||
| 365 | // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual | 375 | // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual |
| 366 | // pixel values. | 376 | // pixel values. |
| 367 | const u32 tile_size{IsFormatBCn(format) ? 4U : 1U}; | 377 | const u32 tile_size_x{GetDefaultBlockWidth(format)}; |
| 378 | const u32 tile_size_y{GetDefaultBlockHeight(format)}; | ||
| 368 | 379 | ||
| 369 | if (morton_to_gl) { | 380 | if (morton_to_gl) { |
| 370 | const std::vector<u8> data = Tegra::Texture::UnswizzleTexture( | 381 | const std::vector<u8> data = |
| 371 | addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth); | 382 | Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel, |
| 383 | stride, height, depth, block_height, block_depth); | ||
| 372 | const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())}; | 384 | const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())}; |
| 373 | memcpy(gl_buffer, data.data(), size_to_copy); | 385 | memcpy(gl_buffer, data.data(), size_to_copy); |
| 374 | } else { | 386 | } else { |
| 375 | Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth, | 387 | Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x, |
| 388 | (height + tile_size_y - 1) / tile_size_y, depth, | ||
| 376 | bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr), | 389 | bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr), |
| 377 | gl_buffer, false, block_height, block_depth); | 390 | gl_buffer, false, block_height, block_depth); |
| 378 | } | 391 | } |
| @@ -440,6 +453,8 @@ static constexpr GLConversionArray morton_to_gl_fns = { | |||
| 440 | MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, | 453 | MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, |
| 441 | MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, | 454 | MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, |
| 442 | MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, | 455 | MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, |
| 456 | MortonCopy<true, PixelFormat::ASTC_2D_5X5>, | ||
| 457 | MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, | ||
| 443 | MortonCopy<true, PixelFormat::Z32F>, | 458 | MortonCopy<true, PixelFormat::Z32F>, |
| 444 | MortonCopy<true, PixelFormat::Z16>, | 459 | MortonCopy<true, PixelFormat::Z16>, |
| 445 | MortonCopy<true, PixelFormat::Z24S8>, | 460 | MortonCopy<true, PixelFormat::Z24S8>, |
| @@ -508,6 +523,8 @@ static constexpr GLConversionArray gl_to_morton_fns = { | |||
| 508 | nullptr, | 523 | nullptr, |
| 509 | nullptr, | 524 | nullptr, |
| 510 | nullptr, | 525 | nullptr, |
| 526 | nullptr, | ||
| 527 | nullptr, | ||
| 511 | MortonCopy<false, PixelFormat::Z32F>, | 528 | MortonCopy<false, PixelFormat::Z32F>, |
| 512 | MortonCopy<false, PixelFormat::Z16>, | 529 | MortonCopy<false, PixelFormat::Z16>, |
| 513 | MortonCopy<false, PixelFormat::Z24S8>, | 530 | MortonCopy<false, PixelFormat::Z24S8>, |
| @@ -754,6 +771,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, | |||
| 754 | break; | 771 | break; |
| 755 | case SurfaceTarget::Texture3D: | 772 | case SurfaceTarget::Texture3D: |
| 756 | case SurfaceTarget::Texture2DArray: | 773 | case SurfaceTarget::Texture2DArray: |
| 774 | case SurfaceTarget::TextureCubeArray: | ||
| 757 | glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height, | 775 | glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height, |
| 758 | static_cast<GLsizei>(dst_params.depth), dest_format.format, | 776 | static_cast<GLsizei>(dst_params.depth), dest_format.format, |
| 759 | dest_format.type, nullptr); | 777 | dest_format.type, nullptr); |
| @@ -806,6 +824,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | |||
| 806 | break; | 824 | break; |
| 807 | case SurfaceTarget::Texture3D: | 825 | case SurfaceTarget::Texture3D: |
| 808 | case SurfaceTarget::Texture2DArray: | 826 | case SurfaceTarget::Texture2DArray: |
| 827 | case SurfaceTarget::TextureCubeArray: | ||
| 809 | glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, | 828 | glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, |
| 810 | format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), | 829 | format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), |
| 811 | params.depth); | 830 | params.depth); |
| @@ -897,21 +916,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { | |||
| 897 | * typical desktop GPUs. | 916 | * typical desktop GPUs. |
| 898 | */ | 917 | */ |
| 899 | static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, | 918 | static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, |
| 900 | u32 width, u32 height) { | 919 | u32 width, u32 height, u32 depth) { |
| 901 | switch (pixel_format) { | 920 | switch (pixel_format) { |
| 902 | case PixelFormat::ASTC_2D_4X4: | 921 | case PixelFormat::ASTC_2D_4X4: |
| 903 | case PixelFormat::ASTC_2D_8X8: | 922 | case PixelFormat::ASTC_2D_8X8: |
| 904 | case PixelFormat::ASTC_2D_8X5: | 923 | case PixelFormat::ASTC_2D_8X5: |
| 905 | case PixelFormat::ASTC_2D_5X4: | 924 | case PixelFormat::ASTC_2D_5X4: |
| 925 | case PixelFormat::ASTC_2D_5X5: | ||
| 906 | case PixelFormat::ASTC_2D_4X4_SRGB: | 926 | case PixelFormat::ASTC_2D_4X4_SRGB: |
| 907 | case PixelFormat::ASTC_2D_8X8_SRGB: | 927 | case PixelFormat::ASTC_2D_8X8_SRGB: |
| 908 | case PixelFormat::ASTC_2D_8X5_SRGB: | 928 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| 909 | case PixelFormat::ASTC_2D_5X4_SRGB: { | 929 | case PixelFormat::ASTC_2D_5X4_SRGB: |
| 930 | case PixelFormat::ASTC_2D_5X5_SRGB: { | ||
| 910 | // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. | 931 | // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. |
| 911 | u32 block_width{}; | 932 | u32 block_width{}; |
| 912 | u32 block_height{}; | 933 | u32 block_height{}; |
| 913 | std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); | 934 | std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); |
| 914 | data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height); | 935 | data = |
| 936 | Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height); | ||
| 915 | break; | 937 | break; |
| 916 | } | 938 | } |
| 917 | case PixelFormat::S8Z24: | 939 | case PixelFormat::S8Z24: |
| @@ -971,7 +993,7 @@ void CachedSurface::LoadGLBuffer() { | |||
| 971 | } | 993 | } |
| 972 | for (u32 i = 0; i < params.max_mip_level; i++) | 994 | for (u32 i = 0; i < params.max_mip_level; i++) |
| 973 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), | 995 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), |
| 974 | params.MipHeight(i)); | 996 | params.MipHeight(i), params.MipDepth(i)); |
| 975 | } | 997 | } |
| 976 | 998 | ||
| 977 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); | 999 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); |
| @@ -1055,6 +1077,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | |||
| 1055 | &gl_buffer[mip_map][buffer_offset]); | 1077 | &gl_buffer[mip_map][buffer_offset]); |
| 1056 | break; | 1078 | break; |
| 1057 | case SurfaceTarget::Texture2DArray: | 1079 | case SurfaceTarget::Texture2DArray: |
| 1080 | case SurfaceTarget::TextureCubeArray: | ||
| 1058 | glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, | 1081 | glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, |
| 1059 | static_cast<GLsizei>(params.MipWidth(mip_map)), | 1082 | static_cast<GLsizei>(params.MipWidth(mip_map)), |
| 1060 | static_cast<GLsizei>(params.MipHeight(mip_map)), | 1083 | static_cast<GLsizei>(params.MipHeight(mip_map)), |
| @@ -1104,6 +1127,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | |||
| 1104 | tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); | 1127 | tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); |
| 1105 | break; | 1128 | break; |
| 1106 | case SurfaceTarget::Texture2DArray: | 1129 | case SurfaceTarget::Texture2DArray: |
| 1130 | case SurfaceTarget::TextureCubeArray: | ||
| 1107 | glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, | 1131 | glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, |
| 1108 | static_cast<GLsizei>(rect.GetWidth()), | 1132 | static_cast<GLsizei>(rect.GetWidth()), |
| 1109 | static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, | 1133 | static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, |
| @@ -1307,6 +1331,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface, | |||
| 1307 | case SurfaceTarget::TextureCubemap: | 1331 | case SurfaceTarget::TextureCubemap: |
| 1308 | case SurfaceTarget::Texture3D: | 1332 | case SurfaceTarget::Texture3D: |
| 1309 | case SurfaceTarget::Texture2DArray: | 1333 | case SurfaceTarget::Texture2DArray: |
| 1334 | case SurfaceTarget::TextureCubeArray: | ||
| 1310 | AccurateCopySurface(old_surface, new_surface); | 1335 | AccurateCopySurface(old_surface, new_surface); |
| 1311 | break; | 1336 | break; |
| 1312 | default: | 1337 | default: |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index f255f4419..c0b6bc4e6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -49,6 +49,8 @@ struct SurfaceParams { | |||
| 49 | return "Texture2DArray"; | 49 | return "Texture2DArray"; |
| 50 | case SurfaceTarget::TextureCubemap: | 50 | case SurfaceTarget::TextureCubemap: |
| 51 | return "TextureCubemap"; | 51 | return "TextureCubemap"; |
| 52 | case SurfaceTarget::TextureCubeArray: | ||
| 53 | return "TextureCubeArray"; | ||
| 52 | default: | 54 | default: |
| 53 | LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target)); | 55 | LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target)); |
| 54 | UNREACHABLE(); | 56 | UNREACHABLE(); |
| @@ -139,7 +141,7 @@ struct SurfaceParams { | |||
| 139 | } | 141 | } |
| 140 | 142 | ||
| 141 | u32 MipDepth(u32 mip_level) const { | 143 | u32 MipDepth(u32 mip_level) const { |
| 142 | return std::max(1U, depth >> mip_level); | 144 | return is_layered ? depth : std::max(1U, depth >> mip_level); |
| 143 | } | 145 | } |
| 144 | 146 | ||
| 145 | // Auto block resizing algorithm from: | 147 | // Auto block resizing algorithm from: |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp new file mode 100644 index 000000000..c10863337 --- /dev/null +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -0,0 +1,146 @@ | |||
| 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 <utility> | ||
| 6 | #include <glad/glad.h> | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 9 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 11 | |||
| 12 | namespace OpenGL { | ||
| 13 | |||
| 14 | void OGLTexture::Create() { | ||
| 15 | if (handle != 0) | ||
| 16 | return; | ||
| 17 | glGenTextures(1, &handle); | ||
| 18 | } | ||
| 19 | |||
| 20 | void OGLTexture::Release() { | ||
| 21 | if (handle == 0) | ||
| 22 | return; | ||
| 23 | glDeleteTextures(1, &handle); | ||
| 24 | OpenGLState::GetCurState().UnbindTexture(handle).Apply(); | ||
| 25 | handle = 0; | ||
| 26 | } | ||
| 27 | |||
| 28 | void OGLSampler::Create() { | ||
| 29 | if (handle != 0) | ||
| 30 | return; | ||
| 31 | glGenSamplers(1, &handle); | ||
| 32 | } | ||
| 33 | |||
| 34 | void OGLSampler::Release() { | ||
| 35 | if (handle == 0) | ||
| 36 | return; | ||
| 37 | glDeleteSamplers(1, &handle); | ||
| 38 | OpenGLState::GetCurState().ResetSampler(handle).Apply(); | ||
| 39 | handle = 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | void OGLShader::Create(const char* source, GLenum type) { | ||
| 43 | if (handle != 0) | ||
| 44 | return; | ||
| 45 | if (source == nullptr) | ||
| 46 | return; | ||
| 47 | handle = GLShader::LoadShader(source, type); | ||
| 48 | } | ||
| 49 | |||
| 50 | void OGLShader::Release() { | ||
| 51 | if (handle == 0) | ||
| 52 | return; | ||
| 53 | glDeleteShader(handle); | ||
| 54 | handle = 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shader, | ||
| 58 | const char* frag_shader, bool separable_program) { | ||
| 59 | OGLShader vert, geo, frag; | ||
| 60 | if (vert_shader) | ||
| 61 | vert.Create(vert_shader, GL_VERTEX_SHADER); | ||
| 62 | if (geo_shader) | ||
| 63 | geo.Create(geo_shader, GL_GEOMETRY_SHADER); | ||
| 64 | if (frag_shader) | ||
| 65 | frag.Create(frag_shader, GL_FRAGMENT_SHADER); | ||
| 66 | Create(separable_program, vert.handle, geo.handle, frag.handle); | ||
| 67 | } | ||
| 68 | |||
| 69 | void OGLProgram::Release() { | ||
| 70 | if (handle == 0) | ||
| 71 | return; | ||
| 72 | glDeleteProgram(handle); | ||
| 73 | OpenGLState::GetCurState().ResetProgram(handle).Apply(); | ||
| 74 | handle = 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | void OGLPipeline::Create() { | ||
| 78 | if (handle != 0) | ||
| 79 | return; | ||
| 80 | glGenProgramPipelines(1, &handle); | ||
| 81 | } | ||
| 82 | |||
| 83 | void OGLPipeline::Release() { | ||
| 84 | if (handle == 0) | ||
| 85 | return; | ||
| 86 | glDeleteProgramPipelines(1, &handle); | ||
| 87 | OpenGLState::GetCurState().ResetPipeline(handle).Apply(); | ||
| 88 | handle = 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | void OGLBuffer::Create() { | ||
| 92 | if (handle != 0) | ||
| 93 | return; | ||
| 94 | glGenBuffers(1, &handle); | ||
| 95 | } | ||
| 96 | |||
| 97 | void OGLBuffer::Release() { | ||
| 98 | if (handle == 0) | ||
| 99 | return; | ||
| 100 | glDeleteBuffers(1, &handle); | ||
| 101 | OpenGLState::GetCurState().ResetBuffer(handle).Apply(); | ||
| 102 | handle = 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | void OGLSync::Create() { | ||
| 106 | if (handle != 0) | ||
| 107 | return; | ||
| 108 | handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | ||
| 109 | } | ||
| 110 | |||
| 111 | void OGLSync::Release() { | ||
| 112 | if (handle == 0) | ||
| 113 | return; | ||
| 114 | glDeleteSync(handle); | ||
| 115 | handle = 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | void OGLVertexArray::Create() { | ||
| 119 | if (handle != 0) | ||
| 120 | return; | ||
| 121 | glGenVertexArrays(1, &handle); | ||
| 122 | } | ||
| 123 | |||
| 124 | void OGLVertexArray::Release() { | ||
| 125 | if (handle == 0) | ||
| 126 | return; | ||
| 127 | glDeleteVertexArrays(1, &handle); | ||
| 128 | OpenGLState::GetCurState().ResetVertexArray(handle).Apply(); | ||
| 129 | handle = 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | void OGLFramebuffer::Create() { | ||
| 133 | if (handle != 0) | ||
| 134 | return; | ||
| 135 | glGenFramebuffers(1, &handle); | ||
| 136 | } | ||
| 137 | |||
| 138 | void OGLFramebuffer::Release() { | ||
| 139 | if (handle == 0) | ||
| 140 | return; | ||
| 141 | glDeleteFramebuffers(1, &handle); | ||
| 142 | OpenGLState::GetCurState().ResetFramebuffer(handle).Apply(); | ||
| 143 | handle = 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 3bc1b83b5..e33f1e973 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <glad/glad.h> | 8 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/renderer_opengl/gl_shader_util.h" | 10 | #include "video_core/renderer_opengl/gl_shader_util.h" |
| 11 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 12 | 11 | ||
| 13 | namespace OpenGL { | 12 | namespace OpenGL { |
| 14 | 13 | ||
| @@ -29,20 +28,10 @@ public: | |||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | /// Creates a new internal OpenGL resource and stores the handle | 30 | /// Creates a new internal OpenGL resource and stores the handle |
| 32 | void Create() { | 31 | void Create(); |
| 33 | if (handle != 0) | ||
| 34 | return; | ||
| 35 | glGenTextures(1, &handle); | ||
| 36 | } | ||
| 37 | 32 | ||
| 38 | /// Deletes the internal OpenGL resource | 33 | /// Deletes the internal OpenGL resource |
| 39 | void Release() { | 34 | void Release(); |
| 40 | if (handle == 0) | ||
| 41 | return; | ||
| 42 | glDeleteTextures(1, &handle); | ||
| 43 | OpenGLState::GetCurState().UnbindTexture(handle).Apply(); | ||
| 44 | handle = 0; | ||
| 45 | } | ||
| 46 | 35 | ||
| 47 | GLuint handle = 0; | 36 | GLuint handle = 0; |
| 48 | }; | 37 | }; |
| @@ -64,20 +53,10 @@ public: | |||
| 64 | } | 53 | } |
| 65 | 54 | ||
| 66 | /// Creates a new internal OpenGL resource and stores the handle | 55 | /// Creates a new internal OpenGL resource and stores the handle |
| 67 | void Create() { | 56 | void Create(); |
| 68 | if (handle != 0) | ||
| 69 | return; | ||
| 70 | glGenSamplers(1, &handle); | ||
| 71 | } | ||
| 72 | 57 | ||
| 73 | /// Deletes the internal OpenGL resource | 58 | /// Deletes the internal OpenGL resource |
| 74 | void Release() { | 59 | void Release(); |
| 75 | if (handle == 0) | ||
| 76 | return; | ||
| 77 | glDeleteSamplers(1, &handle); | ||
| 78 | OpenGLState::GetCurState().ResetSampler(handle).Apply(); | ||
| 79 | handle = 0; | ||
| 80 | } | ||
| 81 | 60 | ||
| 82 | GLuint handle = 0; | 61 | GLuint handle = 0; |
| 83 | }; | 62 | }; |
| @@ -98,20 +77,9 @@ public: | |||
| 98 | return *this; | 77 | return *this; |
| 99 | } | 78 | } |
| 100 | 79 | ||
| 101 | void Create(const char* source, GLenum type) { | 80 | void Create(const char* source, GLenum type); |
| 102 | if (handle != 0) | ||
| 103 | return; | ||
| 104 | if (source == nullptr) | ||
| 105 | return; | ||
| 106 | handle = GLShader::LoadShader(source, type); | ||
| 107 | } | ||
| 108 | 81 | ||
| 109 | void Release() { | 82 | void Release(); |
| 110 | if (handle == 0) | ||
| 111 | return; | ||
| 112 | glDeleteShader(handle); | ||
| 113 | handle = 0; | ||
| 114 | } | ||
| 115 | 83 | ||
| 116 | GLuint handle = 0; | 84 | GLuint handle = 0; |
| 117 | }; | 85 | }; |
| @@ -141,25 +109,10 @@ public: | |||
| 141 | 109 | ||
| 142 | /// Creates a new internal OpenGL resource and stores the handle | 110 | /// Creates a new internal OpenGL resource and stores the handle |
| 143 | void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader, | 111 | void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader, |
| 144 | bool separable_program = false) { | 112 | bool separable_program = false); |
| 145 | OGLShader vert, geo, frag; | ||
| 146 | if (vert_shader) | ||
| 147 | vert.Create(vert_shader, GL_VERTEX_SHADER); | ||
| 148 | if (geo_shader) | ||
| 149 | geo.Create(geo_shader, GL_GEOMETRY_SHADER); | ||
| 150 | if (frag_shader) | ||
| 151 | frag.Create(frag_shader, GL_FRAGMENT_SHADER); | ||
| 152 | Create(separable_program, vert.handle, geo.handle, frag.handle); | ||
| 153 | } | ||
| 154 | 113 | ||
| 155 | /// Deletes the internal OpenGL resource | 114 | /// Deletes the internal OpenGL resource |
| 156 | void Release() { | 115 | void Release(); |
| 157 | if (handle == 0) | ||
| 158 | return; | ||
| 159 | glDeleteProgram(handle); | ||
| 160 | OpenGLState::GetCurState().ResetProgram(handle).Apply(); | ||
| 161 | handle = 0; | ||
| 162 | } | ||
| 163 | 116 | ||
| 164 | GLuint handle = 0; | 117 | GLuint handle = 0; |
| 165 | }; | 118 | }; |
| @@ -178,20 +131,10 @@ public: | |||
| 178 | } | 131 | } |
| 179 | 132 | ||
| 180 | /// Creates a new internal OpenGL resource and stores the handle | 133 | /// Creates a new internal OpenGL resource and stores the handle |
| 181 | void Create() { | 134 | void Create(); |
| 182 | if (handle != 0) | ||
| 183 | return; | ||
| 184 | glGenProgramPipelines(1, &handle); | ||
| 185 | } | ||
| 186 | 135 | ||
| 187 | /// Deletes the internal OpenGL resource | 136 | /// Deletes the internal OpenGL resource |
| 188 | void Release() { | 137 | void Release(); |
| 189 | if (handle == 0) | ||
| 190 | return; | ||
| 191 | glDeleteProgramPipelines(1, &handle); | ||
| 192 | OpenGLState::GetCurState().ResetPipeline(handle).Apply(); | ||
| 193 | handle = 0; | ||
| 194 | } | ||
| 195 | 138 | ||
| 196 | GLuint handle = 0; | 139 | GLuint handle = 0; |
| 197 | }; | 140 | }; |
| @@ -213,20 +156,10 @@ public: | |||
| 213 | } | 156 | } |
| 214 | 157 | ||
| 215 | /// Creates a new internal OpenGL resource and stores the handle | 158 | /// Creates a new internal OpenGL resource and stores the handle |
| 216 | void Create() { | 159 | void Create(); |
| 217 | if (handle != 0) | ||
| 218 | return; | ||
| 219 | glGenBuffers(1, &handle); | ||
| 220 | } | ||
| 221 | 160 | ||
| 222 | /// Deletes the internal OpenGL resource | 161 | /// Deletes the internal OpenGL resource |
| 223 | void Release() { | 162 | void Release(); |
| 224 | if (handle == 0) | ||
| 225 | return; | ||
| 226 | glDeleteBuffers(1, &handle); | ||
| 227 | OpenGLState::GetCurState().ResetBuffer(handle).Apply(); | ||
| 228 | handle = 0; | ||
| 229 | } | ||
| 230 | 163 | ||
| 231 | GLuint handle = 0; | 164 | GLuint handle = 0; |
| 232 | }; | 165 | }; |
| @@ -247,19 +180,10 @@ public: | |||
| 247 | } | 180 | } |
| 248 | 181 | ||
| 249 | /// Creates a new internal OpenGL resource and stores the handle | 182 | /// Creates a new internal OpenGL resource and stores the handle |
| 250 | void Create() { | 183 | void Create(); |
| 251 | if (handle != 0) | ||
| 252 | return; | ||
| 253 | handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | ||
| 254 | } | ||
| 255 | 184 | ||
| 256 | /// Deletes the internal OpenGL resource | 185 | /// Deletes the internal OpenGL resource |
| 257 | void Release() { | 186 | void Release(); |
| 258 | if (handle == 0) | ||
| 259 | return; | ||
| 260 | glDeleteSync(handle); | ||
| 261 | handle = 0; | ||
| 262 | } | ||
| 263 | 187 | ||
| 264 | GLsync handle = 0; | 188 | GLsync handle = 0; |
| 265 | }; | 189 | }; |
| @@ -281,20 +205,10 @@ public: | |||
| 281 | } | 205 | } |
| 282 | 206 | ||
| 283 | /// Creates a new internal OpenGL resource and stores the handle | 207 | /// Creates a new internal OpenGL resource and stores the handle |
| 284 | void Create() { | 208 | void Create(); |
| 285 | if (handle != 0) | ||
| 286 | return; | ||
| 287 | glGenVertexArrays(1, &handle); | ||
| 288 | } | ||
| 289 | 209 | ||
| 290 | /// Deletes the internal OpenGL resource | 210 | /// Deletes the internal OpenGL resource |
| 291 | void Release() { | 211 | void Release(); |
| 292 | if (handle == 0) | ||
| 293 | return; | ||
| 294 | glDeleteVertexArrays(1, &handle); | ||
| 295 | OpenGLState::GetCurState().ResetVertexArray(handle).Apply(); | ||
| 296 | handle = 0; | ||
| 297 | } | ||
| 298 | 212 | ||
| 299 | GLuint handle = 0; | 213 | GLuint handle = 0; |
| 300 | }; | 214 | }; |
| @@ -316,20 +230,10 @@ public: | |||
| 316 | } | 230 | } |
| 317 | 231 | ||
| 318 | /// Creates a new internal OpenGL resource and stores the handle | 232 | /// Creates a new internal OpenGL resource and stores the handle |
| 319 | void Create() { | 233 | void Create(); |
| 320 | if (handle != 0) | ||
| 321 | return; | ||
| 322 | glGenFramebuffers(1, &handle); | ||
| 323 | } | ||
| 324 | 234 | ||
| 325 | /// Deletes the internal OpenGL resource | 235 | /// Deletes the internal OpenGL resource |
| 326 | void Release() { | 236 | void Release(); |
| 327 | if (handle == 0) | ||
| 328 | return; | ||
| 329 | glDeleteFramebuffers(1, &handle); | ||
| 330 | OpenGLState::GetCurState().ResetFramebuffer(handle).Apply(); | ||
| 331 | handle = 0; | ||
| 332 | } | ||
| 333 | 237 | ||
| 334 | GLuint handle = 0; | 238 | GLuint handle = 0; |
| 335 | }; | 239 | }; |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 36fe1f04c..2a069cdd8 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 8 | 8 | ||
| 9 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 9 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 10 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 10 | #include "video_core/renderer_opengl/maxwell_to_gl.h" | 11 | #include "video_core/renderer_opengl/maxwell_to_gl.h" |
| 11 | 12 | ||
| 12 | namespace OpenGL::GLShader { | 13 | namespace OpenGL::GLShader { |
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index d9a97e30b..051ad3964 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -19,6 +19,8 @@ SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_t | |||
| 19 | return SurfaceTarget::Texture3D; | 19 | return SurfaceTarget::Texture3D; |
| 20 | case Tegra::Texture::TextureType::TextureCubemap: | 20 | case Tegra::Texture::TextureType::TextureCubemap: |
| 21 | return SurfaceTarget::TextureCubemap; | 21 | return SurfaceTarget::TextureCubemap; |
| 22 | case Tegra::Texture::TextureType::TextureCubeArray: | ||
| 23 | return SurfaceTarget::TextureCubeArray; | ||
| 22 | case Tegra::Texture::TextureType::Texture1DArray: | 24 | case Tegra::Texture::TextureType::Texture1DArray: |
| 23 | return SurfaceTarget::Texture1DArray; | 25 | return SurfaceTarget::Texture1DArray; |
| 24 | case Tegra::Texture::TextureType::Texture2DArray: | 26 | case Tegra::Texture::TextureType::Texture2DArray: |
| @@ -39,6 +41,7 @@ bool SurfaceTargetIsLayered(SurfaceTarget target) { | |||
| 39 | case SurfaceTarget::Texture1DArray: | 41 | case SurfaceTarget::Texture1DArray: |
| 40 | case SurfaceTarget::Texture2DArray: | 42 | case SurfaceTarget::Texture2DArray: |
| 41 | case SurfaceTarget::TextureCubemap: | 43 | case SurfaceTarget::TextureCubemap: |
| 44 | case SurfaceTarget::TextureCubeArray: | ||
| 42 | return true; | 45 | return true; |
| 43 | default: | 46 | default: |
| 44 | LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target)); | 47 | LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target)); |
| @@ -297,6 +300,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, | |||
| 297 | return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4; | 300 | return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4; |
| 298 | case Tegra::Texture::TextureFormat::ASTC_2D_5X4: | 301 | case Tegra::Texture::TextureFormat::ASTC_2D_5X4: |
| 299 | return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4; | 302 | return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4; |
| 303 | case Tegra::Texture::TextureFormat::ASTC_2D_5X5: | ||
| 304 | return is_srgb ? PixelFormat::ASTC_2D_5X5_SRGB : PixelFormat::ASTC_2D_5X5; | ||
| 300 | case Tegra::Texture::TextureFormat::ASTC_2D_8X8: | 305 | case Tegra::Texture::TextureFormat::ASTC_2D_8X8: |
| 301 | return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8; | 306 | return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8; |
| 302 | case Tegra::Texture::TextureFormat::ASTC_2D_8X5: | 307 | case Tegra::Texture::TextureFormat::ASTC_2D_8X5: |
| @@ -440,10 +445,12 @@ bool IsPixelFormatASTC(PixelFormat format) { | |||
| 440 | switch (format) { | 445 | switch (format) { |
| 441 | case PixelFormat::ASTC_2D_4X4: | 446 | case PixelFormat::ASTC_2D_4X4: |
| 442 | case PixelFormat::ASTC_2D_5X4: | 447 | case PixelFormat::ASTC_2D_5X4: |
| 448 | case PixelFormat::ASTC_2D_5X5: | ||
| 443 | case PixelFormat::ASTC_2D_8X8: | 449 | case PixelFormat::ASTC_2D_8X8: |
| 444 | case PixelFormat::ASTC_2D_8X5: | 450 | case PixelFormat::ASTC_2D_8X5: |
| 445 | case PixelFormat::ASTC_2D_4X4_SRGB: | 451 | case PixelFormat::ASTC_2D_4X4_SRGB: |
| 446 | case PixelFormat::ASTC_2D_5X4_SRGB: | 452 | case PixelFormat::ASTC_2D_5X4_SRGB: |
| 453 | case PixelFormat::ASTC_2D_5X5_SRGB: | ||
| 447 | case PixelFormat::ASTC_2D_8X8_SRGB: | 454 | case PixelFormat::ASTC_2D_8X8_SRGB: |
| 448 | case PixelFormat::ASTC_2D_8X5_SRGB: | 455 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| 449 | return true; | 456 | return true; |
| @@ -453,27 +460,7 @@ bool IsPixelFormatASTC(PixelFormat format) { | |||
| 453 | } | 460 | } |
| 454 | 461 | ||
| 455 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { | 462 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { |
| 456 | switch (format) { | 463 | return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)}; |
| 457 | case PixelFormat::ASTC_2D_4X4: | ||
| 458 | return {4, 4}; | ||
| 459 | case PixelFormat::ASTC_2D_5X4: | ||
| 460 | return {5, 4}; | ||
| 461 | case PixelFormat::ASTC_2D_8X8: | ||
| 462 | return {8, 8}; | ||
| 463 | case PixelFormat::ASTC_2D_8X5: | ||
| 464 | return {8, 5}; | ||
| 465 | case PixelFormat::ASTC_2D_4X4_SRGB: | ||
| 466 | return {4, 4}; | ||
| 467 | case PixelFormat::ASTC_2D_5X4_SRGB: | ||
| 468 | return {5, 4}; | ||
| 469 | case PixelFormat::ASTC_2D_8X8_SRGB: | ||
| 470 | return {8, 8}; | ||
| 471 | case PixelFormat::ASTC_2D_8X5_SRGB: | ||
| 472 | return {8, 5}; | ||
| 473 | default: | ||
| 474 | LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format)); | ||
| 475 | UNREACHABLE(); | ||
| 476 | } | ||
| 477 | } | 464 | } |
| 478 | 465 | ||
| 479 | bool IsFormatBCn(PixelFormat format) { | 466 | bool IsFormatBCn(PixelFormat format) { |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 3232e437f..dfdb8d122 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -72,19 +72,21 @@ enum class PixelFormat { | |||
| 72 | ASTC_2D_8X8_SRGB = 54, | 72 | ASTC_2D_8X8_SRGB = 54, |
| 73 | ASTC_2D_8X5_SRGB = 55, | 73 | ASTC_2D_8X5_SRGB = 55, |
| 74 | ASTC_2D_5X4_SRGB = 56, | 74 | ASTC_2D_5X4_SRGB = 56, |
| 75 | ASTC_2D_5X5 = 57, | ||
| 76 | ASTC_2D_5X5_SRGB = 58, | ||
| 75 | 77 | ||
| 76 | MaxColorFormat, | 78 | MaxColorFormat, |
| 77 | 79 | ||
| 78 | // Depth formats | 80 | // Depth formats |
| 79 | Z32F = 57, | 81 | Z32F = 59, |
| 80 | Z16 = 58, | 82 | Z16 = 60, |
| 81 | 83 | ||
| 82 | MaxDepthFormat, | 84 | MaxDepthFormat, |
| 83 | 85 | ||
| 84 | // DepthStencil formats | 86 | // DepthStencil formats |
| 85 | Z24S8 = 59, | 87 | Z24S8 = 61, |
| 86 | S8Z24 = 60, | 88 | S8Z24 = 62, |
| 87 | Z32FS8 = 61, | 89 | Z32FS8 = 63, |
| 88 | 90 | ||
| 89 | MaxDepthStencilFormat, | 91 | MaxDepthStencilFormat, |
| 90 | 92 | ||
| @@ -118,6 +120,7 @@ enum class SurfaceTarget { | |||
| 118 | Texture1DArray, | 120 | Texture1DArray, |
| 119 | Texture2DArray, | 121 | Texture2DArray, |
| 120 | TextureCubemap, | 122 | TextureCubemap, |
| 123 | TextureCubeArray, | ||
| 121 | }; | 124 | }; |
| 122 | 125 | ||
| 123 | /** | 126 | /** |
| @@ -188,6 +191,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) { | |||
| 188 | 4, // ASTC_2D_8X8_SRGB | 191 | 4, // ASTC_2D_8X8_SRGB |
| 189 | 4, // ASTC_2D_8X5_SRGB | 192 | 4, // ASTC_2D_8X5_SRGB |
| 190 | 4, // ASTC_2D_5X4_SRGB | 193 | 4, // ASTC_2D_5X4_SRGB |
| 194 | 4, // ASTC_2D_5X5 | ||
| 195 | 4, // ASTC_2D_5X5_SRGB | ||
| 191 | 1, // Z32F | 196 | 1, // Z32F |
| 192 | 1, // Z16 | 197 | 1, // Z16 |
| 193 | 1, // Z24S8 | 198 | 1, // Z24S8 |
| @@ -199,6 +204,79 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) { | |||
| 199 | return compression_factor_table[static_cast<std::size_t>(format)]; | 204 | return compression_factor_table[static_cast<std::size_t>(format)]; |
| 200 | } | 205 | } |
| 201 | 206 | ||
| 207 | static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { | ||
| 208 | if (format == PixelFormat::Invalid) | ||
| 209 | return 0; | ||
| 210 | constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ | ||
| 211 | 1, // ABGR8U | ||
| 212 | 1, // ABGR8S | ||
| 213 | 1, // ABGR8UI | ||
| 214 | 1, // B5G6R5U | ||
| 215 | 1, // A2B10G10R10U | ||
| 216 | 1, // A1B5G5R5U | ||
| 217 | 1, // R8U | ||
| 218 | 1, // R8UI | ||
| 219 | 1, // RGBA16F | ||
| 220 | 1, // RGBA16U | ||
| 221 | 1, // RGBA16UI | ||
| 222 | 1, // R11FG11FB10F | ||
| 223 | 1, // RGBA32UI | ||
| 224 | 4, // DXT1 | ||
| 225 | 4, // DXT23 | ||
| 226 | 4, // DXT45 | ||
| 227 | 4, // DXN1 | ||
| 228 | 4, // DXN2UNORM | ||
| 229 | 4, // DXN2SNORM | ||
| 230 | 4, // BC7U | ||
| 231 | 4, // BC6H_UF16 | ||
| 232 | 4, // BC6H_SF16 | ||
| 233 | 4, // ASTC_2D_4X4 | ||
| 234 | 1, // G8R8U | ||
| 235 | 1, // G8R8S | ||
| 236 | 1, // BGRA8 | ||
| 237 | 1, // RGBA32F | ||
| 238 | 1, // RG32F | ||
| 239 | 1, // R32F | ||
| 240 | 1, // R16F | ||
| 241 | 1, // R16U | ||
| 242 | 1, // R16S | ||
| 243 | 1, // R16UI | ||
| 244 | 1, // R16I | ||
| 245 | 1, // RG16 | ||
| 246 | 1, // RG16F | ||
| 247 | 1, // RG16UI | ||
| 248 | 1, // RG16I | ||
| 249 | 1, // RG16S | ||
| 250 | 1, // RGB32F | ||
| 251 | 1, // RGBA8_SRGB | ||
| 252 | 1, // RG8U | ||
| 253 | 1, // RG8S | ||
| 254 | 1, // RG32UI | ||
| 255 | 1, // R32UI | ||
| 256 | 8, // ASTC_2D_8X8 | ||
| 257 | 8, // ASTC_2D_8X5 | ||
| 258 | 5, // ASTC_2D_5X4 | ||
| 259 | 1, // BGRA8_SRGB | ||
| 260 | 4, // DXT1_SRGB | ||
| 261 | 4, // DXT23_SRGB | ||
| 262 | 4, // DXT45_SRGB | ||
| 263 | 4, // BC7U_SRGB | ||
| 264 | 4, // ASTC_2D_4X4_SRGB | ||
| 265 | 8, // ASTC_2D_8X8_SRGB | ||
| 266 | 8, // ASTC_2D_8X5_SRGB | ||
| 267 | 5, // ASTC_2D_5X4_SRGB | ||
| 268 | 5, // ASTC_2D_5X5 | ||
| 269 | 5, // ASTC_2D_5X5_SRGB | ||
| 270 | 1, // Z32F | ||
| 271 | 1, // Z16 | ||
| 272 | 1, // Z24S8 | ||
| 273 | 1, // S8Z24 | ||
| 274 | 1, // Z32FS8 | ||
| 275 | }}; | ||
| 276 | ASSERT(static_cast<std::size_t>(format) < block_width_table.size()); | ||
| 277 | return block_width_table[static_cast<std::size_t>(format)]; | ||
| 278 | } | ||
| 279 | |||
| 202 | static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { | 280 | static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { |
| 203 | if (format == PixelFormat::Invalid) | 281 | if (format == PixelFormat::Invalid) |
| 204 | return 0; | 282 | return 0; |
| @@ -261,6 +339,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { | |||
| 261 | 8, // ASTC_2D_8X8_SRGB | 339 | 8, // ASTC_2D_8X8_SRGB |
| 262 | 5, // ASTC_2D_8X5_SRGB | 340 | 5, // ASTC_2D_8X5_SRGB |
| 263 | 4, // ASTC_2D_5X4_SRGB | 341 | 4, // ASTC_2D_5X4_SRGB |
| 342 | 5, // ASTC_2D_5X5 | ||
| 343 | 5, // ASTC_2D_5X5_SRGB | ||
| 264 | 1, // Z32F | 344 | 1, // Z32F |
| 265 | 1, // Z16 | 345 | 1, // Z16 |
| 266 | 1, // Z24S8 | 346 | 1, // Z24S8 |
| @@ -299,7 +379,7 @@ static constexpr u32 GetFormatBpp(PixelFormat format) { | |||
| 299 | 128, // BC7U | 379 | 128, // BC7U |
| 300 | 128, // BC6H_UF16 | 380 | 128, // BC6H_UF16 |
| 301 | 128, // BC6H_SF16 | 381 | 128, // BC6H_SF16 |
| 302 | 32, // ASTC_2D_4X4 | 382 | 128, // ASTC_2D_4X4 |
| 303 | 16, // G8R8U | 383 | 16, // G8R8U |
| 304 | 16, // G8R8S | 384 | 16, // G8R8S |
| 305 | 32, // BGRA8 | 385 | 32, // BGRA8 |
| @@ -322,18 +402,20 @@ static constexpr u32 GetFormatBpp(PixelFormat format) { | |||
| 322 | 16, // RG8S | 402 | 16, // RG8S |
| 323 | 64, // RG32UI | 403 | 64, // RG32UI |
| 324 | 32, // R32UI | 404 | 32, // R32UI |
| 325 | 16, // ASTC_2D_8X8 | 405 | 128, // ASTC_2D_8X8 |
| 326 | 16, // ASTC_2D_8X5 | 406 | 128, // ASTC_2D_8X5 |
| 327 | 32, // ASTC_2D_5X4 | 407 | 128, // ASTC_2D_5X4 |
| 328 | 32, // BGRA8_SRGB | 408 | 32, // BGRA8_SRGB |
| 329 | 64, // DXT1_SRGB | 409 | 64, // DXT1_SRGB |
| 330 | 128, // DXT23_SRGB | 410 | 128, // DXT23_SRGB |
| 331 | 128, // DXT45_SRGB | 411 | 128, // DXT45_SRGB |
| 332 | 128, // BC7U | 412 | 128, // BC7U |
| 333 | 32, // ASTC_2D_4X4_SRGB | 413 | 128, // ASTC_2D_4X4_SRGB |
| 334 | 16, // ASTC_2D_8X8_SRGB | 414 | 128, // ASTC_2D_8X8_SRGB |
| 335 | 16, // ASTC_2D_8X5_SRGB | 415 | 128, // ASTC_2D_8X5_SRGB |
| 336 | 32, // ASTC_2D_5X4_SRGB | 416 | 128, // ASTC_2D_5X4_SRGB |
| 417 | 128, // ASTC_2D_5X5 | ||
| 418 | 128, // ASTC_2D_5X5_SRGB | ||
| 337 | 32, // Z32F | 419 | 32, // Z32F |
| 338 | 16, // Z16 | 420 | 16, // Z16 |
| 339 | 32, // Z24S8 | 421 | 32, // Z24S8 |
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index b1feacae9..bc50a4876 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp | |||
| @@ -1598,27 +1598,29 @@ static void DecompressBlock(uint8_t inBuf[16], const uint32_t blockWidth, | |||
| 1598 | namespace Tegra::Texture::ASTC { | 1598 | namespace Tegra::Texture::ASTC { |
| 1599 | 1599 | ||
| 1600 | std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, | 1600 | std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, |
| 1601 | uint32_t block_width, uint32_t block_height) { | 1601 | uint32_t depth, uint32_t block_width, uint32_t block_height) { |
| 1602 | uint32_t blockIdx = 0; | 1602 | uint32_t blockIdx = 0; |
| 1603 | std::vector<uint8_t> outData(height * width * 4); | 1603 | std::vector<uint8_t> outData(height * width * depth * 4); |
| 1604 | for (uint32_t j = 0; j < height; j += block_height) { | 1604 | for (uint32_t k = 0; k < depth; k++) { |
| 1605 | for (uint32_t i = 0; i < width; i += block_width) { | 1605 | for (uint32_t j = 0; j < height; j += block_height) { |
| 1606 | for (uint32_t i = 0; i < width; i += block_width) { | ||
| 1606 | 1607 | ||
| 1607 | uint8_t* blockPtr = data.data() + blockIdx * 16; | 1608 | uint8_t* blockPtr = data.data() + blockIdx * 16; |
| 1608 | 1609 | ||
| 1609 | // Blocks can be at most 12x12 | 1610 | // Blocks can be at most 12x12 |
| 1610 | uint32_t uncompData[144]; | 1611 | uint32_t uncompData[144]; |
| 1611 | ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); | 1612 | ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); |
| 1612 | 1613 | ||
| 1613 | uint32_t decompWidth = std::min(block_width, width - i); | 1614 | uint32_t decompWidth = std::min(block_width, width - i); |
| 1614 | uint32_t decompHeight = std::min(block_height, height - j); | 1615 | uint32_t decompHeight = std::min(block_height, height - j); |
| 1615 | 1616 | ||
| 1616 | uint8_t* outRow = outData.data() + (j * width + i) * 4; | 1617 | uint8_t* outRow = outData.data() + (j * width + i) * 4; |
| 1617 | for (uint32_t jj = 0; jj < decompHeight; jj++) { | 1618 | for (uint32_t jj = 0; jj < decompHeight; jj++) { |
| 1618 | memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); | 1619 | memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); |
| 1619 | } | 1620 | } |
| 1620 | 1621 | ||
| 1621 | blockIdx++; | 1622 | blockIdx++; |
| 1623 | } | ||
| 1622 | } | 1624 | } |
| 1623 | } | 1625 | } |
| 1624 | 1626 | ||
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h index f0d7c0e56..d419dd025 100644 --- a/src/video_core/textures/astc.h +++ b/src/video_core/textures/astc.h | |||
| @@ -10,6 +10,6 @@ | |||
| 10 | namespace Tegra::Texture::ASTC { | 10 | namespace Tegra::Texture::ASTC { |
| 11 | 11 | ||
| 12 | std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, | 12 | std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, |
| 13 | uint32_t block_width, uint32_t block_height); | 13 | uint32_t depth, uint32_t block_width, uint32_t block_height); |
| 14 | 14 | ||
| 15 | } // namespace Tegra::Texture::ASTC | 15 | } // namespace Tegra::Texture::ASTC |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 550ca856c..3066abf61 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -227,12 +227,14 @@ u32 BytesPerPixel(TextureFormat format) { | |||
| 227 | } | 227 | } |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, | 230 | std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, |
| 231 | u32 height, u32 depth, u32 block_height, u32 block_depth) { | 231 | u32 bytes_per_pixel, u32 width, u32 height, u32 depth, |
| 232 | u32 block_height, u32 block_depth) { | ||
| 232 | std::vector<u8> unswizzled_data(width * height * depth * bytes_per_pixel); | 233 | std::vector<u8> unswizzled_data(width * height * depth * bytes_per_pixel); |
| 233 | CopySwizzledData(width / tile_size, height / tile_size, depth, bytes_per_pixel, bytes_per_pixel, | 234 | CopySwizzledData((width + tile_size_x - 1) / tile_size_x, |
| 234 | Memory::GetPointer(address), unswizzled_data.data(), true, block_height, | 235 | (height + tile_size_y - 1) / tile_size_y, depth, bytes_per_pixel, |
| 235 | block_depth); | 236 | bytes_per_pixel, Memory::GetPointer(address), unswizzled_data.data(), true, |
| 237 | block_height, block_depth); | ||
| 236 | return unswizzled_data; | 238 | return unswizzled_data; |
| 237 | } | 239 | } |
| 238 | 240 | ||
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index b390219e4..ba065510b 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -19,8 +19,8 @@ inline std::size_t GetGOBSize() { | |||
| 19 | /** | 19 | /** |
| 20 | * Unswizzles a swizzled texture without changing its format. | 20 | * Unswizzles a swizzled texture without changing its format. |
| 21 | */ | 21 | */ |
| 22 | std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, | 22 | std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, |
| 23 | u32 height, u32 depth, | 23 | u32 bytes_per_pixel, u32 width, u32 height, u32 depth, |
| 24 | u32 block_height = TICEntry::DefaultBlockHeight, | 24 | u32 block_height = TICEntry::DefaultBlockHeight, |
| 25 | u32 block_depth = TICEntry::DefaultBlockHeight); | 25 | u32 block_depth = TICEntry::DefaultBlockHeight); |
| 26 | 26 | ||
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 0adbab27d..707747422 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp | |||
| @@ -386,9 +386,9 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 386 | 386 | ||
| 387 | // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles. | 387 | // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles. |
| 388 | // Needs to be fixed if we plan to use this feature more, otherwise we may remove it. | 388 | // Needs to be fixed if we plan to use this feature more, otherwise we may remove it. |
| 389 | auto unswizzled_data = | 389 | auto unswizzled_data = Tegra::Texture::UnswizzleTexture( |
| 390 | Tegra::Texture::UnswizzleTexture(*address, 1, Tegra::Texture::BytesPerPixel(surface_format), | 390 | *address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width, |
| 391 | surface_width, surface_height, 1U); | 391 | surface_height, 1U); |
| 392 | 392 | ||
| 393 | auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, | 393 | auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, |
| 394 | surface_width, surface_height); | 394 | surface_width, surface_height); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c5a56cbfd..74a44be37 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -142,6 +142,9 @@ static void InitializeLogging() { | |||
| 142 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 142 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); |
| 143 | FileUtil::CreateFullPath(log_dir); | 143 | FileUtil::CreateFullPath(log_dir); |
| 144 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 144 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 145 | #ifdef _WIN32 | ||
| 146 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | ||
| 147 | #endif | ||
| 145 | } | 148 | } |
| 146 | 149 | ||
| 147 | GMainWindow::GMainWindow() | 150 | GMainWindow::GMainWindow() |
| @@ -454,6 +457,7 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 454 | connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); | 457 | connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); |
| 455 | 458 | ||
| 456 | // Help | 459 | // Help |
| 460 | connect(ui.action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder); | ||
| 457 | connect(ui.action_Rederive, &QAction::triggered, this, | 461 | connect(ui.action_Rederive, &QAction::triggered, this, |
| 458 | std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning)); | 462 | std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning)); |
| 459 | connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout); | 463 | connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout); |
| @@ -1374,6 +1378,11 @@ void GMainWindow::OnLoadAmiibo() { | |||
| 1374 | } | 1378 | } |
| 1375 | } | 1379 | } |
| 1376 | 1380 | ||
| 1381 | void GMainWindow::OnOpenYuzuFolder() { | ||
| 1382 | QDesktopServices::openUrl(QUrl::fromLocalFile( | ||
| 1383 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)))); | ||
| 1384 | } | ||
| 1385 | |||
| 1377 | void GMainWindow::OnAbout() { | 1386 | void GMainWindow::OnAbout() { |
| 1378 | AboutDialog aboutDialog(this); | 1387 | AboutDialog aboutDialog(this); |
| 1379 | aboutDialog.exec(); | 1388 | aboutDialog.exec(); |
| @@ -1532,7 +1541,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 1532 | "derivation. It will be attempted but may not complete.<br><br>") + | 1541 | "derivation. It will be attempted but may not complete.<br><br>") + |
| 1533 | errors + | 1542 | errors + |
| 1534 | tr("<br><br>You can get all of these and dump all of your games easily by " | 1543 | tr("<br><br>You can get all of these and dump all of your games easily by " |
| 1535 | "following <a href='https://yuzu-emu.org/help/quickstart/quickstart/'>the " | 1544 | "following <a href='https://yuzu-emu.org/help/quickstart/'>the " |
| 1536 | "quickstart guide</a>. Alternatively, you can use another method of dumping " | 1545 | "quickstart guide</a>. Alternatively, you can use another method of dumping " |
| 1537 | "to obtain all of your keys.")); | 1546 | "to obtain all of your keys.")); |
| 1538 | } | 1547 | } |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index af637d89e..929250e8c 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -167,6 +167,7 @@ private slots: | |||
| 167 | void OnMenuRecentFile(); | 167 | void OnMenuRecentFile(); |
| 168 | void OnConfigure(); | 168 | void OnConfigure(); |
| 169 | void OnLoadAmiibo(); | 169 | void OnLoadAmiibo(); |
| 170 | void OnOpenYuzuFolder(); | ||
| 170 | void OnAbout(); | 171 | void OnAbout(); |
| 171 | void OnToggleFilterBar(); | 172 | void OnToggleFilterBar(); |
| 172 | void OnDisplayTitleBars(bool); | 173 | void OnDisplayTitleBars(bool); |
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 48d099591..28cf269e7 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -110,6 +110,7 @@ | |||
| 110 | <string>&Help</string> | 110 | <string>&Help</string> |
| 111 | </property> | 111 | </property> |
| 112 | <addaction name="action_Report_Compatibility"/> | 112 | <addaction name="action_Report_Compatibility"/> |
| 113 | <addaction name="action_Open_yuzu_Folder" /> | ||
| 113 | <addaction name="separator"/> | 114 | <addaction name="separator"/> |
| 114 | <addaction name="action_About"/> | 115 | <addaction name="action_About"/> |
| 115 | </widget> | 116 | </widget> |
| @@ -277,6 +278,11 @@ | |||
| 277 | <bool>false</bool> | 278 | <bool>false</bool> |
| 278 | </property> | 279 | </property> |
| 279 | </action> | 280 | </action> |
| 281 | <action name="action_Open_yuzu_Folder"> | ||
| 282 | <property name="text"> | ||
| 283 | <string>Open yuzu Folder</string> | ||
| 284 | </property> | ||
| 285 | </action> | ||
| 280 | </widget> | 286 | </widget> |
| 281 | <resources/> | 287 | <resources/> |
| 282 | <connections/> | 288 | <connections/> |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index c8b93b85b..806127b12 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -76,6 +76,9 @@ static void InitializeLogging() { | |||
| 76 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 76 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); |
| 77 | FileUtil::CreateFullPath(log_dir); | 77 | FileUtil::CreateFullPath(log_dir); |
| 78 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 78 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 79 | #ifdef _WIN32 | ||
| 80 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | ||
| 81 | #endif | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | /// Application entry point | 84 | /// Application entry point |