Compare commits

...

3 Commits

Author SHA1 Message Date
Berkan Diler
0d3b82477e Use new ArgumentNullException and ObjectDisposedException throw-helper API (#4163) 2022-12-27 20:27:11 +01:00
riperiperi
470be03c2f GPU: Add fallback when 16-bit formats are not supported (#4108)
* Add conversion for 16 bit RGBA formats (not supported in Rosetta)

* Rebase fix

Rebase fix

* Forgot to remove this

* Fix RGBA16 format conversion

* Add RGBA4 -> RGBA8 conversion

* Handle host stride alignment

* Address Feedback Part 1

* Can't count

* Don't zero out rgb when alpha is 0

* Separate RGBA4 and 5-bit component formats

Not sure of a better way to name them...

* Add A1B5G5R5 conversion

* Put this in the right place.

* Make format naming consistent for capabilities

* Change method names
2022-12-26 15:50:27 -03:00
Hunter
c963b3c804 Added Generic Math to BitUtils (#3929)
* Generic Math Update

Updated Several functions in Ryujinx.Common/Utilities/BitUtils to use generic math

* Updated BitUtil calls

* Removed Whitespace

* Switched decrement

* Fixed changed method calls.

The method calls were originally changed on accident due to me relying too much on intellisense doing stuff for me

* Update Ryujinx.Common/Utilities/BitUtils.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-12-26 14:11:05 +00:00
41 changed files with 416 additions and 339 deletions

View File

@@ -80,10 +80,7 @@ namespace ARMeilleure.Common
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_pages) lock (_pages)
{ {
@@ -100,10 +97,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception> /// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
public AddressTable(Level[] levels) public AddressTable(Level[] levels)
{ {
if (levels == null) ArgumentNullException.ThrowIfNull(levels);
{
throw new ArgumentNullException(nameof(levels));
}
if (levels.Length < 2) if (levels.Length < 2)
{ {
@@ -141,10 +135,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception> /// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
public ref TEntry GetValue(ulong address) public ref TEntry GetValue(ulong address)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
if (!IsValid(address)) if (!IsValid(address))
{ {

View File

@@ -49,10 +49,7 @@ namespace ARMeilleure.Common
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return ref _countTable.GetValue(_index); return ref _countTable.GetValue(_index);
} }

View File

@@ -53,10 +53,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public int Allocate() public int Allocate()
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {
@@ -83,10 +80,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public void Free(int index) public void Free(int index)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {
@@ -108,10 +102,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception> /// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception>
public ref TEntry GetValue(int index) public ref TEntry GetValue(int index)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {

View File

@@ -48,10 +48,7 @@ namespace ARMeilleure.IntermediateRepresentation
public void AddSuccessor(BasicBlock block) public void AddSuccessor(BasicBlock block)
{ {
if (block == null) ArgumentNullException.ThrowIfNull(block);
{
ThrowNull(nameof(block));
}
if ((uint)_succCount + 1 > MaxSuccessors) if ((uint)_succCount + 1 > MaxSuccessors)
{ {
@@ -100,10 +97,7 @@ namespace ARMeilleure.IntermediateRepresentation
public void SetSuccessor(int index, BasicBlock block) public void SetSuccessor(int index, BasicBlock block)
{ {
if (block == null) ArgumentNullException.ThrowIfNull(block);
{
ThrowNull(nameof(block));
}
if ((uint)index >= (uint)_succCount) if ((uint)index >= (uint)_succCount)
{ {
@@ -144,7 +138,6 @@ namespace ARMeilleure.IntermediateRepresentation
} }
} }
private static void ThrowNull(string name) => throw new ArgumentNullException(name);
private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors."); private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors.");

View File

@@ -25,10 +25,7 @@ namespace ARMeilleure.Translation
public static Delegate GetDelegate(MethodInfo info) public static Delegate GetDelegate(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray(); Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
Type returnType = info.ReturnType; Type returnType = info.ReturnType;

View File

@@ -35,10 +35,7 @@ namespace ARMeilleure.Translation
public static IntPtr GetDelegateFuncPtr(MethodInfo info) public static IntPtr GetDelegateFuncPtr(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
string key = GetKey(info); string key = GetKey(info);
@@ -52,10 +49,7 @@ namespace ARMeilleure.Translation
public static int GetDelegateIndex(MethodInfo info) public static int GetDelegateIndex(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
string key = GetKey(info); string key = GetKey(info);

View File

@@ -67,10 +67,7 @@ namespace ARMeilleure.Translation
/// <returns>True if the value was added, false if the start key was already in the dictionary</returns> /// <returns>True if the value was added, false if the start key was already in the dictionary</returns>
public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback) public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback)
{ {
if (value == null) ArgumentNullException.ThrowIfNull(value);
{
throw new ArgumentNullException(nameof(value));
}
return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node); return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node);
} }
@@ -85,10 +82,7 @@ namespace ARMeilleure.Translation
/// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns> /// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns>
public V GetOrAdd(K start, K end, V value) public V GetOrAdd(K start, K end, V value)
{ {
if (value == null) ArgumentNullException.ThrowIfNull(value);
{
throw new ArgumentNullException(nameof(value));
}
BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node); BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node);
return node.Value; return node.Value;
@@ -152,10 +146,7 @@ namespace ARMeilleure.Translation
/// <returns>Node reference in the tree</returns> /// <returns>Node reference in the tree</returns>
private IntervalTreeNode<K, V> GetNode(K key) private IntervalTreeNode<K, V> GetNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
IntervalTreeNode<K, V> node = _root; IntervalTreeNode<K, V> node = _root;
while (node != null) while (node != null)

View File

@@ -30,10 +30,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _dispatchStub.Value; return _dispatchStub.Value;
} }
@@ -47,10 +44,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _slowDispatchStub.Value; return _slowDispatchStub.Value;
} }
@@ -64,10 +58,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _dispatchLoop.Value; return _dispatchLoop.Value;
} }
@@ -81,7 +72,9 @@ namespace ARMeilleure.Translation
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(Translator translator) public TranslatorStubs(Translator translator)
{ {
_translator = translator ?? throw new ArgumentNullException(nameof(translator)); ArgumentNullException.ThrowIfNull(translator);
_translator = translator;
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true); _dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true); _dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
} }

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Common
if (size != 0) if (size != 0)
{ {
ulong alignedOffset = BitUtils.AlignUp(Offset, align); ulong alignedOffset = BitUtils.AlignUp<ulong>(Offset, (ulong)align);
if (alignedOffset + size <= (ulong)BackingMemory.Length) if (alignedOffset + size <= (ulong)BackingMemory.Length)
{ {
@@ -55,7 +55,7 @@ namespace Ryujinx.Audio.Renderer.Common
public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged
{ {
return BitUtils.AlignUp(currentSize, align) + (ulong)Unsafe.SizeOf<T>() * count; return BitUtils.AlignUp<ulong>(currentSize, (ulong)align) + (ulong)Unsafe.SizeOf<T>() * count;
} }
} }
} }

View File

@@ -167,7 +167,7 @@ namespace Ryujinx.Audio.Renderer.Server
return ResultCode.WorkBufferTooSmall; return ResultCode.WorkBufferTooSmall;
} }
_depopBuffer = workBufferAllocator.Allocate<float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); _depopBuffer = workBufferAllocator.Allocate<float>(BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
if (_depopBuffer.IsEmpty) if (_depopBuffer.IsEmpty)
{ {
@@ -772,7 +772,7 @@ namespace Ryujinx.Audio.Renderer.Server
size = WorkBufferAllocator.GetTargetSize<float>(size, Constants.TargetSampleCount * (Constants.VoiceChannelCountMax + parameter.MixBufferCount) * (parameter.SinkCount + parameter.SubMixBufferCount), 0x10); size = WorkBufferAllocator.GetTargetSize<float>(size, Constants.TargetSampleCount * (Constants.VoiceChannelCountMax + parameter.MixBufferCount) * (parameter.SinkCount + parameter.SubMixBufferCount), 0x10);
// Depop buffer // Depop buffer
size = WorkBufferAllocator.GetTargetSize<float>(size, (ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); size = WorkBufferAllocator.GetTargetSize<float>(size, BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
// Voice // Voice
size = WorkBufferAllocator.GetTargetSize<VoiceState>(size, parameter.VoiceCount, VoiceState.Alignment); size = WorkBufferAllocator.GetTargetSize<VoiceState>(size, parameter.VoiceCount, VoiceState.Alignment);
@@ -804,10 +804,10 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
ulong performanceMetricsPerFramesSize = PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter, ref behaviourContext) * (parameter.PerformanceMetricFramesCount + 1) + 0xC; ulong performanceMetricsPerFramesSize = PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter, ref behaviourContext) * (parameter.PerformanceMetricFramesCount + 1) + 0xC;
size += BitUtils.AlignUp(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment); size += BitUtils.AlignUp<ulong>(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment);
} }
return BitUtils.AlignUp(size, Constants.WorkBufferAlignment); return BitUtils.AlignUp<ulong>(size, Constants.WorkBufferAlignment);
} }
public ResultCode QuerySystemEvent(out IWritableEvent systemEvent) public ResultCode QuerySystemEvent(out IWritableEvent systemEvent)

View File

@@ -24,10 +24,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public int Get(K key, ref V[] overlaps) public int Get(K key, ref V[] overlaps)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
IntervalTreeNode<K, V> node = GetNode(key); IntervalTreeNode<K, V> node = GetNode(key);
@@ -61,15 +58,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception>
public int Get(K start, K end, ref V[] overlaps, int overlapCount = 0) public int Get(K start, K end, ref V[] overlaps, int overlapCount = 0)
{ {
if (start == null) ArgumentNullException.ThrowIfNull(start);
{ ArgumentNullException.ThrowIfNull(end);
throw new ArgumentNullException(nameof(start));
}
if (end == null)
{
throw new ArgumentNullException(nameof(end));
}
GetValues(Root, start, end, ref overlaps, ref overlapCount); GetValues(Root, start, end, ref overlaps, ref overlapCount);
@@ -85,20 +75,9 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception> /// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception>
public void Add(K start, K end, V value) public void Add(K start, K end, V value)
{ {
if (start == null) ArgumentNullException.ThrowIfNull(start);
{ ArgumentNullException.ThrowIfNull(end);
throw new ArgumentNullException(nameof(start)); ArgumentNullException.ThrowIfNull(value);
}
if (end == null)
{
throw new ArgumentNullException(nameof(end));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Insert(start, end, value); Insert(start, end, value);
} }
@@ -112,10 +91,7 @@ namespace Ryujinx.Common.Collections
/// <returns>Number of deleted values</returns> /// <returns>Number of deleted values</returns>
public int Remove(K key, V value) public int Remove(K key, V value)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
int removed = Delete(key, value); int removed = Delete(key, value);
@@ -168,10 +144,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private IntervalTreeNode<K, V> GetNode(K key) private IntervalTreeNode<K, V> GetNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
IntervalTreeNode<K, V> node = Root; IntervalTreeNode<K, V> node = Root;
while (node != null) while (node != null)
@@ -462,10 +435,8 @@ namespace Ryujinx.Common.Collections
public bool ContainsKey(K key) public bool ContainsKey(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
return GetNode(key) != null; return GetNode(key) != null;
} }
} }

View File

@@ -17,10 +17,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
public void Add(T node) public void Add(T node)
{ {
if (node == null) ArgumentNullException.ThrowIfNull(node);
{
throw new ArgumentNullException(nameof(node));
}
Insert(node); Insert(node);
} }
@@ -32,10 +29,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
public void Remove(T node) public void Remove(T node)
{ {
if (node == null) ArgumentNullException.ThrowIfNull(node);
{
throw new ArgumentNullException(nameof(node));
}
if (Delete(node) != null) if (Delete(node) != null)
{ {
Count--; Count--;
@@ -50,10 +45,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="searchNode"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="searchNode"/> is null</exception>
public T GetNode(T searchNode) public T GetNode(T searchNode)
{ {
if (searchNode == null) ArgumentNullException.ThrowIfNull(searchNode);
{
throw new ArgumentNullException(nameof(searchNode));
}
T node = Root; T node = Root;
while (node != null) while (node != null)

View File

@@ -92,10 +92,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
protected static T Minimum(T node) protected static T Minimum(T node)
{ {
if (node == null) ArgumentNullException.ThrowIfNull(node);
{
throw new ArgumentNullException(nameof(node));
}
T tmp = node; T tmp = node;
while (tmp.Left != null) while (tmp.Left != null)
{ {

View File

@@ -22,10 +22,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public V Get(K key) public V Get(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
Node<K, V> node = GetNode(key); Node<K, V> node = GetNode(key);
@@ -47,14 +44,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception>
public void Add(K key, V value) public void Add(K key, V value)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{ ArgumentNullException.ThrowIfNull(value);
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Insert(key, value); Insert(key, value);
} }
@@ -66,10 +57,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public void Remove(K key) public void Remove(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
if (Delete(key) != null) if (Delete(key) != null)
{ {
Count--; Count--;
@@ -217,10 +206,7 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> GetNode(K key) private Node<K, V> GetNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
Node<K, V> node = Root; Node<K, V> node = Root;
while (node != null) while (node != null)
@@ -370,10 +356,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> FloorNode(K key) private Node<K, V> FloorNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
Node<K, V> tmp = Root; Node<K, V> tmp = Root;
while (tmp != null) while (tmp != null)
@@ -424,10 +408,8 @@ namespace Ryujinx.Common.Collections
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> CeilingNode(K key) private Node<K, V> CeilingNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
Node<K, V> tmp = Root; Node<K, V> tmp = Root;
while (tmp != null) while (tmp != null)
@@ -477,10 +459,8 @@ namespace Ryujinx.Common.Collections
// Method descriptions are not provided as they are already included as part of the interface. // Method descriptions are not provided as they are already included as part of the interface.
public bool ContainsKey(K key) public bool ContainsKey(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
return GetNode(key) != null; return GetNode(key) != null;
} }
@@ -493,10 +473,8 @@ namespace Ryujinx.Common.Collections
public bool TryGetValue(K key, [MaybeNullWhen(false)] out V value) public bool TryGetValue(K key, [MaybeNullWhen(false)] out V value)
{ {
if (null == key) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
Node<K, V> node = GetNode(key); Node<K, V> node = GetNode(key);
value = node != null ? node.Value : default; value = node != null ? node.Value : default;
return node != null; return node != null;
@@ -504,10 +482,7 @@ namespace Ryujinx.Common.Collections
public void Add(KeyValuePair<K, V> item) public void Add(KeyValuePair<K, V> item)
{ {
if (item.Key == null) ArgumentNullException.ThrowIfNull(item.Key);
{
throw new ArgumentNullException(nameof(item.Key));
}
Add(item.Key, item.Value); Add(item.Key, item.Value);
} }

View File

@@ -1,82 +1,26 @@
using System;
using System.Numerics; using System.Numerics;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {
public static class BitUtils public static class BitUtils
{ {
public static uint AlignUp(uint value, int size) public static T AlignUp<T>(T value, T size)
where T : IBinaryInteger<T>
{ {
return (uint)AlignUp((int)value, size); return (value + (size - T.One)) & -size;
} }
public static int AlignUp(int value, int size) public static T AlignDown<T>(T value, T size)
{ where T : IBinaryInteger<T>
return (value + (size - 1)) & -size;
}
public static ulong AlignUp(ulong value, int size)
{
return (ulong)AlignUp((long)value, size);
}
public static long AlignUp(long value, int size)
{
return AlignUp(value, (long)size);
}
public static ulong AlignUp(ulong value, ulong size)
{
return (ulong)AlignUp((long)value, (long)size);
}
public static long AlignUp(long value, long size)
{
return (value + (size - 1)) & -size;
}
public static uint AlignDown(uint value, int size)
{
return (uint)AlignDown((int)value, size);
}
public static int AlignDown(int value, int size)
{ {
return value & -size; return value & -size;
} }
public static ulong AlignDown(ulong value, int size) public static T DivRoundUp<T>(T value, T dividend)
where T : IBinaryInteger<T>
{ {
return (ulong)AlignDown((long)value, size); return (value + (dividend - T.One)) / dividend;
}
public static long AlignDown(long value, int size)
{
return AlignDown(value, (long)size);
}
public static ulong AlignDown(ulong value, ulong size)
{
return (ulong)AlignDown((long)value, (long)size);
}
public static long AlignDown(long value, long size)
{
return value & -size;
}
public static int DivRoundUp(int value, int dividend)
{
return (value + dividend - 1) / dividend;
}
public static ulong DivRoundUp(ulong value, uint dividend)
{
return (value + dividend - 1) / dividend;
}
public static long DivRoundUp(long value, int dividend)
{
return (value + dividend - 1) / dividend;
} }
public static int Pow2RoundUp(int value) public static int Pow2RoundUp(int value)

View File

@@ -18,7 +18,9 @@ namespace Ryujinx.Graphics.GAL
public readonly bool Supports3DTextureCompression; public readonly bool Supports3DTextureCompression;
public readonly bool SupportsBgraFormat; public readonly bool SupportsBgraFormat;
public readonly bool SupportsR4G4Format; public readonly bool SupportsR4G4Format;
public readonly bool SupportsR4G4B4A4Format;
public readonly bool SupportsSnormBufferTextureFormat; public readonly bool SupportsSnormBufferTextureFormat;
public readonly bool Supports5BitComponentFormat;
public readonly bool SupportsFragmentShaderInterlock; public readonly bool SupportsFragmentShaderInterlock;
public readonly bool SupportsFragmentShaderOrderingIntel; public readonly bool SupportsFragmentShaderOrderingIntel;
public readonly bool SupportsGeometryShaderPassthrough; public readonly bool SupportsGeometryShaderPassthrough;
@@ -55,7 +57,9 @@ namespace Ryujinx.Graphics.GAL
bool supports3DTextureCompression, bool supports3DTextureCompression,
bool supportsBgraFormat, bool supportsBgraFormat,
bool supportsR4G4Format, bool supportsR4G4Format,
bool supportsR4G4B4A4Format,
bool supportsSnormBufferTextureFormat, bool supportsSnormBufferTextureFormat,
bool supports5BitComponentFormat,
bool supportsFragmentShaderInterlock, bool supportsFragmentShaderInterlock,
bool supportsFragmentShaderOrderingIntel, bool supportsFragmentShaderOrderingIntel,
bool supportsGeometryShaderPassthrough, bool supportsGeometryShaderPassthrough,
@@ -89,7 +93,9 @@ namespace Ryujinx.Graphics.GAL
Supports3DTextureCompression = supports3DTextureCompression; Supports3DTextureCompression = supports3DTextureCompression;
SupportsBgraFormat = supportsBgraFormat; SupportsBgraFormat = supportsBgraFormat;
SupportsR4G4Format = supportsR4G4Format; SupportsR4G4Format = supportsR4G4Format;
SupportsR4G4B4A4Format = supportsR4G4B4A4Format;
SupportsSnormBufferTextureFormat = supportsSnormBufferTextureFormat; SupportsSnormBufferTextureFormat = supportsSnormBufferTextureFormat;
Supports5BitComponentFormat = supports5BitComponentFormat;
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock; SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel; SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough; SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;

View File

@@ -448,6 +448,27 @@ namespace Ryujinx.Graphics.GAL
return false; return false;
} }
/// <summary>
/// Checks if the texture format is 16 bit packed.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is 16 bit packed, false otherwise</returns>
public static bool Is16BitPacked(this Format format)
{
switch (format)
{
case Format.B5G6R5Unorm:
case Format.B5G5R5A1Unorm:
case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm:
case Format.R5G6B5Unorm:
case Format.R4G4B4A4Unorm:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is an ASTC format. /// Checks if the texture format is an ASTC format.
/// </summary> /// </summary>

View File

@@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
_isLinear = (argument & 1) != 0; _isLinear = (argument & 1) != 0;
_offset = 0; _offset = 0;
_size = (int)(BitUtils.AlignUp(state.LineLengthIn, 4) * state.LineCount); _size = (int)(BitUtils.AlignUp<uint>(state.LineLengthIn, 4) * state.LineCount);
int count = _size / 4; int count = _size / 4;

View File

@@ -911,7 +911,40 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm) else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm)
{ {
result = PixelConverter.ConvertR4G4ToR4G4B4A4(result); result = PixelConverter.ConvertR4G4ToR4G4B4A4(result, width);
if (!_context.Capabilities.SupportsR4G4B4A4Format)
{
result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width);
}
}
else if (Format == Format.R4G4B4A4Unorm)
{
if (!_context.Capabilities.SupportsR4G4B4A4Format)
{
result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width);
}
}
else if (!_context.Capabilities.Supports5BitComponentFormat && Format.Is16BitPacked())
{
switch (Format)
{
case Format.B5G6R5Unorm:
case Format.R5G6B5Unorm:
result = PixelConverter.ConvertR5G6B5ToR8G8B8A8(result, width);
break;
case Format.B5G5R5A1Unorm:
case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm:
result = PixelConverter.ConvertR5G5B5ToR8G8B8A8(result, width, Format == Format.R5G5B5X1Unorm);
break;
case Format.A1B5G5R5Unorm:
result = PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result, width);
break;
case Format.R4G4B4A4Unorm:
result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width);
break;
}
} }
return result; return result;

View File

@@ -131,9 +131,28 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
if (!caps.SupportsR4G4Format && info.FormatInfo.Format == Format.R4G4Unorm) if (!caps.SupportsR4G4Format && info.FormatInfo.Format == Format.R4G4Unorm)
{
if (caps.SupportsR4G4B4A4Format)
{ {
return new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4); return new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4);
} }
else
{
return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
}
}
if (info.FormatInfo.Format == Format.R4G4B4A4Unorm)
{
if (!caps.SupportsR4G4B4A4Format)
{
return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
}
}
else if (!caps.Supports5BitComponentFormat && info.FormatInfo.Format.Is16BitPacked())
{
return new FormatInfo(info.FormatInfo.Format.IsBgr() ? Format.B8G8R8A8Unorm : Format.R8G8B8A8Unorm, 1, 1, 4, 4);
}
return info.FormatInfo; return info.FormatInfo;
} }

View File

@@ -252,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
RecordStorageAlignment(_cpStorageBuffers, index, gpuVa); RecordStorageAlignment(_cpStorageBuffers, index, gpuVa);
gpuVa = BitUtils.AlignDown(gpuVa, _context.Capabilities.StorageBufferOffsetAlignment); gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
@@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
RecordStorageAlignment(buffers, index, gpuVa); RecordStorageAlignment(buffers, index, gpuVa);
gpuVa = BitUtils.AlignDown(gpuVa, _context.Capabilities.StorageBufferOffsetAlignment); gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);

View File

@@ -114,7 +114,9 @@ namespace Ryujinx.Graphics.OpenGL
supports3DTextureCompression: false, supports3DTextureCompression: false,
supportsBgraFormat: false, supportsBgraFormat: false,
supportsR4G4Format: false, supportsR4G4Format: false,
supportsR4G4B4A4Format: true,
supportsSnormBufferTextureFormat: false, supportsSnormBufferTextureFormat: false,
supports5BitComponentFormat: true,
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock, supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering, supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough, supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Texture
{ {
public static class LayoutConverter public static class LayoutConverter
{ {
private const int HostStrideAlignment = 4; public const int HostStrideAlignment = 4;
public static void ConvertBlockLinearToLinear( public static void ConvertBlockLinearToLinear(
Span<byte> dst, Span<byte> dst,

View File

@@ -1,3 +1,4 @@
using Ryujinx.Common;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@@ -7,9 +8,27 @@ namespace Ryujinx.Graphics.Texture
{ {
public static class PixelConverter public static class PixelConverter
{ {
public unsafe static byte[] ConvertR4G4ToR4G4B4A4(ReadOnlySpan<byte> data) private static (int remainder, int outRemainder, int height) GetLineRemainders(int length, int width, int bpp, int outBpp)
{
int stride = BitUtils.AlignUp(width * bpp, LayoutConverter.HostStrideAlignment);
int remainder = stride / bpp - width;
int outStride = BitUtils.AlignUp(width * outBpp, LayoutConverter.HostStrideAlignment);
int outRemainder = outStride / outBpp - width;
return (remainder, outRemainder, length / stride);
}
public unsafe static byte[] ConvertR4G4ToR4G4B4A4(ReadOnlySpan<byte> data, int width)
{ {
byte[] output = new byte[data.Length * 2]; byte[] output = new byte[data.Length * 2];
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 1, 2);
Span<ushort> outputSpan = MemoryMarshal.Cast<byte, ushort>(output);
if (remainder == 0)
{
int start = 0; int start = 0;
if (Sse41.IsSupported) if (Sse41.IsSupported)
@@ -26,12 +45,170 @@ namespace Ryujinx.Graphics.Texture
} }
} }
Span<ushort> outputSpan = MemoryMarshal.Cast<byte, ushort>(output);
for (int i = start; i < data.Length; i++) for (int i = start; i < data.Length; i++)
{ {
outputSpan[i] = (ushort)data[i]; outputSpan[i] = (ushort)data[i];
} }
}
else
{
int offset = 0;
int outOffset = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
outputSpan[outOffset++] = data[offset++];
}
offset += remainder;
outOffset += outRemainder;
}
}
return output;
}
public unsafe static byte[] ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{
byte[] output = new byte[data.Length * 2];
int offset = 0;
int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
uint packed = inputSpan[offset++];
uint outputPacked = 0xff000000;
outputPacked |= (packed << 3) & 0x000000f8;
outputPacked |= (packed << 8) & 0x00f80000;
// Replicate 5 bit components.
outputPacked |= (outputPacked >> 5) & 0x00070007;
// Include and replicate 6 bit component.
outputPacked |= ((packed << 5) & 0x0000fc00) | ((packed >> 1) & 0x00000300);
outputSpan[outOffset++] = outputPacked;
}
offset += remainder;
outOffset += outRemainder;
}
return output;
}
public unsafe static byte[] ConvertR5G5B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width, bool forceAlpha)
{
byte[] output = new byte[data.Length * 2];
int offset = 0;
int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
uint packed = inputSpan[offset++];
uint a = forceAlpha ? 1 : (packed >> 15);
uint outputPacked = a * 0xff000000;
outputPacked |= (packed << 3) & 0x000000f8;
outputPacked |= (packed << 6) & 0x0000f800;
outputPacked |= (packed << 9) & 0x00f80000;
// Replicate 5 bit components.
outputPacked |= (outputPacked >> 5) & 0x00070707;
outputSpan[outOffset++] = outputPacked;
}
offset += remainder;
outOffset += outRemainder;
}
return output;
}
public unsafe static byte[] ConvertA1B5G5R5ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{
byte[] output = new byte[data.Length * 2];
int offset = 0;
int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
uint packed = inputSpan[offset++];
uint a = packed >> 15;
uint outputPacked = a * 0xff000000;
outputPacked |= (packed >> 8) & 0x000000f8;
outputPacked |= (packed << 5) & 0x0000f800;
outputPacked |= (packed << 18) & 0x00f80000;
// Replicate 5 bit components.
outputPacked |= (outputPacked >> 5) & 0x00070707;
outputSpan[outOffset++] = outputPacked;
}
offset += remainder;
outOffset += outRemainder;
}
return output;
}
public unsafe static byte[] ConvertR4G4B4A4ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{
byte[] output = new byte[data.Length * 2];
int offset = 0;
int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
uint packed = inputSpan[offset++];
uint outputPacked = packed & 0x0000000f;
outputPacked |= (packed << 4) & 0x00000f00;
outputPacked |= (packed << 8) & 0x000f0000;
outputPacked |= (packed << 12) & 0x0f000000;
outputSpan[outOffset++] = outputPacked * 0x11;
}
offset += remainder;
outOffset += outRemainder;
}
return output; return output;
} }

View File

@@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
var range = _freeRanges[i]; var range = _freeRanges[i];
ulong alignedOffset = BitUtils.AlignUp(range.Offset, (int)alignment); ulong alignedOffset = BitUtils.AlignUp<ulong>(range.Offset, alignment);
ulong sizeDelta = alignedOffset - range.Offset; ulong sizeDelta = alignedOffset - range.Offset;
ulong usableSize = range.Size - sizeDelta; ulong usableSize = range.Size - sizeDelta;
@@ -196,7 +196,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
ulong blockAlignedSize = BitUtils.AlignUp(size, _blockAlignment); ulong blockAlignedSize = BitUtils.AlignUp<ulong>(size, (ulong)_blockAlignment);
var memoryAllocateInfo = new MemoryAllocateInfo() var memoryAllocateInfo = new MemoryAllocateInfo()
{ {

View File

@@ -396,6 +396,17 @@ namespace Ryujinx.Graphics.Vulkan
GAL.Format.Etc2RgbSrgb, GAL.Format.Etc2RgbSrgb,
GAL.Format.Etc2RgbUnorm); GAL.Format.Etc2RgbUnorm);
bool supports5BitComponentFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
GAL.Format.R5G6B5Unorm,
GAL.Format.R5G5B5A1Unorm,
GAL.Format.R5G5B5X1Unorm,
GAL.Format.B5G6R5Unorm,
GAL.Format.B5G5R5A1Unorm,
GAL.Format.A1B5G5R5Unorm);
bool supportsR4G4B4A4Format = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
GAL.Format.R4G4B4A4Unorm);
PhysicalDeviceVulkan12Features featuresVk12 = new PhysicalDeviceVulkan12Features() PhysicalDeviceVulkan12Features featuresVk12 = new PhysicalDeviceVulkan12Features()
{ {
SType = StructureType.PhysicalDeviceVulkan12Features SType = StructureType.PhysicalDeviceVulkan12Features
@@ -425,7 +436,9 @@ namespace Ryujinx.Graphics.Vulkan
supports3DTextureCompression: true, supports3DTextureCompression: true,
supportsBgraFormat: true, supportsBgraFormat: true,
supportsR4G4Format: false, supportsR4G4Format: false,
supportsR4G4B4A4Format: supportsR4G4B4A4Format,
supportsSnormBufferTextureFormat: true, supportsSnormBufferTextureFormat: true,
supports5BitComponentFormat: supports5BitComponentFormat,
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock, supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
supportsFragmentShaderOrderingIntel: false, supportsFragmentShaderOrderingIntel: false,
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough, supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,

View File

@@ -81,8 +81,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
attributeMask |= MemoryAttribute.DeviceMapped; attributeMask |= MemoryAttribute.DeviceMapped;
} }
ulong clientAddrTruncated = BitUtils.AlignDown(desc.ClientAddress, KPageTableBase.PageSize); ulong clientAddrTruncated = BitUtils.AlignDown<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
ulong clientAddrRounded = BitUtils.AlignUp (desc.ClientAddress, KPageTableBase.PageSize); ulong clientAddrRounded = BitUtils.AlignUp<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
// Check if address is not aligned, in this case we need to perform 2 copies. // Check if address is not aligned, in this case we need to perform 2 copies.
if (clientAddrTruncated != clientAddrRounded) if (clientAddrTruncated != clientAddrRounded)
@@ -113,9 +113,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
ulong clientEndAddr = desc.ClientAddress + desc.Size; ulong clientEndAddr = desc.ClientAddress + desc.Size;
ulong serverEndAddr = desc.ServerAddress + desc.Size; ulong serverEndAddr = desc.ServerAddress + desc.Size;
ulong clientEndAddrTruncated = BitUtils.AlignDown(clientEndAddr, KPageTableBase.PageSize); ulong clientEndAddrTruncated = BitUtils.AlignDown<ulong>(clientEndAddr, (ulong)KPageTableBase.PageSize);
ulong clientEndAddrRounded = BitUtils.AlignUp (clientEndAddr, KPageTableBase.PageSize); ulong clientEndAddrRounded = BitUtils.AlignUp<ulong>(clientEndAddr, KPageTableBase.PageSize);
ulong serverEndAddrTruncated = BitUtils.AlignDown(serverEndAddr, KPageTableBase.PageSize); ulong serverEndAddrTruncated = BitUtils.AlignDown<ulong>(serverEndAddr, (ulong)KPageTableBase.PageSize);
if (clientEndAddrTruncated < clientEndAddrRounded && if (clientEndAddrTruncated < clientEndAddrRounded &&
(clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated)) (clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated))

