Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
216
src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs
Normal file
216
src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs
Normal file
|
@ -0,0 +1,216 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Binary data serializer.
|
||||
/// </summary>
|
||||
struct BinarySerializer
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
private Stream _activeStream;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new binary serializer.
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream to read from or write into</param>
|
||||
public BinarySerializer(Stream stream)
|
||||
{
|
||||
_stream = stream;
|
||||
_activeStream = stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from the stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="data">Data read</param>
|
||||
public void Read<T>(ref T data) where T : unmanaged
|
||||
{
|
||||
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
||||
for (int offset = 0; offset < buffer.Length;)
|
||||
{
|
||||
offset += _activeStream.Read(buffer.Slice(offset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to read data from the stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="data">Data read</param>
|
||||
/// <returns>True if the read was successful, false otherwise</returns>
|
||||
public bool TryRead<T>(ref T data) where T : unmanaged
|
||||
{
|
||||
// Length is unknown on compressed streams.
|
||||
if (_activeStream == _stream)
|
||||
{
|
||||
int size = Unsafe.SizeOf<T>();
|
||||
if (_activeStream.Length - _activeStream.Position < size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Read(ref data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data prefixed with a magic and size from the stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="data">Data read</param>
|
||||
/// <param name="magic">Expected magic value, for validation</param>
|
||||
public void ReadWithMagicAndSize<T>(ref T data, uint magic) where T : unmanaged
|
||||
{
|
||||
uint actualMagic = 0;
|
||||
int size = 0;
|
||||
Read(ref actualMagic);
|
||||
Read(ref size);
|
||||
|
||||
if (actualMagic != magic)
|
||||
{
|
||||
throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedInvalidMagic);
|
||||
}
|
||||
|
||||
// Structs are expected to expand but not shrink between versions.
|
||||
if (size > Unsafe.SizeOf<T>())
|
||||
{
|
||||
throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedInvalidLength);
|
||||
}
|
||||
|
||||
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1)).Slice(0, size);
|
||||
for (int offset = 0; offset < buffer.Length;)
|
||||
{
|
||||
offset += _activeStream.Read(buffer.Slice(offset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data into the stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="data">Data to be written</param>
|
||||
public void Write<T>(ref T data) where T : unmanaged
|
||||
{
|
||||
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
||||
_activeStream.Write(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data prefixed with a magic and size into the stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="data">Data to write</param>
|
||||
/// <param name="magic">Magic value to write</param>
|
||||
public void WriteWithMagicAndSize<T>(ref T data, uint magic) where T : unmanaged
|
||||
{
|
||||
int size = Unsafe.SizeOf<T>();
|
||||
Write(ref magic);
|
||||
Write(ref size);
|
||||
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
||||
_activeStream.Write(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that all data that will be read from the stream has been compressed.
|
||||
/// </summary>
|
||||
public void BeginCompression()
|
||||
{
|
||||
CompressionAlgorithm algorithm = CompressionAlgorithm.None;
|
||||
Read(ref algorithm);
|
||||
|
||||
if (algorithm == CompressionAlgorithm.Deflate)
|
||||
{
|
||||
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that all data that will be written into the stream should be compressed.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">Compression algorithm that should be used</param>
|
||||
public void BeginCompression(CompressionAlgorithm algorithm)
|
||||
{
|
||||
Write(ref algorithm);
|
||||
|
||||
if (algorithm == CompressionAlgorithm.Deflate)
|
||||
{
|
||||
_activeStream = new DeflateStream(_stream, CompressionLevel.SmallestSize, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the end of a compressed chunck.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Any data written after this will not be compressed unless <see cref="BeginCompression(CompressionAlgorithm)"/> is called again.
|
||||
/// Any data read after this will be assumed to be uncompressed unless <see cref="BeginCompression"/> is called again.
|
||||
/// </remarks>
|
||||
public void EndCompression()
|
||||
{
|
||||
if (_activeStream != _stream)
|
||||
{
|
||||
_activeStream.Dispose();
|
||||
_activeStream = _stream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads compressed data from the stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <paramref name="data"/> must have the exact length of the uncompressed data,
|
||||
/// otherwise decompression will fail.
|
||||
/// </remarks>
|
||||
/// <param name="stream">Stream to read from</param>
|
||||
/// <param name="data">Buffer to write the uncompressed data into</param>
|
||||
public static void ReadCompressed(Stream stream, Span<byte> data)
|
||||
{
|
||||
CompressionAlgorithm algorithm = (CompressionAlgorithm)stream.ReadByte();
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case CompressionAlgorithm.None:
|
||||
stream.Read(data);
|
||||
break;
|
||||
case CompressionAlgorithm.Deflate:
|
||||
stream = new DeflateStream(stream, CompressionMode.Decompress, true);
|
||||
for (int offset = 0; offset < data.Length;)
|
||||
{
|
||||
offset += stream.Read(data.Slice(offset));
|
||||
}
|
||||
stream.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compresses and writes the compressed data into the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream to write into</param>
|
||||
/// <param name="data">Data to compress</param>
|
||||
/// <param name="algorithm">Compression algorithm to be used</param>
|
||||
public static void WriteCompressed(Stream stream, ReadOnlySpan<byte> data, CompressionAlgorithm algorithm)
|
||||
{
|
||||
stream.WriteByte((byte)algorithm);
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case CompressionAlgorithm.None:
|
||||
stream.Write(data);
|
||||
break;
|
||||
case CompressionAlgorithm.Deflate:
|
||||
stream = new DeflateStream(stream, CompressionLevel.SmallestSize, true);
|
||||
stream.Write(data);
|
||||
stream.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue