From 76754f57055cca4510062c04b8d3b85e9d88752b Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 28 Oct 2018 22:14:25 -0300
Subject: [PATCH] video_core: Move surface declarations out of
 gl_rasterizer_cache

---
 src/video_core/CMakeLists.txt                 |   2 +
 .../renderer_opengl/gl_rasterizer.cpp         |   7 +-
 .../renderer_opengl/gl_rasterizer_cache.cpp   | 170 ++--
 .../renderer_opengl/gl_rasterizer_cache.h     | 789 +-----------------
 src/video_core/surface.cpp                    | 499 +++++++++++
 src/video_core/surface.h                      | 385 +++++++++
 6 files changed, 954 insertions(+), 898 deletions(-)
 create mode 100644 src/video_core/surface.cpp
 create mode 100644 src/video_core/surface.h

diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index c5f7128ec6..ddb1a1d69f 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -53,6 +53,8 @@ add_library(video_core STATIC
     renderer_opengl/renderer_opengl.h
     renderer_opengl/utils.cpp
     renderer_opengl/utils.h
+    surface.cpp
+    surface.h
     textures/astc.cpp
     textures/astc.h
     textures/decoders.cpp
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bf381271e0..75e31c6de4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -30,8 +30,8 @@
 namespace OpenGL {
 
 using Maxwell = Tegra::Engines::Maxwell3D::Regs;
-using PixelFormat = SurfaceParams::PixelFormat;
-using SurfaceType = SurfaceParams::SurfaceType;
+using PixelFormat = VideoCore::Surface::PixelFormat;
+using SurfaceType = VideoCore::Surface::SurfaceType;
 
 MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Array Setup", MP_RGB(128, 128, 192));
 MICROPROFILE_DEFINE(OpenGL_Shader, "OpenGL", "Shader Setup", MP_RGB(128, 128, 192));
@@ -703,7 +703,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 
     // Verify that the cached surface is the same size and format as the requested framebuffer
     const auto& params{surface->GetSurfaceParams()};
-    const auto& pixel_format{SurfaceParams::PixelFormatFromGPUPixelFormat(config.pixel_format)};
+    const auto& pixel_format{
+        VideoCore::Surface::PixelFormatFromGPUPixelFormat(config.pixel_format)};
     ASSERT_MSG(params.width == config.width, "Framebuffer width is different");
     ASSERT_MSG(params.height == config.height, "Framebuffer height is different");
     ASSERT_MSG(params.pixel_format == pixel_format, "Framebuffer pixel_format is different");
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 1d43a419d7..f194a76872 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -17,15 +17,20 @@
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/renderer_opengl/gl_rasterizer_cache.h"
 #include "video_core/renderer_opengl/utils.h"
+#include "video_core/surface.h"
 #include "video_core/textures/astc.h"
 #include "video_core/textures/decoders.h"
 #include "video_core/utils.h"
 
 namespace OpenGL {
 
-using SurfaceType = SurfaceParams::SurfaceType;
-using PixelFormat = SurfaceParams::PixelFormat;
-using ComponentType = SurfaceParams::ComponentType;
+using VideoCore::Surface::ComponentTypeFromDepthFormat;
+using VideoCore::Surface::ComponentTypeFromRenderTarget;
+using VideoCore::Surface::ComponentTypeFromTexture;
+using VideoCore::Surface::PixelFormatFromDepthFormat;
+using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
+using VideoCore::Surface::PixelFormatFromTextureFormat;
+using VideoCore::Surface::SurfaceTargetFromTextureType;
 
 struct FormatTuple {
     GLint internal_format;
@@ -35,46 +40,6 @@ struct FormatTuple {
     bool compressed;
 };
 
-static bool IsPixelFormatASTC(PixelFormat format) {
-    switch (format) {
-    case PixelFormat::ASTC_2D_4X4:
-    case PixelFormat::ASTC_2D_5X4:
-    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_8X8_SRGB:
-    case PixelFormat::ASTC_2D_8X5_SRGB:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static 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();
-    }
-}
-
 void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
     auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
     const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
@@ -267,7 +232,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
     return params;
 }
 
-static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
+static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{
     {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8U
     {GL_RGBA8, GL_RGBA, GL_BYTE, ComponentType::SNorm, false},                     // ABGR8S
     {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false},   // ABGR8UI
@@ -355,19 +320,19 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
      ComponentType::Float, false}, // Z32FS8
 }};
 
-static GLenum SurfaceTargetToGL(SurfaceParams::SurfaceTarget target) {
+static GLenum SurfaceTargetToGL(SurfaceTarget target) {
     switch (target) {
-    case SurfaceParams::SurfaceTarget::Texture1D:
+    case SurfaceTarget::Texture1D:
         return GL_TEXTURE_1D;
-    case SurfaceParams::SurfaceTarget::Texture2D:
+    case SurfaceTarget::Texture2D:
         return GL_TEXTURE_2D;
-    case SurfaceParams::SurfaceTarget::Texture3D:
+    case SurfaceTarget::Texture3D:
         return GL_TEXTURE_3D;
-    case SurfaceParams::SurfaceTarget::Texture1DArray:
+    case SurfaceTarget::Texture1DArray:
         return GL_TEXTURE_1D_ARRAY;
-    case SurfaceParams::SurfaceTarget::Texture2DArray:
+    case SurfaceTarget::Texture2DArray:
         return GL_TEXTURE_2D_ARRAY;
-    case SurfaceParams::SurfaceTarget::TextureCubemap:
+    case SurfaceTarget::TextureCubemap:
         return GL_TEXTURE_CUBE_MAP;
     }
     LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
@@ -392,31 +357,10 @@ MathUtil::Rectangle<u32> SurfaceParams::GetRect(u32 mip_level) const {
     return {0, actual_height, MipWidth(mip_level), 0};
 }
 
-/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
-static bool IsFormatBCn(PixelFormat format) {
-    switch (format) {
-    case PixelFormat::DXT1:
-    case PixelFormat::DXT23:
-    case PixelFormat::DXT45:
-    case PixelFormat::DXN1:
-    case PixelFormat::DXN2SNORM:
-    case PixelFormat::DXN2UNORM:
-    case PixelFormat::BC7U:
-    case PixelFormat::BC6H_UF16:
-    case PixelFormat::BC6H_SF16:
-    case PixelFormat::DXT1_SRGB:
-    case PixelFormat::DXT23_SRGB:
-    case PixelFormat::DXT45_SRGB:
-    case PixelFormat::BC7U_SRGB:
-        return true;
-    }
-    return false;
-}
-
 template <bool morton_to_gl, PixelFormat format>
 void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 depth, u8* gl_buffer,
                 std::size_t gl_buffer_size, VAddr addr) {
-    constexpr u32 bytes_per_pixel = SurfaceParams::GetBytesPerPixel(format);
+    constexpr u32 bytes_per_pixel = GetBytesPerPixel(format);
 
     // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
     // pixel values.
@@ -435,7 +379,7 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d
 }
 
 using GLConversionArray = std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t, VAddr),
-                                     SurfaceParams::MaxPixelFormat>;
+                                     VideoCore::Surface::MaxPixelFormat>;
 
 static constexpr GLConversionArray morton_to_gl_fns = {
     // clang-format off
@@ -575,7 +519,7 @@ static constexpr GLConversionArray gl_to_morton_fns = {
 void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params,
                  std::vector<u8>& gl_buffer, u32 mip_level) {
     u32 depth = params.MipDepth(mip_level);
-    if (params.target == SurfaceParams::SurfaceTarget::Texture2D) {
+    if (params.target == SurfaceTarget::Texture2D) {
         // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented.
         depth = 1U;
     }
@@ -622,13 +566,13 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
 
     if (src_params.type == SurfaceType::ColorTexture) {
         switch (src_params.target) {
-        case SurfaceParams::SurfaceTarget::Texture2D:
+        case SurfaceTarget::Texture2D:
             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
                                    GL_TEXTURE_2D, src_surface->Texture().handle, 0);
             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
                                    0, 0);
             break;
-        case SurfaceParams::SurfaceTarget::TextureCubemap:
+        case SurfaceTarget::TextureCubemap:
             glFramebufferTexture2D(
                 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
                 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
@@ -637,12 +581,12 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
                 GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
                 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture2DArray:
             glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
                                       src_surface->Texture().handle, 0, 0);
             glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
             break;
-        case SurfaceParams::SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture3D:
             glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
                                    SurfaceTargetToGL(src_params.target),
                                    src_surface->Texture().handle, 0, 0);
@@ -658,13 +602,13 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
         }
 
         switch (dst_params.target) {
-        case SurfaceParams::SurfaceTarget::Texture2D:
+        case SurfaceTarget::Texture2D:
             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
                                    GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
                                    0, 0);
             break;
-        case SurfaceParams::SurfaceTarget::TextureCubemap:
+        case SurfaceTarget::TextureCubemap:
             glFramebufferTexture2D(
                 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
                 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
@@ -673,13 +617,13 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
                 GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
                 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture2DArray:
             glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
                                       dst_surface->Texture().handle, 0, 0);
             glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
             break;
 
-        case SurfaceParams::SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture3D:
             glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
                                    SurfaceTargetToGL(dst_params.target),
                                    dst_surface->Texture().handle, 0, 0);
@@ -800,21 +744,21 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
         UNREACHABLE();
     } else {
         switch (dst_params.target) {
-        case SurfaceParams::SurfaceTarget::Texture1D:
+        case SurfaceTarget::Texture1D:
             glTextureSubImage1D(dst_surface->Texture().handle, 0, 0, width, dest_format.format,
                                 dest_format.type, nullptr);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2D:
+        case SurfaceTarget::Texture2D:
             glTextureSubImage2D(dst_surface->Texture().handle, 0, 0, 0, width, height,
                                 dest_format.format, dest_format.type, nullptr);
             break;
-        case SurfaceParams::SurfaceTarget::Texture3D:
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture2DArray:
             glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height,
                                 static_cast<GLsizei>(dst_params.depth), dest_format.format,
                                 dest_format.type, nullptr);
             break;
-        case SurfaceParams::SurfaceTarget::TextureCubemap:
+        case SurfaceTarget::TextureCubemap:
             glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0,
                                 static_cast<GLint>(cubemap_face), width, height, 1,
                                 dest_format.format, dest_format.type, nullptr);
@@ -851,17 +795,17 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
     if (!format_tuple.compressed) {
         // Only pre-create the texture for non-compressed textures.
         switch (params.target) {
-        case SurfaceParams::SurfaceTarget::Texture1D:
+        case SurfaceTarget::Texture1D:
             glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level,
                            format_tuple.internal_format, rect.GetWidth());
             break;
-        case SurfaceParams::SurfaceTarget::Texture2D:
-        case SurfaceParams::SurfaceTarget::TextureCubemap:
+        case SurfaceTarget::Texture2D:
+        case SurfaceTarget::TextureCubemap:
             glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level,
                            format_tuple.internal_format, rect.GetWidth(), rect.GetHeight());
             break;
-        case SurfaceParams::SurfaceTarget::Texture3D:
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture2DArray:
             glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level,
                            format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(),
                            params.depth);
