diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
index 173f5fe479..1a22bdbf31 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
@@ -43,7 +43,26 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             var srcCopyTextureFormat = srcCopyTexture.Format.Convert();
 
-            Texture srcTexture = TextureManager.FindOrCreateTexture(srcCopyTexture, srcCopyTextureFormat, true, srcHint);
+            int srcWidthAligned = srcCopyTexture.Stride / srcCopyTextureFormat.BytesPerPixel;
+
+            ulong offset = 0;
+
+            // For an out of bounds copy, we must ensure that the copy wraps to the next line,
+            // so for a copy from a 64x64 texture, in the region [32, 96[, there are 32 pixels that are
+            // outside the bounds of the texture. We fill the destination with the first 32 pixels
+            // of the next line on the source texture.
+            // This can be done by simply adding an offset to the texture address, so that the initial
+            // gap is skipped and the copy is inside bounds again.
+            // This is required by the proprietary guest OpenGL driver.
+            if (srcCopyTexture.LinearLayout && srcCopyTexture.Width == srcX2 && srcX2 > srcWidthAligned && srcX1 > 0)
+            {
+                offset = (ulong)(srcX1 * srcCopyTextureFormat.BytesPerPixel);
+                srcCopyTexture.Width -= srcX1;
+                srcX2 -= srcX1;
+                srcX1 = 0;
+            }
+
+            Texture srcTexture = TextureManager.FindOrCreateTexture(srcCopyTexture, offset, srcCopyTextureFormat, true, srcHint);
 
             if (srcTexture == null)
             {
@@ -64,7 +83,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 dstCopyTextureFormat = dstCopyTexture.Format.Convert();
             }
 
-            Texture dstTexture = TextureManager.FindOrCreateTexture(dstCopyTexture, dstCopyTextureFormat, srcTexture.ScaleMode == TextureScaleMode.Scaled, dstHint);
+            Texture dstTexture = TextureManager.FindOrCreateTexture(dstCopyTexture, 0, dstCopyTextureFormat, srcTexture.ScaleMode == TextureScaleMode.Scaled, dstHint);
 
             if (dstTexture == null)
             {
@@ -90,30 +109,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             srcTexture.HostTexture.CopyTo(dstTexture.HostTexture, srcRegion, dstRegion, linearFilter);
 
-            // For an out of bounds copy, we must ensure that the copy wraps to the next line,
-            // so for a copy from a 64x64 texture, in the region [32, 96[, there are 32 pixels that are
-            // outside the bounds of the texture. We fill the destination with the first 32 pixels
-            // of the next line on the source texture.
-            // This can be emulated with 2 copies (the first copy handles the region inside the bounds,
-            // the second handles the region outside of the bounds).
-            // We must also extend the source texture by one line to ensure we can wrap on the last line.
-            // This is required by the (guest) OpenGL driver.
-            if (srcX2 / srcTexture.Info.SamplesInX > srcTexture.Info.Width)
-            {
-                srcCopyTexture.Height++;
-
-                srcTexture = TextureManager.FindOrCreateTexture(srcCopyTexture, srcCopyTextureFormat, srcTexture.ScaleMode == TextureScaleMode.Scaled, srcHint);
-                scale = srcTexture.ScaleFactor;
-
-                srcRegion = new Extents2D(
-                    (int)Math.Ceiling(scale * ((srcX1 / srcTexture.Info.SamplesInX) - srcTexture.Info.Width)),
-                    (int)Math.Ceiling(scale * ((srcY1 / srcTexture.Info.SamplesInY) + 1)),
-                    (int)Math.Ceiling(scale * ((srcX2 / srcTexture.Info.SamplesInX) - srcTexture.Info.Width)),
-                    (int)Math.Ceiling(scale * ((srcY2 / srcTexture.Info.SamplesInY) + 1)));
-
-                srcTexture.HostTexture.CopyTo(dstTexture.HostTexture, srcRegion, dstRegion, linearFilter);
-            }
-
             dstTexture.SignalModified();
         }
     }
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index e08e55eea6..94939ae477 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -476,11 +476,12 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// Tries to find an existing texture, or create a new one if not found.
         /// </summary>
         /// <param name="copyTexture">Copy texture to find or create</param>
+        /// <param name="offset">Offset to be added to the physical texture address</param>
         /// <param name="formatInfo">Format information of the copy texture</param>
         /// <param name="preferScaling">Indicates if the texture should be scaled from the start</param>
         /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
         /// <returns>The texture</returns>
-        public Texture FindOrCreateTexture(CopyTexture copyTexture, FormatInfo formatInfo, bool preferScaling = true, Size? sizeHint = null)
+        public Texture FindOrCreateTexture(CopyTexture copyTexture, ulong offset, FormatInfo formatInfo, bool preferScaling = true, Size? sizeHint = null)
         {
             int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY();
             int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ();
@@ -497,7 +498,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
 
             TextureInfo info = new TextureInfo(
-                copyTexture.Address.Pack(),
+                copyTexture.Address.Pack() + offset,
                 width,
                 copyTexture.Height,
                 copyTexture.Depth,