View File

@@ -1005,7 +1005,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
recvListEndAddr = recvListBaseAddr + size; recvListEndAddr = recvListBaseAddr + size;
} }
recvListBufferAddress = BitUtils.AlignUp(recvListBaseAddr + dstOffset, 0x10); recvListBufferAddress = BitUtils.AlignUp<ulong>(recvListBaseAddr + dstOffset, 0x10);
ulong endAddress = recvListBufferAddress + descriptor.BufferSize; ulong endAddress = recvListBufferAddress + descriptor.BufferSize;

View File

@@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KernelResult Map(ulong address, ulong size, KMemoryPermission perm) public KernelResult Map(ulong address, ulong size, KMemoryPermission perm)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
@@ -73,7 +73,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KernelResult MapToOwner(ulong address, ulong size, KMemoryPermission permission) public KernelResult MapToOwner(ulong address, ulong size, KMemoryPermission permission)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
@@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KernelResult Unmap(ulong address, ulong size) public KernelResult Unmap(ulong address, ulong size)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
@@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KernelResult UnmapFromOwner(ulong address, ulong size) public KernelResult UnmapFromOwner(ulong address, ulong size)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }

View File

@@ -101,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
for (int depth = HighestDepthIndex; depth >= 0; depth--) for (int depth = HighestDepthIndex; depth >= 0; depth--)
{ {
_bitStorages[depth] = storage; _bitStorages[depth] = storage;
size = BitUtils.DivRoundUp(size, UInt64BitSize); size = BitUtils.DivRoundUp<ulong>(size, (ulong)UInt64BitSize);
storage = storage.Slice((int)size); storage = storage.Slice((int)size);
} }
@@ -288,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
for (int depth = GetRequiredDepth(regionSize) - 1; depth >= 0; depth--) for (int depth = GetRequiredDepth(regionSize) - 1; depth >= 0; depth--)
{ {
regionSize = BitUtils.DivRoundUp(regionSize, UInt64BitSize); regionSize = BitUtils.DivRoundUp<ulong>(regionSize, UInt64BitSize);
overheadBits += (int)regionSize; overheadBits += (int)regionSize;
} }

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
int diff = 1 << (NextShift - Shift); int diff = 1 << (NextShift - Shift);
offset = BitUtils.AlignDown(offset, diff); offset = BitUtils.AlignDown(offset, (ulong)diff);
if (_bitmap.ClearRange(offset, diff)) if (_bitmap.ClearRange(offset, diff))
{ {

View File

@@ -203,8 +203,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
heapRegion.Size = 0x180000000; heapRegion.Size = 0x180000000;
stackRegion.Size = 0x80000000; stackRegion.Size = 0x80000000;
tlsIoRegion.Size = 0x1000000000; tlsIoRegion.Size = 0x1000000000;
CodeRegionStart = BitUtils.AlignDown(address, 0x200000); CodeRegionStart = BitUtils.AlignDown<ulong>(address, 0x200000);
codeRegionSize = BitUtils.AlignUp(endAddr, 0x200000) - CodeRegionStart; codeRegionSize = BitUtils.AlignUp<ulong>(endAddr, 0x200000) - CodeRegionStart;
stackAndTlsIoStart = 0; stackAndTlsIoStart = 0;
stackAndTlsIoEnd = 0; stackAndTlsIoEnd = 0;
baseAddress = 0x8000000; baseAddress = 0x8000000;
@@ -1584,8 +1584,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfResource; return KernelResult.OutOfResource;
} }
ulong srcMapAddress = BitUtils.AlignUp(src, PageSize); ulong srcMapAddress = BitUtils.AlignUp<ulong>(src, PageSize);
ulong srcMapEndAddr = BitUtils.AlignDown(src + size, PageSize); ulong srcMapEndAddr = BitUtils.AlignDown<ulong>(src + size, PageSize);
ulong srcMapSize = srcMapEndAddr - srcMapAddress; ulong srcMapSize = srcMapEndAddr - srcMapAddress;
result = MapPagesFromClientProcess(size, src, permission, state, srcPageTable, send, out ulong va); result = MapPagesFromClientProcess(size, src, permission, state, srcPageTable, send, out ulong va);
@@ -1659,10 +1659,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
attributeMask |= MemoryAttribute.DeviceMapped; attributeMask |= MemoryAttribute.DeviceMapped;
} }
ulong addressRounded = BitUtils.AlignUp(address, PageSize); ulong addressRounded = BitUtils.AlignUp<ulong>(address, PageSize);
ulong addressTruncated = BitUtils.AlignDown(address, PageSize); ulong addressTruncated = BitUtils.AlignDown<ulong>(address, PageSize);
ulong endAddrRounded = BitUtils.AlignUp(endAddr, PageSize); ulong endAddrRounded = BitUtils.AlignUp<ulong>(endAddr, PageSize);
ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize); ulong endAddrTruncated = BitUtils.AlignDown<ulong>(endAddr, PageSize);
if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion)) if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion))
{ {
@@ -1769,10 +1769,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong endAddr = address + size; ulong endAddr = address + size;
ulong addressTruncated = BitUtils.AlignDown(address, PageSize); ulong addressTruncated = BitUtils.AlignDown<ulong>(address, PageSize);
ulong addressRounded = BitUtils.AlignUp(address, PageSize); ulong addressRounded = BitUtils.AlignUp<ulong>(address, PageSize);
ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize); ulong endAddrTruncated = BitUtils.AlignDown<ulong>(endAddr, PageSize);
ulong endAddrRounded = BitUtils.AlignUp(endAddr, PageSize); ulong endAddrRounded = BitUtils.AlignUp<ulong>(endAddr, PageSize);
ulong neededSize = endAddrRounded - addressTruncated; ulong neededSize = endAddrRounded - addressTruncated;
@@ -1983,10 +1983,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfResource; return KernelResult.OutOfResource;
} }
ulong addressTruncated = BitUtils.AlignDown(address, PageSize); ulong addressTruncated = BitUtils.AlignDown<ulong>(address, PageSize);
ulong addressRounded = BitUtils.AlignUp(address, PageSize); ulong addressRounded = BitUtils.AlignUp<ulong>(address, PageSize);
ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize); ulong endAddrTruncated = BitUtils.AlignDown<ulong>(endAddr, PageSize);
ulong endAddrRounded = BitUtils.AlignUp(endAddr, PageSize); ulong endAddrRounded = BitUtils.AlignUp<ulong>(endAddr, PageSize);
ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize; ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize;
@@ -2010,10 +2010,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
ulong endAddr = address + size; ulong endAddr = address + size;
ulong addressRounded = BitUtils.AlignUp(address, PageSize); ulong addressRounded = BitUtils.AlignUp<ulong>(address, PageSize);
ulong addressTruncated = BitUtils.AlignDown(address, PageSize); ulong addressTruncated = BitUtils.AlignDown<ulong>(address, PageSize);
ulong endAddrRounded = BitUtils.AlignUp(endAddr, PageSize); ulong endAddrRounded = BitUtils.AlignUp<ulong>(endAddr, PageSize);
ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize); ulong endAddrTruncated = BitUtils.AlignDown<ulong>(endAddr, PageSize);
ulong pagesCount = addressRounded < endAddrTruncated ? (endAddrTruncated - addressRounded) / PageSize : 0; ulong pagesCount = addressRounded < endAddrTruncated ? (endAddrTruncated - addressRounded) / PageSize : 0;
@@ -2540,7 +2540,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
for (int attempt = 0; attempt < 8; attempt++) for (int attempt = 0; attempt < 8; attempt++)
{ {
ulong aslrAddress = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, alignment); ulong aslrAddress = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, (ulong)alignment);
ulong aslrEndAddr = aslrAddress + totalNeededSize; ulong aslrEndAddr = aslrAddress + totalNeededSize;
KMemoryInfo info = _blockManager.FindBlock(aslrAddress).GetInfo(); KMemoryInfo info = _blockManager.FindBlock(aslrAddress).GetInfo();
@@ -2618,7 +2618,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
currBaseAddr += reservedSize; currBaseAddr += reservedSize;
ulong address = BitUtils.AlignDown(currBaseAddr, alignment) + reservedStart; ulong address = BitUtils.AlignDown<ulong>(currBaseAddr, (ulong)alignment) + reservedStart;
if (currBaseAddr > address) if (currBaseAddr > address)
{ {
@@ -2834,7 +2834,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
lock (_blockManager) lock (_blockManager)
{ {
return BitUtils.DivRoundUp(GetMmUsedSize(), PageSize); return BitUtils.DivRoundUp<ulong>(GetMmUsedSize(), PageSize);
} }
} }

View File

@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KProcess process, KProcess process,
KMemoryPermission permission) KMemoryPermission permission)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
@@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KernelResult UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process) public KernelResult UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }

View File

@@ -67,7 +67,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KProcess process, KProcess process,
KMemoryPermission permission) KMemoryPermission permission)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
@@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong size, ulong size,
KProcess process) KProcess process)
{ {
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
{ {
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }

View File

@@ -472,7 +472,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KernelResult FreeThreadLocalStorage(ulong tlsSlotAddr) public KernelResult FreeThreadLocalStorage(ulong tlsSlotAddr)
{ {
ulong tlsPageAddr = BitUtils.AlignDown(tlsSlotAddr, KPageTableBase.PageSize); ulong tlsPageAddr = BitUtils.AlignDown<ulong>(tlsSlotAddr, KPageTableBase.PageSize);
KernelContext.CriticalSection.Enter(); KernelContext.CriticalSection.Enter();
@@ -554,7 +554,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
throw new InvalidOperationException("Trying to start a process with a invalid state!"); throw new InvalidOperationException("Trying to start a process with a invalid state!");
} }
ulong stackSizeRounded = BitUtils.AlignUp(stackSize, KPageTableBase.PageSize); ulong stackSizeRounded = BitUtils.AlignUp<ulong>(stackSize, KPageTableBase.PageSize);
ulong neededSize = stackSizeRounded + _imageSize; ulong neededSize = stackSizeRounded + _imageSize;

View File

@@ -47,7 +47,7 @@ namespace Ryujinx.HLE.HOS
endOffset = kip.BssOffset + kip.BssSize; endOffset = kip.BssOffset + kip.BssSize;
} }
uint codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KPageTableBase.PageSize); uint codeSize = BitUtils.AlignUp<uint>(kip.TextOffset + endOffset, KPageTableBase.PageSize);
int codePagesCount = (int)(codeSize / KPageTableBase.PageSize); int codePagesCount = (int)(codeSize / KPageTableBase.PageSize);
@@ -195,7 +195,7 @@ namespace Ryujinx.HLE.HOS
nsoSize = dataEnd; nsoSize = dataEnd;
} }
nsoSize = BitUtils.AlignUp(nsoSize, KPageTableBase.PageSize); nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
nsoBase[index] = codeStart + (ulong)codeSize; nsoBase[index] = codeStart + (ulong)codeSize;
@@ -349,7 +349,7 @@ namespace Ryujinx.HLE.HOS
return KernelResult.Success; return KernelResult.Success;
} }
size = BitUtils.AlignUp(size, KPageTableBase.PageSize); size = BitUtils.AlignUp<ulong>(size, KPageTableBase.PageSize);
return process.MemoryManager.SetProcessMemoryPermission(address, size, permission); return process.MemoryManager.SetProcessMemoryPermission(address, size, permission);
} }

