diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6f690e87c..2f613c8e5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -13,14 +13,14 @@
-
+
-
+
@@ -39,11 +39,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/Ryujinx.sln b/Ryujinx.sln
index b8304164d..76ebd573f 100644
--- a/Ryujinx.sln
+++ b/Ryujinx.sln
@@ -87,6 +87,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -249,6 +251,10 @@ Global
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/ARMeilleure/Decoders/OpCodeTable.cs b/src/ARMeilleure/Decoders/OpCodeTable.cs
index edc004125..859535670 100644
--- a/src/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/src/ARMeilleure/Decoders/OpCodeTable.cs
@@ -822,6 +822,10 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create);
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create);
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
+ SetA32("<<<<01100110xxxxxxxx11110001xxxx", InstName.Uqadd16, InstEmit32.Uqadd16, OpCode32AluReg.Create);
+ SetA32("<<<<01100110xxxxxxxx11111001xxxx", InstName.Uqadd8, InstEmit32.Uqadd8, OpCode32AluReg.Create);
+ SetA32("<<<<01100110xxxxxxxx11110111xxxx", InstName.Uqsub16, InstEmit32.Uqsub16, OpCode32AluReg.Create);
+ SetA32("<<<<01100110xxxxxxxx11111111xxxx", InstName.Uqsub8, InstEmit32.Uqsub8, OpCode32AluReg.Create);
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create);
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create);
SetA32("<<<<01100101xxxxxxxx11111111xxxx", InstName.Usub8, InstEmit32.Usub8, OpCode32AluReg.Create);
@@ -1007,6 +1011,8 @@ namespace ARMeilleure.Decoders
SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
+ SetAsimd("111100110x01xxxxxxxx1011xxx0xxxx", InstName.Vqrdmulh, InstEmit32.Vqrdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
+ SetAsimd("111100110x10xxxxxxxx1011xxx0xxxx", InstName.Vqrdmulh, InstEmit32.Vqrdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
@@ -1030,6 +1036,7 @@ namespace ARMeilleure.Decoders
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
+ SetAsimd("111100111x>>>xxxxxxx0101>xx1xxxx", InstName.Vsli, InstEmit32.Vsli_I, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
@@ -1054,6 +1061,7 @@ namespace ARMeilleure.Decoders
SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<
+ {
+ EmitSaturateUqadd(context, d, context.Add(n, m), 16);
+ }));
+ }
+
+ public static void Uqadd8(ArmEmitterContext context)
+ {
+ OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
+
+ SetIntA32(context, op.Rd, EmitUnsigned8BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
+ {
+ EmitSaturateUqadd(context, d, context.Add(n, m), 8);
+ }));
+ }
+
+ public static void Uqsub16(ArmEmitterContext context)
+ {
+ OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
+
+ SetIntA32(context, op.Rd, EmitUnsigned16BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
+ {
+ EmitSaturateUqsub(context, d, context.Subtract(n, m), 16);
+ }));
+ }
+
+ public static void Uqsub8(ArmEmitterContext context)
+ {
+ OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
+
+ SetIntA32(context, op.Rd, EmitUnsigned8BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
+ {
+ EmitSaturateUqsub(context, d, context.Subtract(n, m), 8);
+ }));
+ }
+
public static void Usat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@@ -934,6 +976,148 @@ namespace ARMeilleure.Instructions
}
}
+ private static void EmitSaturateUqadd(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
+ {
+ Debug.Assert(saturateTo <= 32);
+
+ if (saturateTo == 32)
+ {
+ // No saturation possible for this case.
+
+ context.Copy(result, value);
+
+ return;
+ }
+ else if (saturateTo == 0)
+ {
+ // Result is always zero if we saturate 0 bits.
+
+ context.Copy(result, Const(0));
+
+ return;
+ }
+
+ // If the result is 0, the values are equal and we don't need saturation.
+ Operand lblNoSat = Label();
+ context.BranchIfFalse(lblNoSat, context.ShiftRightUI(value, Const((int)saturateTo)));
+
+ // Saturate.
+ context.Copy(result, Const(uint.MaxValue >> (32 - (int)saturateTo)));
+
+ Operand lblExit = Label();
+ context.Branch(lblExit);
+
+ context.MarkLabel(lblNoSat);
+
+ context.Copy(result, value);
+
+ context.MarkLabel(lblExit);
+ }
+
+ private static void EmitSaturateUqsub(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
+ {
+ Debug.Assert(saturateTo <= 32);
+
+ if (saturateTo == 32)
+ {
+ // No saturation possible for this case.
+
+ context.Copy(result, value);
+
+ return;
+ }
+ else if (saturateTo == 0)
+ {
+ // Result is always zero if we saturate 0 bits.
+
+ context.Copy(result, Const(0));
+
+ return;
+ }
+
+ // If the result is 0, the values are equal and we don't need saturation.
+ Operand lblNoSat = Label();
+ context.BranchIf(lblNoSat, value, Const(0), Comparison.GreaterOrEqual);
+
+ // Saturate.
+ // Assumes that the value can only underflow, since this is only used for unsigned subtraction.
+ context.Copy(result, Const(0));
+
+ Operand lblExit = Label();
+ context.Branch(lblExit);
+
+ context.MarkLabel(lblNoSat);
+
+ context.Copy(result, value);
+
+ context.MarkLabel(lblExit);
+ }
+
+ private static Operand EmitUnsigned16BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action elementAction)
+ {
+ Operand tempD = context.AllocateLocal(OperandType.I32);
+
+ Operand tempN = context.ZeroExtend16(OperandType.I32, rn);
+ Operand tempM = context.ZeroExtend16(OperandType.I32, rm);
+ elementAction(tempD, tempN, tempM);
+ Operand tempD2 = context.ZeroExtend16(OperandType.I32, tempD);
+
+ tempN = context.ShiftRightUI(rn, Const(16));
+ tempM = context.ShiftRightUI(rm, Const(16));
+ elementAction(tempD, tempN, tempM);
+ return context.BitwiseOr(tempD2, context.ShiftLeft(tempD, Const(16)));
+ }
+
+ private static Operand EmitSigned8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action elementAction)
+ {
+ return Emit8BitPair(context, rn, rm, elementAction, unsigned: false);
+ }
+
+ private static Operand EmitUnsigned8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action elementAction)
+ {
+ return Emit8BitPair(context, rn, rm, elementAction, unsigned: true);
+ }
+
+ private static Operand Emit8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action elementAction, bool unsigned)
+ {
+ Operand tempD = context.AllocateLocal(OperandType.I32);
+ Operand result = default;
+
+ for (int b = 0; b < 4; b++)
+ {
+ Operand nByte = b != 0 ? context.ShiftRightUI(rn, Const(b * 8)) : rn;
+ Operand mByte = b != 0 ? context.ShiftRightUI(rm, Const(b * 8)) : rm;
+
+ if (unsigned)
+ {
+ nByte = context.ZeroExtend8(OperandType.I32, nByte);
+ mByte = context.ZeroExtend8(OperandType.I32, mByte);
+ }
+ else
+ {
+ nByte = context.SignExtend8(OperandType.I32, nByte);
+ mByte = context.SignExtend8(OperandType.I32, mByte);
+ }
+
+ elementAction(tempD, nByte, mByte);
+
+ if (b == 0)
+ {
+ result = context.ZeroExtend8(OperandType.I32, tempD);
+ }
+ else if (b < 3)
+ {
+ result = context.BitwiseOr(result, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, tempD), Const(b * 8)));
+ }
+ else
+ {
+ result = context.BitwiseOr(result, context.ShiftLeft(tempD, Const(24)));
+ }
+ }
+
+ return result;
+ }
+
private static void EmitAluStore(ArmEmitterContext context, Operand value)
{
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
diff --git a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs
index dc2646a55..c807fc858 100644
--- a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs
+++ b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs
@@ -1246,6 +1246,33 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signedSrc: true, signedDst: false), signed: true);
}
+ public static void Vqrdmulh(ArmEmitterContext context)
+ {
+ OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
+ int eSize = 8 << op.Size;
+
+ EmitVectorBinaryOpI32(context, (op1, op2) =>
+ {
+ if (op.Size == 2)
+ {
+ op1 = context.SignExtend32(OperandType.I64, op1);
+ op2 = context.SignExtend32(OperandType.I64, op2);
+ }
+
+ Operand res = context.Multiply(op1, op2);
+ res = context.Add(res, Const(res.Type, 1L << (eSize - 2)));
+ res = context.ShiftRightSI(res, Const(eSize - 1));
+ res = EmitSatQ(context, res, eSize, signedSrc: true, signedDst: true);
+
+ if (op.Size == 2)
+ {
+ res = context.ConvertI64ToI32(res);
+ }
+
+ return res;
+ }, signed: true);
+ }
+
public static void Vqsub(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
diff --git a/src/ARMeilleure/Instructions/InstEmitSimdMove32.cs b/src/ARMeilleure/Instructions/InstEmitSimdMove32.cs
index 9fa740997..fb2641f66 100644
--- a/src/ARMeilleure/Instructions/InstEmitSimdMove32.cs
+++ b/src/ARMeilleure/Instructions/InstEmitSimdMove32.cs
@@ -191,6 +191,26 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res);
}
+ public static void Vswp(ArmEmitterContext context)
+ {
+ OpCode32Simd op = (OpCode32Simd)context.CurrOp;
+
+ if (op.Q)
+ {
+ Operand temp = context.Copy(GetVecA32(op.Qd));
+
+ context.Copy(GetVecA32(op.Qd), GetVecA32(op.Qm));
+ context.Copy(GetVecA32(op.Qm), temp);
+ }
+ else
+ {
+ Operand temp = ExtractScalar(context, OperandType.I64, op.Vd);
+
+ InsertScalar(context, op.Vd, ExtractScalar(context, OperandType.I64, op.Vm));
+ InsertScalar(context, op.Vm, temp);
+ }
+ }
+
public static void Vtbl(ArmEmitterContext context)
{
OpCode32SimdTbl op = (OpCode32SimdTbl)context.CurrOp;
diff --git a/src/ARMeilleure/Instructions/InstEmitSimdShift32.cs b/src/ARMeilleure/Instructions/InstEmitSimdShift32.cs
index e40600a47..e9e3b52b9 100644
--- a/src/ARMeilleure/Instructions/InstEmitSimdShift32.cs
+++ b/src/ARMeilleure/Instructions/InstEmitSimdShift32.cs
@@ -130,6 +130,36 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryNarrowOp32(context, (op1) => context.ShiftRightUI(op1, Const(shift)));
}
+ public static void Vsli_I(ArmEmitterContext context)
+ {
+ OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
+ int shift = op.Shift;
+ int eSize = 8 << op.Size;
+
+ ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0UL;
+
+ Operand res = GetVec(op.Qd);
+
+ int elems = op.GetBytesCount() >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ Operand me = EmitVectorExtractZx(context, op.Qm, op.Im + index, op.Size);
+
+ Operand neShifted = context.ShiftLeft(me, Const(shift));
+
+ Operand de = EmitVectorExtractZx(context, op.Qd, op.Id + index, op.Size);
+
+ Operand deMasked = context.BitwiseAnd(de, Const(mask));
+
+ Operand e = context.BitwiseOr(neShifted, deMasked);
+
+ res = EmitVectorInsert(context, res, e, op.Id + index, op.Size);
+ }
+
+ context.Copy(GetVec(op.Qd), res);
+ }
+
public static void Vsra(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
diff --git a/src/ARMeilleure/Instructions/InstName.cs b/src/ARMeilleure/Instructions/InstName.cs
index 457abbf49..ac85412d1 100644
--- a/src/ARMeilleure/Instructions/InstName.cs
+++ b/src/ARMeilleure/Instructions/InstName.cs
@@ -571,6 +571,10 @@ namespace ARMeilleure.Instructions
Umaal,
Umlal,
Umull,
+ Uqadd16,
+ Uqadd8,
+ Uqsub16,
+ Uqsub8,
Usat,
Usat16,
Usub8,
@@ -645,6 +649,7 @@ namespace ARMeilleure.Instructions
Vqdmulh,
Vqmovn,
Vqmovun,
+ Vqrdmulh,
Vqrshrn,
Vqrshrun,
Vqshrn,
@@ -666,6 +671,7 @@ namespace ARMeilleure.Instructions
Vshll,
Vshr,
Vshrn,
+ Vsli,
Vst1,
Vst2,
Vst3,
@@ -682,6 +688,7 @@ namespace ARMeilleure.Instructions
Vsub,
Vsubl,
Vsubw,
+ Vswp,
Vtbl,
Vtrn,
Vtst,
diff --git a/src/ARMeilleure/Translation/TranslatorQueue.cs b/src/ARMeilleure/Translation/TranslatorQueue.cs
index cee2f9080..831522bc1 100644
--- a/src/ARMeilleure/Translation/TranslatorQueue.cs
+++ b/src/ARMeilleure/Translation/TranslatorQueue.cs
@@ -80,7 +80,10 @@ namespace ARMeilleure.Translation
return true;
}
- Monitor.Wait(Sync);
+ if (!_disposed)
+ {
+ Monitor.Wait(Sync);
+ }
}
}
diff --git a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManager.cs b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManager.cs
index 0a035916c..da5a0ad45 100644
--- a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManager.cs
+++ b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManager.cs
@@ -18,16 +18,12 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
if (version == 2)
{
- return (ulong)PerformanceManagerGeneric.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
+ return (ulong)PerformanceManagerGeneric.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
}
if (version == 1)
{
- return (ulong)PerformanceManagerGeneric.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
+ return (ulong)PerformanceManagerGeneric.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
}
throw new NotImplementedException($"Unknown Performance metrics data format version {version}");
diff --git a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
index 5a70a1bcf..2e5d25b9c 100644
--- a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
+++ b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
@@ -234,7 +234,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
{
performanceEntry = null;
- if (_entryDetailIndex > MaxFrameDetailCount)
+ if (_entryDetailIndex >= MaxFrameDetailCount)
{
return false;
}
@@ -245,7 +245,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(),
};
- uint baseEntryOffset = (uint)(Unsafe.SizeOf() + GetEntriesSize() + Unsafe.SizeOf() * _entryDetailIndex);
+ uint baseEntryOffset = (uint)(Unsafe.SizeOf() + GetEntriesSize() + Unsafe.SizeOf() * _entryDetailIndex);
ref TEntryDetail entryDetail = ref EntriesDetail[_entryDetailIndex];
diff --git a/src/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs b/src/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
deleted file mode 100644
index 05fb29ac7..000000000
--- a/src/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Buffers;
-using System.Threading;
-
-namespace Ryujinx.Common.Memory
-{
- public partial class ByteMemoryPool
- {
- ///
- /// Represents a that wraps an array rented from
- /// and exposes it as
- /// with a length of the requested size.
- ///
- private sealed class ByteMemoryPoolBuffer : IMemoryOwner
- {
- private byte[] _array;
- private readonly int _length;
-
- public ByteMemoryPoolBuffer(int length)
- {
- _array = ArrayPool.Shared.Rent(length);
- _length = length;
- }
-
- ///
- /// Returns a belonging to this owner.
- ///
- public Memory Memory
- {
- get
- {
- byte[] array = _array;
-
- ObjectDisposedException.ThrowIf(array is null, this);
-
- return new Memory(array, 0, _length);
- }
- }
-
- public void Dispose()
- {
- var array = Interlocked.Exchange(ref _array, null);
-
- if (array != null)
- {
- ArrayPool.Shared.Return(array);
- }
- }
- }
- }
-}
diff --git a/src/Ryujinx.Common/Memory/ByteMemoryPool.cs b/src/Ryujinx.Common/Memory/ByteMemoryPool.cs
deleted file mode 100644
index 6fd6a98aa..000000000
--- a/src/Ryujinx.Common/Memory/ByteMemoryPool.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using System.Buffers;
-
-namespace Ryujinx.Common.Memory
-{
- ///
- /// Provides a pool of re-usable byte array instances.
- ///
- public static partial class ByteMemoryPool
- {
- ///
- /// Returns the maximum buffer size supported by this pool.
- ///
- public static int MaxBufferSize => Array.MaxLength;
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer may contain data from a prior use.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner Rent(long length)
- => RentImpl(checked((int)length));
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer may contain data from a prior use.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner Rent(ulong length)
- => RentImpl(checked((int)length));
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer may contain data from a prior use.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner Rent(int length)
- => RentImpl(length);
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer's contents are cleared (set to all 0s) before returning.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner RentCleared(long length)
- => RentCleared(checked((int)length));
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer's contents are cleared (set to all 0s) before returning.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner RentCleared(ulong length)
- => RentCleared(checked((int)length));
-
- ///
- /// Rents a byte memory buffer from .
- /// The buffer's contents are cleared (set to all 0s) before returning.
- ///
- /// The buffer's required length in bytes
- /// A wrapping the rented memory
- ///
- public static IMemoryOwner RentCleared(int length)
- {
- var buffer = RentImpl(length);
-
- buffer.Memory.Span.Clear();
-
- return buffer;
- }
-
- ///
- /// Copies into a newly rented byte memory buffer.
- ///
- /// The byte buffer to copy
- /// A wrapping the rented memory with copied to it
- public static IMemoryOwner RentCopy(ReadOnlySpan buffer)
- {
- var copy = RentImpl(buffer.Length);
-
- buffer.CopyTo(copy.Memory.Span);
-
- return copy;
- }
-
- private static ByteMemoryPoolBuffer RentImpl(int length)
- {
- if ((uint)length > Array.MaxLength)
- {
- throw new ArgumentOutOfRangeException(nameof(length), length, null);
- }
-
- return new ByteMemoryPoolBuffer(length);
- }
- }
-}
diff --git a/src/Ryujinx.Common/Utilities/EmbeddedResources.cs b/src/Ryujinx.Common/Utilities/EmbeddedResources.cs
index e22571c96..7530c012a 100644
--- a/src/Ryujinx.Common/Utilities/EmbeddedResources.cs
+++ b/src/Ryujinx.Common/Utilities/EmbeddedResources.cs
@@ -1,6 +1,6 @@
+using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
-using System.Buffers;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -42,14 +42,14 @@ namespace Ryujinx.Common
return StreamUtils.StreamToBytes(stream);
}
- public static IMemoryOwner ReadFileToRentedMemory(string filename)
+ public static MemoryOwner ReadFileToRentedMemory(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return ReadFileToRentedMemory(assembly, path);
}
- public static IMemoryOwner ReadFileToRentedMemory(Assembly assembly, string filename)
+ public static MemoryOwner ReadFileToRentedMemory(Assembly assembly, string filename)
{
using var stream = GetStream(assembly, filename);
diff --git a/src/Ryujinx.Common/Utilities/StreamUtils.cs b/src/Ryujinx.Common/Utilities/StreamUtils.cs
index 74b6af5ec..aeb6e0d52 100644
--- a/src/Ryujinx.Common/Utilities/StreamUtils.cs
+++ b/src/Ryujinx.Common/Utilities/StreamUtils.cs
@@ -1,6 +1,5 @@
using Microsoft.IO;
using Ryujinx.Common.Memory;
-using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -16,7 +15,7 @@ namespace Ryujinx.Common.Utilities
return output.ToArray();
}
- public static IMemoryOwner StreamToRentedMemory(Stream input)
+ public static MemoryOwner StreamToRentedMemory(Stream input)
{
if (input is MemoryStream inputMemoryStream)
{
@@ -26,9 +25,9 @@ namespace Ryujinx.Common.Utilities
{
long bytesExpected = input.Length;
- IMemoryOwner ownedMemory = ByteMemoryPool.Rent(bytesExpected);
+ MemoryOwner ownedMemory = MemoryOwner.Rent(checked((int)bytesExpected));
- var destSpan = ownedMemory.Memory.Span;
+ var destSpan = ownedMemory.Span;
int totalBytesRead = 0;
@@ -66,14 +65,14 @@ namespace Ryujinx.Common.Utilities
return stream.ToArray();
}
- private static IMemoryOwner MemoryStreamToRentedMemory(MemoryStream input)
+ private static MemoryOwner MemoryStreamToRentedMemory(MemoryStream input)
{
input.Position = 0;
- IMemoryOwner ownedMemory = ByteMemoryPool.Rent(input.Length);
+ MemoryOwner ownedMemory = MemoryOwner.Rent(checked((int)input.Length));
// Discard the return value because we assume reading a MemoryStream always succeeds completely.
- _ = input.Read(ownedMemory.Memory.Span);
+ _ = input.Read(ownedMemory.Span);
return ownedMemory;
}
diff --git a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
index 663d0aeb1..501109b86 100644
--- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
+++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
@@ -303,9 +303,9 @@ namespace Ryujinx.Cpu.Jit
}
else
{
- IMemoryOwner memoryOwner = ByteMemoryPool.Rent(size);
+ MemoryOwner memoryOwner = MemoryOwner.Rent(size);
- Read(va, memoryOwner.Memory.Span);
+ Read(va, memoryOwner.Span);
return new WritableRegion(this, va, memoryOwner);
}
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs
index 88850cb33..d57750fc1 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs
@@ -1,6 +1,5 @@
using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
-using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs
index e2354f448..f1b6e395b 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs
@@ -114,7 +114,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
InstEmitCommon.EmitUnsigned16BitPair(context, rd, rn, rm, (d, n, m) =>
{
context.Arm64Assembler.Add(d, n, m);
- EmitSaturateUnsignedRange(context, d, 16);
+ EmitSaturateUqadd(context, d, 16);
});
}
@@ -123,7 +123,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
InstEmitCommon.EmitUnsigned8BitPair(context, rd, rn, rm, (d, n, m) =>
{
context.Arm64Assembler.Add(d, n, m);
- EmitSaturateUnsignedRange(context, d, 8);
+ EmitSaturateUqadd(context, d, 8);
});
}
@@ -140,7 +140,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
context.Arm64Assembler.Add(d, n, m);
}
- EmitSaturateUnsignedRange(context, d, 16);
+ EmitSaturateUq(context, d, 16, e == 0);
});
}
@@ -157,25 +157,25 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
context.Arm64Assembler.Sub(d, n, m);
}
- EmitSaturateUnsignedRange(context, d, 16);
+ EmitSaturateUq(context, d, 16, e != 0);
});
}
public static void Uqsub16(CodeGenContext context, uint rd, uint rn, uint rm)
{
- InstEmitCommon.EmitSigned16BitPair(context, rd, rn, rm, (d, n, m) =>
+ InstEmitCommon.EmitUnsigned16BitPair(context, rd, rn, rm, (d, n, m) =>
{
context.Arm64Assembler.Sub(d, n, m);
- EmitSaturateUnsignedRange(context, d, 16);
+ EmitSaturateUqsub(context, d, 16);
});
}
public static void Uqsub8(CodeGenContext context, uint rd, uint rn, uint rm)
{
- InstEmitCommon.EmitSigned8BitPair(context, rd, rn, rm, (d, n, m) =>
+ InstEmitCommon.EmitUnsigned8BitPair(context, rd, rn, rm, (d, n, m) =>
{
context.Arm64Assembler.Sub(d, n, m);
- EmitSaturateUnsignedRange(context, d, 8);
+ EmitSaturateUqsub(context, d, 8);
});
}
@@ -358,7 +358,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
}
}
- private static void EmitSaturateUnsignedRange(CodeGenContext context, Operand value, uint saturateTo)
+ private static void EmitSaturateUqadd(CodeGenContext context, Operand value, uint saturateTo)
+ {
+ EmitSaturateUq(context, value, saturateTo, isSub: false);
+ }
+
+ private static void EmitSaturateUqsub(CodeGenContext context, Operand value, uint saturateTo)
+ {
+ EmitSaturateUq(context, value, saturateTo, isSub: true);
+ }
+
+ private static void EmitSaturateUq(CodeGenContext context, Operand value, uint saturateTo, bool isSub)
{
Debug.Assert(saturateTo <= 32);
@@ -379,7 +389,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
return;
}
- context.Arm64Assembler.Lsr(tempRegister.Operand, value, InstEmitCommon.Const(32 - (int)saturateTo));
+ context.Arm64Assembler.Lsr(tempRegister.Operand, value, InstEmitCommon.Const((int)saturateTo));
int branchIndex = context.CodeWriter.InstructionPointer;
@@ -387,7 +397,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
context.Arm64Assembler.Cbz(tempRegister.Operand, 0);
// Saturate.
- context.Arm64Assembler.Mov(value, uint.MaxValue >> (32 - (int)saturateTo));
+ context.Arm64Assembler.Mov(value, isSub ? 0u : uint.MaxValue >> (32 - (int)saturateTo));
int delta = context.CodeWriter.InstructionPointer - branchIndex;
context.CodeWriter.WriteInstructionAt(branchIndex, context.CodeWriter.ReadInstructionAt(branchIndex) | (uint)((delta & 0x7ffff) << 5));
diff --git a/src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs b/src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs
index fc075a264..cb1a7c3ab 100644
--- a/src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs
+++ b/src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Memory;
using System;
-using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -145,9 +144,9 @@ namespace Ryujinx.Graphics.Device
}
else
{
- IMemoryOwner memoryOwner = ByteMemoryPool.Rent(size);
+ MemoryOwner memoryOwner = MemoryOwner.Rent(size);
- GetSpan(va, size).CopyTo(memoryOwner.Memory.Span);
+ ReadImpl(va, memoryOwner.Span);
return new WritableRegion(this, va, memoryOwner, tracked: true);
}
diff --git a/src/Ryujinx.Graphics.Device/DeviceState.cs b/src/Ryujinx.Graphics.Device/DeviceState.cs
index de8582a3b..54178a414 100644
--- a/src/Ryujinx.Graphics.Device/DeviceState.cs
+++ b/src/Ryujinx.Graphics.Device/DeviceState.cs
@@ -39,7 +39,10 @@ namespace Ryujinx.Graphics.Device
{
var field = fields[fieldIndex];
- int sizeOfField = SizeCalculator.SizeOf(field.FieldType);
+ var currentFieldOffset = (int)Marshal.OffsetOf(field.Name);
+ var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf() : (int)Marshal.OffsetOf(fields[fieldIndex + 1].Name);
+
+ int sizeOfField = nextFieldOffset - currentFieldOffset;
for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4)
{
diff --git a/src/Ryujinx.Graphics.Device/SizeCalculator.cs b/src/Ryujinx.Graphics.Device/SizeCalculator.cs
deleted file mode 100644
index 54820ec36..000000000
--- a/src/Ryujinx.Graphics.Device/SizeCalculator.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-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."),
- };
- }
- }
-}
diff --git a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs
index 44090291d..79c84db01 100644
--- a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs
+++ b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs
@@ -1,6 +1,5 @@
using Ryujinx.Common;
using System;
-using System.Numerics;
namespace Ryujinx.Graphics.GAL
{
@@ -113,25 +112,6 @@ namespace Ryujinx.Graphics.GAL
return 1;
}
- public int GetLevelsClamped()
- {
- int maxSize = Width;
-
- if (Target != Target.Texture1D &&
- Target != Target.Texture1DArray)
- {
- maxSize = Math.Max(maxSize, Height);
- }
-
- if (Target == Target.Texture3D)
- {
- maxSize = Math.Max(maxSize, Depth);
- }
-
- int maxLevels = BitOperations.Log2((uint)maxSize) + 1;
- return Math.Min(Levels, maxLevels);
- }
-
private static int GetLevelSize(int size, int level)
{
return Math.Max(1, size >> level);
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs
index 93e43ce3c..78099f74a 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs
@@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
if (target != null)
{
target.SynchronizeMemory();
- var dataCopy = ByteMemoryPool.RentCopy(data);
+ var dataCopy = MemoryOwner.RentCopy(data);
target.SetData(dataCopy, 0, 0, new GAL.Rectangle(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount));
target.SignalModified();
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
index e54855a8f..effcb7bbb 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
@@ -79,7 +79,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
var field = fields[fieldIndex];
- int sizeOfField = SizeCalculator.SizeOf(field.FieldType);
+ var currentFieldOffset = (int)Marshal.OffsetOf(field.Name);
+ var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf() : (int)Marshal.OffsetOf(fields[fieldIndex + 1].Name);
+
+ int sizeOfField = nextFieldOffset - currentFieldOffset;
if (fieldToDelegate.TryGetValue(field.Name, out int entryIndex))
{
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
index dd55e7d1d..35051c6e0 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
@@ -415,7 +415,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
#pragma warning disable CS0649 // Field is never assigned to
public int Width;
public int Height;
- public int Depth;
+ public ushort Depth;
+ public ushort Flags;
+
+ public readonly bool UnpackIsLayered()
+ {
+ return (Flags & 1) == 0;
+ }
#pragma warning restore CS0649
}
diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
index dde28dbd7..3b6c407cc 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -1,4 +1,5 @@
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
@@ -805,7 +806,7 @@ namespace Ryujinx.Graphics.Gpu.Image
sliceDepth,
levels,
layers,
- out IMemoryOwner decoded))
+ out MemoryOwner decoded))
{
string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}";
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
index 01e34c777..8b9243b1e 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
@@ -340,7 +340,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// True if any used entries of the pool might have been modified, false otherwise
public bool SamplerPoolModified()
{
- return SamplerPool.WasModified(ref _samplerPoolSequence);
+ return SamplerPool != null && SamplerPool.WasModified(ref _samplerPoolSequence);
}
}
@@ -516,12 +516,15 @@ namespace Ryujinx.Graphics.Gpu.Image
}
// Check if any of our cached samplers changed on the pool.
- foreach ((int samplerId, (Sampler sampler, SamplerDescriptor descriptor)) in SamplerIds)
+ if (SamplerPool != null)
{
- if (SamplerPool.GetCachedItem(samplerId) != sampler ||
- (sampler == null && SamplerPool.IsValidId(samplerId) && !SamplerPool.GetDescriptorRef(samplerId).Equals(descriptor)))
+ foreach ((int samplerId, (Sampler sampler, SamplerDescriptor descriptor)) in SamplerIds)
{
- return true;
+ if (SamplerPool.GetCachedItem(samplerId) != sampler ||
+ (sampler == null && SamplerPool.IsValidId(samplerId) && !SamplerPool.GetDescriptorRef(samplerId).Equals(descriptor)))
+ {
+ return true;
+ }
}
}
@@ -899,13 +902,19 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
- Sampler sampler = samplerPool?.Get(samplerId);
-
entry.TextureIds[textureId] = (texture, descriptor);
- entry.SamplerIds[samplerId] = (sampler, samplerPool?.GetDescriptorRef(samplerId) ?? default);
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
- ISampler hostSampler = sampler?.GetHostSampler(texture);
+ ISampler hostSampler = null;
+
+ if (!isImage && bindingInfo.Target != Target.TextureBuffer)
+ {
+ Sampler sampler = samplerPool?.Get(samplerId);
+
+ entry.SamplerIds[samplerId] = (sampler, samplerPool?.GetDescriptorRef(samplerId) ?? default);
+
+ hostSampler = sampler?.GetHostSampler(texture);
+ }
Format format = bindingInfo.Format;
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index b9ff060e2..b6fa842e3 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -468,13 +468,11 @@ namespace Ryujinx.Graphics.Gpu.Image
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
+ layered &= size.UnpackIsLayered();
+
Target target;
- if (dsState.MemoryLayout.UnpackIsTarget3D())
- {
- target = Target.Texture3D;
- }
- else if ((samplesInX | samplesInY) != 1)
+ if ((samplesInX | samplesInY) != 1)
{
target = size.Depth > 1 && layered
? Target.Texture2DMultisampleArray
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index a4035577d..4ed0a93c1 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -6,6 +6,7 @@ using Ryujinx.Memory.Range;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Numerics;
using System.Threading;
namespace Ryujinx.Graphics.Gpu.Image
@@ -490,6 +491,8 @@ namespace Ryujinx.Graphics.Gpu.Image
levels = (maxLod - minLod) + 1;
}
+ levels = ClampLevels(target, width, height, depthOrLayers, levels);
+
SwizzleComponent swizzleR = descriptor.UnpackSwizzleR().Convert();
SwizzleComponent swizzleG = descriptor.UnpackSwizzleG().Convert();
SwizzleComponent swizzleB = descriptor.UnpackSwizzleB().Convert();
@@ -540,6 +543,34 @@ namespace Ryujinx.Graphics.Gpu.Image
swizzleA);
}
+ ///
+ /// Clamps the amount of mipmap levels to the maximum allowed for the given texture dimensions.
+ ///
+ /// Number of texture dimensions (1D, 2D, 3D, Cube, etc)
+ /// Width of the texture
+ /// Height of the texture, ignored for 1D textures
+ /// Depth of the texture for 3D textures, otherwise ignored
+ /// Original amount of mipmap levels
+ /// Clamped mipmap levels
+ private static int ClampLevels(Target target, int width, int height, int depthOrLayers, int levels)
+ {
+ int maxSize = width;
+
+ if (target != Target.Texture1D &&
+ target != Target.Texture1DArray)
+ {
+ maxSize = Math.Max(maxSize, height);
+ }
+
+ if (target == Target.Texture3D)
+ {
+ maxSize = Math.Max(maxSize, depthOrLayers);
+ }
+
+ int maxLevels = BitOperations.Log2((uint)maxSize) + 1;
+ return Math.Min(levels, maxLevels);
+ }
+
///
/// Gets the texture depth-stencil mode, based on the swizzle components of each color channel.
/// The depth-stencil mode is determined based on how the driver sets those parameters.
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
index 0b6c78fac..59a940a4f 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
@@ -2,7 +2,6 @@ using Ryujinx.Common.Memory;
using Ryujinx.Memory;
using Ryujinx.Memory.Range;
using System;
-using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -242,9 +241,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
else
{
- IMemoryOwner memoryOwner = ByteMemoryPool.Rent(size);
+ MemoryOwner memoryOwner = MemoryOwner.Rent(size);
- GetSpan(va, size).CopyTo(memoryOwner.Memory.Span);
+ ReadImpl(va, memoryOwner.Span, tracked);
return new WritableRegion(this, va, memoryOwner, tracked);
}
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs
index 4d09c3aab..b22cc01b8 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs
@@ -192,9 +192,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
else
{
- IMemoryOwner memoryOwner = ByteMemoryPool.Rent(range.GetSize());
+ MemoryOwner memoryOwner = MemoryOwner.Rent(checked((int)range.GetSize()));
- Memory memory = memoryOwner.Memory;
+ Span memorySpan = memoryOwner.Span;
int offset = 0;
for (int i = 0; i < range.Count; i++)
@@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
int size = (int)currentRange.Size;
if (currentRange.Address != MemoryManager.PteUnmapped)
{
- GetSpan(currentRange.Address, size).CopyTo(memory.Span.Slice(offset, size));
+ GetSpan(currentRange.Address, size).CopyTo(memorySpan.Slice(offset, size));
}
offset += size;
}
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/FormatConverter.cs b/src/Ryujinx.Graphics.OpenGL/Image/FormatConverter.cs
index 434f25900..490c0c585 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/FormatConverter.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/FormatConverter.cs
@@ -1,6 +1,5 @@
using Ryujinx.Common.Memory;
using System;
-using System.Buffers;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
@@ -10,11 +9,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
static class FormatConverter
{
- public unsafe static IMemoryOwner ConvertS8D24ToD24S8(ReadOnlySpan data)
+ public unsafe static MemoryOwner ConvertS8D24ToD24S8(ReadOnlySpan data)
{
- IMemoryOwner outputMemory = ByteMemoryPool.Rent(data.Length);
+ MemoryOwner outputMemory = MemoryOwner.Rent(data.Length);
- Span output = outputMemory.Memory.Span;
+ Span output = outputMemory.Span;
int start = 0;
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
index 79c6cb685..0ebafb04e 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
internalFormat = (SizedInternalFormat)format.PixelInternalFormat;
}
- int levels = Info.GetLevelsClamped();
+ int levels = Info.Levels;
switch (Info.Target)
{
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index 8a18e6132..946eb755c 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
pixelInternalFormat = format.PixelInternalFormat;
}
- int levels = Info.GetLevelsClamped();
+ int levels = Info.Levels;
GL.TextureView(
Handle,
@@ -267,7 +267,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
public unsafe PinnedSpan GetData()
{
int size = 0;
- int levels = Info.GetLevelsClamped();
+ int levels = Info.Levels;
for (int level = 0; level < levels; level++)
{
@@ -426,7 +426,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
faces = 6;
}
- int levels = Info.GetLevelsClamped();
+ int levels = Info.Levels;
for (int level = 0; level < levels; level++)
{
@@ -716,7 +716,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
int width = Info.Width;
int height = Info.Height;
int depth = Info.Depth;
- int levels = Info.GetLevelsClamped();
+ int levels = Info.Levels;
int offset = 0;
diff --git a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs
index 3f65e1225..92e39d2e0 100644
--- a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs
+++ b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
-using System.Buffers;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -293,9 +292,9 @@ namespace Ryujinx.Graphics.Texture.Astc
int depth,
int levels,
int layers,
- out IMemoryOwner decoded)
+ out MemoryOwner decoded)
{
- decoded = ByteMemoryPool.Rent(QueryDecompressedSize(width, height, depth, levels, layers));
+ decoded = MemoryOwner.Rent(QueryDecompressedSize(width, height, depth, levels, layers));
AstcDecoder decoder = new(data, decoded.Memory, blockWidth, blockHeight, width, height, depth, levels, layers);
diff --git a/src/Ryujinx.Graphics.Texture/BCnDecoder.cs b/src/Ryujinx.Graphics.Texture/BCnDecoder.cs
index eb85334a2..d7b1f0fa9 100644
--- a/src/Ryujinx.Graphics.Texture/BCnDecoder.cs
+++ b/src/Ryujinx.Graphics.Texture/BCnDecoder.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using System;
-using System.Buffers;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Texture
private const int BlockWidth = 4;
private const int BlockHeight = 4;
- public static IMemoryOwner DecodeBC1(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeBC1(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
@@ -23,12 +22,12 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
+ MemoryOwner output = MemoryOwner.Rent(size);
Span tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span tileAsUint = MemoryMarshal.Cast(tile);
- Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputAsUint = MemoryMarshal.Cast(output.Span);
Span> tileAsVector128 = MemoryMarshal.Cast>(tile);
@@ -102,7 +101,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC2(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeBC2(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
@@ -111,12 +110,12 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
+ MemoryOwner output = MemoryOwner.Rent(size);
Span tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span tileAsUint = MemoryMarshal.Cast(tile);
- Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputAsUint = MemoryMarshal.Cast(output.Span);
Span> tileAsVector128 = MemoryMarshal.Cast>(tile);
@@ -197,7 +196,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC3(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeBC3(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
@@ -206,13 +205,13 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
+ MemoryOwner output = MemoryOwner.Rent(size);
Span tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span rPal = stackalloc byte[8];
Span tileAsUint = MemoryMarshal.Cast(tile);
- Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputAsUint = MemoryMarshal.Cast(output.Span);
Span> tileAsVector128 = MemoryMarshal.Cast>(tile);
@@ -294,7 +293,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC4(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
+ public static MemoryOwner DecodeBC4(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
{
int size = 0;
@@ -306,8 +305,8 @@ namespace Ryujinx.Graphics.Texture
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
int alignedWidth = BitUtils.AlignUp(width, 4);
- IMemoryOwner output = ByteMemoryPool.Rent(size);
- Span outputSpan = output.Memory.Span;
+ MemoryOwner output = MemoryOwner.Rent(size);
+ Span outputSpan = output.Span;
ReadOnlySpan data64 = MemoryMarshal.Cast(data);
@@ -402,7 +401,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC5(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
+ public static MemoryOwner DecodeBC5(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
{
int size = 0;
@@ -414,7 +413,7 @@ namespace Ryujinx.Graphics.Texture
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
int alignedWidth = BitUtils.AlignUp(width, 2);
- IMemoryOwner output = ByteMemoryPool.Rent(size);
+ MemoryOwner output = MemoryOwner.Rent(size);
ReadOnlySpan data64 = MemoryMarshal.Cast(data);
@@ -423,7 +422,7 @@ namespace Ryujinx.Graphics.Texture
Span rPal = stackalloc byte[8];
Span gPal = stackalloc byte[8];
- Span outputAsUshort = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputAsUshort = MemoryMarshal.Cast(output.Span);
Span rTileAsUint = MemoryMarshal.Cast(rTile);
Span gTileAsUint = MemoryMarshal.Cast(gTile);
@@ -527,7 +526,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC6(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
+ public static MemoryOwner DecodeBC6(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed)
{
int size = 0;
@@ -536,8 +535,8 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 8;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
- Span outputSpan = output.Memory.Span;
+ MemoryOwner output = MemoryOwner.Rent(size);
+ Span outputSpan = output.Span;
int inputOffset = 0;
int outputOffset = 0;
@@ -566,7 +565,7 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeBC7(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeBC7(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
@@ -575,8 +574,8 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
- Span outputSpan = output.Memory.Span;
+ MemoryOwner output = MemoryOwner.Rent(size);
+ Span outputSpan = output.Span;
int inputOffset = 0;
int outputOffset = 0;
diff --git a/src/Ryujinx.Graphics.Texture/BCnEncoder.cs b/src/Ryujinx.Graphics.Texture/BCnEncoder.cs
index 253ba305c..4db8a182b 100644
--- a/src/Ryujinx.Graphics.Texture/BCnEncoder.cs
+++ b/src/Ryujinx.Graphics.Texture/BCnEncoder.cs
@@ -2,7 +2,6 @@ using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Texture.Encoders;
using System;
-using System.Buffers;
namespace Ryujinx.Graphics.Texture
{
@@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Texture
private const int BlockWidth = 4;
private const int BlockHeight = 4;
- public static IMemoryOwner EncodeBC7(Memory data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner EncodeBC7(Memory data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
@@ -23,7 +22,7 @@ namespace Ryujinx.Graphics.Texture
size += w * h * 16 * Math.Max(1, depth >> l) * layers;
}
- IMemoryOwner output = ByteMemoryPool.Rent(size);
+ MemoryOwner output = MemoryOwner.Rent(size);
Memory outputMemory = output.Memory;
int imageBaseIOffs = 0;
diff --git a/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs b/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs
index 52801ff47..49e7154c8 100644
--- a/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs
+++ b/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using System;
-using System.Buffers;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
@@ -51,15 +50,15 @@ namespace Ryujinx.Graphics.Texture
new int[] { -3, -5, -7, -9, 2, 4, 6, 8 },
};
- public static IMemoryOwner DecodeRgb(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeRgb(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
ReadOnlySpan dataUlong = MemoryMarshal.Cast(data);
int inputOffset = 0;
- IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers));
+ MemoryOwner output = MemoryOwner.Rent(CalculateOutputSize(width, height, depth, levels, layers));
- Span outputUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputUint = MemoryMarshal.Cast(output.Span);
Span tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0;
@@ -113,15 +112,15 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodePta(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodePta(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
ReadOnlySpan dataUlong = MemoryMarshal.Cast(data);
int inputOffset = 0;
- IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers));
+ MemoryOwner output = MemoryOwner.Rent(CalculateOutputSize(width, height, depth, levels, layers));
- Span outputUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputUint = MemoryMarshal.Cast(output.Span);
Span tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0;
@@ -170,15 +169,15 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner DecodeRgba(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
+ public static MemoryOwner DecodeRgba(ReadOnlySpan data, int width, int height, int depth, int levels, int layers)
{
ReadOnlySpan dataUlong = MemoryMarshal.Cast(data);
int inputOffset = 0;
- IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers));
+ MemoryOwner output = MemoryOwner.Rent(CalculateOutputSize(width, height, depth, levels, layers));
- Span outputUint = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputUint = MemoryMarshal.Cast(output.Span);
Span tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0;
diff --git a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs
index d6732674b..5426af205 100644
--- a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs
+++ b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using System;
-using System.Buffers;
using System.Runtime.Intrinsics;
using static Ryujinx.Graphics.Texture.BlockLinearConstants;
@@ -95,7 +94,7 @@ namespace Ryujinx.Graphics.Texture
};
}
- public static IMemoryOwner ConvertBlockLinearToLinear(
+ public static MemoryOwner ConvertBlockLinearToLinear(
int width,
int height,
int depth,
@@ -121,8 +120,8 @@ namespace Ryujinx.Graphics.Texture
blockHeight,
bytesPerPixel);
- IMemoryOwner outputOwner = ByteMemoryPool.Rent(outSize);
- Span output = outputOwner.Memory.Span;
+ MemoryOwner outputOwner = MemoryOwner.Rent(outSize);
+ Span output = outputOwner.Span;
int outOffs = 0;
@@ -249,7 +248,7 @@ namespace Ryujinx.Graphics.Texture
return outputOwner;
}
- public static IMemoryOwner ConvertLinearStridedToLinear(
+ public static MemoryOwner ConvertLinearStridedToLinear(
int width,
int height,
int blockWidth,
@@ -265,8 +264,8 @@ namespace Ryujinx.Graphics.Texture
int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
lineSize = Math.Min(lineSize, outStride);
- IMemoryOwner output = ByteMemoryPool.Rent(h * outStride);
- Span outSpan = output.Memory.Span;
+ MemoryOwner output = MemoryOwner.Rent(h * outStride);
+ Span outSpan = output.Span;
int outOffs = 0;
int inOffs = 0;
diff --git a/src/Ryujinx.Graphics.Texture/PixelConverter.cs b/src/Ryujinx.Graphics.Texture/PixelConverter.cs
index 4475cc98a..3676d9199 100644
--- a/src/Ryujinx.Graphics.Texture/PixelConverter.cs
+++ b/src/Ryujinx.Graphics.Texture/PixelConverter.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using System;
-using System.Buffers;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
@@ -21,13 +20,14 @@ namespace Ryujinx.Graphics.Texture
return (remainder, outRemainder, length / stride);
}
- public unsafe static IMemoryOwner ConvertR4G4ToR4G4B4A4(ReadOnlySpan data, int width)
+ public unsafe static MemoryOwner ConvertR4G4ToR4G4B4A4(ReadOnlySpan data, int width)
{
- IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2);
+ MemoryOwner output = MemoryOwner.Rent(data.Length * 2);
+ Span outputSpan = output.Span;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 1, 2);
- Span outputSpan = MemoryMarshal.Cast(output.Memory.Span);
+ Span outputSpanUInt16 = MemoryMarshal.Cast(outputSpan);
if (remainder == 0)
{
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Texture
int sizeTrunc = data.Length & ~7;
start = sizeTrunc;
- fixed (byte* inputPtr = data, outputPtr = output.Memory.Span)
+ fixed (byte* inputPtr = data, outputPtr = outputSpan)
{
for (ulong offset = 0; offset < (ulong)sizeTrunc; offset += 8)
{
@@ -49,7 +49,7 @@ namespace Ryujinx.Graphics.Texture
for (int i = start; i < data.Length; i++)
{
- outputSpan[i] = data[i];
+ outputSpanUInt16[i] = data[i];
}
}
else
@@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Texture
{
for (int x = 0; x < width; x++)
{
- outputSpan[outOffset++] = data[offset++];
+ outputSpanUInt16[outOffset++] = data[offset++];
}
offset += remainder;
@@ -72,16 +72,16 @@ namespace Ryujinx.Graphics.Texture
return output;
}
- public static IMemoryOwner ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan data, int width)
+ public static MemoryOwner ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan