mirror of
				https://github.com/yuzu-emu/yuzu.git
				synced 2025-11-04 08:13:41 +00:00 
			
		
		
		
	Merge branch 'master' into Texture2DArray
This commit is contained in:
		
						commit
						d3b9599b2d
					
				@ -12,7 +12,8 @@
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <share.h> // For _SH_DENYWR
 | 
			
		||||
#include <share.h>   // For _SH_DENYWR
 | 
			
		||||
#include <windows.h> // For OutputDebugStringA
 | 
			
		||||
#else
 | 
			
		||||
#define _SH_DENYWR 0
 | 
			
		||||
#endif
 | 
			
		||||
@ -139,12 +140,18 @@ void FileBackend::Write(const Entry& entry) {
 | 
			
		||||
    if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    bytes_written += file.WriteString(FormatLogMessage(entry) + '\n');
 | 
			
		||||
    bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n'));
 | 
			
		||||
    if (entry.log_level >= Level::Error) {
 | 
			
		||||
        file.Flush();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DebuggerBackend::Write(const Entry& entry) {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    ::OutputDebugStringA(FormatLogMessage(entry).append(1, '\n').c_str());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
 | 
			
		||||
#define ALL_LOG_CLASSES()                                                                          \
 | 
			
		||||
    CLS(Log)                                                                                       \
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,20 @@ private:
 | 
			
		||||
    std::size_t bytes_written;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Backend that writes to Visual Studio's output window
 | 
			
		||||
 */
 | 
			
		||||
class DebuggerBackend : public Backend {
 | 
			
		||||
public:
 | 
			
		||||
    static const char* Name() {
 | 
			
		||||
        return "debugger";
 | 
			
		||||
    }
 | 
			
		||||
    const char* GetName() const override {
 | 
			
		||||
        return Name();
 | 
			
		||||
    }
 | 
			
		||||
    void Write(const Entry& entry) override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void AddBackend(std::unique_ptr<Backend> backend);
 | 
			
		||||
 | 
			
		||||
void RemoveBackend(std::string_view backend_name);
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,7 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
 | 
			
		||||
 | 
			
		||||
    std::size_t worker_sz = WorkerBufferSize(channel_count);
 | 
			
		||||
    ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large");
 | 
			
		||||
    ASSERT_MSG(buffer_sz >= worker_sz, "Worker buffer too large");
 | 
			
		||||
    std::unique_ptr<OpusDecoder, OpusDeleter> decoder{
 | 
			
		||||
        static_cast<OpusDecoder*>(operator new(worker_sz))};
 | 
			
		||||
    if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
 | 
			
		||||
 | 
			
		||||
@ -427,6 +427,9 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const {
 | 
			
		||||
    // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
 | 
			
		||||
    // be signalled at least once, and signaled after a new controller is connected?
 | 
			
		||||
    styleset_changed_event->Signal();
 | 
			
		||||
    return styleset_changed_event;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -96,6 +96,8 @@ public:
 | 
			
		||||
        // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
 | 
			
		||||
 | 
			
		||||
        CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
 | 
			
		||||
 | 
			
		||||
        ReloadInputDevices();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ActivateController(HidController controller) {
 | 
			
		||||
 | 
			
		||||
@ -58,9 +58,9 @@ public:
 | 
			
		||||
        /// Rotate source image 90 degrees clockwise
 | 
			
		||||
        Rotate90 = 0x04,
 | 
			
		||||
        /// Rotate source image 180 degrees
 | 
			
		||||
        Roate180 = 0x03,
 | 
			
		||||
        Rotate180 = 0x03,
 | 
			
		||||
        /// Rotate source image 270 degrees clockwise
 | 
			
		||||
        Roate270 = 0x07,
 | 
			
		||||
        Rotate270 = 0x07,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct Buffer {
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,7 @@ add_library(video_core STATIC
 | 
			
		||||
    renderer_opengl/gl_rasterizer.h
 | 
			
		||||
    renderer_opengl/gl_rasterizer_cache.cpp
 | 
			
		||||
    renderer_opengl/gl_rasterizer_cache.h
 | 
			
		||||
    renderer_opengl/gl_resource_manager.cpp
 | 
			
		||||
    renderer_opengl/gl_resource_manager.h
 | 
			
		||||
    renderer_opengl/gl_shader_cache.cpp
 | 
			
		||||
    renderer_opengl/gl_shader_cache.h
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
#include "core/settings.h"
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
#include "video_core/renderer_opengl/utils.h"
 | 
			
		||||
#include "video_core/surface.h"
 | 
			
		||||
#include "video_core/textures/astc.h"
 | 
			
		||||
@ -58,16 +59,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
 | 
			
		||||
 | 
			
		||||
std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,
 | 
			
		||||
                                                 bool uncompressed) const {
 | 
			
		||||
    const u32 compression_factor{GetCompressionFactor(pixel_format)};
 | 
			
		||||
    const u32 tile_x{GetDefaultBlockWidth(pixel_format)};
 | 
			
		||||
    const u32 tile_y{GetDefaultBlockHeight(pixel_format)};
 | 
			
		||||
    const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
 | 
			
		||||
    u32 m_depth = (layer_only ? 1U : depth);
 | 
			
		||||
    u32 m_width = MipWidth(mip_level);
 | 
			
		||||
    u32 m_height = MipHeight(mip_level);
 | 
			
		||||
    m_width = uncompressed ? m_width
 | 
			
		||||
                           : std::max(1U, (m_width + compression_factor - 1) / compression_factor);
 | 
			
		||||
    m_height = uncompressed
 | 
			
		||||
                   ? m_height
 | 
			
		||||
                   : std::max(1U, (m_height + compression_factor - 1) / compression_factor);
 | 
			
		||||
    m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x);
 | 
			
		||||
    m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);
 | 
			
		||||
    m_depth = std::max(1U, m_depth >> mip_level);
 | 
			
		||||
    u32 m_block_height = MipBlockHeight(mip_level);
 | 
			
		||||
    u32 m_block_depth = MipBlockDepth(mip_level);
 | 
			
		||||
@ -128,6 +127,13 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
 | 
			
		||||
            params.target = SurfaceTarget::Texture2D;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
        params.depth = config.tic.Depth() * 6;
 | 
			
		||||
        if (!entry.IsArray()) {
 | 
			
		||||
            ASSERT(params.depth == 6);
 | 
			
		||||
            params.target = SurfaceTarget::TextureCubemap;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target));
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
@ -305,6 +311,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
 | 
			
		||||
    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
 | 
			
		||||
    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
 | 
			
		||||
    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
 | 
			
		||||
    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},        // ASTC_2D_5X5
 | 
			
		||||
    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
 | 
			
		||||
 | 
			
		||||
    // Depth formats
 | 
			
		||||
    {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
 | 
			
		||||
@ -334,6 +342,8 @@ static GLenum SurfaceTargetToGL(SurfaceTarget target) {
 | 
			
		||||
        return GL_TEXTURE_2D_ARRAY;
 | 
			
		||||
    case SurfaceTarget::TextureCubemap:
 | 
			
		||||
        return GL_TEXTURE_CUBE_MAP;
 | 
			
		||||
    case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
        return GL_TEXTURE_CUBE_MAP_ARRAY_ARB;
 | 
			
		||||
    }
 | 
			
		||||
    LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
 | 
			
		||||
    UNREACHABLE();
 | 
			
		||||
@ -364,15 +374,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d
 | 
			
		||||
 | 
			
		||||
    // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
 | 
			
		||||
    // pixel values.
 | 
			
		||||
    const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
 | 
			
		||||
    const u32 tile_size_x{GetDefaultBlockWidth(format)};
 | 
			
		||||
    const u32 tile_size_y{GetDefaultBlockHeight(format)};
 | 
			
		||||
 | 
			
		||||
    if (morton_to_gl) {
 | 
			
		||||
        const std::vector<u8> data = Tegra::Texture::UnswizzleTexture(
 | 
			
		||||
            addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth);
 | 
			
		||||
        const std::vector<u8> data =
 | 
			
		||||
            Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel,
 | 
			
		||||
                                             stride, height, depth, block_height, block_depth);
 | 
			
		||||
        const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())};
 | 
			
		||||
        memcpy(gl_buffer, data.data(), size_to_copy);
 | 
			
		||||
    } else {
 | 
			
		||||
        Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth,
 | 
			
		||||
        Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x,
 | 
			
		||||
                                         (height + tile_size_y - 1) / tile_size_y, depth,
 | 
			
		||||
                                         bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr),
 | 
			
		||||
                                         gl_buffer, false, block_height, block_depth);
 | 
			
		||||
    }
 | 
			
		||||
