summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/logging/backend.cpp11
-rw-r--r--src/common/logging/backend.h14
-rw-r--r--src/core/hle/service/audio/hwopus.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp3
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h4
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp53
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h4
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp146
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h132
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h1
-rw-r--r--src/video_core/surface.cpp29
-rw-r--r--src/video_core/surface.h108
-rw-r--r--src/video_core/textures/astc.cpp32
-rw-r--r--src/video_core/textures/astc.h2
-rw-r--r--src/video_core/textures/decoders.cpp12
-rw-r--r--src/video_core/textures/decoders.h4
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp6
-rw-r--r--src/yuzu/main.cpp11
-rw-r--r--src/yuzu/main.h1
-rw-r--r--src/yuzu/main.ui6
-rw-r--r--src/yuzu_cmd/yuzu.cpp3
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
149void 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 */
109class DebuggerBackend : public Backend {
110public:
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
106void AddBackend(std::unique_ptr<Backend> backend); 120void AddBackend(std::unique_ptr<Backend> backend);
107 121
108void RemoveBackend(std::string_view backend_name); 122void 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
429Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const { 429Kernel::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
59std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only, 60std::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 */
899static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, 918static 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
977MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); 999MICROPROFILE_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
12namespace OpenGL {
13
14void OGLTexture::Create() {
15 if (handle != 0)
16 return;
17 glGenTextures(1, &handle);
18}
19
20void OGLTexture::Release() {
21 if (handle == 0)
22 return;
23 glDeleteTextures(1, &handle);
24 OpenGLState::GetCurState().UnbindTexture(handle).Apply();
25 handle = 0;
26}
27
28void OGLSampler::Create() {
29 if (handle != 0)
30 return;
31 glGenSamplers(1, &handle);
32}
33
34void OGLSampler::Release() {
35 if (handle == 0)
36 return;
37 glDeleteSamplers(1, &handle);
38 OpenGLState::GetCurState().ResetSampler(handle).Apply();
39 handle = 0;
40}
41
42void 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
50void OGLShader::Release() {
51 if (handle == 0)
52 return;
53 glDeleteShader(handle);
54 handle = 0;
55}
56
57void 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
69void OGLProgram::Release() {
70 if (handle == 0)
71 return;
72 glDeleteProgram(handle);
73 OpenGLState::GetCurState().ResetProgram(handle).Apply();
74 handle = 0;
75}
76
77void OGLPipeline::Create() {
78 if (handle != 0)
79 return;
80 glGenProgramPipelines(1, &handle);
81}
82
83void OGLPipeline::Release() {
84 if (handle == 0)
85 return;
86 glDeleteProgramPipelines(1, &handle);
87 OpenGLState::GetCurState().ResetPipeline(handle).Apply();
88 handle = 0;
89}
90
91void OGLBuffer::Create() {
92 if (handle != 0)
93 return;
94 glGenBuffers(1, &handle);
95}
96
97void OGLBuffer::Release() {
98 if (handle == 0)
99 return;
100 glDeleteBuffers(1, &handle);
101 OpenGLState::GetCurState().ResetBuffer(handle).Apply();
102 handle = 0;
103}
104
105void OGLSync::Create() {
106 if (handle != 0)
107 return;
108 handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
109}
110
111void OGLSync::Release() {
112 if (handle == 0)
113 return;
114 glDeleteSync(handle);
115 handle = 0;
116}
117
118void OGLVertexArray::Create() {
119 if (handle != 0)
120 return;
121 glGenVertexArrays(1, &handle);
122}
123
124void OGLVertexArray::Release() {
125 if (handle == 0)
126 return;
127 glDeleteVertexArrays(1, &handle);
128 OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
129 handle = 0;
130}
131
132void OGLFramebuffer::Create() {
133 if (handle != 0)
134 return;
135 glGenFramebuffers(1, &handle);
136}
137
138void 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
13namespace OpenGL { 12namespace 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
12namespace OpenGL::GLShader { 13namespace 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
455std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { 462std::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
479bool IsFormatBCn(PixelFormat format) { 466bool 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
207static 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
202static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { 280static 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,
1598namespace Tegra::Texture::ASTC { 1598namespace Tegra::Texture::ASTC {
1599 1599
1600std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, 1600std::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 @@
10namespace Tegra::Texture::ASTC { 10namespace Tegra::Texture::ASTC {
11 11
12std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, 12std::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
230std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, 230std::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 */
22std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, 22std::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
147GMainWindow::GMainWindow() 150GMainWindow::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
1381void GMainWindow::OnOpenYuzuFolder() {
1382 QDesktopServices::openUrl(QUrl::fromLocalFile(
1383 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir))));
1384}
1385
1377void GMainWindow::OnAbout() { 1386void 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>&amp;Help</string> 110 <string>&amp;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