@@ -916,7 +860,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bo
 
     S8Z24 s8z24_pixel{};
     Z24S8 z24s8_pixel{};
-    constexpr auto bpp{SurfaceParams::GetBytesPerPixel(PixelFormat::S8Z24)};
+    constexpr auto bpp{GetBytesPerPixel(PixelFormat::S8Z24)};
     for (std::size_t y = 0; y < height; ++y) {
         for (std::size_t x = 0; x < width; ++x) {
             const std::size_t offset{bpp * (y * width + x)};
@@ -936,7 +880,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bo
 }
 
 static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
-    constexpr auto bpp{SurfaceParams::GetBytesPerPixel(PixelFormat::G8R8U)};
+    constexpr auto bpp{GetBytesPerPixel(PixelFormat::G8R8U)};
     for (std::size_t y = 0; y < height; ++y) {
         for (std::size_t x = 0; x < width; ++x) {
             const std::size_t offset{bpp * (y * width + x)};
@@ -1042,7 +986,7 @@ void CachedSurface::FlushGLBuffer() {
 
     const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
     // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
-    ASSERT(params.width * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 == 0);
+    ASSERT(params.width * GetBytesPerPixel(params.pixel_format) % 4 == 0);
     glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.width));
     ASSERT(!tuple.compressed);
     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
@@ -1074,7 +1018,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
     std::size_t buffer_offset =
         static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) +
                                  static_cast<std::size_t>(x0)) *
-        SurfaceParams::GetBytesPerPixel(params.pixel_format);
+        GetBytesPerPixel(params.pixel_format);
 
     const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
     const GLuint target_tex = texture.handle;
@@ -1090,35 +1034,34 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
     cur_state.Apply();
 
     // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
