示例#1
0
        private static unsafe void Save(string fileName)
        {
            int translatedFuncsCount;

            int headerSize = Unsafe.SizeOf <Header>();

            Header header = new Header()
            {
                Magic = _headerMagic,

                CacheFileVersion = InternalVersion,
                Endianness       = GetEndianness(),
                FeatureInfo      = GetFeatureInfo(),
                OSPlatform       = GetOSPlatform(),

                InfosLength        = (int)_infosStream.Length,
                CodesLength        = _codesList.Length(),
                RelocsLength       = (int)_relocsStream.Length,
                UnwindInfosLength  = (int)_unwindInfosStream.Length,
                PtcJumpTableLength = PtcJumpTable.GetSerializeSize(PtcJumpTable)
            };

            long size = (long)headerSize + header.InfosLength + header.CodesLength + header.RelocsLength + header.UnwindInfosLength + header.PtcJumpTableLength;

            Span <byte> sizeBytes = new byte[sizeof(long)];

            BinaryPrimitives.WriteInt64LittleEndian(sizeBytes, size);
            Hash128 sizeHash = XXHash128.ComputeHash(sizeBytes);

            Span <byte> sizeHashBytes = new byte[Unsafe.SizeOf <Hash128>()];

            MemoryMarshal.Write <Hash128>(sizeHashBytes, ref sizeHash);

            IntPtr intPtr = IntPtr.Zero;

            try
            {
                intPtr = Marshal.AllocHGlobal(new IntPtr(size));

                using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite))
                {
                    stream.Seek((long)headerSize, SeekOrigin.Begin);

                    ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, header.InfosLength);
                    _infosStream.WriteTo(stream);

                    ReadOnlySpan <byte> codesBytes = (int)header.CodesLength > 0 ? new(stream.PositionPointer, (int)header.CodesLength) : ReadOnlySpan <byte> .Empty;
                    _codesList.WriteTo(stream);

                    ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, header.RelocsLength);
                    _relocsStream.WriteTo(stream);

                    ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, header.UnwindInfosLength);
                    _unwindInfosStream.WriteTo(stream);

                    ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, header.PtcJumpTableLength);
                    PtcJumpTable.Serialize(stream, PtcJumpTable);

                    header.InfosHash        = XXHash128.ComputeHash(infosBytes);
                    header.CodesHash        = XXHash128.ComputeHash(codesBytes);
                    header.RelocsHash       = XXHash128.ComputeHash(relocsBytes);
                    header.UnwindInfosHash  = XXHash128.ComputeHash(unwindInfosBytes);
                    header.PtcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes);

                    Debug.Assert(stream.Position == stream.Length);

                    stream.Seek(0L, SeekOrigin.Begin);
                    SerializeStructure(stream, header);

                    translatedFuncsCount = GetEntriesCount();

                    ResetCarriersIfNeeded();
                    PtcJumpTable.ClearIfNeeded();

                    using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
                        using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
                        {
                            try
                            {
                                compressedStream.Write(sizeHashBytes);
                                compressedStream.Write(sizeBytes);

                                stream.Seek(0L, SeekOrigin.Begin);
                                stream.CopyTo(deflateStream);
                            }
                            catch
                            {
                                compressedStream.Position = 0L;
                            }

                            if (compressedStream.Position < compressedStream.Length)
                            {
                                compressedStream.SetLength(compressedStream.Position);
                            }
                        }
                }
            }
            finally
            {
                if (intPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(intPtr);
                }
            }

            long fileSize = new FileInfo(fileName).Length;

            if (fileSize != 0L)
            {
                Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount}).");
            }
        }
示例#2
0
 /// <summary>
 /// Compute a guest hash from shader entries.
 /// </summary>
 /// <param name="cachedShaderEntries">The guest shader entries to use</param>
 /// <param name="tfd">The optional transform feedback descriptors</param>
 /// <returns>A guest hash from shader entries</returns>
 public static Hash128 ComputeGuestHashFromCache(ReadOnlySpan <GuestShaderCacheEntry> cachedShaderEntries, TransformFeedbackDescriptor[] tfd = null)
 {
     return(XXHash128.ComputeHash(ComputeGuestProgramCode(cachedShaderEntries, tfd, true)));
 }
示例#3
0
            public void SetHeaderHash()
            {
                Span <OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);

                HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf <OuterHeader>() - Unsafe.SizeOf <Hash128>()));
            }