View File

@@ -321,7 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
ulong bssStart = dataStart + (ulong)relocatableObject.Data.Length; ulong bssStart = dataStart + (ulong)relocatableObject.Data.Length;
ulong bssEnd = BitUtils.AlignUp(bssStart + (ulong)relocatableObject.BssSize, KPageTableBase.PageSize); ulong bssEnd = BitUtils.AlignUp<ulong>(bssStart + relocatableObject.BssSize, KPageTableBase.PageSize);
process.CpuMemory.Write(textStart, relocatableObject.Text); process.CpuMemory.Write(textStart, relocatableObject.Text);
process.CpuMemory.Write(roStart, relocatableObject.Ro); process.CpuMemory.Write(roStart, relocatableObject.Ro);

View File

@@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
uint headerSize = (uint)Unsafe.SizeOf<ParcelHeader>(); uint headerSize = (uint)Unsafe.SizeOf<ParcelHeader>();
_rawData = new byte[BitUtils.AlignUp(headerSize + payloadSize + objectsSize, 4)]; _rawData = new byte[BitUtils.AlignUp<uint>(headerSize + payloadSize + objectsSize, 4)];
Header.PayloadSize = payloadSize; Header.PayloadSize = payloadSize;
Header.ObjectsSize = objectsSize; Header.ObjectsSize = objectsSize;

View File

@@ -32,20 +32,9 @@ namespace Ryujinx.HLE
public Switch(HLEConfiguration configuration) public Switch(HLEConfiguration configuration)
{ {
if (configuration.GpuRenderer == null) ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
{ ArgumentNullException.ThrowIfNull(configuration.AudioDeviceDriver);
throw new ArgumentNullException(nameof(configuration.GpuRenderer)); ArgumentNullException.ThrowIfNull(configuration.UserChannelPersistence);
}
if (configuration.AudioDeviceDriver == null)
{
throw new ArgumentNullException(nameof(configuration.AudioDeviceDriver));
}
if (configuration.UserChannelPersistence == null)
{
throw new ArgumentNullException(nameof(configuration.UserChannelPersistence));
}
Configuration = configuration; Configuration = configuration;
FileSystem = Configuration.VirtualFileSystem; FileSystem = Configuration.VirtualFileSystem;

View File

@@ -279,10 +279,7 @@ namespace Ryujinx.Memory
{ {
IntPtr ptr = _pointer; IntPtr ptr = _pointer;
if (ptr == IntPtr.Zero) ObjectDisposedException.ThrowIf(ptr == IntPtr.Zero, this);
{
ThrowObjectDisposed();
}
int size = Unsafe.SizeOf<T>(); int size = Unsafe.SizeOf<T>();
@@ -312,10 +309,7 @@ namespace Ryujinx.Memory
{ {
IntPtr ptr = _pointer; IntPtr ptr = _pointer;
if (ptr == IntPtr.Zero) ObjectDisposedException.ThrowIf(ptr == IntPtr.Zero, this);
{
ThrowObjectDisposed();
}
ulong endOffset = offset + size; ulong endOffset = offset + size;
@@ -454,7 +448,6 @@ namespace Ryujinx.Memory
return true; return true;
} }
private static void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock));
private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException(); private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
} }
} }

View File

@@ -411,10 +411,7 @@ namespace Ryujinx.Memory.Tracking
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(GetType().FullName);
}
_disposed = true; _disposed = true;