mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:18:58 -06:00 
			
		
		
		
	Implement fast DMA texture to texture copy (#7299)
* Implement fast DMA texture to texture copy * PR feedback
This commit is contained in:
		@@ -276,8 +276,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
 | 
				
			|||||||
                    dstBaseOffset += dstStride * (yCount - 1);
 | 
					                    dstBaseOffset += dstStride * (yCount - 1);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // If remapping is disabled, we always copy the components directly, in order.
 | 
					                // If remapping is disabled, we always copy the components directly, in order.
 | 
				
			||||||
                // If it's enabled, but the mapping is just XYZW, we also copy them in order.
 | 
					                // If it's enabled, but the mapping is just XYZW, we also copy them in order.
 | 
				
			||||||
                bool isIdentityRemap = !remap ||
 | 
					                bool isIdentityRemap = !remap ||
 | 
				
			||||||
@@ -289,6 +287,52 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
 | 
				
			|||||||
                bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
 | 
					                bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
 | 
				
			||||||
                bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
 | 
					                bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Check if the source texture exists on the GPU, if it does, do a GPU side copy.
 | 
				
			||||||
 | 
					                // Otherwise, we would need to flush the source texture which is costly.
 | 
				
			||||||
 | 
					                // We don't expect the source to be linear in such cases, as linear source usually indicates buffer or CPU written data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (completeSource && completeDest && !srcLinear && isIdentityRemap)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var source = memoryManager.Physical.TextureCache.FindTexture(
 | 
				
			||||||
 | 
					                        memoryManager,
 | 
				
			||||||
 | 
					                        srcGpuVa,
 | 
				
			||||||
 | 
					                        srcBpp,
 | 
				
			||||||
 | 
					                        srcStride,
 | 
				
			||||||
 | 
					                        src.Height,
 | 
				
			||||||
 | 
					                        xCount,
 | 
				
			||||||
 | 
					                        yCount,
 | 
				
			||||||
 | 
					                        srcLinear,
 | 
				
			||||||
 | 
					                        src.MemoryLayout.UnpackGobBlocksInY(),
 | 
				
			||||||
 | 
					                        src.MemoryLayout.UnpackGobBlocksInZ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (source != null && source.Height == yCount)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        source.SynchronizeMemory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        var target = memoryManager.Physical.TextureCache.FindOrCreateTexture(
 | 
				
			||||||
 | 
					                            memoryManager,
 | 
				
			||||||
 | 
					                            source.Info.FormatInfo,
 | 
				
			||||||
 | 
					                            dstGpuVa,
 | 
				
			||||||
 | 
					                            xCount,
 | 
				
			||||||
 | 
					                            yCount,
 | 
				
			||||||
 | 
					                            dstStride,
 | 
				
			||||||
 | 
					                            dstLinear,
 | 
				
			||||||
 | 
					                            dst.MemoryLayout.UnpackGobBlocksInY(),
 | 
				
			||||||
 | 
					                            dst.MemoryLayout.UnpackGobBlocksInZ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (source.ScaleFactor != target.ScaleFactor)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            target.PropagateScale(source);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        source.HostTexture.CopyTo(target.HostTexture, 0, 0);
 | 
				
			||||||
 | 
					                        target.SignalModified();
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Try to set the texture data directly,
 | 
					                // Try to set the texture data directly,
 | 
				
			||||||
                // but only if we are doing a complete copy,
 | 
					                // but only if we are doing a complete copy,
 | 
				
			||||||
                // and not for block linear to linear copies, since those are typically accessed from the CPU.
 | 
					                // and not for block linear to linear copies, since those are typically accessed from the CPU.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -347,6 +347,53 @@ namespace Ryujinx.Graphics.Gpu.Image
 | 
				
			|||||||
            return texture;
 | 
					            return texture;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tries to find an existing texture, or create a new one if not found.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
 | 
				
			||||||
 | 
					        /// <param name="formatInfo">Format of the texture</param>
 | 
				
			||||||
 | 
					        /// <param name="gpuAddress">GPU virtual address of the texture</param>
 | 
				
			||||||
 | 
					        /// <param name="xCount">Texture width in bytes</param>
 | 
				
			||||||
 | 
					        /// <param name="yCount">Texture height</param>
 | 
				
			||||||
 | 
					        /// <param name="stride">Texture stride if linear, otherwise ignored</param>
 | 
				
			||||||
 | 
					        /// <param name="isLinear">Indicates if the texture is linear or block linear</param>
 | 
				
			||||||
 | 
					        /// <param name="gobBlocksInY">GOB blocks in Y for block linear textures</param>
 | 
				
			||||||
 | 
					        /// <param name="gobBlocksInZ">GOB blocks in Z for 3D block linear textures</param>
 | 
				
			||||||
 | 
					        /// <returns>The texture</returns>
 | 
				
			||||||
 | 
					        public Texture FindOrCreateTexture(
 | 
				
			||||||
 | 
					            MemoryManager memoryManager,
 | 
				
			||||||
 | 
					            FormatInfo formatInfo,
 | 
				
			||||||
 | 
					            ulong gpuAddress,
 | 
				
			||||||
 | 
					            int xCount,
 | 
				
			||||||
 | 
					            int yCount,
 | 
				
			||||||
 | 
					            int stride,
 | 
				
			||||||
 | 
					            bool isLinear,
 | 
				
			||||||
 | 
					            int gobBlocksInY,
 | 
				
			||||||
 | 
					            int gobBlocksInZ)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            TextureInfo info = new(
 | 
				
			||||||
 | 
					                gpuAddress,
 | 
				
			||||||
 | 
					                xCount / formatInfo.BytesPerPixel,
 | 
				
			||||||
 | 
					                yCount,
 | 
				
			||||||
 | 
					                1,
 | 
				
			||||||
 | 
					                1,
 | 
				
			||||||
 | 
					                1,
 | 
				
			||||||
 | 
					                1,
 | 
				
			||||||
 | 
					                stride,
 | 
				
			||||||
 | 
					                isLinear,
 | 
				
			||||||
 | 
					                gobBlocksInY,
 | 
				
			||||||
 | 
					                gobBlocksInZ,
 | 
				
			||||||
 | 
					                1,
 | 
				
			||||||
 | 
					                Target.Texture2D,
 | 
				
			||||||
 | 
					                formatInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.ForCopy, info, 0, sizeHint: new Size(xCount, yCount, 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            texture?.SynchronizeMemory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return texture;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Tries to find an existing texture, or create a new one if not found.
 | 
					        /// Tries to find an existing texture, or create a new one if not found.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user