/// <summary> /// Tries to find an existing texture matching the given buffer copy destination. If none is found, returns null. /// </summary> /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> /// <param name="tex">The texture information</param> /// <param name="gpuVa">GPU virtual address of the texture</param> /// <param name="bpp">Bytes per pixel</param> /// <param name="stride">If <paramref name="linear"/> is true, should have the texture stride, otherwise ignored</param> /// <param name="xCount">Number of pixels to be copied per line</param> /// <param name="yCount">Number of lines to be copied</param> /// <param name="linear">True if the texture has a linear layout, false otherwise</param> /// <returns>A matching texture, or null if there is no match</returns> public Texture FindTexture( MemoryManager memoryManager, DmaTexture tex, ulong gpuVa, int bpp, int stride, int xCount, int yCount, bool linear) { ulong address = memoryManager.Translate(gpuVa); if (address == MemoryManager.PteUnmapped) { return(null); } int addressMatches = _textures.FindOverlaps(address, ref _textureOverlaps); for (int i = 0; i < addressMatches; i++) { Texture texture = _textureOverlaps[i]; FormatInfo format = texture.Info.FormatInfo; if (texture.Info.DepthOrLayers > 1) { continue; } bool match; if (linear) { // Size is not available for linear textures. Use the stride and end of the copy region instead. match = texture.Info.IsLinear && texture.Info.Stride == stride && tex.RegionY + yCount <= texture.Info.Height; } else { // Bpp may be a mismatch between the target texture and the param. // Due to the way linear strided and block layouts work, widths can be multiplied by Bpp for comparison. // Note: tex.Width is the aligned texture size. Prefer param.XCount, as the destination should be a texture with that exact size. bool sizeMatch = xCount * bpp == texture.Info.Width * format.BytesPerPixel && tex.Height == texture.Info.Height; bool formatMatch = !texture.Info.IsLinear && texture.Info.GobBlocksInY == tex.MemoryLayout.UnpackGobBlocksInY() && texture.Info.GobBlocksInZ == tex.MemoryLayout.UnpackGobBlocksInZ(); match = sizeMatch && formatMatch; } if (match) { _cache.Lift(texture); return(texture); } } return(null); }
/// <summary> /// Tries to find an existing texture matching the given buffer copy destination. If none is found, returns null. /// </summary> /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> /// <param name="tex">The texture information</param> /// <param name="gpuVa">GPU virtual address of the texture</param> /// <param name="bpp">Bytes per pixel</param> /// <param name="stride">If <paramref name="linear"/> is true, should have the texture stride, otherwise ignored</param> /// <param name="xCount">Number of pixels to be copied per line</param> /// <param name="yCount">Number of lines to be copied</param> /// <param name="linear">True if the texture has a linear layout, false otherwise</param> /// <returns>A matching texture, or null if there is no match</returns> public Texture FindTexture( MemoryManager memoryManager, DmaTexture tex, ulong gpuVa, int bpp, int stride, int xCount, int yCount, bool linear) { ulong address = memoryManager.Translate(gpuVa); if (address == MemoryManager.PteUnmapped) { return(null); } int addressMatches = _textures.FindOverlaps(address, ref _textureOverlaps); Texture textureMatch = null; for (int i = 0; i < addressMatches; i++) { Texture texture = _textureOverlaps[i]; FormatInfo format = texture.Info.FormatInfo; if (texture.Info.DepthOrLayers > 1 || texture.Info.Levels > 1 || texture.Info.FormatInfo.IsCompressed) { // Don't support direct buffer copies to anything that isn't a single 2D image, uncompressed. continue; } bool match; if (linear) { // Size is not available for linear textures. Use the stride and end of the copy region instead. match = texture.Info.IsLinear && texture.Info.Stride == stride && tex.RegionY + yCount <= texture.Info.Height; } else { // Bpp may be a mismatch between the target texture and the param. // Due to the way linear strided and block layouts work, widths can be multiplied by Bpp for comparison. // Note: tex.Width is the aligned texture size. Prefer param.XCount, as the destination should be a texture with that exact size. bool sizeMatch = xCount * bpp == texture.Info.Width * format.BytesPerPixel && tex.Height == texture.Info.Height; bool formatMatch = !texture.Info.IsLinear && texture.Info.GobBlocksInY == tex.MemoryLayout.UnpackGobBlocksInY() && texture.Info.GobBlocksInZ == tex.MemoryLayout.UnpackGobBlocksInZ(); match = sizeMatch && formatMatch; } if (match) { if (textureMatch == null) { textureMatch = texture; } else if (texture.Group != textureMatch.Group) { return(null); // It's ambiguous which texture should match between multiple choices, so leave it up to the slow path. } } } return(textureMatch); }