示例#4
0
        private static unsafe bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
                {
                    Hash128 currentSizeHash = DeserializeStructure <Hash128>(compressedStream);

                    Span <byte> sizeBytes = new byte[sizeof(long)];
                    compressedStream.Read(sizeBytes);
                    Hash128 expectedSizeHash = XXHash128.ComputeHash(sizeBytes);

                    if (currentSizeHash != expectedSizeHash)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    long size = BinaryPrimitives.ReadInt64LittleEndian(sizeBytes);

                    IntPtr intPtr = IntPtr.Zero;

                    try
                    {
                        intPtr = Marshal.AllocHGlobal(new IntPtr(size));

                        using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite))
                        {
                            try
                            {
                                deflateStream.CopyTo(stream);
                            }
                            catch
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            Debug.Assert(stream.Position == stream.Length);

                            stream.Seek(0L, SeekOrigin.Begin);

                            Header header = DeserializeStructure <Header>(stream);

                            if (header.Magic != _headerMagic)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.CacheFileVersion != InternalVersion)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.Endianness != GetEndianness())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.FeatureInfo != GetFeatureInfo())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.OSPlatform != GetOSPlatform())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, header.InfosLength);
                            stream.Seek(header.InfosLength, SeekOrigin.Current);

                            Hash128 infosHash = XXHash128.ComputeHash(infosBytes);

                            if (header.InfosHash != infosHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> codesBytes = (int)header.CodesLength > 0 ? new(stream.PositionPointer, (int)header.CodesLength) : ReadOnlySpan <byte> .Empty;
                            stream.Seek(header.CodesLength, SeekOrigin.Current);

                            Hash128 codesHash = XXHash128.ComputeHash(codesBytes);

                            if (header.CodesHash != codesHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, header.RelocsLength);
                            stream.Seek(header.RelocsLength, SeekOrigin.Current);

                            Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes);

                            if (header.RelocsHash != relocsHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, header.UnwindInfosLength);
                            stream.Seek(header.UnwindInfosLength, SeekOrigin.Current);

                            Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);

                            if (header.UnwindInfosHash != unwindInfosHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, header.PtcJumpTableLength);
                            stream.Seek(header.PtcJumpTableLength, SeekOrigin.Current);

                            Hash128 ptcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes);

                            if (header.PtcJumpTableHash != ptcJumpTableHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            Debug.Assert(stream.Position == stream.Length);

                            stream.Seek((long)Unsafe.SizeOf <Header>(), SeekOrigin.Begin);

                            _infosStream.Write(infosBytes);
                            stream.Seek(header.InfosLength, SeekOrigin.Current);

                            _codesList.ReadFrom(stream);

                            _relocsStream.Write(relocsBytes);
                            stream.Seek(header.RelocsLength, SeekOrigin.Current);

                            _unwindInfosStream.Write(unwindInfosBytes);
                            stream.Seek(header.UnwindInfosLength, SeekOrigin.Current);

                            PtcJumpTable = PtcJumpTable.Deserialize(stream);

                            Debug.Assert(stream.Position == stream.Length);
                        }
                    }
                    finally
                    {
                        if (intPtr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(intPtr);
                        }
                    }
                }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()}).");

            return(true);
        }
示例#5
0
 /// <summary>
 /// Computes the hash of some data using the current cache hashing algorithm.
 /// </summary>
 /// <param name="data">Some data to generate a hash for.</param>
 /// <returns>The hash of some data using the current hashing algorithm of the cache</returns>
 public Hash128 ComputeHash(ReadOnlySpan <byte> data)
 {
     return(XXHash128.ComputeHash(data));
 }
示例#6
0
            public bool IsHeaderValid()
            {
                Span <InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);

                return(XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf <InnerHeader>() - Unsafe.SizeOf <Hash128>())) == HeaderHash);
            }
