diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 3ceab54a2..f893b3e3e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1019,41 +1019,33 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe
 
 bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) {
     u32 copy_size = Common::AlignDown(config.texture_copy.size, 16);
-
-    if (copy_size == 0)
+    if (copy_size == 0) {
         return false;
+    }
 
     u32 input_gap = config.texture_copy.input_gap * 16;
     u32 input_width = config.texture_copy.input_width * 16;
-    if (input_width == 0) {
-        if (input_gap == 0) {
-            input_width = copy_size;
-        } else {
-            return false;
-        }
+    if (input_width == 0 && input_gap != 0) {
+        return false;
+    }
+    if (input_gap == 0 || input_width >= copy_size) {
+        input_width = copy_size;
+        input_gap = 0;
+    }
+    if (copy_size % input_width != 0) {
+        return false;
     }
 
     u32 output_gap = config.texture_copy.output_gap * 16;
     u32 output_width = config.texture_copy.output_width * 16;
-    if (output_width == 0) {
-        if (output_gap == 0) {
-            output_width = copy_size;
-        } else {
-            return false;
-        }
+    if (output_width == 0 && output_gap != 0) {
+        return false;
     }
-
-    if (input_width >= copy_size) {
-        input_width = copy_size;
-        input_gap = 0;
-    }
-
-    if (output_width >= copy_size) {
+    if (output_gap == 0 || output_width >= copy_size) {
         output_width = copy_size;
         output_gap = 0;
     }
-
-    if (input_width != output_width || copy_size % input_width != 0) {
+    if (copy_size % output_width != 0) {
         return false;
     }
 
@@ -1068,12 +1060,16 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
     MathUtil::Rectangle<u32> src_rect;
     Surface src_surface;
     std::tie(src_surface, src_rect) = res_cache.GetTexCopySurface(src_params);
-    if (src_surface == nullptr)
+    if (src_surface == nullptr) {
         return false;
+    }
 
-    if ((output_gap * 8) % SurfaceParams::GetFormatBpp(src_surface->pixel_format) != 0 ||
-        (src_surface->is_tiled && src_surface->PixelsInBytes(output_gap) % 64 != 0))
+    if (output_gap != 0 &&
+        (output_width != src_surface->BytesInPixels(src_rect.GetWidth() / src_surface->res_scale) *
+                             (src_surface->is_tiled ? 8 : 1) ||
+         output_gap % src_surface->BytesInPixels(src_surface->is_tiled ? 64 : 1) != 0)) {
         return false;
+    }
 
     SurfaceParams dst_params = *src_surface;
     dst_params.addr = config.GetPhysicalOutputAddress();
@@ -1091,11 +1087,13 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
     Surface dst_surface;
     std::tie(dst_surface, dst_rect) =
         res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, load_gap);
-    if (src_surface == nullptr)
+    if (src_surface == nullptr) {
         return false;
+    }
 
-    if (!res_cache.BlitSurfaces(src_surface, src_rect, dst_surface, dst_rect))
+    if (!res_cache.BlitSurfaces(src_surface, src_rect, dst_surface, dst_rect)) {
         return false;
+    }
 
     res_cache.InvalidateRegion(dst_params.addr, dst_params.size, dst_surface);
     return true;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 066a58085..d51ac5b1e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -390,6 +390,7 @@ SurfaceParams SurfaceParams::FromInterval(SurfaceInterval interval) const {
             addr + Common::AlignUp(boost::icl::last_next(interval) - addr, tiled_alignment);
         params.addr = aligned_start;
         params.width = PixelsInBytes(aligned_end - aligned_start) / (is_tiled ? 8 : 1);
+        params.stride = params.width;
         params.height = is_tiled ? 8 : 1;
     }
     params.UpdateParams();
@@ -447,57 +448,45 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su
 }
 
 bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
-    return (other_surface.addr == addr && other_surface.width == width &&
-            other_surface.height == height && other_surface.stride == stride &&
-            other_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
-            other_surface.is_tiled == is_tiled);
+    return other_surface.addr == addr && other_surface.width == width &&
+           other_surface.height == height && other_surface.stride == stride &&
+           other_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
+           other_surface.is_tiled == is_tiled;
 }
 
 bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
-    return (sub_surface.addr >= addr && sub_surface.end <= end &&
-            sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
-            sub_surface.is_tiled == is_tiled &&
-            (sub_surface.addr - addr) * 8 % GetFormatBpp() == 0 &&
-            (!is_tiled || PixelsInBytes(sub_surface.addr - addr) % 64 == 0) &&
-            (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
-            GetSubRect(sub_surface).left + sub_surface.width <= stride);
+    return sub_surface.addr >= addr && sub_surface.end <= end &&
+           sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
+           sub_surface.is_tiled == is_tiled &&
+           (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
+           (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
+           GetSubRect(sub_surface).left + sub_surface.width <= stride;
 }
 
 bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
-    if (pixel_format == PixelFormat::Invalid || pixel_format != expanded_surface.pixel_format ||
-        is_tiled != expanded_surface.is_tiled || addr > expanded_surface.end ||
-        expanded_surface.addr > end || stride != expanded_surface.stride)
-        return false;
-
-    const u32 byte_offset =
-        std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr);
-
-    const int x0 = byte_offset % BytesInPixels(stride);
-    const int y0 = byte_offset / BytesInPixels(stride);
-
-    return x0 == 0 && (!is_tiled || y0 % 8 == 0);
+    return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format &&
+           addr <= expanded_surface.end && expanded_surface.addr <= end &&
+           is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride &&
+           (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) %
+                   BytesInPixels(stride * (is_tiled ? 8 : 1)) ==
+               0;
 }
 
 bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const {
     if (pixel_format == PixelFormat::Invalid || addr > texcopy_params.addr ||
-        end < texcopy_params.end || ((texcopy_params.addr - addr) * 8) % GetFormatBpp() != 0 ||
-        (texcopy_params.width * 8) % GetFormatBpp() != 0 ||
-        (texcopy_params.stride * 8) % GetFormatBpp() != 0)
+        end < texcopy_params.end) {
         return false;
-
-    const u32 begin_pixel_index = PixelsInBytes(texcopy_params.addr - addr);
-
-    if (!is_tiled) {
-        const int x0 = begin_pixel_index % stride;
-        return ((texcopy_params.height == 1 || PixelsInBytes(texcopy_params.stride) == stride) &&
-                x0 + PixelsInBytes(texcopy_params.width) <= stride);
     }
-
-    const int x0 = (begin_pixel_index % (stride * 8)) / 8;
-    return (PixelsInBytes(texcopy_params.addr - addr) % 64 == 0 &&
-            PixelsInBytes(texcopy_params.width) % 64 == 0 &&
-            (texcopy_params.height == 1 || PixelsInBytes(texcopy_params.stride) == stride * 8) &&
-            x0 + PixelsInBytes(texcopy_params.width / 8) <= stride);
+    if (texcopy_params.width != texcopy_params.stride) {
+        const u32 tile_stride = BytesInPixels(stride * (is_tiled ? 8 : 1));
+        return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
+               texcopy_params.width % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
+               (texcopy_params.height == 1 || texcopy_params.stride == tile_stride) &&
+               ((texcopy_params.addr - addr) % tile_stride) + texcopy_params.width <= tile_stride;
+    } else {
+        return FromInterval(texcopy_params.GetInterval()).GetInterval() ==
+               texcopy_params.GetInterval();
+    }
 }
 
 bool CachedSurface::CanFill(const SurfaceParams& dest_surface,
@@ -1245,14 +1234,17 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams&
     if (match_surface != nullptr) {
         ValidateSurface(match_surface, params.addr, params.size);
 
-        SurfaceParams match_subrect = params;
-        match_subrect.width = match_surface->PixelsInBytes(params.width);
-        match_subrect.stride = match_surface->PixelsInBytes(params.stride);
-
-        if (match_surface->is_tiled) {
-            match_subrect.width /= 8;
-            match_subrect.stride /= 8;
-            match_subrect.height *= 8;
+        SurfaceParams match_subrect;
+        if (params.width != params.stride) {
+            match_subrect = params;
+            match_subrect.width =
+                match_surface->PixelsInBytes(params.width) / (match_surface->is_tiled ? 8 : 1);
+            match_subrect.stride =
+                match_surface->PixelsInBytes(params.stride) / (match_surface->is_tiled ? 8 : 1);
+            match_subrect.height *= (match_surface->is_tiled ? 8 : 1);
+        } else {
+            match_subrect = match_surface->FromInterval(params.GetInterval());
+            ASSERT(match_subrect.GetInterval() == params.GetInterval());
         }
 
         rect = match_surface->GetScaledSubRect(match_subrect);