コード例 #1
0
ファイル: TextureCache.cs プロジェクト: neozumm/Ryujinx
        /// <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);
        }
コード例 #2
0
        /// <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);
        }