示例#7
0
        private static unsafe void Save(string fileName)
        {
            int translatedFuncsCount;

            int hashSize = Unsafe.SizeOf <Hash128>();

            int size = hashSize + Header.Size + GetMemoryStreamsLength() + PtcJumpTable.GetSerializeSize(PtcJumpTable);

            Span <byte> sizeBytes = new byte[sizeof(int)];

            BinaryPrimitives.WriteInt32LittleEndian(sizeBytes, size);
            Hash128 sizeHash = XXHash128.ComputeHash(sizeBytes);

            Span <byte> sizeHashBytes = new byte[hashSize];

            MemoryMarshal.Write <Hash128>(sizeHashBytes, ref sizeHash);

            IntPtr intPtr = IntPtr.Zero;

            try
            {
                intPtr = Marshal.AllocHGlobal(size);

                using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite))
                {
                    stream.Seek((long)hashSize, SeekOrigin.Begin);

                    WriteHeader(stream);

                    _infosStream.WriteTo(stream);
                    _codesStream.WriteTo(stream);
                    _relocsStream.WriteTo(stream);
                    _unwindInfosStream.WriteTo(stream);

                    PtcJumpTable.Serialize(stream, PtcJumpTable);

                    stream.Seek((long)hashSize, SeekOrigin.Begin);
                    ReadOnlySpan <byte> streamBytes = new(stream.PositionPointer, (int)(stream.Length - stream.Position));
                    Hash128             hash        = XXHash128.ComputeHash(streamBytes);

                    stream.Seek(0L, SeekOrigin.Begin);
                    SerializeStructure(stream, hash);

                    translatedFuncsCount = GetInfosEntriesCount();

                    ResetMemoryStreamsIfNeeded();
                    PtcJumpTable.ClearIfNeeded();

                    using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
                        using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
                        {
                            try
                            {
                                compressedStream.Write(sizeHashBytes);
                                compressedStream.Write(sizeBytes);

                                stream.Seek(0L, SeekOrigin.Begin);
                                stream.CopyTo(deflateStream);
                            }
                            catch
                            {
                                compressedStream.Position = 0L;
                            }

                            if (compressedStream.Position < compressedStream.Length)
                            {
                                compressedStream.SetLength(compressedStream.Position);
                            }
                        }
                }
            }
            finally
            {
                if (intPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(intPtr);
                }
            }

            long fileSize = new FileInfo(fileName).Length;

            if (fileSize != 0L)
            {
                Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount}).");
            }
        }
示例#8
0
        private static void Save(string fileName)
        {
            int profiledFuncsCount;

            OuterHeader outerHeader = new OuterHeader();

            outerHeader.Magic = _outerHeaderMagic;

            outerHeader.InfoFileVersion = InternalVersion;
            outerHeader.Endianness      = Ptc.GetEndianness();

            outerHeader.SetHeaderHash();

            using (MemoryStream stream = new MemoryStream())
            {
                Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);

                stream.Seek((long)Unsafe.SizeOf <Hash128>(), SeekOrigin.Begin);

                lock (_lock)
                {
                    Serialize(stream, ProfiledFuncs);

                    profiledFuncsCount = ProfiledFuncs.Count;
                }

                Debug.Assert(stream.Position == stream.Length);

                stream.Seek((long)Unsafe.SizeOf <Hash128>(), SeekOrigin.Begin);
                Hash128 hash = XXHash128.ComputeHash(GetReadOnlySpan(stream));

                stream.Seek(0L, SeekOrigin.Begin);
                SerializeStructure(stream, hash);

                if (hash == _lastHash)
                {
                    return;
                }

                using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
                    using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
                    {
                        try
                        {
                            SerializeStructure(compressedStream, outerHeader);

                            stream.WriteTo(deflateStream);

                            _lastHash = hash;
                        }
                        catch
                        {
                            compressedStream.Position = 0L;

                            _lastHash = default;
                        }

                        if (compressedStream.Position < compressedStream.Length)
                        {
                            compressedStream.SetLength(compressedStream.Position);
                        }
                    }
            }

            long fileSize = new FileInfo(fileName).Length;

            if (fileSize != 0L)
            {
                Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount}).");
            }
        }
示例#9
0
        private static bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
                {
                    OuterHeader outerHeader = DeserializeStructure <OuterHeader>(compressedStream);

                    if (!outerHeader.IsHeaderValid())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.Magic != _outerHeaderMagic)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.InfoFileVersion != InternalVersion)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.Endianness != Ptc.GetEndianness())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    using (MemoryStream stream = new MemoryStream())
                    {
                        Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);

                        try
                        {
                            deflateStream.CopyTo(stream);
                        }
                        catch
                        {
                            InvalidateCompressedStream(compressedStream);

                            return(false);
                        }

                        Debug.Assert(stream.Position == stream.Length);

                        stream.Seek(0L, SeekOrigin.Begin);

                        Hash128 expectedHash = DeserializeStructure <Hash128>(stream);

                        Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream));

                        if (actualHash != expectedHash)
                        {
                            InvalidateCompressedStream(compressedStream);

                            return(false);
                        }

                        ProfiledFuncs = Deserialize(stream);

                        Debug.Assert(stream.Position == stream.Length);

                        _lastHash = actualHash;
                    }
                }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count}).");

            return(true);
        }