@ -440,6 +453,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {
 | 
			
		||||
        MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::Z32F>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::Z16>,
 | 
			
		||||
        MortonCopy<true, PixelFormat::Z24S8>,
 | 
			
		||||
@ -508,6 +523,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {
 | 
			
		||||
        nullptr,
 | 
			
		||||
        nullptr,
 | 
			
		||||
        nullptr,
 | 
			
		||||
        nullptr,
 | 
			
		||||
        nullptr,
 | 
			
		||||
        MortonCopy<false, PixelFormat::Z32F>,
 | 
			
		||||
        MortonCopy<false, PixelFormat::Z16>,
 | 
			
		||||
        MortonCopy<false, PixelFormat::Z24S8>,
 | 
			
		||||
@ -754,6 +771,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
 | 
			
		||||
            break;
 | 
			
		||||
        case SurfaceTarget::Texture3D:
 | 
			
		||||
        case SurfaceTarget::Texture2DArray:
 | 
			
		||||
        case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
            glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height,
 | 
			
		||||
                                static_cast<GLsizei>(dst_params.depth), dest_format.format,
 | 
			
		||||
                                dest_format.type, nullptr);
 | 
			
		||||
@ -806,6 +824,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
 | 
			
		||||
            break;
 | 
			
		||||
        case SurfaceTarget::Texture3D:
 | 
			
		||||
        case SurfaceTarget::Texture2DArray:
 | 
			
		||||
        case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
            glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level,
 | 
			
		||||
                           format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(),
 | 
			
		||||
                           params.depth);
 | 
			
		||||