-    ASSERT(params.MipWidth(mip_map) * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 ==
-           0);
+    ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0);
     glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map)));
 
     GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false));
     glActiveTexture(GL_TEXTURE0);
     if (tuple.compressed) {
         switch (params.target) {
-        case SurfaceParams::SurfaceTarget::Texture2D:
+        case SurfaceTarget::Texture2D:
             glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
                                    static_cast<GLsizei>(params.MipWidth(mip_map)),
                                    static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size,
                                    &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture3D:
             glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
                                    static_cast<GLsizei>(params.MipWidth(mip_map)),
                                    static_cast<GLsizei>(params.MipHeight(mip_map)),
                                    static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size,
                                    &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture2DArray:
             glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
                                    static_cast<GLsizei>(params.MipWidth(mip_map)),
                                    static_cast<GLsizei>(params.MipHeight(mip_map)),
                                    static_cast<GLsizei>(params.depth), 0, image_size,
                                    &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::TextureCubemap: {
+        case SurfaceTarget::TextureCubemap: {
             GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map));
             for (std::size_t face = 0; face < params.depth; ++face) {
                 glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face),
@@ -1143,30 +1086,30 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
     } else {
 
         switch (params.target) {
-        case SurfaceParams::SurfaceTarget::Texture1D:
+        case SurfaceTarget::Texture1D:
             glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0,
                             static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type,
                             &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2D:
+        case SurfaceTarget::Texture2D:
             glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0,
                             static_cast<GLsizei>(rect.GetWidth()),
                             static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
                             &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::Texture3D:
+        case SurfaceTarget::Texture3D:
             glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
                             static_cast<GLsizei>(rect.GetWidth()),
                             static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map),
                             tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::Texture2DArray:
+        case SurfaceTarget::Texture2DArray:
             glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
                             static_cast<GLsizei>(rect.GetWidth()),
                             static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
                             tuple.type, &gl_buffer[mip_map][buffer_offset]);
             break;
-        case SurfaceParams::SurfaceTarget::TextureCubemap: {
+        case SurfaceTarget::TextureCubemap: {
             std::size_t start = buffer_offset;
             for (std::size_t face = 0; face < params.depth; ++face) {
                 glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map,
@@ -1341,8 +1284,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
     // For compatible surfaces, we can just do fast glCopyImageSubData based copy
     if (old_params.target == new_params.target && old_params.type == new_params.type &&
         old_params.depth == new_params.depth && old_params.depth == 1 &&
-        SurfaceParams::GetFormatBpp(old_params.pixel_format) ==
-            SurfaceParams::GetFormatBpp(new_params.pixel_format)) {
+        GetFormatBpp(old_params.pixel_format) == GetFormatBpp(new_params.pixel_format)) {
         FastCopySurface(old_surface, new_surface);
         return new_surface;
     }
@@ -1355,15 +1297,15 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
     const bool is_blit{old_params.pixel_format == new_params.pixel_format};
 
     switch (new_params.target) {
-    case SurfaceParams::SurfaceTarget::Texture2D:
+    case SurfaceTarget::Texture2D:
         if (is_blit) {
             BlitSurface(old_surface, new_surface, read_framebuffer.handle, draw_framebuffer.handle);
         } else {
             CopySurface(old_surface, new_surface, copy_pbo.handle);
         }
         break;
-    case SurfaceParams::SurfaceTarget::TextureCubemap:
-    case SurfaceParams::SurfaceTarget::Texture3D:
+    case SurfaceTarget::TextureCubemap:
+    case SurfaceTarget::Texture3D:
         AccurateCopySurface(old_surface, new_surface);
         break;
     default:
@@ -1373,7 +1315,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
     }
 
     return new_surface;
-} // namespace OpenGL
+}
 
 Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr addr) const {
     return TryGet(addr);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index e72f4f2d27..f255f4419c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -7,6 +7,7 @@
 #include <array>
 #include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "common/alignment.h"
@@ -18,6 +19,7 @@
 #include "video_core/rasterizer_cache.h"
 #include "video_core/renderer_opengl/gl_resource_manager.h"
 #include "video_core/renderer_opengl/gl_shader_gen.h"
+#include "video_core/surface.h"
 #include "video_core/textures/decoders.h"
 #include "video_core/textures/texture.h"
 
@@ -27,135 +29,12 @@ class CachedSurface;
 using Surface = std::shared_ptr<CachedSurface>;
 using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, MathUtil::Rectangle<u32>>;
 
+using SurfaceTarget = VideoCore::Surface::SurfaceTarget;
+using SurfaceType = VideoCore::Surface::SurfaceType;
+using PixelFormat = VideoCore::Surface::PixelFormat;
+using ComponentType = VideoCore::Surface::ComponentType;
+
 struct SurfaceParams {
-    enum class PixelFormat {
-        ABGR8U = 0,
-        ABGR8S = 1,
-        ABGR8UI = 2,
-        B5G6R5U = 3,
-        A2B10G10R10U = 4,
-        A1B5G5R5U = 5,
-        R8U = 6,
-        R8UI = 7,
-        RGBA16F = 8,
-        RGBA16U = 9,
-        RGBA16UI = 10,
-        R11FG11FB10F = 11,
-        RGBA32UI = 12,
-        DXT1 = 13,
-        DXT23 = 14,
-        DXT45 = 15,
-        DXN1 = 16, // This is also known as BC4
-        DXN2UNORM = 17,
-        DXN2SNORM = 18,
-        BC7U = 19,
-        BC6H_UF16 = 20,
-        BC6H_SF16 = 21,
-        ASTC_2D_4X4 = 22,
-        G8R8U = 23,
-        G8R8S = 24,
-        BGRA8 = 25,
-        RGBA32F = 26,
-        RG32F = 27,
-        R32F = 28,
-        R16F = 29,
-        R16U = 30,
-        R16S = 31,
-        R16UI = 32,
-        R16I = 33,
-        RG16 = 34,
-        RG16F = 35,
-        RG16UI = 36,
-        RG16I = 37,
-        RG16S = 38,
-        RGB32F = 39,
-        RGBA8_SRGB = 40,
-        RG8U = 41,
-        RG8S = 42,
-        RG32UI = 43,
-        R32UI = 44,
-        ASTC_2D_8X8 = 45,
-        ASTC_2D_8X5 = 46,
-        ASTC_2D_5X4 = 47,
-        BGRA8_SRGB = 48,
-        DXT1_SRGB = 49,
-        DXT23_SRGB = 50,
-        DXT45_SRGB = 51,
-        BC7U_SRGB = 52,
-        ASTC_2D_4X4_SRGB = 53,
-        ASTC_2D_8X8_SRGB = 54,
-        ASTC_2D_8X5_SRGB = 55,
-        ASTC_2D_5X4_SRGB = 56,
-
-        MaxColorFormat,
-
-        // Depth formats
-        Z32F = 57,
-        Z16 = 58,
-
-        MaxDepthFormat,
-
-        // DepthStencil formats
-        Z24S8 = 59,
-        S8Z24 = 60,
-        Z32FS8 = 61,
-
-        MaxDepthStencilFormat,
-
-        Max = MaxDepthStencilFormat,
-        Invalid = 255,
-    };
-
-    static constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max);
-
-    enum class ComponentType {
-        Invalid = 0,
-        SNorm = 1,
-        UNorm = 2,
-        SInt = 3,
-        UInt = 4,
-        Float = 5,
-    };
-
-    enum class SurfaceType {
-        ColorTexture = 0,
-        Depth = 1,
-        DepthStencil = 2,
-        Fill = 3,
-        Invalid = 4,
-    };
-
-    enum class SurfaceTarget {
-        Texture1D,
-        Texture2D,
-        Texture3D,
-        Texture1DArray,
-        Texture2DArray,
-        TextureCubemap,
-    };
-
-    static SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) {
-        switch (texture_type) {
-        case Tegra::Texture::TextureType::Texture1D:
-            return SurfaceTarget::Texture1D;
-        case Tegra::Texture::TextureType::Texture2D:
-        case Tegra::Texture::TextureType::Texture2DNoMipmap:
-            return SurfaceTarget::Texture2D;
-        case Tegra::Texture::TextureType::Texture3D:
-            return SurfaceTarget::Texture3D;
-        case Tegra::Texture::TextureType::TextureCubemap:
-            return SurfaceTarget::TextureCubemap;
-        case Tegra::Texture::TextureType::Texture1DArray:
-            return SurfaceTarget::Texture1DArray;
-        case Tegra::Texture::TextureType::Texture2DArray:
-            return SurfaceTarget::Texture2DArray;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", static_cast<u32>(texture_type));
-            UNREACHABLE();
-            return SurfaceTarget::Texture2D;
-        }
-    }
-
     static std::string SurfaceTargetName(SurfaceTarget target) {
         switch (target) {
         case SurfaceTarget::Texture1D:
@@ -177,660 +56,8 @@ struct SurfaceParams {
         }
     }
 
-    static bool SurfaceTargetIsLayered(SurfaceTarget target) {
-        switch (target) {
-        case SurfaceTarget::Texture1D:
-        case SurfaceTarget::Texture2D:
-        case SurfaceTarget::Texture3D:
-            return false;
-        case SurfaceTarget::Texture1DArray:
-        case SurfaceTarget::Texture2DArray:
-        case SurfaceTarget::TextureCubemap:
-            return true;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
-            UNREACHABLE();
-            return false;
-        }
-    }
-
-    /**
-     * Gets the compression factor for the specified PixelFormat. This applies to just the
-     * "compressed width" and "compressed height", not the overall compression factor of a
-     * compressed image. This is used for maintaining proper surface sizes for compressed
-     * texture formats.
-     */
-    static constexpr u32 GetCompressionFactor(PixelFormat format) {
-        if (format == PixelFormat::Invalid)
-            return 0;
-
-        constexpr std::array<u32, MaxPixelFormat> compression_factor_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
-            4, // ASTC_2D_8X8
-            4, // ASTC_2D_8X5
-            4, // ASTC_2D_5X4
-            1, // BGRA8_SRGB
-            4, // DXT1_SRGB
-            4, // DXT23_SRGB
-            4, // DXT45_SRGB
-            4, // BC7U_SRGB
-            4, // ASTC_2D_4X4_SRGB
-            4, // ASTC_2D_8X8_SRGB
-            4, // ASTC_2D_8X5_SRGB
-            4, // ASTC_2D_5X4_SRGB
-            1, // Z32F
-            1, // Z16
-            1, // Z24S8
-            1, // S8Z24
-            1, // Z32FS8
-        }};
-
-        ASSERT(static_cast<std::size_t>(format) < compression_factor_table.size());
-        return compression_factor_table[static_cast<std::size_t>(format)];
-    }
-
-    static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
-        if (format == PixelFormat::Invalid)
-            return 0;
-        constexpr std::array<u32, MaxPixelFormat> block_height_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
-            5, // ASTC_2D_8X5
-            4, // 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
-            5, // ASTC_2D_8X5_SRGB
-            4, // ASTC_2D_5X4_SRGB
-            1, // Z32F
-            1, // Z16
-            1, // Z24S8
-            1, // S8Z24
-            1, // Z32FS8
-        }};
-        ASSERT(static_cast<std::size_t>(format) < block_height_table.size());
-        return block_height_table[static_cast<std::size_t>(format)];
-    }
-
-    static constexpr u32 GetFormatBpp(PixelFormat format) {
-        if (format == PixelFormat::Invalid)
-            return 0;
-
-        constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
-            32,  // ABGR8U
-            32,  // ABGR8S
-            32,  // ABGR8UI
-            16,  // B5G6R5U
-            32,  // A2B10G10R10U
-            16,  // A1B5G5R5U
-            8,   // R8U
-            8,   // R8UI
-            64,  // RGBA16F
-            64,  // RGBA16U
-            64,  // RGBA16UI
-            32,  // R11FG11FB10F
-            128, // RGBA32UI
-            64,  // DXT1
-            128, // DXT23
-            128, // DXT45
-            64,  // DXN1
-            128, // DXN2UNORM
-            128, // DXN2SNORM
-            128, // BC7U
-            128, // BC6H_UF16
-            128, // BC6H_SF16
-            32,  // ASTC_2D_4X4
-            16,  // G8R8U
-            16,  // G8R8S
-            32,  // BGRA8
-            128, // RGBA32F
-            64,  // RG32F
-            32,  // R32F
-            16,  // R16F
-            16,  // R16U
-            16,  // R16S
-            16,  // R16UI
-            16,  // R16I
-            32,  // RG16
-            32,  // RG16F
-            32,  // RG16UI
-            32,  // RG16I
-            32,  // RG16S
-            96,  // RGB32F
-            32,  // RGBA8_SRGB
-            16,  // RG8U
-            16,  // RG8S
-            64,  // RG32UI
-            32,  // R32UI
-            16,  // ASTC_2D_8X8
-            16,  // ASTC_2D_8X5
-            32,  // 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
-            32,  // Z32F
-            16,  // Z16
-            32,  // Z24S8
-            32,  // S8Z24
-            64,  // Z32FS8
-        }};
-
-        ASSERT(static_cast<std::size_t>(format) < bpp_table.size());
-        return bpp_table[static_cast<std::size_t>(format)];
-    }
-
     u32 GetFormatBpp() const {
-        return GetFormatBpp(pixel_format);
-    }
-
-    static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
-        switch (format) {
-        case Tegra::DepthFormat::S8_Z24_UNORM:
-            return PixelFormat::S8Z24;
-        case Tegra::DepthFormat::Z24_S8_UNORM:
-            return PixelFormat::Z24S8;
-        case Tegra::DepthFormat::Z32_FLOAT:
-            return PixelFormat::Z32F;
-        case Tegra::DepthFormat::Z16_UNORM:
-            return PixelFormat::Z16;
-        case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
-            return PixelFormat::Z32FS8;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
-            UNREACHABLE();
-        }
-    }
-
-    static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
-        switch (format) {
-        // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
-        // gamma.
-        case Tegra::RenderTargetFormat::RGBA8_SRGB:
-            return PixelFormat::RGBA8_SRGB;
-        case Tegra::RenderTargetFormat::RGBA8_UNORM:
-            return PixelFormat::ABGR8U;
-        case Tegra::RenderTargetFormat::RGBA8_SNORM:
-            return PixelFormat::ABGR8S;
-        case Tegra::RenderTargetFormat::RGBA8_UINT:
-            return PixelFormat::ABGR8UI;
-        case Tegra::RenderTargetFormat::BGRA8_SRGB:
-            return PixelFormat::BGRA8_SRGB;
-        case Tegra::RenderTargetFormat::BGRA8_UNORM:
-            return PixelFormat::BGRA8;
-        case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
-            return PixelFormat::A2B10G10R10U;
-        case Tegra::RenderTargetFormat::RGBA16_FLOAT:
-            return PixelFormat::RGBA16F;
-        case Tegra::RenderTargetFormat::RGBA16_UNORM:
-            return PixelFormat::RGBA16U;
-        case Tegra::RenderTargetFormat::RGBA16_UINT:
-            return PixelFormat::RGBA16UI;
-        case Tegra::RenderTargetFormat::RGBA32_FLOAT:
-            return PixelFormat::RGBA32F;
-        case Tegra::RenderTargetFormat::RG32_FLOAT:
-            return PixelFormat::RG32F;
-        case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
-            return PixelFormat::R11FG11FB10F;
-        case Tegra::RenderTargetFormat::B5G6R5_UNORM:
-            return PixelFormat::B5G6R5U;
-        case Tegra::RenderTargetFormat::BGR5A1_UNORM:
-            return PixelFormat::A1B5G5R5U;
-        case Tegra::RenderTargetFormat::RGBA32_UINT:
-            return PixelFormat::RGBA32UI;
-        case Tegra::RenderTargetFormat::R8_UNORM:
-            return PixelFormat::R8U;
-        case Tegra::RenderTargetFormat::R8_UINT:
-            return PixelFormat::R8UI;
-        case Tegra::RenderTargetFormat::RG16_FLOAT:
-            return PixelFormat::RG16F;
-        case Tegra::RenderTargetFormat::RG16_UINT:
-            return PixelFormat::RG16UI;
-        case Tegra::RenderTargetFormat::RG16_SINT:
-            return PixelFormat::RG16I;
-        case Tegra::RenderTargetFormat::RG16_UNORM:
-            return PixelFormat::RG16;
-        case Tegra::RenderTargetFormat::RG16_SNORM:
-            return PixelFormat::RG16S;
-        case Tegra::RenderTargetFormat::RG8_UNORM:
-            return PixelFormat::RG8U;
-        case Tegra::RenderTargetFormat::RG8_SNORM:
-            return PixelFormat::RG8S;
-        case Tegra::RenderTargetFormat::R16_FLOAT:
-            return PixelFormat::R16F;
-        case Tegra::RenderTargetFormat::R16_UNORM:
-            return PixelFormat::R16U;
-        case Tegra::RenderTargetFormat::R16_SNORM:
-            return PixelFormat::R16S;
-        case Tegra::RenderTargetFormat::R16_UINT:
-            return PixelFormat::R16UI;
-        case Tegra::RenderTargetFormat::R16_SINT:
-            return PixelFormat::R16I;
-        case Tegra::RenderTargetFormat::R32_FLOAT:
-            return PixelFormat::R32F;
-        case Tegra::RenderTargetFormat::R32_UINT:
-            return PixelFormat::R32UI;
-        case Tegra::RenderTargetFormat::RG32_UINT:
-            return PixelFormat::RG32UI;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
-            UNREACHABLE();
-        }
-    }
-
-    static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
-                                                    Tegra::Texture::ComponentType component_type,
-                                                    bool is_srgb) {
-        // TODO(Subv): Properly implement this
-        switch (format) {
-        case Tegra::Texture::TextureFormat::A8R8G8B8:
-            if (is_srgb) {
-                return PixelFormat::RGBA8_SRGB;
-            }
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::ABGR8U;
-            case Tegra::Texture::ComponentType::SNORM:
-                return PixelFormat::ABGR8S;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::ABGR8UI;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::B5G6R5:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::B5G6R5U;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::A2B10G10R10:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::A2B10G10R10U;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::A1B5G5R5:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::A1B5G5R5U;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R8:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::R8U;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::R8UI;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::G8R8:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::G8R8U;
-            case Tegra::Texture::ComponentType::SNORM:
-                return PixelFormat::G8R8S;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R16_G16_B16_A16:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::RGBA16U;
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::RGBA16F;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::BF10GF11RF11:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::R11FG11FB10F;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R32_G32_B32_A32:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::RGBA32F;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::RGBA32UI;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R32_G32:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::RG32F;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::RG32UI;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R32_G32_B32:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::RGB32F;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R16:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::R16F;
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::R16U;
-            case Tegra::Texture::ComponentType::SNORM:
-                return PixelFormat::R16S;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::R16UI;
-            case Tegra::Texture::ComponentType::SINT:
-                return PixelFormat::R16I;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::R32:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::R32F;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::R32UI;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::ZF32:
-            return PixelFormat::Z32F;
-        case Tegra::Texture::TextureFormat::Z16:
-            return PixelFormat::Z16;
-        case Tegra::Texture::TextureFormat::Z24S8:
-            return PixelFormat::Z24S8;
-        case Tegra::Texture::TextureFormat::DXT1:
-            return is_srgb ? PixelFormat::DXT1_SRGB : PixelFormat::DXT1;
-        case Tegra::Texture::TextureFormat::DXT23:
-            return is_srgb ? PixelFormat::DXT23_SRGB : PixelFormat::DXT23;
-        case Tegra::Texture::TextureFormat::DXT45:
-            return is_srgb ? PixelFormat::DXT45_SRGB : PixelFormat::DXT45;
-        case Tegra::Texture::TextureFormat::DXN1:
-            return PixelFormat::DXN1;
-        case Tegra::Texture::TextureFormat::DXN2:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::DXN2UNORM;
-            case Tegra::Texture::ComponentType::SNORM:
-                return PixelFormat::DXN2SNORM;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        case Tegra::Texture::TextureFormat::BC7U:
-            return is_srgb ? PixelFormat::BC7U_SRGB : PixelFormat::BC7U;
-        case Tegra::Texture::TextureFormat::BC6H_UF16:
-            return PixelFormat::BC6H_UF16;
-        case Tegra::Texture::TextureFormat::BC6H_SF16:
-            return PixelFormat::BC6H_SF16;
-        case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
-            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_8X8:
-            return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
-        case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
-            return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;
-        case Tegra::Texture::TextureFormat::R16_G16:
-            switch (component_type) {
-            case Tegra::Texture::ComponentType::FLOAT:
-                return PixelFormat::RG16F;
-            case Tegra::Texture::ComponentType::UNORM:
-                return PixelFormat::RG16;
-            case Tegra::Texture::ComponentType::SNORM:
-                return PixelFormat::RG16S;
-            case Tegra::Texture::ComponentType::UINT:
-                return PixelFormat::RG16UI;
-            case Tegra::Texture::ComponentType::SINT:
-                return PixelFormat::RG16I;
-            }
-            LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
-                         static_cast<u32>(component_type));
-            UNREACHABLE();
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}",
-                         static_cast<u32>(format), static_cast<u32>(component_type));
-            UNREACHABLE();
-        }
-    }
-
-    static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
-        // TODO(Subv): Implement more component types
-        switch (type) {
-        case Tegra::Texture::ComponentType::UNORM:
-            return ComponentType::UNorm;
-        case Tegra::Texture::ComponentType::FLOAT:
-            return ComponentType::Float;
-        case Tegra::Texture::ComponentType::SNORM:
-            return ComponentType::SNorm;
-        case Tegra::Texture::ComponentType::UINT:
-            return ComponentType::UInt;
-        case Tegra::Texture::ComponentType::SINT:
-            return ComponentType::SInt;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
-            UNREACHABLE();
-        }
-    }
-
-    static ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) {
-        // TODO(Subv): Implement more render targets
-        switch (format) {
-        case Tegra::RenderTargetFormat::RGBA8_UNORM:
-        case Tegra::RenderTargetFormat::RGBA8_SRGB:
-        case Tegra::RenderTargetFormat::BGRA8_UNORM:
-        case Tegra::RenderTargetFormat::BGRA8_SRGB:
-        case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
-        case Tegra::RenderTargetFormat::R8_UNORM:
-        case Tegra::RenderTargetFormat::RG16_UNORM:
-        case Tegra::RenderTargetFormat::R16_UNORM:
-        case Tegra::RenderTargetFormat::B5G6R5_UNORM:
-        case Tegra::RenderTargetFormat::BGR5A1_UNORM:
-        case Tegra::RenderTargetFormat::RG8_UNORM:
-        case Tegra::RenderTargetFormat::RGBA16_UNORM:
-            return ComponentType::UNorm;
-        case Tegra::RenderTargetFormat::RGBA8_SNORM:
-        case Tegra::RenderTargetFormat::RG16_SNORM:
-        case Tegra::RenderTargetFormat::R16_SNORM:
-        case Tegra::RenderTargetFormat::RG8_SNORM:
-            return ComponentType::SNorm;
-        case Tegra::RenderTargetFormat::RGBA16_FLOAT:
-        case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
-        case Tegra::RenderTargetFormat::RGBA32_FLOAT:
-        case Tegra::RenderTargetFormat::RG32_FLOAT:
-        case Tegra::RenderTargetFormat::RG16_FLOAT:
-        case Tegra::RenderTargetFormat::R16_FLOAT:
-        case Tegra::RenderTargetFormat::R32_FLOAT:
-            return ComponentType::Float;
-        case Tegra::RenderTargetFormat::RGBA32_UINT:
-        case Tegra::RenderTargetFormat::RGBA16_UINT:
-        case Tegra::RenderTargetFormat::RG16_UINT:
-        case Tegra::RenderTargetFormat::R8_UINT:
-        case Tegra::RenderTargetFormat::R16_UINT:
-        case Tegra::RenderTargetFormat::RG32_UINT:
-        case Tegra::RenderTargetFormat::R32_UINT:
-        case Tegra::RenderTargetFormat::RGBA8_UINT:
-            return ComponentType::UInt;
-        case Tegra::RenderTargetFormat::RG16_SINT:
-        case Tegra::RenderTargetFormat::R16_SINT:
-            return ComponentType::SInt;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
-            UNREACHABLE();
-        }
-    }
-
-    static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
-        switch (format) {
-        case Tegra::FramebufferConfig::PixelFormat::ABGR8:
-            return PixelFormat::ABGR8U;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
-            UNREACHABLE();
-        }
-    }
-
-    static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) {
-        switch (format) {
-        case Tegra::DepthFormat::Z16_UNORM:
-        case Tegra::DepthFormat::S8_Z24_UNORM:
-        case Tegra::DepthFormat::Z24_S8_UNORM:
-            return ComponentType::UNorm;
-        case Tegra::DepthFormat::Z32_FLOAT:
-        case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
-            return ComponentType::Float;
-        default:
-            LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
-            UNREACHABLE();
-        }
-    }
-
-    static SurfaceType GetFormatType(PixelFormat pixel_format) {
-        if (static_cast<std::size_t>(pixel_format) <
-            static_cast<std::size_t>(PixelFormat::MaxColorFormat)) {
-            return SurfaceType::ColorTexture;
-        }
-
-        if (static_cast<std::size_t>(pixel_format) <
-            static_cast<std::size_t>(PixelFormat::MaxDepthFormat)) {
-            return SurfaceType::Depth;
-        }
-
-        if (static_cast<std::size_t>(pixel_format) <
-            static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) {
-            return SurfaceType::DepthStencil;
-        }
-
-        // TODO(Subv): Implement the other formats
-        ASSERT(false);
-
-        return SurfaceType::Invalid;
-    }
-
-    /// Returns the sizer in bytes of the specified pixel format
-    static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) {
-        if (pixel_format == SurfaceParams::PixelFormat::Invalid) {
-            return 0;
-        }
-        return GetFormatBpp(pixel_format) / CHAR_BIT;
+        return VideoCore::Surface::GetFormatBpp(pixel_format);
     }
 
     /// Returns the rectangle corresponding to this surface
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
new file mode 100644
index 0000000000..d9a97e30b9
--- /dev/null
+++ b/src/video_core/surface.cpp
@@ -0,0 +1,499 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/common_types.h"
+#include "common/math_util.h"
+#include "video_core/surface.h"
+
+namespace VideoCore::Surface {
+
+SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) {
+    switch (texture_type) {
+    case Tegra::Texture::TextureType::Texture1D:
+        return SurfaceTarget::Texture1D;
+    case Tegra::Texture::TextureType::Texture2D:
+    case Tegra::Texture::TextureType::Texture2DNoMipmap:
+        return SurfaceTarget::Texture2D;
+    case Tegra::Texture::TextureType::Texture3D:
+        return SurfaceTarget::Texture3D;
+    case Tegra::Texture::TextureType::TextureCubemap:
+        return SurfaceTarget::TextureCubemap;
+    case Tegra::Texture::TextureType::Texture1DArray:
+        return SurfaceTarget::Texture1DArray;
+    case Tegra::Texture::TextureType::Texture2DArray:
+        return SurfaceTarget::Texture2DArray;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", static_cast<u32>(texture_type));
+        UNREACHABLE();
+        return SurfaceTarget::Texture2D;
+    }
+}
+
+bool SurfaceTargetIsLayered(SurfaceTarget target) {
+    switch (target) {
+    case SurfaceTarget::Texture1D:
+    case SurfaceTarget::Texture2D:
+    case SurfaceTarget::Texture3D:
+        return false;
+    case SurfaceTarget::Texture1DArray:
+    case SurfaceTarget::Texture2DArray:
+    case SurfaceTarget::TextureCubemap:
+        return true;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
+        UNREACHABLE();
+        return false;
+    }
+}
+
+PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
+    switch (format) {
+    case Tegra::DepthFormat::S8_Z24_UNORM:
+        return PixelFormat::S8Z24;
+    case Tegra::DepthFormat::Z24_S8_UNORM:
+        return PixelFormat::Z24S8;
+    case Tegra::DepthFormat::Z32_FLOAT:
+        return PixelFormat::Z32F;
+    case Tegra::DepthFormat::Z16_UNORM:
+        return PixelFormat::Z16;
+    case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
+        return PixelFormat::Z32FS8;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
+        UNREACHABLE();
+    }
+}
+
+PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
+    switch (format) {
+        // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
+        // gamma.
+    case Tegra::RenderTargetFormat::RGBA8_SRGB:
+        return PixelFormat::RGBA8_SRGB;
+    case Tegra::RenderTargetFormat::RGBA8_UNORM:
+        return PixelFormat::ABGR8U;
+    case Tegra::RenderTargetFormat::RGBA8_SNORM:
+        return PixelFormat::ABGR8S;
+    case Tegra::RenderTargetFormat::RGBA8_UINT:
+        return PixelFormat::ABGR8UI;
+    case Tegra::RenderTargetFormat::BGRA8_SRGB:
+        return PixelFormat::BGRA8_SRGB;
+    case Tegra::RenderTargetFormat::BGRA8_UNORM:
+        return PixelFormat::BGRA8;
+    case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
+        return PixelFormat::A2B10G10R10U;
+    case Tegra::RenderTargetFormat::RGBA16_FLOAT:
+        return PixelFormat::RGBA16F;
+    case Tegra::RenderTargetFormat::RGBA16_UNORM:
+        return PixelFormat::RGBA16U;
+    case Tegra::RenderTargetFormat::RGBA16_UINT:
+        return PixelFormat::RGBA16UI;
+    case Tegra::RenderTargetFormat::RGBA32_FLOAT:
+        return PixelFormat::RGBA32F;
+    case Tegra::RenderTargetFormat::RG32_FLOAT:
+        return PixelFormat::RG32F;
+    case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
+        return PixelFormat::R11FG11FB10F;
+    case Tegra::RenderTargetFormat::B5G6R5_UNORM:
+        return PixelFormat::B5G6R5U;
+    case Tegra::RenderTargetFormat::BGR5A1_UNORM:
+        return PixelFormat::A1B5G5R5U;
+    case Tegra::RenderTargetFormat::RGBA32_UINT:
+        return PixelFormat::RGBA32UI;
+    case Tegra::RenderTargetFormat::R8_UNORM:
+        return PixelFormat::R8U;
+    case Tegra::RenderTargetFormat::R8_UINT:
+        return PixelFormat::R8UI;
+    case Tegra::RenderTargetFormat::RG16_FLOAT:
+        return PixelFormat::RG16F;
+    case Tegra::RenderTargetFormat::RG16_UINT:
+        return PixelFormat::RG16UI;
+    case Tegra::RenderTargetFormat::RG16_SINT:
+        return PixelFormat::RG16I;
+    case Tegra::RenderTargetFormat::RG16_UNORM:
+        return PixelFormat::RG16;
+    case Tegra::RenderTargetFormat::RG16_SNORM:
+        return PixelFormat::RG16S;
+    case Tegra::RenderTargetFormat::RG8_UNORM:
+        return PixelFormat::RG8U;
+    case Tegra::RenderTargetFormat::RG8_SNORM:
+        return PixelFormat::RG8S;
+    case Tegra::RenderTargetFormat::R16_FLOAT:
+        return PixelFormat::R16F;
+    case Tegra::RenderTargetFormat::R16_UNORM:
+        return PixelFormat::R16U;
+    case Tegra::RenderTargetFormat::R16_SNORM:
+        return PixelFormat::R16S;
+    case Tegra::RenderTargetFormat::R16_UINT:
+        return PixelFormat::R16UI;
+    case Tegra::RenderTargetFormat::R16_SINT:
+        return PixelFormat::R16I;
+    case Tegra::RenderTargetFormat::R32_FLOAT:
+        return PixelFormat::R32F;
+    case Tegra::RenderTargetFormat::R32_UINT:
+        return PixelFormat::R32UI;
+    case Tegra::RenderTargetFormat::RG32_UINT:
+        return PixelFormat::RG32UI;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
+        UNREACHABLE();
+    }
+}
+
+PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
+                                         Tegra::Texture::ComponentType component_type,
+                                         bool is_srgb) {
+    // TODO(Subv): Properly implement this
+    switch (format) {
+    case Tegra::Texture::TextureFormat::A8R8G8B8:
+        if (is_srgb) {
+            return PixelFormat::RGBA8_SRGB;
+        }
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::ABGR8U;
+        case Tegra::Texture::ComponentType::SNORM:
+            return PixelFormat::ABGR8S;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::ABGR8UI;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::B5G6R5:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::B5G6R5U;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::A2B10G10R10:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::A2B10G10R10U;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::A1B5G5R5:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::A1B5G5R5U;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R8:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::R8U;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::R8UI;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::G8R8:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::G8R8U;
+        case Tegra::Texture::ComponentType::SNORM:
+            return PixelFormat::G8R8S;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R16_G16_B16_A16:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::RGBA16U;
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::RGBA16F;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::BF10GF11RF11:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::R11FG11FB10F;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R32_G32_B32_A32:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::RGBA32F;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::RGBA32UI;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R32_G32:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::RG32F;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::RG32UI;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R32_G32_B32:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::RGB32F;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R16:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::R16F;
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::R16U;
+        case Tegra::Texture::ComponentType::SNORM:
+            return PixelFormat::R16S;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::R16UI;
+        case Tegra::Texture::ComponentType::SINT:
+            return PixelFormat::R16I;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::R32:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::R32F;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::R32UI;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::ZF32:
+        return PixelFormat::Z32F;
+    case Tegra::Texture::TextureFormat::Z16:
+        return PixelFormat::Z16;
+    case Tegra::Texture::TextureFormat::Z24S8:
+        return PixelFormat::Z24S8;
+    case Tegra::Texture::TextureFormat::DXT1:
+        return is_srgb ? PixelFormat::DXT1_SRGB : PixelFormat::DXT1;
+    case Tegra::Texture::TextureFormat::DXT23:
+        return is_srgb ? PixelFormat::DXT23_SRGB : PixelFormat::DXT23;
+    case Tegra::Texture::TextureFormat::DXT45:
+        return is_srgb ? PixelFormat::DXT45_SRGB : PixelFormat::DXT45;
+    case Tegra::Texture::TextureFormat::DXN1:
+        return PixelFormat::DXN1;
+    case Tegra::Texture::TextureFormat::DXN2:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::DXN2UNORM;
+        case Tegra::Texture::ComponentType::SNORM:
+            return PixelFormat::DXN2SNORM;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    case Tegra::Texture::TextureFormat::BC7U:
+        return is_srgb ? PixelFormat::BC7U_SRGB : PixelFormat::BC7U;
+    case Tegra::Texture::TextureFormat::BC6H_UF16:
+        return PixelFormat::BC6H_UF16;
+    case Tegra::Texture::TextureFormat::BC6H_SF16:
+        return PixelFormat::BC6H_SF16;
+    case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
+        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_8X8:
+        return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
+    case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
+        return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;
+    case Tegra::Texture::TextureFormat::R16_G16:
+        switch (component_type) {
+        case Tegra::Texture::ComponentType::FLOAT:
+            return PixelFormat::RG16F;
+        case Tegra::Texture::ComponentType::UNORM:
+            return PixelFormat::RG16;
+        case Tegra::Texture::ComponentType::SNORM:
+            return PixelFormat::RG16S;
+        case Tegra::Texture::ComponentType::UINT:
+            return PixelFormat::RG16UI;
+        case Tegra::Texture::ComponentType::SINT:
+            return PixelFormat::RG16I;
+        }
+        LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", static_cast<u32>(component_type));
+        UNREACHABLE();
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}", static_cast<u32>(format),
+                     static_cast<u32>(component_type));
+        UNREACHABLE();
+    }
+}
+
+ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
+    // TODO(Subv): Implement more component types
+    switch (type) {
+    case Tegra::Texture::ComponentType::UNORM:
+        return ComponentType::UNorm;
+    case Tegra::Texture::ComponentType::FLOAT:
+        return ComponentType::Float;
+    case Tegra::Texture::ComponentType::SNORM:
+        return ComponentType::SNorm;
+    case Tegra::Texture::ComponentType::UINT:
+        return ComponentType::UInt;
+    case Tegra::Texture::ComponentType::SINT:
+        return ComponentType::SInt;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
+        UNREACHABLE();
+    }
+}
+
+ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) {
+    // TODO(Subv): Implement more render targets
+    switch (format) {
+    case Tegra::RenderTargetFormat::RGBA8_UNORM:
+    case Tegra::RenderTargetFormat::RGBA8_SRGB:
+    case Tegra::RenderTargetFormat::BGRA8_UNORM:
+    case Tegra::RenderTargetFormat::BGRA8_SRGB:
+    case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
+    case Tegra::RenderTargetFormat::R8_UNORM:
+    case Tegra::RenderTargetFormat::RG16_UNORM:
+    case Tegra::RenderTargetFormat::R16_UNORM:
+    case Tegra::RenderTargetFormat::B5G6R5_UNORM:
+    case Tegra::RenderTargetFormat::BGR5A1_UNORM:
+    case Tegra::RenderTargetFormat::RG8_UNORM:
+    case Tegra::RenderTargetFormat::RGBA16_UNORM:
+        return ComponentType::UNorm;
+    case Tegra::RenderTargetFormat::RGBA8_SNORM:
+    case Tegra::RenderTargetFormat::RG16_SNORM:
+    case Tegra::RenderTargetFormat::R16_SNORM:
+    case Tegra::RenderTargetFormat::RG8_SNORM:
+        return ComponentType::SNorm;
+    case Tegra::RenderTargetFormat::RGBA16_FLOAT:
+    case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
+    case Tegra::RenderTargetFormat::RGBA32_FLOAT:
+    case Tegra::RenderTargetFormat::RG32_FLOAT:
+    case Tegra::RenderTargetFormat::RG16_FLOAT:
+    case Tegra::RenderTargetFormat::R16_FLOAT:
+    case Tegra::RenderTargetFormat::R32_FLOAT:
+        return ComponentType::Float;
+    case Tegra::RenderTargetFormat::RGBA32_UINT:
+    case Tegra::RenderTargetFormat::RGBA16_UINT:
+    case Tegra::RenderTargetFormat::RG16_UINT:
+    case Tegra::RenderTargetFormat::R8_UINT:
+    case Tegra::RenderTargetFormat::R16_UINT:
+    case Tegra::RenderTargetFormat::RG32_UINT:
+    case Tegra::RenderTargetFormat::R32_UINT:
+    case Tegra::RenderTargetFormat::RGBA8_UINT:
+        return ComponentType::UInt;
+    case Tegra::RenderTargetFormat::RG16_SINT:
+    case Tegra::RenderTargetFormat::R16_SINT:
+        return ComponentType::SInt;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
+        UNREACHABLE();
+    }
+}
+
+PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
+    switch (format) {
+    case Tegra::FramebufferConfig::PixelFormat::ABGR8:
+        return PixelFormat::ABGR8U;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
+        UNREACHABLE();
+    }
+}
+
+ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) {
+    switch (format) {
+    case Tegra::DepthFormat::Z16_UNORM:
+    case Tegra::DepthFormat::S8_Z24_UNORM:
+    case Tegra::DepthFormat::Z24_S8_UNORM:
+        return ComponentType::UNorm;
+    case Tegra::DepthFormat::Z32_FLOAT:
+    case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
+        return ComponentType::Float;
+    default:
+        LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
+        UNREACHABLE();
+    }
+}
+
+SurfaceType GetFormatType(PixelFormat pixel_format) {
+    if (static_cast<std::size_t>(pixel_format) <
+        static_cast<std::size_t>(PixelFormat::MaxColorFormat)) {
+        return SurfaceType::ColorTexture;
+    }
+
+    if (static_cast<std::size_t>(pixel_format) <
+        static_cast<std::size_t>(PixelFormat::MaxDepthFormat)) {
+        return SurfaceType::Depth;
+    }
+
+    if (static_cast<std::size_t>(pixel_format) <
+        static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) {
+        return SurfaceType::DepthStencil;
+    }
+
+    // TODO(Subv): Implement the other formats
+    ASSERT(false);
+
+    return SurfaceType::Invalid;
+}
+
+bool IsPixelFormatASTC(PixelFormat format) {
+    switch (format) {
+    case PixelFormat::ASTC_2D_4X4:
+    case PixelFormat::ASTC_2D_5X4:
+    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_8X8_SRGB:
+    case PixelFormat::ASTC_2D_8X5_SRGB:
+        return true;
+    default:
+        return false;
+    }
+}
+
+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();
+    }
+}
+
+bool IsFormatBCn(PixelFormat format) {
+    switch (format) {
+    case PixelFormat::DXT1:
+    case PixelFormat::DXT23:
+    case PixelFormat::DXT45:
+    case PixelFormat::DXN1:
+    case PixelFormat::DXN2SNORM:
+    case PixelFormat::DXN2UNORM:
+    case PixelFormat::BC7U:
+    case PixelFormat::BC6H_UF16:
+    case PixelFormat::BC6H_SF16:
+    case PixelFormat::DXT1_SRGB:
+    case PixelFormat::DXT23_SRGB:
+    case PixelFormat::DXT45_SRGB:
+    case PixelFormat::BC7U_SRGB:
+        return true;
+    }
+    return false;
+}
+
+} // namespace VideoCore::Surface
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
new file mode 100644
index 0000000000..3232e437f3
--- /dev/null
+++ b/src/video_core/surface.h
@@ -0,0 +1,385 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <climits>
+#include <utility>
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "video_core/gpu.h"
+#include "video_core/textures/texture.h"
+
+namespace VideoCore::Surface {
+
+enum class PixelFormat {
+    ABGR8U = 0,
+    ABGR8S = 1,
+    ABGR8UI = 2,
+    B5G6R5U = 3,
+    A2B10G10R10U = 4,
+    A1B5G5R5U = 5,
+    R8U = 6,
+    R8UI = 7,
+    RGBA16F = 8,
+    RGBA16U = 9,
+    RGBA16UI = 10,
+    R11FG11FB10F = 11,
+    RGBA32UI = 12,
+    DXT1 = 13,
+    DXT23 = 14,
+    DXT45 = 15,
+    DXN1 = 16, // This is also known as BC4
+    DXN2UNORM = 17,
+    DXN2SNORM = 18,
+    BC7U = 19,
+    BC6H_UF16 = 20,
+    BC6H_SF16 = 21,
+    ASTC_2D_4X4 = 22,
+    G8R8U = 23,
+    G8R8S = 24,
+    BGRA8 = 25,
+    RGBA32F = 26,
+    RG32F = 27,
+    R32F = 28,
+    R16F = 29,
+    R16U = 30,
+    R16S = 31,
+    R16UI = 32,
+    R16I = 33,
+    RG16 = 34,
+    RG16F = 35,
+    RG16UI = 36,
+    RG16I = 37,
+    RG16S = 38,
+    RGB32F = 39,
+    RGBA8_SRGB = 40,
+    RG8U = 41,
+    RG8S = 42,
+    RG32UI = 43,
+    R32UI = 44,
+    ASTC_2D_8X8 = 45,
+    ASTC_2D_8X5 = 46,
+    ASTC_2D_5X4 = 47,
+    BGRA8_SRGB = 48,
+    DXT1_SRGB = 49,
+    DXT23_SRGB = 50,
+    DXT45_SRGB = 51,
+    BC7U_SRGB = 52,
+    ASTC_2D_4X4_SRGB = 53,
+    ASTC_2D_8X8_SRGB = 54,
+    ASTC_2D_8X5_SRGB = 55,
+    ASTC_2D_5X4_SRGB = 56,
+
+    MaxColorFormat,
+
+    // Depth formats
+    Z32F = 57,
+    Z16 = 58,
+
+    MaxDepthFormat,
+
+    // DepthStencil formats
+    Z24S8 = 59,
+    S8Z24 = 60,
+    Z32FS8 = 61,
+
+    MaxDepthStencilFormat,
+
+    Max = MaxDepthStencilFormat,
+    Invalid = 255,
+};
+
+static constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max);
+
+enum class ComponentType {
+    Invalid = 0,
+    SNorm = 1,
+    UNorm = 2,
+    SInt = 3,
+    UInt = 4,
+    Float = 5,
+};
+
+enum class SurfaceType {
+    ColorTexture = 0,
+    Depth = 1,
+    DepthStencil = 2,
+    Fill = 3,
+    Invalid = 4,
+};
+
+enum class SurfaceTarget {
+    Texture1D,
+    Texture2D,
+    Texture3D,
+    Texture1DArray,
+    Texture2DArray,
+    TextureCubemap,
+};
+
+/**
+ * Gets the compression factor for the specified PixelFormat. This applies to just the
+ * "compressed width" and "compressed height", not the overall compression factor of a
+ * compressed image. This is used for maintaining proper surface sizes for compressed
+ * texture formats.
+ */
+static constexpr u32 GetCompressionFactor(PixelFormat format) {
+    if (format == PixelFormat::Invalid)
+        return 0;
+
+    constexpr std::array<u32, MaxPixelFormat> compression_factor_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
+        4, // ASTC_2D_8X8
+        4, // ASTC_2D_8X5
+        4, // ASTC_2D_5X4
+        1, // BGRA8_SRGB
+        4, // DXT1_SRGB
+        4, // DXT23_SRGB
+        4, // DXT45_SRGB
+        4, // BC7U_SRGB
+        4, // ASTC_2D_4X4_SRGB
+        4, // ASTC_2D_8X8_SRGB
+        4, // ASTC_2D_8X5_SRGB
+        4, // ASTC_2D_5X4_SRGB
+        1, // Z32F
+        1, // Z16
+        1, // Z24S8
+        1, // S8Z24
+        1, // Z32FS8
+    }};
+
+    ASSERT(static_cast<std::size_t>(format) < compression_factor_table.size());
+    return compression_factor_table[static_cast<std::size_t>(format)];
+}
+
+static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
+    if (format == PixelFormat::Invalid)
+        return 0;
+
+    constexpr std::array<u32, MaxPixelFormat> block_height_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
+        5, // ASTC_2D_8X5
+        4, // 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
+        5, // ASTC_2D_8X5_SRGB
+        4, // ASTC_2D_5X4_SRGB
+        1, // Z32F
+        1, // Z16
+        1, // Z24S8
+        1, // S8Z24
+        1, // Z32FS8
+    }};
+
+    ASSERT(static_cast<std::size_t>(format) < block_height_table.size());
+    return block_height_table[static_cast<std::size_t>(format)];
+}
+
+static constexpr u32 GetFormatBpp(PixelFormat format) {
+    if (format == PixelFormat::Invalid)
+        return 0;
+
+    constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
+        32,  // ABGR8U
+        32,  // ABGR8S
+        32,  // ABGR8UI
+        16,  // B5G6R5U
+        32,  // A2B10G10R10U
+        16,  // A1B5G5R5U
+        8,   // R8U
+        8,   // R8UI
+        64,  // RGBA16F
+        64,  // RGBA16U
+        64,  // RGBA16UI
+        32,  // R11FG11FB10F
+        128, // RGBA32UI
+        64,  // DXT1
+        128, // DXT23
+        128, // DXT45
+        64,  // DXN1
+        128, // DXN2UNORM
+        128, // DXN2SNORM
+        128, // BC7U
+        128, // BC6H_UF16
+        128, // BC6H_SF16
+        32,  // ASTC_2D_4X4
+        16,  // G8R8U
+        16,  // G8R8S
+        32,  // BGRA8
+        128, // RGBA32F
+        64,  // RG32F
+        32,  // R32F
+        16,  // R16F
+        16,  // R16U
+        16,  // R16S
+        16,  // R16UI
+        16,  // R16I
+        32,  // RG16
+        32,  // RG16F
+        32,  // RG16UI
+        32,  // RG16I
+        32,  // RG16S
+        96,  // RGB32F
+        32,  // RGBA8_SRGB
+        16,  // RG8U
+        16,  // RG8S
+        64,  // RG32UI
+        32,  // R32UI
+        16,  // ASTC_2D_8X8
+        16,  // ASTC_2D_8X5
+        32,  // 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
+        32,  // Z32F
+        16,  // Z16
+        32,  // Z24S8
+        32,  // S8Z24
+        64,  // Z32FS8
+    }};
+
+    ASSERT(static_cast<std::size_t>(format) < bpp_table.size());
+    return bpp_table[static_cast<std::size_t>(format)];
+}
+
+/// Returns the sizer in bytes of the specified pixel format
+static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) {
+    if (pixel_format == PixelFormat::Invalid) {
+        return 0;
+    }
+    return GetFormatBpp(pixel_format) / CHAR_BIT;
+}
+
+SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
+
+bool SurfaceTargetIsLayered(SurfaceTarget target);
+
+PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format);
+
+PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format);
+
+PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
+                                         Tegra::Texture::ComponentType component_type,
+                                         bool is_srgb);
+
+ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type);
+
+ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format);
+
+PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format);
+
+ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format);
+
+SurfaceType GetFormatType(PixelFormat pixel_format);
+
+bool IsPixelFormatASTC(PixelFormat format);
+
+std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
+
+/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
+bool IsFormatBCn(PixelFormat format);
+
+} // namespace VideoCore::Surface