/// <summary> /// Tries to find an existing texture matching the given buffer copy destination. If none is found, returns null. /// </summary> /// <param name="tex">The texture information</param> /// <param name="cbp">The copy buffer parameters</param> /// <param name="swizzle">The copy buffer swizzle</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(CopyBufferTexture tex, CopyBufferParams cbp, CopyBufferSwizzle swizzle, bool linear) { ulong address = _context.MemoryManager.Translate(cbp.DstAddress.Pack()); if (address == MemoryManager.BadAddress) { return(null); } int bpp = swizzle.UnpackDstComponentsCount() * swizzle.UnpackComponentSize(); 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 == cbp.DstStride && tex.RegionY + cbp.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 = cbp.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) { return(texture); } } return(null); }
/// <summary> /// Determine if a buffer-to-texture region covers the entirety of a texture. /// </summary> /// <param name="cbp">Copy command parameters</param> /// <param name="tex">Texture to compare</param> /// <param name="linear">True if the texture is linear, false if block linear</param> /// <param name="stride">Texture stride</param> /// <returns></returns> private bool IsTextureCopyComplete(CopyBufferParams cbp, CopyBufferTexture tex, bool linear, int stride) { if (linear) { return(tex.RegionX == 0 && tex.RegionY == 0 && stride == BitUtils.AlignUp(cbp.XCount, StrideAlignment)); } else { return(tex.RegionX == 0 && tex.RegionY == 0 && tex.Width == BitUtils.AlignUp(cbp.XCount, GobAlignment) && tex.Height == cbp.YCount); } }
/// <summary> /// Determine if a buffer-to-texture region covers the entirety of a texture. /// </summary> /// <param name="cbp">Copy command parameters</param> /// <param name="tex">Texture to compare</param> /// <param name="linear">True if the texture is linear, false if block linear</param> /// <param name="bpp">Texture bytes per pixel</param> /// <param name="stride">Texture stride</param> /// <returns></returns> private bool IsTextureCopyComplete(CopyBufferParams cbp, CopyBufferTexture tex, bool linear, int bpp, int stride) { if (linear) { int alignWidth = Constants.StrideAlignment / bpp; return(tex.RegionX == 0 && tex.RegionY == 0 && stride / bpp == BitUtils.AlignUp(cbp.XCount, alignWidth)); } else { int alignWidth = Constants.GobAlignment / bpp; return(tex.RegionX == 0 && tex.RegionY == 0 && tex.Width == BitUtils.AlignUp(cbp.XCount, alignWidth) && tex.Height == cbp.YCount); } }