Move solution and projects to src

This commit is contained in:
TSR Berry 2023-04-08 01:22:00 +02:00 committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View file

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Device
{
public class DeviceState<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TState> : IDeviceState where TState : unmanaged
{
private const int RegisterSize = sizeof(int);
public TState State;
private uint Size => (uint)(Unsafe.SizeOf<TState>() + RegisterSize - 1) / RegisterSize;
private readonly Func<int>[] _readCallbacks;
private readonly Action<int>[] _writeCallbacks;
private readonly Dictionary<uint, string> _fieldNamesForDebug;
private readonly Action<string> _debugLogCallback;
public DeviceState(IReadOnlyDictionary<string, RwCallback> callbacks = null, Action<string> debugLogCallback = null)
{
_readCallbacks = new Func<int>[Size];
_writeCallbacks = new Action<int>[Size];
if (debugLogCallback != null)
{
_fieldNamesForDebug = new Dictionary<uint, string>();
_debugLogCallback = debugLogCallback;
}
var fields = typeof(TState).GetFields();
int offset = 0;
for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
{
var field = fields[fieldIndex];
int sizeOfField = SizeCalculator.SizeOf(field.FieldType);
for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4)
{
int index = (offset + i) / RegisterSize;
if (callbacks != null && callbacks.TryGetValue(field.Name, out var cb))
{
if (cb.Read != null)
{
_readCallbacks[index] = cb.Read;
}
if (cb.Write != null)
{
_writeCallbacks[index] = cb.Write;
}
}
}
if (debugLogCallback != null)
{
_fieldNamesForDebug.Add((uint)offset, field.Name);
}
offset += sizeOfField;
}
Debug.Assert(offset == Unsafe.SizeOf<TState>());
}
public int Read(int offset)
{
uint index = (uint)offset / RegisterSize;
if (index < Size)
{
uint alignedOffset = index * RegisterSize;
var readCallback = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_readCallbacks), (IntPtr)index);
if (readCallback != null)
{
return readCallback();
}
else
{
return GetRefUnchecked<int>(alignedOffset);
}
}
return 0;
}
public void Write(int offset, int data)
{
uint index = (uint)offset / RegisterSize;
if (index < Size)
{
uint alignedOffset = index * RegisterSize;
DebugWrite(alignedOffset, data);
GetRefIntAlignedUncheck(index) = data;
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (IntPtr)index)?.Invoke(data);
}
}
public void WriteWithRedundancyCheck(int offset, int data, out bool changed)
{
uint index = (uint)offset / RegisterSize;
if (index < Size)
{
uint alignedOffset = index * RegisterSize;
DebugWrite(alignedOffset, data);
ref var storage = ref GetRefIntAlignedUncheck(index);
changed = storage != data;
storage = data;
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (IntPtr)index)?.Invoke(data);
}
else
{
changed = false;
}
}
[Conditional("DEBUG")]
private void DebugWrite(uint alignedOffset, int data)
{
if (_fieldNamesForDebug != null && _fieldNamesForDebug.TryGetValue(alignedOffset, out string fieldName))
{
_debugLogCallback($"{typeof(TState).Name}.{fieldName} = 0x{data:X}");
}
}
public ref T GetRef<T>(int offset) where T : unmanaged
{
if ((uint)(offset + Unsafe.SizeOf<T>()) > Unsafe.SizeOf<TState>())
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
return ref GetRefUnchecked<T>((uint)offset);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ref T GetRefUnchecked<T>(uint offset) where T : unmanaged
{
return ref Unsafe.As<TState, T>(ref Unsafe.AddByteOffset(ref State, (IntPtr)offset));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ref int GetRefIntAlignedUncheck(ulong index)
{
return ref Unsafe.Add(ref Unsafe.As<TState, int>(ref State), (IntPtr)index);
}
}
}

View file

@ -0,0 +1,8 @@
namespace Ryujinx.Graphics.Device
{
public interface IDeviceState
{
int Read(int offset);
void Write(int offset, int data);
}
}

View file

@ -0,0 +1,9 @@
namespace Ryujinx.Graphics.Device
{
public interface IDeviceStateWithContext : IDeviceState
{
long CreateContext();
void DestroyContext(long id);
void BindContext(long id);
}
}

View file

@ -0,0 +1,16 @@
using System;
namespace Ryujinx.Graphics.Device
{
public readonly struct RwCallback
{
public Action<int> Write { get; }
public Func<int> Read { get; }
public RwCallback(Action<int> write, Func<int> read)
{
Write = write;
Read = read;
}
}
}

View file

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,63 @@
using System;
using System.Reflection;
namespace Ryujinx.Graphics.Device
{
public static class SizeCalculator
{
public static int SizeOf(Type type)
{
// Is type a enum type?
if (type.IsEnum)
{
type = type.GetEnumUnderlyingType();
}
// Is type a pointer type?
if (type.IsPointer || type == typeof(IntPtr) || type == typeof(UIntPtr))
{
return IntPtr.Size;
}
// Is type a struct type?
if (type.IsValueType && !type.IsPrimitive)
{
// Check if the struct has a explicit size, if so, return that.
if (type.StructLayoutAttribute.Size != 0)
{
return type.StructLayoutAttribute.Size;
}
// Otherwise we calculate the sum of the sizes of all fields.
int size = 0;
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
{
size += SizeOf(fields[fieldIndex].FieldType);
}
return size;
}
// Primitive types.
return (Type.GetTypeCode(type)) switch
{
TypeCode.SByte => sizeof(sbyte),
TypeCode.Byte => sizeof(byte),
TypeCode.Int16 => sizeof(short),
TypeCode.UInt16 => sizeof(ushort),
TypeCode.Int32 => sizeof(int),
TypeCode.UInt32 => sizeof(uint),
TypeCode.Int64 => sizeof(long),
TypeCode.UInt64 => sizeof(ulong),
TypeCode.Char => sizeof(char),
TypeCode.Single => sizeof(float),
TypeCode.Double => sizeof(double),
TypeCode.Decimal => sizeof(decimal),
TypeCode.Boolean => sizeof(bool),
_ => throw new ArgumentException($"Length for type \"{type.Name}\" is unknown.")
};
}
}
}