@ -897,21 +916,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
 | 
			
		||||
 * typical desktop GPUs.
 | 
			
		||||
 */
 | 
			
		||||
static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
 | 
			
		||||
                                               u32 width, u32 height) {
 | 
			
		||||
                                               u32 width, u32 height, u32 depth) {
 | 
			
		||||
    switch (pixel_format) {
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X5:
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4_SRGB: {
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X5_SRGB: {
 | 
			
		||||
        // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
 | 
			
		||||
        u32 block_width{};
 | 
			
		||||
        u32 block_height{};
 | 
			
		||||
        std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
 | 
			
		||||
        data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
 | 
			
		||||
        data =
 | 
			
		||||
            Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case PixelFormat::S8Z24:
 | 
			
		||||
@ -971,7 +993,7 @@ void CachedSurface::LoadGLBuffer() {
 | 
			
		||||
    }
 | 
			
		||||
    for (u32 i = 0; i < params.max_mip_level; i++)
 | 
			
		||||
        ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i),
 | 
			
		||||
                                           params.MipHeight(i));
 | 
			
		||||
                                           params.MipHeight(i), params.MipDepth(i));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
                                   &gl_buffer[mip_map][buffer_offset]);
 | 
			
		||||
            break;
 | 
			
		||||
        case SurfaceTarget::Texture2DArray:
 | 
			
		||||
        case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
            glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
 | 
			
		||||
                                   static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
			
		||||
                                   static_cast<GLsizei>(params.MipHeight(mip_map)),
 | 
			
		||||
@ -1104,6 +1127,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
 | 
			
		||||
                            tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
 | 
			
		||||
            break;
 | 
			
		||||
        case SurfaceTarget::Texture2DArray:
 | 
			
		||||
        case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
            glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
 | 
			
		||||
                            static_cast<GLsizei>(rect.GetWidth()),
 | 
			
		||||
                            static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
 | 
			
		||||
@ -1307,6 +1331,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
 | 
			
		||||
    case SurfaceTarget::TextureCubemap:
 | 
			
		||||
    case SurfaceTarget::Texture3D:
 | 
			
		||||
    case SurfaceTarget::Texture2DArray:
 | 
			
		||||
    case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
        AccurateCopySurface(old_surface, new_surface);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,8 @@ struct SurfaceParams {
 | 
			
		||||
            return "Texture2DArray";
 | 
			
		||||
        case SurfaceTarget::TextureCubemap:
 | 
			
		||||
            return "TextureCubemap";
 | 
			
		||||
        case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
            return "TextureCubeArray";
 | 
			
		||||
        default:
 | 
			
		||||
            LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
@ -139,7 +141,7 @@ struct SurfaceParams {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u32 MipDepth(u32 mip_level) const {
 | 
			
		||||
        return std::max(1U, depth >> mip_level);
 | 
			
		||||
        return is_layered ? depth : std::max(1U, depth >> mip_level);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Auto block resizing algorithm from:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										146
									
								
								src/video_core/renderer_opengl/gl_resource_manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/video_core/renderer_opengl/gl_resource_manager.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
// Copyright 2015 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_util.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
void OGLTexture::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenTextures(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLTexture::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteTextures(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().UnbindTexture(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLSampler::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenSamplers(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLSampler::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteSamplers(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetSampler(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLShader::Create(const char* source, GLenum type) {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    if (source == nullptr)
 | 
			
		||||
        return;
 | 
			
		||||
    handle = GLShader::LoadShader(source, type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLShader::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteShader(handle);
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shader,
 | 
			
		||||
                                  const char* frag_shader, bool separable_program) {
 | 
			
		||||
    OGLShader vert, geo, frag;
 | 
			
		||||
    if (vert_shader)
 | 
			
		||||
        vert.Create(vert_shader, GL_VERTEX_SHADER);
 | 
			
		||||
    if (geo_shader)
 | 
			
		||||
        geo.Create(geo_shader, GL_GEOMETRY_SHADER);
 | 
			
		||||
    if (frag_shader)
 | 
			
		||||
        frag.Create(frag_shader, GL_FRAGMENT_SHADER);
 | 
			
		||||
    Create(separable_program, vert.handle, geo.handle, frag.handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLProgram::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteProgram(handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetProgram(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLPipeline::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenProgramPipelines(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLPipeline::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteProgramPipelines(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetPipeline(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLBuffer::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenBuffers(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLBuffer::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteBuffers(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetBuffer(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLSync::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLSync::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteSync(handle);
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLVertexArray::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenVertexArrays(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLVertexArray::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteVertexArrays(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLFramebuffer::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glGenFramebuffers(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLFramebuffer::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
    glDeleteFramebuffers(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetFramebuffer(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace OpenGL
 | 
			
		||||
@ -8,7 +8,6 @@
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_util.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
@ -29,20 +28,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenTextures(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteTextures(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().UnbindTexture(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -64,20 +53,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenSamplers(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteSamplers(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetSampler(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -98,20 +77,9 @@ public:
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Create(const char* source, GLenum type) {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        if (source == nullptr)
 | 
			
		||||
            return;
 | 
			
		||||
        handle = GLShader::LoadShader(source, type);
 | 
			
		||||
    }
 | 
			
		||||
    void Create(const char* source, GLenum type);
 | 
			
		||||
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteShader(handle);
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -141,25 +109,10 @@ public:
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader,
 | 
			
		||||
                          bool separable_program = false) {
 | 
			
		||||
        OGLShader vert, geo, frag;
 | 
			
		||||
        if (vert_shader)
 | 
			
		||||
            vert.Create(vert_shader, GL_VERTEX_SHADER);
 | 
			
		||||
        if (geo_shader)
 | 
			
		||||
            geo.Create(geo_shader, GL_GEOMETRY_SHADER);
 | 
			
		||||
        if (frag_shader)
 | 
			
		||||
            frag.Create(frag_shader, GL_FRAGMENT_SHADER);
 | 
			
		||||
        Create(separable_program, vert.handle, geo.handle, frag.handle);
 | 
			
		||||
    }
 | 
			
		||||
                          bool separable_program = false);
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteProgram(handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetProgram(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -178,20 +131,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenProgramPipelines(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteProgramPipelines(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetPipeline(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -213,20 +156,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenBuffers(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteBuffers(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetBuffer(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -247,19 +180,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteSync(handle);
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLsync handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -281,20 +205,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenVertexArrays(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteVertexArrays(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -316,20 +230,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create() {
 | 
			
		||||
        if (handle != 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glGenFramebuffers(1, &handle);
 | 
			
		||||
    }
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release() {
 | 
			
		||||
        if (handle == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        glDeleteFramebuffers(1, &handle);
 | 
			
		||||
        OpenGLState::GetCurState().ResetFramebuffer(handle).Apply();
 | 
			
		||||
        handle = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
 | 
			
		||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
#include "video_core/renderer_opengl/maxwell_to_gl.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL::GLShader {
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,8 @@ SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_t
 | 
			
		||||
        return SurfaceTarget::Texture3D;
 | 
			
		||||
    case Tegra::Texture::TextureType::TextureCubemap:
 | 
			
		||||
        return SurfaceTarget::TextureCubemap;
 | 
			
		||||
    case Tegra::Texture::TextureType::TextureCubeArray:
 | 
			
		||||
        return SurfaceTarget::TextureCubeArray;
 | 
			
		||||
    case Tegra::Texture::TextureType::Texture1DArray:
 | 
			
		||||
        return SurfaceTarget::Texture1DArray;
 | 
			
		||||
    case Tegra::Texture::TextureType::Texture2DArray:
 | 
			
		||||
@ -39,6 +41,7 @@ bool SurfaceTargetIsLayered(SurfaceTarget target) {
 | 
			
		||||
    case SurfaceTarget::Texture1DArray:
 | 
			
		||||
    case SurfaceTarget::Texture2DArray:
 | 
			
		||||
    case SurfaceTarget::TextureCubemap:
 | 
			
		||||
    case SurfaceTarget::TextureCubeArray:
 | 
			
		||||
        return true;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
 | 
			
		||||
@ -297,6 +300,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
 | 
			
		||||
        return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;
 | 
			
		||||
    case Tegra::Texture::TextureFormat::ASTC_2D_5X4:
 | 
			
		||||
        return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4;
 | 
			
		||||
    case Tegra::Texture::TextureFormat::ASTC_2D_5X5:
 | 
			
		||||
        return is_srgb ? PixelFormat::ASTC_2D_5X5_SRGB : PixelFormat::ASTC_2D_5X5;
 | 
			
		||||
    case Tegra::Texture::TextureFormat::ASTC_2D_8X8:
 | 
			
		||||
        return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
 | 
			
		||||
    case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
 | 
			
		||||
@ -440,10 +445,12 @@ bool IsPixelFormatASTC(PixelFormat format) {
 | 
			
		||||
    switch (format) {
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X5:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5:
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X5_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8_SRGB:
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5_SRGB:
 | 
			
		||||
        return true;
 | 
			
		||||
@ -453,27 +460,7 @@ bool IsPixelFormatASTC(PixelFormat format) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
 | 
			
		||||
    switch (format) {
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4:
 | 
			
		||||
        return {4, 4};
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4:
 | 
			
		||||
        return {5, 4};
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8:
 | 
			
		||||
        return {8, 8};
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5:
 | 
			
		||||
        return {8, 5};
 | 
			
		||||
    case PixelFormat::ASTC_2D_4X4_SRGB:
 | 
			
		||||
        return {4, 4};
 | 
			
		||||
    case PixelFormat::ASTC_2D_5X4_SRGB:
 | 
			
		||||
        return {5, 4};
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X8_SRGB:
 | 
			
		||||
        return {8, 8};
 | 
			
		||||
    case PixelFormat::ASTC_2D_8X5_SRGB:
 | 
			
		||||
        return {8, 5};
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
    }
 | 
			
		||||
    return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsFormatBCn(PixelFormat format) {
 | 
			
		||||
 | 
			
		||||
@ -72,19 +72,21 @@ enum class PixelFormat {
 | 
			
		||||
    ASTC_2D_8X8_SRGB = 54,
 | 
			
		||||
    ASTC_2D_8X5_SRGB = 55,
 | 
			
		||||
    ASTC_2D_5X4_SRGB = 56,
 | 
			
		||||
    ASTC_2D_5X5 = 57,
 | 
			
		||||
    ASTC_2D_5X5_SRGB = 58,
 | 
			
		||||
 | 
			
		||||
    MaxColorFormat,
 | 
			
		||||
 | 
			
		||||
    // Depth formats
 | 
			
		||||
    Z32F = 57,
 | 
			
		||||
    Z16 = 58,
 | 
			
		||||
    Z32F = 59,
 | 
			
		||||
    Z16 = 60,
 | 
			
		||||
 | 
			
		||||
    MaxDepthFormat,
 | 
			
		||||
 | 
			
		||||
    // DepthStencil formats
 | 
			
		||||
    Z24S8 = 59,
 | 
			
		||||
    S8Z24 = 60,
 | 
			
		||||
    Z32FS8 = 61,
 | 
			
		||||
    Z24S8 = 61,
 | 
			
		||||
    S8Z24 = 62,
 | 
			
		||||
    Z32FS8 = 63,
 | 
			
		||||
 | 
			
		||||
    MaxDepthStencilFormat,
 | 
			
		||||
 | 
			
		||||
@ -118,6 +120,7 @@ enum class SurfaceTarget {
 | 
			
		||||
    Texture1DArray,
 | 
			
		||||
    Texture2DArray,
 | 
			
		||||
    TextureCubemap,
 | 
			
		||||
    TextureCubeArray,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -188,6 +191,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
 | 
			
		||||
        4, // ASTC_2D_8X8_SRGB
 | 
			
		||||
        4, // ASTC_2D_8X5_SRGB
 | 
			
		||||
        4, // ASTC_2D_5X4_SRGB
 | 
			
		||||
        4, // ASTC_2D_5X5
 | 
			
		||||
        4, // ASTC_2D_5X5_SRGB
 | 
			
		||||
        1, // Z32F
 | 
			
		||||
        1, // Z16
 | 
			
		||||
        1, // Z24S8
 | 
			
		||||
@ -199,6 +204,79 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
 | 
			
		||||
    return compression_factor_table[static_cast<std::size_t>(format)];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
 | 
			
		||||
    if (format == PixelFormat::Invalid)
 | 
			
		||||
        return 0;
 | 
			
		||||
    constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
 | 
			
		||||
        1, // ABGR8U
 | 
			
		||||
        1, // ABGR8S
 | 
			
		||||
        1, // ABGR8UI
 | 
			
		||||
        1, // B5G6R5U
 | 
			
		||||
        1, // A2B10G10R10U
 | 
			
		||||
        1, // A1B5G5R5U
 | 
			
		||||
        1, // R8U
 | 
			
		||||
        1, // R8UI
 | 
			
		||||
        1, // RGBA16F
 | 
			
		||||
        1, // RGBA16U
 | 
			
		||||
        1, // RGBA16UI
 | 
			
		||||
        1, // R11FG11FB10F
 | 
			
		||||
        1, // RGBA32UI
 | 
			
		||||
        4, // DXT1
 | 
			
		||||
        4, // DXT23
 | 
			
		||||
        4, // DXT45
 | 
			
		||||
        4, // DXN1
 | 
			
		||||
        4, // DXN2UNORM
 | 
			
		||||
        4, // DXN2SNORM
 | 
			
		||||
        4, // BC7U
 | 
			
		||||
        4, // BC6H_UF16
 | 
			
		||||
        4, // BC6H_SF16
 | 
			
		||||
        4, // ASTC_2D_4X4
 | 
			
		||||
        1, // G8R8U
 | 
			
		||||
        1, // G8R8S
 | 
			
		||||
        1, // BGRA8
 | 
			
		||||
        1, // RGBA32F
 | 
			
		||||
        1, // RG32F
 | 
			
		||||
        1, // R32F
 | 
			
		||||
        1, // R16F
 | 
			
		||||
        1, // R16U
 | 
			
		||||
        1, // R16S
 | 
			
		||||
        1, // R16UI
 | 
			
		||||
        1, // R16I
 | 
			
		||||
        1, // RG16
 | 
			
		||||
        1, // RG16F
 | 
			
		||||
        1, // RG16UI
 | 
			
		||||
        1, // RG16I
 | 
			
		||||
        1, // RG16S
 | 
			
		||||
        1, // RGB32F
 | 
			
		||||
        1, // RGBA8_SRGB
 | 
			
		||||
        1, // RG8U
 | 
			
		||||
        1, // RG8S
 | 
			
		||||
        1, // RG32UI
 | 
			
		||||
        1, // R32UI
 | 
			
		||||
        8, // ASTC_2D_8X8
 | 
			
		||||
        8, // ASTC_2D_8X5
 | 
			
		||||
        5, // ASTC_2D_5X4
 | 
			
		||||
        1, // BGRA8_SRGB
 | 
			
		||||
        4, // DXT1_SRGB
 | 
			
		||||
        4, // DXT23_SRGB
 | 
			
		||||
        4, // DXT45_SRGB
 | 
			
		||||
        4, // BC7U_SRGB
 | 
			
		||||
        4, // ASTC_2D_4X4_SRGB
 | 
			
		||||
        8, // ASTC_2D_8X8_SRGB
 | 
			
		||||
        8, // ASTC_2D_8X5_SRGB
 | 
			
		||||
        5, // ASTC_2D_5X4_SRGB
 | 
			
		||||
        5, // ASTC_2D_5X5
 | 
			
		||||
        5, // ASTC_2D_5X5_SRGB
 | 
			
		||||
        1, // Z32F
 | 
			
		||||
        1, // Z16
 | 
			
		||||
        1, // Z24S8
 | 
			
		||||
        1, // S8Z24
 | 
			
		||||
        1, // Z32FS8
 | 
			
		||||
    }};
 | 
			
		||||
    ASSERT(static_cast<std::size_t>(format) < block_width_table.size());
 | 
			
		||||
    return block_width_table[static_cast<std::size_t>(format)];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
 | 
			
		||||
    if (format == PixelFormat::Invalid)
 | 
			
		||||
        return 0;
 | 
			
		||||
@ -261,6 +339,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
 | 
			
		||||
        8, // ASTC_2D_8X8_SRGB
 | 
			
		||||
        5, // ASTC_2D_8X5_SRGB
 | 
			
		||||
        4, // ASTC_2D_5X4_SRGB
 | 
			
		||||
        5, // ASTC_2D_5X5
 | 
			
		||||
        5, // ASTC_2D_5X5_SRGB
 | 
			
		||||
        1, // Z32F
 | 
			
		||||
        1, // Z16
 | 
			
		||||
        1, // Z24S8
 | 
			
		||||
@ -299,7 +379,7 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
 | 
			
		||||
        128, // BC7U
 | 
			
		||||
        128, // BC6H_UF16
 | 
			
		||||
        128, // BC6H_SF16
 | 
			
		||||
        32,  // ASTC_2D_4X4
 | 
			
		||||
        128, // ASTC_2D_4X4
 | 
			
		||||
        16,  // G8R8U
 | 
			
		||||
        16,  // G8R8S
 | 
			
		||||
        32,  // BGRA8
 | 
			
		||||
@ -322,18 +402,20 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
 | 
			
		||||
        16,  // RG8S
 | 
			
		||||
        64,  // RG32UI
 | 
			
		||||
        32,  // R32UI
 | 
			
		||||
        16,  // ASTC_2D_8X8
 | 
			
		||||
        16,  // ASTC_2D_8X5
 | 
			
		||||
        32,  // ASTC_2D_5X4
 | 
			
		||||
        128, // ASTC_2D_8X8
 | 
			
		||||
        128, // ASTC_2D_8X5
 | 
			
		||||
        128, // ASTC_2D_5X4
 | 
			
		||||
        32,  // BGRA8_SRGB
 | 
			
		||||
        64,  // DXT1_SRGB
 | 
			
		||||
        128, // DXT23_SRGB
 | 
			
		||||
        128, // DXT45_SRGB
 | 
			
		||||
        128, // BC7U
 | 
			
		||||
        32,  // ASTC_2D_4X4_SRGB
 | 
			
		||||
        16,  // ASTC_2D_8X8_SRGB
 | 
			
		||||
        16,  // ASTC_2D_8X5_SRGB
 | 
			
		||||
        32,  // ASTC_2D_5X4_SRGB
 | 
			
		||||
        128, // ASTC_2D_4X4_SRGB
 | 
			
		||||
        128, // ASTC_2D_8X8_SRGB
 | 
			
		||||
        128, // ASTC_2D_8X5_SRGB
 | 
			
		||||
        128, // ASTC_2D_5X4_SRGB
 | 
			
		||||
        128, // ASTC_2D_5X5
 | 
			
		||||
        128, // ASTC_2D_5X5_SRGB
 | 
			
		||||
        32,  // Z32F
 | 
			
		||||
        16,  // Z16
 | 
			
		||||
        32,  // Z24S8
 | 
			
		||||
 | 
			
		||||
@ -1598,27 +1598,29 @@ static void DecompressBlock(uint8_t inBuf[16], const uint32_t blockWidth,
 | 
			
		||||
namespace Tegra::Texture::ASTC {
 | 
			
		||||
 | 
			
		||||
std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height,
 | 
			
		||||
                                uint32_t block_width, uint32_t block_height) {
 | 
			
		||||
                                uint32_t depth, uint32_t block_width, uint32_t block_height) {
 | 
			
		||||
    uint32_t blockIdx = 0;
 | 
			
		||||
    std::vector<uint8_t> outData(height * width * 4);
 | 
			
		||||
    for (uint32_t j = 0; j < height; j += block_height) {
 | 
			
		||||
        for (uint32_t i = 0; i < width; i += block_width) {
 | 
			
		||||
    std::vector<uint8_t> outData(height * width * depth * 4);
 | 
			
		||||
    for (uint32_t k = 0; k < depth; k++) {
 | 
			
		||||
        for (uint32_t j = 0; j < height; j += block_height) {
 | 
			
		||||
            for (uint32_t i = 0; i < width; i += block_width) {
 | 
			
		||||
 | 
			
		||||
            uint8_t* blockPtr = data.data() + blockIdx * 16;
 | 
			
		||||
                uint8_t* blockPtr = data.data() + blockIdx * 16;
 | 
			
		||||
 | 
			
		||||
            // Blocks can be at most 12x12
 | 
			
		||||
            uint32_t uncompData[144];
 | 
			
		||||
            ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData);
 | 
			
		||||
                // Blocks can be at most 12x12
 | 
			
		||||
                uint32_t uncompData[144];
 | 
			
		||||
                ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData);
 | 
			
		||||
 | 
			
		||||
            uint32_t decompWidth = std::min(block_width, width - i);
 | 
			
		||||
            uint32_t decompHeight = std::min(block_height, height - j);
 | 
			
		||||
                uint32_t decompWidth = std::min(block_width, width - i);
 | 
			
		||||
                uint32_t decompHeight = std::min(block_height, height - j);
 | 
			
		||||
 | 
			
		||||
            uint8_t* outRow = outData.data() + (j * width + i) * 4;
 | 
			
		||||
            for (uint32_t jj = 0; jj < decompHeight; jj++) {
 | 
			
		||||
                memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4);
 | 
			
		||||
                uint8_t* outRow = outData.data() + (j * width + i) * 4;
 | 
			
		||||
                for (uint32_t jj = 0; jj < decompHeight; jj++) {
 | 
			
		||||
                    memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                blockIdx++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            blockIdx++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,6 @@
 | 
			
		||||
namespace Tegra::Texture::ASTC {
 | 
			
		||||
 | 
			
		||||
std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height,
 | 
			
		||||
                                uint32_t block_width, uint32_t block_height);
 | 
			
		||||
                                uint32_t depth, uint32_t block_width, uint32_t block_height);
 | 
			
		||||
 | 
			
		||||
} // namespace Tegra::Texture::ASTC
 | 
			
		||||
 | 
			
		||||
@ -227,12 +227,14 @@ u32 BytesPerPixel(TextureFormat format) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
 | 
			
		||||
                                 u32 height, u32 depth, u32 block_height, u32 block_depth) {
 | 
			
		||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y,
 | 
			
		||||
                                 u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
 | 
			
		||||
                                 u32 block_height, u32 block_depth) {
 | 
			
		||||
    std::vector<u8> unswizzled_data(width * height * depth * bytes_per_pixel);
 | 
			
		||||
    CopySwizzledData(width / tile_size, height / tile_size, depth, bytes_per_pixel, bytes_per_pixel,
 | 
			
		||||
                     Memory::GetPointer(address), unswizzled_data.data(), true, block_height,
 | 
			
		||||
                     block_depth);
 | 
			
		||||
    CopySwizzledData((width + tile_size_x - 1) / tile_size_x,
 | 
			
		||||
                     (height + tile_size_y - 1) / tile_size_y, depth, bytes_per_pixel,
 | 
			
		||||
                     bytes_per_pixel, Memory::GetPointer(address), unswizzled_data.data(), true,
 | 
			
		||||
                     block_height, block_depth);
 | 
			
		||||
    return unswizzled_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,8 +19,8 @@ inline std::size_t GetGOBSize() {
 | 
			
		||||
/**
 | 
			
		||||
 * Unswizzles a swizzled texture without changing its format.
 | 
			
		||||
 */
 | 
			
		||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
 | 
			
		||||
                                 u32 height, u32 depth,
 | 
			
		||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y,
 | 
			
		||||
                                 u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
 | 
			
		||||
                                 u32 block_height = TICEntry::DefaultBlockHeight,
 | 
			
		||||
                                 u32 block_depth = TICEntry::DefaultBlockHeight);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -386,9 +386,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
 | 
			
		||||
    // Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
 | 
			
		||||
    auto unswizzled_data =
 | 
			
		||||
        Tegra::Texture::UnswizzleTexture(*address, 1, Tegra::Texture::BytesPerPixel(surface_format),
 | 
			
		||||
                                         surface_width, surface_height, 1U);
 | 
			
		||||
    auto unswizzled_data = Tegra::Texture::UnswizzleTexture(
 | 
			
		||||
        *address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width,
 | 
			
		||||
        surface_height, 1U);
 | 
			
		||||
 | 
			
		||||
    auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
 | 
			
		||||
                                                      surface_width, surface_height);
 | 
			
		||||
 | 
			
		||||
@ -142,6 +142,9 @@ static void InitializeLogging() {
 | 
			
		||||
    const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir);
 | 
			
		||||
    FileUtil::CreateFullPath(log_dir);
 | 
			
		||||
    Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GMainWindow::GMainWindow()
 | 
			
		||||
@ -454,6 +457,7 @@ void GMainWindow::ConnectMenuEvents() {
 | 
			
		||||
    connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
 | 
			
		||||
 | 
			
		||||
    // Help
 | 
			
		||||
    connect(ui.action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder);
 | 
			
		||||
    connect(ui.action_Rederive, &QAction::triggered, this,
 | 
			
		||||
            std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning));
 | 
			
		||||
    connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout);
 | 
			
		||||
@ -1374,6 +1378,11 @@ void GMainWindow::OnLoadAmiibo() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnOpenYuzuFolder() {
 | 
			
		||||
    QDesktopServices::openUrl(QUrl::fromLocalFile(
 | 
			
		||||
        QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir))));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnAbout() {
 | 
			
		||||
    AboutDialog aboutDialog(this);
 | 
			
		||||
    aboutDialog.exec();
 | 
			
		||||
@ -1532,7 +1541,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
 | 
			
		||||
                   "derivation. It will be attempted but may not complete.<br><br>") +
 | 
			
		||||
                    errors +
 | 
			
		||||
                    tr("<br><br>You can get all of these and dump all of your games easily by "
 | 
			
		||||
                       "following <a href='https://yuzu-emu.org/help/quickstart/quickstart/'>the "
 | 
			
		||||
                       "following <a href='https://yuzu-emu.org/help/quickstart/'>the "
 | 
			
		||||
                       "quickstart guide</a>. Alternatively, you can use another method of dumping "
 | 
			
		||||
                       "to obtain all of your keys."));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -167,6 +167,7 @@ private slots:
 | 
			
		||||
    void OnMenuRecentFile();
 | 
			
		||||
    void OnConfigure();
 | 
			
		||||
    void OnLoadAmiibo();
 | 
			
		||||
    void OnOpenYuzuFolder();
 | 
			
		||||
    void OnAbout();
 | 
			
		||||
    void OnToggleFilterBar();
 | 
			
		||||
    void OnDisplayTitleBars(bool);
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,7 @@
 | 
			
		||||
     <string>&Help</string>
 | 
			
		||||
    </property>
 | 
			
		||||
    <addaction name="action_Report_Compatibility"/>
 | 
			
		||||
    <addaction name="action_Open_yuzu_Folder" />
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="action_About"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
@ -277,6 +278,11 @@
 | 
			
		||||
       <bool>false</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
   <action name="action_Open_yuzu_Folder">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Open yuzu Folder</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
  </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections/>
 | 
			
		||||
 | 
			
		||||
@ -76,6 +76,9 @@ static void InitializeLogging() {
 | 
			
		||||
    const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir);
 | 
			
		||||
    FileUtil::CreateFullPath(log_dir);
 | 
			
		||||
    Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Application entry point
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user