diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 2a0858eac..561c6913d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -49,9 +49,11 @@ struct FormatTuple {
 };
 
 static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
-    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1},                   // ABGR8
-    {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1},                      // B5G6R5
-    {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
+    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1},                     // ABGR8
+    {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1},                        // B5G6R5
+    {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16},   // DXT1
+    {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
+    {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
 }};
 
 static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
@@ -81,23 +83,6 @@ static u16 GetResolutionScaleFactor() {
                                 : Settings::values.resolution_factor);
 }
 
-template <bool morton_to_gl, PixelFormat format>
-static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) {
-    constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
-    constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
-    for (u32 y = 0; y < 8; ++y) {
-        for (u32 x = 0; x < 8; ++x) {
-            u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel;
-            u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel;
-            if (morton_to_gl) {
-                std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel);
-            } else {
-                std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel);
-            }
-        }
-    }
-}
-
 template <bool morton_to_gl, PixelFormat format>
 void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start,
                 VAddr end) {
@@ -121,9 +106,9 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr b
 static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
                             SurfaceParams::MaxPixelFormat>
     morton_to_gl_fns = {
-        MortonCopy<true, PixelFormat::ABGR8>,
-        MortonCopy<true, PixelFormat::B5G6R5>,
-        MortonCopy<true, PixelFormat::DXT1>,
+        MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
+        MortonCopy<true, PixelFormat::DXT1>,  MortonCopy<true, PixelFormat::DXT23>,
+        MortonCopy<true, PixelFormat::DXT45>,
 };
 
 static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
@@ -131,7 +116,9 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
     gl_to_morton_fns = {
         MortonCopy<false, PixelFormat::ABGR8>,
         MortonCopy<false, PixelFormat::B5G6R5>,
-        // TODO(Subv): Swizzling the DXT1 format is not yet supported
+        // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported
+        nullptr,
+        nullptr,
         nullptr,
 };
 
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 23e4d02d8..6861efe16 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -55,6 +55,8 @@ struct SurfaceParams {
         ABGR8 = 0,
         B5G6R5 = 1,
         DXT1 = 2,
+        DXT23 = 3,
+        DXT45 = 4,
 
         Max,
         Invalid = 255,
@@ -84,9 +86,11 @@ struct SurfaceParams {
             return 0;
 
         constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
-            32, // ABGR8
-            16, // B5G6R5
-            64, // DXT1
+            32,  // ABGR8
+            16,  // B5G6R5
+            64,  // DXT1
+            128, // DXT23
+            128, // DXT45
         };
 
         ASSERT(static_cast<size_t>(format) < bpp_table.size());
@@ -125,6 +129,10 @@ struct SurfaceParams {
             return PixelFormat::B5G6R5;
         case Tegra::Texture::TextureFormat::DXT1:
             return PixelFormat::DXT1;
+        case Tegra::Texture::TextureFormat::DXT23:
+            return PixelFormat::DXT23;
+        case Tegra::Texture::TextureFormat::DXT45:
+            return PixelFormat::DXT45;
         default:
             NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
             UNREACHABLE();
@@ -140,6 +148,10 @@ struct SurfaceParams {
             return Tegra::Texture::TextureFormat::B5G6R5;
         case PixelFormat::DXT1:
             return Tegra::Texture::TextureFormat::DXT1;
+        case PixelFormat::DXT23:
+            return Tegra::Texture::TextureFormat::DXT23;
+        case PixelFormat::DXT45:
+            return Tegra::Texture::TextureFormat::DXT45;
         default:
             UNREACHABLE();
         }
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index f4c7e40df..4df687786 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -48,6 +48,10 @@ u32 BytesPerPixel(TextureFormat format) {
     case TextureFormat::DXT1:
         // In this case a 'pixel' actually refers to a 4x4 tile.
         return 8;
+    case TextureFormat::DXT23:
+    case TextureFormat::DXT45:
+        // In this case a 'pixel' actually refers to a 4x4 tile.
+        return 16;
     case TextureFormat::A8R8G8B8:
         return 4;
     case TextureFormat::B5G6R5:
@@ -67,7 +71,9 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
 
     switch (format) {
     case TextureFormat::DXT1:
-        // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values.
+    case TextureFormat::DXT23:
+    case TextureFormat::DXT45:
+        // In the DXT formats, each 4x4 tile is swizzled instead of just individual pixel values.
         CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
                          unswizzled_data.data(), true, block_height);
         break;
@@ -91,6 +97,8 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
     // TODO(Subv): Implement.
     switch (format) {
     case TextureFormat::DXT1:
+    case TextureFormat::DXT23:
+    case TextureFormat::DXT45:
     case TextureFormat::A8R8G8B8:
     case TextureFormat::B5G6R5:
         // TODO(Subv): For the time being just forward the same data without any decoding.