示例#10
0
文件: Ptc.cs 项目: yunnypuff/Ryujinx
 internal static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)
 {
     return(XXHash128.ComputeHash(memory.GetSpan(address, checked ((int)(guestSize)))));
 }
示例#11
0
文件: Ptc.cs 项目: yunnypuff/Ryujinx
        private static unsafe void Save(string fileName)
        {
            int translatedFuncsCount;

            InnerHeader innerHeader = new InnerHeader();

            innerHeader.Magic = _innerHeaderMagic;

            innerHeader.InfosLength        = (int)_infosStream.Length;
            innerHeader.CodesLength        = _codesList.Length();
            innerHeader.RelocsLength       = (int)_relocsStream.Length;
            innerHeader.UnwindInfosLength  = (int)_unwindInfosStream.Length;
            innerHeader.PtcJumpTableLength = PtcJumpTable.GetSerializeSize(PtcJumpTable);

            OuterHeader outerHeader = new OuterHeader();

            outerHeader.Magic = _outerHeaderMagic;

            outerHeader.CacheFileVersion  = InternalVersion;
            outerHeader.Endianness        = GetEndianness();
            outerHeader.FeatureInfo       = GetFeatureInfo();
            outerHeader.MemoryManagerMode = GetMemoryManagerMode();
            outerHeader.OSPlatform        = GetOSPlatform();

            outerHeader.UncompressedStreamSize =
                (long)Unsafe.SizeOf <InnerHeader>() +
                innerHeader.InfosLength +
                innerHeader.CodesLength +
                innerHeader.RelocsLength +
                innerHeader.UnwindInfosLength +
                innerHeader.PtcJumpTableLength;

            outerHeader.SetHeaderHash();

            IntPtr intPtr = IntPtr.Zero;

            try
            {
                intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));

                using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite))
                {
                    stream.Seek((long)Unsafe.SizeOf <InnerHeader>(), SeekOrigin.Begin);

                    ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
                    _infosStream.WriteTo(stream);

                    ReadOnlySpan <byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan <byte> .Empty;
                    _codesList.WriteTo(stream);

                    ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
                    _relocsStream.WriteTo(stream);

                    ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
                    _unwindInfosStream.WriteTo(stream);

                    ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, innerHeader.PtcJumpTableLength);
                    PtcJumpTable.Serialize(stream, PtcJumpTable);

                    Debug.Assert(stream.Position == stream.Length);

                    innerHeader.InfosHash        = XXHash128.ComputeHash(infosBytes);
                    innerHeader.CodesHash        = XXHash128.ComputeHash(codesBytes);
                    innerHeader.RelocsHash       = XXHash128.ComputeHash(relocsBytes);
                    innerHeader.UnwindInfosHash  = XXHash128.ComputeHash(unwindInfosBytes);
                    innerHeader.PtcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes);

                    innerHeader.SetHeaderHash();

                    stream.Seek(0L, SeekOrigin.Begin);
                    SerializeStructure(stream, innerHeader);

                    translatedFuncsCount = GetEntriesCount();

                    ResetCarriersIfNeeded();
                    PtcJumpTable.ClearIfNeeded();

                    using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
                        using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
                        {
                            try
                            {
                                SerializeStructure(compressedStream, outerHeader);

                                stream.Seek(0L, SeekOrigin.Begin);
                                stream.CopyTo(deflateStream);
                            }
                            catch
                            {
                                compressedStream.Position = 0L;
                            }

                            if (compressedStream.Position < compressedStream.Length)
                            {
                                compressedStream.SetLength(compressedStream.Position);
                            }
                        }
                }
            }
            finally
            {
                if (intPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(intPtr);
                }
            }

            long fileSize = new FileInfo(fileName).Length;

            if (fileSize != 0L)
            {
                Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount}).");
            }
        }