Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9288ffd26d | ||
|
2cdc82cb91 | ||
|
6aa8d71588 | ||
|
9becbd7d72 | ||
|
e055217292 | ||
|
fbaf62c230 | ||
|
b186ec9fc5 |
@@ -21,7 +21,7 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.18.0" />
|
<PackageVersion Include="LibHac" Version="0.18.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||||
|
@@ -1296,11 +1296,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const byte mask = 0b01_00_11_10;
|
const byte Mask = 0b01_00_11_10;
|
||||||
|
|
||||||
context.Assembler.Pshufd(src1, src1, mask);
|
context.Assembler.Pshufd(src1, src1, Mask);
|
||||||
context.Assembler.Movq(dest, src1);
|
context.Assembler.Movq(dest, src1);
|
||||||
context.Assembler.Pshufd(src1, src1, mask);
|
context.Assembler.Pshufd(src1, src1, Mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1853,9 +1853,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// that the OS will map all pages that we'll use. We do that by
|
// that the OS will map all pages that we'll use. We do that by
|
||||||
// doing a dummy read on those pages, forcing a page fault and
|
// doing a dummy read on those pages, forcing a page fault and
|
||||||
// the OS to map them. If they are already mapped, nothing happens.
|
// the OS to map them. If they are already mapped, nothing happens.
|
||||||
const int pageMask = PageSize - 1;
|
const int PageMask = PageSize - 1;
|
||||||
|
|
||||||
size = (size + pageMask) & ~pageMask;
|
size = (size + PageMask) & ~PageMask;
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
Operand temp = Register(CallingConvention.GetIntReturnRegister());
|
Operand temp = Register(CallingConvention.GetIntReturnRegister());
|
||||||
|
@@ -304,9 +304,9 @@ namespace ARMeilleure.Decoders
|
|||||||
}
|
}
|
||||||
else if (opCode is IOpCode32MemMult opMemMult)
|
else if (opCode is IOpCode32MemMult opMemMult)
|
||||||
{
|
{
|
||||||
const int pcMask = 1 << RegisterAlias.Aarch32Pc;
|
const int PCMask = 1 << RegisterAlias.Aarch32Pc;
|
||||||
|
|
||||||
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
|
rt = (opMemMult.RegisterMask & PCMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
|
||||||
rn = opMemMult.Rn;
|
rn = opMemMult.Rn;
|
||||||
wBack = opMemMult.PostOffset != 0;
|
wBack = opMemMult.PostOffset != 0;
|
||||||
isLoad = opMemMult.IsLoad;
|
isLoad = opMemMult.IsLoad;
|
||||||
|
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal file
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
class OpCode32SimdCvtFFixed : OpCode32Simd
|
||||||
|
{
|
||||||
|
public int Fbits { get; protected set; }
|
||||||
|
|
||||||
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, true);
|
||||||
|
|
||||||
|
public OpCode32SimdCvtFFixed(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
|
{
|
||||||
|
Opc = (opCode >> 8) & 0x1;
|
||||||
|
|
||||||
|
Size = Opc == 1 ? 0 : 2;
|
||||||
|
Fbits = 64 - ((opCode >> 16) & 0x3f);
|
||||||
|
|
||||||
|
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
|
||||||
|
{
|
||||||
|
Instruction = InstDescriptor.Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -918,6 +918,7 @@ namespace ARMeilleure.Decoders
|
|||||||
SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
|
SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
|
||||||
|
SetAsimd("1111001x1x1xxxxxxxxx111x0xx1xxxx", InstName.Vcvt, InstEmit32.Vcvt_V_Fixed, OpCode32SimdCvtFFixed.Create, OpCode32SimdCvtFFixed.CreateT32); // Between floating point and fixed point, vector.
|
||||||
SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
|
SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
|
||||||
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
|
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
|
||||||
|
@@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||||||
throw new InvalidOperationException("Function entry point is not contained in a block.");
|
throw new InvalidOperationException("Function entry point is not contained in a block.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const ulong allowance = 4;
|
const ulong Allowance = 4;
|
||||||
|
|
||||||
Block entryBlock = blocks[entryBlockId];
|
Block entryBlock = blocks[entryBlockId];
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||||||
{
|
{
|
||||||
Block block = blocks[i];
|
Block block = blocks[i];
|
||||||
|
|
||||||
if (endBlock.EndAddress < block.Address - allowance)
|
if (endBlock.EndAddress < block.Address - Allowance)
|
||||||
{
|
{
|
||||||
break; // End of contiguous function.
|
break; // End of contiguous function.
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||||||
{
|
{
|
||||||
Block block = blocks[i];
|
Block block = blocks[i];
|
||||||
|
|
||||||
if (startBlock.Address > block.EndAddress + allowance)
|
if (startBlock.Address > block.EndAddress + Allowance)
|
||||||
{
|
{
|
||||||
break; // End of contiguous function.
|
break; // End of contiguous function.
|
||||||
}
|
}
|
||||||
|
@@ -114,6 +114,35 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Vcvt_V_Fixed(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
|
||||||
|
|
||||||
|
var toFixed = op.Opc == 1;
|
||||||
|
int fracBits = op.Fbits;
|
||||||
|
var unsigned = op.U;
|
||||||
|
|
||||||
|
if (toFixed) // F32 to S32 or U32 (fixed)
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpF32(context, (op1) =>
|
||||||
|
{
|
||||||
|
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
|
||||||
|
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
|
||||||
|
|
||||||
|
return context.Call(info, scaledValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else // S32 or U32 (fixed) to F32
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpI32(context, (op1) =>
|
||||||
|
{
|
||||||
|
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
|
||||||
|
|
||||||
|
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
|
||||||
|
}, !unsigned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Vcvt_FD(ArmEmitterContext context)
|
public static void Vcvt_FD(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||||
|
@@ -1299,17 +1299,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128);
|
Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128);
|
||||||
|
|
||||||
const int sm0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0;
|
const int SM0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0;
|
||||||
const int sm1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0;
|
const int SM1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0;
|
||||||
const int sm2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0;
|
const int SM2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0;
|
||||||
const int sm3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0;
|
const int SM3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0;
|
||||||
|
|
||||||
Operand nCopy = context.Copy(GetVec(op.Rn));
|
Operand nCopy = context.Copy(GetVec(op.Rn));
|
||||||
|
|
||||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm0));
|
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM0));
|
||||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm1));
|
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM1));
|
||||||
Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm2));
|
Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM2));
|
||||||
Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm3));
|
Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM3));
|
||||||
|
|
||||||
Operand res = emit(emit(part0, part1), emit(part2, part3));
|
Operand res = emit(emit(part0, part1), emit(part2, part3));
|
||||||
|
|
||||||
@@ -1340,13 +1340,13 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if ((op.Size & 1) == 0)
|
if ((op.Size & 1) == 0)
|
||||||
{
|
{
|
||||||
const int sm0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
|
const int SM0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
|
||||||
const int sm1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
|
const int SM1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
|
||||||
|
|
||||||
Operand zeroN = context.VectorZeroUpper64(n);
|
Operand zeroN = context.VectorZeroUpper64(n);
|
||||||
|
|
||||||
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm0));
|
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM0));
|
||||||
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm1));
|
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM1));
|
||||||
}
|
}
|
||||||
else /* if ((op.Size & 1) == 1) */
|
else /* if ((op.Size & 1) == 1) */
|
||||||
{
|
{
|
||||||
@@ -1412,11 +1412,11 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else /* if (op.RegisterSize == RegisterSize.Simd128) */
|
else /* if (op.RegisterSize == RegisterSize.Simd128) */
|
||||||
{
|
{
|
||||||
const int sm0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0;
|
const int SM0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0;
|
||||||
const int sm1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0;
|
const int SM1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0;
|
||||||
|
|
||||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm0));
|
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM0));
|
||||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm1));
|
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM1));
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), emit(part0, part1));
|
context.Copy(GetVec(op.Rd), emit(part0, part1));
|
||||||
}
|
}
|
||||||
|
@@ -408,7 +408,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (Optimizations.UseGfni)
|
if (Optimizations.UseGfni)
|
||||||
{
|
{
|
||||||
const long bitMatrix =
|
const long BitMatrix =
|
||||||
(0b10000000L << 56) |
|
(0b10000000L << 56) |
|
||||||
(0b01000000L << 48) |
|
(0b01000000L << 48) |
|
||||||
(0b00100000L << 40) |
|
(0b00100000L << 40) |
|
||||||
@@ -418,7 +418,7 @@ namespace ARMeilleure.Instructions
|
|||||||
(0b00000010L << 8) |
|
(0b00000010L << 8) |
|
||||||
(0b00000001L << 0);
|
(0b00000001L << 0);
|
||||||
|
|
||||||
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
|
Operand vBitMatrix = X86GetAllElements(context, BitMatrix);
|
||||||
|
|
||||||
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
|
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
|
||||||
|
|
||||||
@@ -469,12 +469,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand n = GetVec(op.Rn);
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
const long maskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
|
const long MaskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
|
||||||
const long maskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
|
const long MaskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
|
||||||
|
|
||||||
Operand mask = X86GetScalar(context, maskE0);
|
Operand mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
|
|
||||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||||
|
|
||||||
@@ -503,21 +503,21 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (op.Size == 0)
|
if (op.Size == 0)
|
||||||
{
|
{
|
||||||
const long maskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
|
const long MaskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
|
||||||
const long maskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
|
const long MaskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
|
||||||
|
|
||||||
mask = X86GetScalar(context, maskE0);
|
mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
}
|
}
|
||||||
else /* if (op.Size == 1) */
|
else /* if (op.Size == 1) */
|
||||||
{
|
{
|
||||||
const long maskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
|
const long MaskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
|
||||||
const long maskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
|
const long MaskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
|
||||||
|
|
||||||
mask = X86GetScalar(context, maskE0);
|
mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||||
@@ -547,30 +547,30 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (op.Size == 0)
|
if (op.Size == 0)
|
||||||
{
|
{
|
||||||
const long maskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
|
const long MaskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
|
||||||
const long maskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
|
const long MaskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
|
||||||
|
|
||||||
mask = X86GetScalar(context, maskE0);
|
mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
}
|
}
|
||||||
else if (op.Size == 1)
|
else if (op.Size == 1)
|
||||||
{
|
{
|
||||||
const long maskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
|
const long MaskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
|
||||||
const long maskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
|
const long MaskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
|
||||||
|
|
||||||
mask = X86GetScalar(context, maskE0);
|
mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
}
|
}
|
||||||
else /* if (op.Size == 2) */
|
else /* if (op.Size == 2) */
|
||||||
{
|
{
|
||||||
const long maskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
|
const long MaskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
|
||||||
const long maskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
|
const long MaskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
|
||||||
|
|
||||||
mask = X86GetScalar(context, maskE0);
|
mask = X86GetScalar(context, MaskE0);
|
||||||
|
|
||||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||||
|
@@ -175,10 +175,10 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static ushort FPRoundCv(double real, ExecutionContext context)
|
public static ushort FPRoundCv(double real, ExecutionContext context)
|
||||||
{
|
{
|
||||||
const int minimumExp = -14;
|
const int MinimumExp = -14;
|
||||||
|
|
||||||
const int e = 5;
|
const int E = 5;
|
||||||
const int f = 10;
|
const int F = 10;
|
||||||
|
|
||||||
bool sign;
|
bool sign;
|
||||||
double mantissa;
|
double mantissa;
|
||||||
@@ -208,15 +208,15 @@ namespace ARMeilleure.Instructions
|
|||||||
exponent++;
|
exponent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0);
|
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||||
|
|
||||||
if (biasedExp == 0u)
|
if (biasedExp == 0u)
|
||||||
{
|
{
|
||||||
mantissa /= Math.Pow(2d, minimumExp - exponent);
|
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f));
|
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||||
double error = mantissa * Math.Pow(2d, f) - (double)intMant;
|
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||||
|
|
||||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||||
{
|
{
|
||||||
@@ -256,12 +256,12 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
intMant++;
|
intMant++;
|
||||||
|
|
||||||
if (intMant == 1u << f)
|
if (intMant == 1u << F)
|
||||||
{
|
{
|
||||||
biasedExp = 1u;
|
biasedExp = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intMant == 1u << (f + 1))
|
if (intMant == 1u << (F + 1))
|
||||||
{
|
{
|
||||||
biasedExp++;
|
biasedExp++;
|
||||||
intMant >>= 1;
|
intMant >>= 1;
|
||||||
@@ -272,7 +272,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if ((context.Fpcr & FPCR.Ahp) == 0)
|
if ((context.Fpcr & FPCR.Ahp) == 0)
|
||||||
{
|
{
|
||||||
if (biasedExp >= (1u << e) - 1u)
|
if (biasedExp >= (1u << E) - 1u)
|
||||||
{
|
{
|
||||||
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
|
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (biasedExp >= 1u << e)
|
if (biasedExp >= 1u << E)
|
||||||
{
|
{
|
||||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
||||||
|
|
||||||
@@ -354,10 +354,10 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static float FPRoundCv(double real, ExecutionContext context)
|
private static float FPRoundCv(double real, ExecutionContext context)
|
||||||
{
|
{
|
||||||
const int minimumExp = -126;
|
const int MinimumExp = -126;
|
||||||
|
|
||||||
const int e = 8;
|
const int E = 8;
|
||||||
const int f = 23;
|
const int F = 23;
|
||||||
|
|
||||||
bool sign;
|
bool sign;
|
||||||
double mantissa;
|
double mantissa;
|
||||||
@@ -387,22 +387,22 @@ namespace ARMeilleure.Instructions
|
|||||||
exponent++;
|
exponent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < minimumExp)
|
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
|
||||||
{
|
{
|
||||||
context.Fpsr |= FPSR.Ufc;
|
context.Fpsr |= FPSR.Ufc;
|
||||||
|
|
||||||
return SoftFloat32.FPZero(sign);
|
return SoftFloat32.FPZero(sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0);
|
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||||
|
|
||||||
if (biasedExp == 0u)
|
if (biasedExp == 0u)
|
||||||
{
|
{
|
||||||
mantissa /= Math.Pow(2d, minimumExp - exponent);
|
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f));
|
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||||
double error = mantissa * Math.Pow(2d, f) - (double)intMant;
|
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||||
|
|
||||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||||
{
|
{
|
||||||
@@ -442,12 +442,12 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
intMant++;
|
intMant++;
|
||||||
|
|
||||||
if (intMant == 1u << f)
|
if (intMant == 1u << F)
|
||||||
{
|
{
|
||||||
biasedExp = 1u;
|
biasedExp = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intMant == 1u << (f + 1))
|
if (intMant == 1u << (F + 1))
|
||||||
{
|
{
|
||||||
biasedExp++;
|
biasedExp++;
|
||||||
intMant >>= 1;
|
intMant >>= 1;
|
||||||
@@ -456,7 +456,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
if (biasedExp >= (1u << e) - 1u)
|
if (biasedExp >= (1u << E) - 1u)
|
||||||
{
|
{
|
||||||
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
|
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
|
||||||
|
|
||||||
@@ -529,10 +529,10 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static double FPRoundCv(double real, ExecutionContext context)
|
private static double FPRoundCv(double real, ExecutionContext context)
|
||||||
{
|
{
|
||||||
const int minimumExp = -1022;
|
const int MinimumExp = -1022;
|
||||||
|
|
||||||
const int e = 11;
|
const int E = 11;
|
||||||
const int f = 52;
|
const int F = 52;
|
||||||
|
|
||||||
bool sign;
|
bool sign;
|
||||||
double mantissa;
|
double mantissa;
|
||||||
@@ -562,22 +562,22 @@ namespace ARMeilleure.Instructions
|
|||||||
exponent++;
|
exponent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < minimumExp)
|
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
|
||||||
{
|
{
|
||||||
context.Fpsr |= FPSR.Ufc;
|
context.Fpsr |= FPSR.Ufc;
|
||||||
|
|
||||||
return SoftFloat64.FPZero(sign);
|
return SoftFloat64.FPZero(sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0);
|
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||||
|
|
||||||
if (biasedExp == 0u)
|
if (biasedExp == 0u)
|
||||||
{
|
{
|
||||||
mantissa /= Math.Pow(2d, minimumExp - exponent);
|
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, f));
|
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||||
double error = mantissa * Math.Pow(2d, f) - (double)intMant;
|
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||||
|
|
||||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||||
{
|
{
|
||||||
@@ -617,12 +617,12 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
intMant++;
|
intMant++;
|
||||||
|
|
||||||
if (intMant == 1ul << f)
|
if (intMant == 1ul << F)
|
||||||
{
|
{
|
||||||
biasedExp = 1u;
|
biasedExp = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intMant == 1ul << (f + 1))
|
if (intMant == 1ul << (F + 1))
|
||||||
{
|
{
|
||||||
biasedExp++;
|
biasedExp++;
|
||||||
intMant >>= 1;
|
intMant >>= 1;
|
||||||
@@ -631,7 +631,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
if (biasedExp >= (1u << e) - 1u)
|
if (biasedExp >= (1u << E) - 1u)
|
||||||
{
|
{
|
||||||
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
|
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ using ARMeilleure.Translation.Cache;
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
namespace ARMeilleure.Signal
|
namespace ARMeilleure.Signal
|
||||||
@@ -261,20 +260,20 @@ namespace ARMeilleure.Signal
|
|||||||
{
|
{
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
const ulong mcontextOffset = 48; // uc_mcontext
|
const ulong McontextOffset = 48; // uc_mcontext
|
||||||
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(mcontextOffset)));
|
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(McontextOffset)));
|
||||||
|
|
||||||
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
const ulong esrOffset = 8; // __es.__esr
|
const ulong EsrOffset = 8; // __es.__esr
|
||||||
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(esrOffset)));
|
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
|
||||||
return context.BitwiseAnd(esr, Const(0x40ul));
|
return context.BitwiseAnd(esr, Const(0x40ul));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||||
{
|
{
|
||||||
const ulong errOffset = 4; // __es.__err
|
const ulong ErrOffset = 4; // __es.__err
|
||||||
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(errOffset)));
|
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
|
||||||
return context.BitwiseAnd(err, Const(2ul));
|
return context.BitwiseAnd(err, Const(2ul));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,10 +286,10 @@ namespace ARMeilleure.Signal
|
|||||||
Operand loopLabel = Label();
|
Operand loopLabel = Label();
|
||||||
Operand successLabel = Label();
|
Operand successLabel = Label();
|
||||||
|
|
||||||
const ulong auxOffset = 464; // uc_mcontext.__reserved
|
const ulong AuxOffset = 464; // uc_mcontext.__reserved
|
||||||
const uint esrMagic = 0x45535201;
|
const uint EsrMagic = 0x45535201;
|
||||||
|
|
||||||
context.Copy(auxPtr, context.Add(ucontextPtr, Const(auxOffset)));
|
context.Copy(auxPtr, context.Add(ucontextPtr, Const(AuxOffset)));
|
||||||
|
|
||||||
context.MarkLabel(loopLabel);
|
context.MarkLabel(loopLabel);
|
||||||
|
|
||||||
@@ -299,7 +298,7 @@ namespace ARMeilleure.Signal
|
|||||||
// _aarch64_ctx::size
|
// _aarch64_ctx::size
|
||||||
Operand size = context.Load(OperandType.I32, context.Add(auxPtr, Const(4ul)));
|
Operand size = context.Load(OperandType.I32, context.Add(auxPtr, Const(4ul)));
|
||||||
|
|
||||||
context.BranchIf(successLabel, magic, Const(esrMagic), Comparison.Equal);
|
context.BranchIf(successLabel, magic, Const(EsrMagic), Comparison.Equal);
|
||||||
|
|
||||||
context.Copy(auxPtr, context.Add(auxPtr, context.ZeroExtend32(OperandType.I64, size)));
|
context.Copy(auxPtr, context.Add(auxPtr, context.ZeroExtend32(OperandType.I64, size)));
|
||||||
|
|
||||||
@@ -314,8 +313,8 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||||
{
|
{
|
||||||
const int errOffset = 192; // uc_mcontext.gregs[REG_ERR]
|
const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
|
||||||
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(errOffset)));
|
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
|
||||||
return context.BitwiseAnd(err, Const(2ul));
|
return context.BitwiseAnd(err, Const(2ul));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 5292; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 5343; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
@@ -880,7 +880,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
private void ReportProgress(object state)
|
private void ReportProgress(object state)
|
||||||
{
|
{
|
||||||
const int refreshRate = 50; // ms.
|
const int RefreshRate = 50; // ms.
|
||||||
|
|
||||||
AutoResetEvent endEvent = (AutoResetEvent)state;
|
AutoResetEvent endEvent = (AutoResetEvent)state;
|
||||||
|
|
||||||
@@ -896,7 +896,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
count = newCount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!endEvent.WaitOne(refreshRate));
|
while (!endEvent.WaitOne(RefreshRate));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)
|
public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)
|
||||||
|
@@ -43,7 +43,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
public void Process(CommandList context)
|
public void Process(CommandList context)
|
||||||
{
|
{
|
||||||
const int targetChannelCount = 2;
|
const int TargetChannelCount = 2;
|
||||||
|
|
||||||
ulong currentOffset = CurrentOffset;
|
ulong currentOffset = CurrentOffset;
|
||||||
|
|
||||||
@@ -59,10 +59,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
for (int y = 0; y < context.SampleCount; y++)
|
for (int y = 0; y < context.SampleCount; y++)
|
||||||
{
|
{
|
||||||
context.MemoryManager.Write(targetOffset + (ulong)y * targetChannelCount, PcmHelper.Saturate(inputBuffer[y]));
|
context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, PcmHelper.Saturate(inputBuffer[y]));
|
||||||
}
|
}
|
||||||
|
|
||||||
currentOffset += context.SampleCount * targetChannelCount;
|
currentOffset += context.SampleCount * TargetChannelCount;
|
||||||
|
|
||||||
if (currentOffset >= CircularBufferSize)
|
if (currentOffset >= CircularBufferSize)
|
||||||
{
|
{
|
||||||
|
@@ -56,7 +56,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount)
|
private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount)
|
||||||
{
|
{
|
||||||
const ushort channelCount = 1;
|
const ushort ChannelCount = 1;
|
||||||
|
|
||||||
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
|
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
|
||||||
float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
|
float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
|
||||||
@@ -70,7 +70,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
float temp = input * inGain + delayLineValue * feedbackGain;
|
float temp = input * inGain + delayLineValue * feedbackGain;
|
||||||
|
|
||||||
state.UpdateLowPassFilter(ref temp, channelCount);
|
state.UpdateLowPassFilter(ref temp, ChannelCount);
|
||||||
|
|
||||||
outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64;
|
outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64;
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private unsafe void ProcessDelayStereo(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private unsafe void ProcessDelayStereo(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
const ushort channelCount = 2;
|
const ushort ChannelCount = 2;
|
||||||
|
|
||||||
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
||||||
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
|
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
|
||||||
@@ -106,7 +106,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||||
|
|
||||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), channelCount);
|
state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), ChannelCount);
|
||||||
|
|
||||||
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
||||||
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
||||||
@@ -116,7 +116,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private unsafe void ProcessDelayQuadraphonic(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private unsafe void ProcessDelayQuadraphonic(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
const ushort channelCount = 4;
|
const ushort ChannelCount = 4;
|
||||||
|
|
||||||
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
||||||
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
|
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
|
||||||
@@ -150,7 +150,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||||
|
|
||||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount);
|
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), ChannelCount);
|
||||||
|
|
||||||
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
||||||
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
||||||
@@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private unsafe void ProcessDelaySurround(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private unsafe void ProcessDelaySurround(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
const ushort channelCount = 6;
|
const ushort ChannelCount = 6;
|
||||||
|
|
||||||
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
|
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
|
||||||
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
|
||||||
@@ -202,7 +202,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||||
|
|
||||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), channelCount);
|
state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), ChannelCount);
|
||||||
|
|
||||||
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
|
||||||
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
|
||||||
|
@@ -65,7 +65,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
int channelCount = (int)device.GetChannelCount();
|
int channelCount = (int)device.GetChannelCount();
|
||||||
uint bufferCount = Math.Min(device.GetChannelCount(), InputCount);
|
uint bufferCount = Math.Min(device.GetChannelCount(), InputCount);
|
||||||
|
|
||||||
const int sampleCount = Constants.TargetSampleCount;
|
const int SampleCount = Constants.TargetSampleCount;
|
||||||
|
|
||||||
uint inputCount;
|
uint inputCount;
|
||||||
|
|
||||||
@@ -79,13 +79,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
inputCount = bufferCount;
|
inputCount = bufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
short[] outputBuffer = new short[inputCount * sampleCount];
|
short[] outputBuffer = new short[inputCount * SampleCount];
|
||||||
|
|
||||||
for (int i = 0; i < bufferCount; i++)
|
for (int i = 0; i < bufferCount; i++)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], sampleCount);
|
ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], SampleCount);
|
||||||
|
|
||||||
for (int j = 0; j < sampleCount; j++)
|
for (int j = 0; j < SampleCount; j++)
|
||||||
{
|
{
|
||||||
outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]);
|
outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]);
|
||||||
}
|
}
|
||||||
|
@@ -96,7 +96,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
private unsafe void ProcessReverb3dGeneric(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable)
|
private unsafe void ProcessReverb3dGeneric(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable)
|
||||||
{
|
{
|
||||||
const int delayLineSampleIndexOffset = 1;
|
const int DelayLineSampleIndexOffset = 1;
|
||||||
|
|
||||||
bool isMono = Parameter.ChannelCount == 1;
|
bool isMono = Parameter.ChannelCount == 1;
|
||||||
bool isSurround = Parameter.ChannelCount == 6;
|
bool isSurround = Parameter.ChannelCount == 6;
|
||||||
@@ -111,14 +111,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
{
|
{
|
||||||
outputValues.Fill(0);
|
outputValues.Fill(0);
|
||||||
|
|
||||||
float tapOut = state.PreDelayLine.TapUnsafe(state.ReflectionDelayTime, delayLineSampleIndexOffset);
|
float tapOut = state.PreDelayLine.TapUnsafe(state.ReflectionDelayTime, DelayLineSampleIndexOffset);
|
||||||
|
|
||||||
for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++)
|
for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++)
|
||||||
{
|
{
|
||||||
int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i];
|
int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i];
|
||||||
int outputIndex = outputEarlyIndicesTable[earlyDelayIndex];
|
int outputIndex = outputEarlyIndicesTable[earlyDelayIndex];
|
||||||
|
|
||||||
float tempTapOut = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], delayLineSampleIndexOffset);
|
float tempTapOut = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], DelayLineSampleIndexOffset);
|
||||||
|
|
||||||
outputValues[outputIndex] += tempTapOut * state.EarlyGain[earlyDelayIndex];
|
outputValues[outputIndex] += tempTapOut * state.EarlyGain[earlyDelayIndex];
|
||||||
}
|
}
|
||||||
|
@@ -44,9 +44,9 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, ref WaveBufferInformation info, Span<WaveBuffer> wavebuffers, ref VoiceUpdateState voiceState, uint targetSampleRate, int sampleCount)
|
public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, ref WaveBufferInformation info, Span<WaveBuffer> wavebuffers, ref VoiceUpdateState voiceState, uint targetSampleRate, int sampleCount)
|
||||||
{
|
{
|
||||||
const int tempBufferSize = 0x3F00;
|
const int TempBufferSize = 0x3F00;
|
||||||
|
|
||||||
Span<short> tempBuffer = stackalloc short[tempBufferSize];
|
Span<short> tempBuffer = stackalloc short[TempBufferSize];
|
||||||
|
|
||||||
float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch;
|
float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch;
|
||||||
|
|
||||||
@@ -60,11 +60,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
int totalNeededSize = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCount);
|
int totalNeededSize = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCount);
|
||||||
|
|
||||||
if (totalNeededSize + pitchMaxLength <= tempBufferSize && totalNeededSize >= 0)
|
if (totalNeededSize + pitchMaxLength <= TempBufferSize && totalNeededSize >= 0)
|
||||||
{
|
{
|
||||||
int sourceSampleCountToProcess = sampleCount;
|
int sourceSampleCountToProcess = sampleCount;
|
||||||
|
|
||||||
int maxSampleCountPerIteration = Math.Min((int)MathF.Truncate((tempBufferSize - fraction) / sampleRateRatio), sampleCount);
|
int maxSampleCountPerIteration = Math.Min((int)MathF.Truncate((TempBufferSize - fraction) / sampleRateRatio), sampleCount);
|
||||||
|
|
||||||
bool isStarving = false;
|
bool isStarving = false;
|
||||||
|
|
||||||
|
@@ -32,11 +32,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
float BlackmanWindow(float x)
|
float BlackmanWindow(float x)
|
||||||
{
|
{
|
||||||
const float a = 0.18f;
|
const float A = 0.18f;
|
||||||
const float a0 = 0.5f - 0.5f * a;
|
const float A0 = 0.5f - 0.5f * A;
|
||||||
const float a1 = -0.5f;
|
const float A1 = -0.5f;
|
||||||
const float a2 = 0.5f * a;
|
const float A2 = 0.5f * A;
|
||||||
return a0 + a1 * MathF.Cos(2 * MathF.PI * x) + a2 * MathF.Cos(4 * MathF.PI * x);
|
return A0 + A1 * MathF.Cos(2 * MathF.PI * x) + A2 * MathF.Cos(4 * MathF.PI * x);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array20<float> result = new Array20<float>();
|
Array20<float> result = new Array20<float>();
|
||||||
|
@@ -60,7 +60,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
|
|
||||||
public uint Estimate(MixRampGroupedCommand command)
|
public uint Estimate(MixRampGroupedCommand command)
|
||||||
{
|
{
|
||||||
const float costPerSample = 7.245f;
|
const float CostPerSample = 7.245f;
|
||||||
|
|
||||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (uint)(_sampleCount * costPerSample * volumeCount);
|
return (uint)(_sampleCount * CostPerSample * volumeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Estimate(MixRampCommand command)
|
public uint Estimate(MixRampCommand command)
|
||||||
|
@@ -256,19 +256,19 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool
|
|||||||
|
|
||||||
MemoryPoolUserState outputState;
|
MemoryPoolUserState outputState;
|
||||||
|
|
||||||
const uint pageSize = 0x1000;
|
const uint PageSize = 0x1000;
|
||||||
|
|
||||||
if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach)
|
if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach)
|
||||||
{
|
{
|
||||||
return UpdateResult.Success;
|
return UpdateResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % pageSize) != 0)
|
if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % PageSize) != 0)
|
||||||
{
|
{
|
||||||
return UpdateResult.InvalidParameter;
|
return UpdateResult.InvalidParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inParameter.Size == 0 || (inParameter.Size % pageSize) != 0)
|
if (inParameter.Size == 0 || (inParameter.Size % PageSize) != 0)
|
||||||
{
|
{
|
||||||
return UpdateResult.InvalidParameter;
|
return UpdateResult.InvalidParameter;
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Ui.App.Common;
|
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
|
using Ryujinx.Ui.App.Common;
|
||||||
using Ryujinx.Ui.Common.Helper;
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@@ -40,9 +40,9 @@ namespace Ryujinx.Ava.UI.Models
|
|||||||
|
|
||||||
private string GetSizeString()
|
private string GetSizeString()
|
||||||
{
|
{
|
||||||
const int scale = 1024;
|
const int Scale = 1024;
|
||||||
string[] orders = { "GiB", "MiB", "KiB" };
|
string[] orders = { "GiB", "MiB", "KiB" };
|
||||||
long max = (long)Math.Pow(scale, orders.Length);
|
long max = (long)Math.Pow(Scale, orders.Length);
|
||||||
|
|
||||||
foreach (string order in orders)
|
foreach (string order in orders)
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace Ryujinx.Ava.UI.Models
|
|||||||
return $"{decimal.Divide(Size, max):##.##} {order}";
|
return $"{decimal.Divide(Size, max):##.##} {order}";
|
||||||
}
|
}
|
||||||
|
|
||||||
max /= scale;
|
max /= Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "0 KiB";
|
return "0 KiB";
|
||||||
|
@@ -1124,13 +1124,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
|
var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
|
||||||
|
|
||||||
const float colorMultiple = 0.5f;
|
const float ColorMultiple = 0.5f;
|
||||||
|
|
||||||
Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B);
|
Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B);
|
||||||
Color progressBgColor = Color.FromRgb(
|
Color progressBgColor = Color.FromRgb(
|
||||||
(byte)(dominantColor.R * colorMultiple),
|
(byte)(dominantColor.R * ColorMultiple),
|
||||||
(byte)(dominantColor.G * colorMultiple),
|
(byte)(dominantColor.G * ColorMultiple),
|
||||||
(byte)(dominantColor.B * colorMultiple));
|
(byte)(dominantColor.B * ColorMultiple));
|
||||||
|
|
||||||
ProgressBarForegroundColor = new SolidColorBrush(progressFgColor);
|
ProgressBarForegroundColor = new SolidColorBrush(progressFgColor);
|
||||||
ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor);
|
ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor);
|
||||||
|
@@ -18,14 +18,14 @@ using Ryujinx.HLE.FileSystem;
|
|||||||
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
using Ryujinx.Ui.Common.Configuration.System;
|
using Ryujinx.Ui.Common.Configuration.System;
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
||||||
using Silk.NET.Vulkan;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
@@ -44,10 +44,10 @@ namespace Ryujinx.Common.SystemInfo
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int flavor = 4; // HOST_VM_INFO64
|
const int Flavor = 4; // HOST_VM_INFO64
|
||||||
uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
|
uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
|
||||||
VMStatistics64 stats = new();
|
VMStatistics64 stats = new();
|
||||||
result = host_statistics64(port, flavor, ref stats, ref count);
|
result = host_statistics64(port, Flavor, ref stats, ref count);
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
@@ -29,10 +29,10 @@ namespace Ryujinx.Common.SystemInterop
|
|||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
private void RegisterPosix()
|
private void RegisterPosix()
|
||||||
{
|
{
|
||||||
const int stdErrFileno = 2;
|
const int StdErrFileno = 2;
|
||||||
|
|
||||||
(int readFd, int writeFd) = MakePipe();
|
(int readFd, int writeFd) = MakePipe();
|
||||||
dup2(writeFd, stdErrFileno);
|
dup2(writeFd, StdErrFileno);
|
||||||
|
|
||||||
_pipeReader = CreateFileDescriptorStream(readFd);
|
_pipeReader = CreateFileDescriptorStream(readFd);
|
||||||
_pipeWriter = CreateFileDescriptorStream(writeFd);
|
_pipeWriter = CreateFileDescriptorStream(writeFd);
|
||||||
|
@@ -6,8 +6,8 @@ using Ryujinx.Memory.Range;
|
|||||||
using Ryujinx.Memory.Tracking;
|
using Ryujinx.Memory.Tracking;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Memory
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
@@ -51,6 +51,6 @@
|
|||||||
/*!\brief An iterator reached the end of list.
|
/*!\brief An iterator reached the end of list.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CodecListEnd
|
CodecListEnd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
{
|
{
|
||||||
10 => (ushort)Math.Clamp(val, 0, 1023),
|
10 => (ushort)Math.Clamp(val, 0, 1023),
|
||||||
12 => (ushort)Math.Clamp(val, 0, 4095),
|
12 => (ushort)Math.Clamp(val, 0, 4095),
|
||||||
_ => (ushort)Math.Clamp(val, 0, 255)
|
_ => (ushort)Math.Clamp(val, 0, 255),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
private static int GetMsb(uint n)
|
private static int GetMsb(uint n)
|
||||||
{
|
{
|
||||||
Debug.Assert(n != 0);
|
Debug.Assert(n != 0);
|
||||||
|
|
||||||
return 31 ^ BitOperations.LeadingZeroCount(n);
|
return 31 ^ BitOperations.LeadingZeroCount(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
public bool InUse;
|
public bool InUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PoolItem[] _pool = new PoolItem[PoolEntries];
|
private readonly PoolItem[] _pool = new PoolItem[PoolEntries];
|
||||||
|
|
||||||
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
@@ -9,7 +9,6 @@ using System.Diagnostics;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
@@ -48,7 +47,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,11 +63,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4:
|
||||||
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8:
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx16x16:
|
||||||
|
Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,15 +90,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan()[..256].Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +138,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,11 +154,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4:
|
||||||
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8:
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx16x16:
|
||||||
|
Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,15 +181,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan()[..256].Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +207,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
||||||
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
||||||
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
||||||
Span<byte> dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset);
|
Span<byte> dstSpan = pd.Dst.Buf.AsSpan()[dstOffset..];
|
||||||
|
|
||||||
if (mi.SbType < BlockSize.Block8x8)
|
if (mi.SbType < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
@@ -223,7 +246,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
||||||
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
||||||
Span<byte> dst = pd.Dst.Buf.AsSpan().Slice(4 * row * pd.Dst.Stride + 4 * col);
|
Span<byte> dst = pd.Dst.Buf.AsSpan()[(4 * row * pd.Dst.Stride + 4 * col)..];
|
||||||
|
|
||||||
if (eob > 0)
|
if (eob > 0)
|
||||||
{
|
{
|
||||||
@@ -589,9 +612,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
refr,
|
refr,
|
||||||
xs,
|
xs,
|
||||||
ys);
|
ys);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xd.CurBuf.HighBd)
|
if (xd.CurBuf.HighBd)
|
||||||
{
|
{
|
||||||
ReconInter.HighbdInterPredictor(
|
ReconInter.HighbdInterPredictor(
|
||||||
@@ -793,6 +818,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
|
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
|
||||||
|
|
||||||
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
|
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
|
||||||
|
|
||||||
return ref xd.Mi[0].Value;
|
return ref xd.Mi[0].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -928,8 +954,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// Update the partition context at the end notes. Set partition bits
|
// Update the partition context at the end notes. Set partition bits
|
||||||
// of block sizes larger than the current one to be one, and partition
|
// of block sizes larger than the current one to be one, and partition
|
||||||
// bits of smaller block sizes to be zero.
|
// bits of smaller block sizes to be zero.
|
||||||
aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above);
|
aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above);
|
||||||
leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left);
|
leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PartitionType ReadPartition(
|
private static PartitionType ReadPartition(
|
||||||
@@ -1030,7 +1056,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2);
|
DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2);
|
||||||
DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2);
|
DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid partition type"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid partition type");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1134,7 +1162,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols);
|
int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols);
|
||||||
int tileCols = 1 << cm.Log2TileCols;
|
int tileCols = 1 << cm.Log2TileCols;
|
||||||
int tileRows = 1 << cm.Log2TileRows;
|
int tileRows = 1 << cm.Log2TileRows;
|
||||||
Array4<Array64<TileBuffer>> tileBuffers = new Array4<Array64<TileBuffer>>();
|
Array4<Array64<TileBuffer>> tileBuffers = new();
|
||||||
int tileRow, tileCol;
|
int tileRow, tileCol;
|
||||||
int miRow, miCol;
|
int miRow, miCol;
|
||||||
|
|
||||||
@@ -1168,7 +1196,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
for (tileRow = 0; tileRow < tileRows; ++tileRow)
|
for (tileRow = 0; tileRow < tileRows; ++tileRow)
|
||||||
{
|
{
|
||||||
TileInfo tile = new TileInfo();
|
TileInfo tile = new();
|
||||||
tile.SetRow(ref cm, tileRow);
|
tile.SetRow(ref cm, tileRow);
|
||||||
for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize)
|
for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize)
|
||||||
{
|
{
|
||||||
@@ -1234,10 +1262,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
} while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd);
|
} while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd);
|
||||||
|
|
||||||
tileData.DataEnd = bitReaderEnd;
|
tileData.DataEnd = bitReaderEnd;
|
||||||
|
|
||||||
return !tileData.Xd.Corrupted;
|
return !tileData.Xd.Corrupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads)
|
public static ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads)
|
||||||
{
|
{
|
||||||
ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null;
|
ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null;
|
||||||
|
|
||||||
@@ -1250,8 +1279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Debug.Assert(tileCols <= (1 << 6));
|
Debug.Assert(tileCols <= (1 << 6));
|
||||||
Debug.Assert(tileRows == 1);
|
Debug.Assert(tileRows == 1);
|
||||||
|
|
||||||
cm.AboveContext.AsSpan().Fill(0);
|
cm.AboveContext.AsSpan().Clear();
|
||||||
cm.AboveSegContext.AsSpan().Fill(0);
|
cm.AboveSegContext.AsSpan().Clear();
|
||||||
|
|
||||||
for (n = 0; n < numWorkers; ++n)
|
for (n = 0; n < numWorkers; ++n)
|
||||||
{
|
{
|
||||||
@@ -1262,17 +1291,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
tileData.Counts = new Vp9BackwardUpdates();
|
tileData.Counts = new Vp9BackwardUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array64<TileBuffer> tileBuffers = new Array64<TileBuffer>();
|
Array64<TileBuffer> tileBuffers = new();
|
||||||
|
|
||||||
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
||||||
|
|
||||||
tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
|
tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers);
|
||||||
|
|
||||||
if (numWorkers == tileCols)
|
if (numWorkers == tileCols)
|
||||||
{
|
{
|
||||||
TileBuffer largest = tileBuffers[0];
|
TileBuffer largest = tileBuffers[0];
|
||||||
Span<TileBuffer> buffers = tileBuffers.AsSpan();
|
Span<TileBuffer> buffers = tileBuffers.AsSpan();
|
||||||
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1));
|
buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]);
|
||||||
tileBuffers[tileCols - 1] = largest;
|
tileBuffers[tileCols - 1] = largest;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1307,9 +1336,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
bufStart += count;
|
bufStart += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Vp9Common> cmPtr = new Ptr<Vp9Common>(ref cm);
|
Ptr<Vp9Common> cmPtr = new(ref cm);
|
||||||
|
|
||||||
Parallel.For(0, numWorkers, (n) =>
|
Parallel.For(0, numWorkers, n =>
|
||||||
{
|
{
|
||||||
ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles];
|
ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles];
|
||||||
|
|
||||||
@@ -1335,6 +1364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
|
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
|
||||||
|
|
||||||
return bitReaderEnd;
|
return bitReaderEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,8 +5,6 @@ using Ryujinx.Graphics.Video;
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
|
|
||||||
using MvRef = Ryujinx.Graphics.Nvdec.Vp9.Types.MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
@@ -61,10 +59,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
|
case TxSize.Tx8x8:
|
||||||
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
|
return fc.Tx8x8Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
|
case TxSize.Tx16x16:
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
|
return fc.Tx16x16Prob[ctx].AsSpan();
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
return fc.Tx32x32Prob[ctx].AsSpan();
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
|
return ReadOnlySpan<byte>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +76,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
|
case TxSize.Tx8x8:
|
||||||
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
|
return counts.Tx8x8[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
|
case TxSize.Tx16x16:
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
|
return counts.Tx16x16[ctx].AsSpan();
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
return counts.Tx32x32[ctx].AsSpan();
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
|
return Span<uint>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,11 +120,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
||||||
{
|
{
|
||||||
@@ -129,6 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,11 +188,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +224,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return predictedSegmentId;
|
return predictedSegmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +239,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +249,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetSkipContext();
|
int ctx = xd.GetSkipContext();
|
||||||
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
@@ -247,7 +259,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
return skip;
|
return skip;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||||
{
|
{
|
||||||
@@ -284,6 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
// Result
|
// Result
|
||||||
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
||||||
|
|
||||||
return sign ? -mag : mag;
|
return sign ? -mag : mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +309,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
||||||
bool useHP = allowHP && refr.UseMvHp();
|
bool useHP = allowHP && refr.UseMvHp();
|
||||||
Mv diff = new Mv();
|
Mv diff = new();
|
||||||
|
|
||||||
if (Mv.MvJointVertical(jointType))
|
if (Mv.MvJointVertical(jointType))
|
||||||
{
|
{
|
||||||
@@ -328,11 +340,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
return mode; // SingleReference or CompoundReference
|
return mode; // SingleReference or CompoundReference
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return cm.ReferenceMode;
|
return cm.ReferenceMode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read the referncence frame
|
// Read the referncence frame
|
||||||
private static void ReadRefFrames(
|
private static void ReadRefFrames(
|
||||||
@@ -434,7 +444,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
break;
|
break;
|
||||||
default: mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]); break;
|
default:
|
||||||
|
mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
||||||
@@ -503,7 +515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ZeroMvPair(ref mv);
|
ZeroMvPair(ref mv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: return false;
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -514,8 +527,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetIntraInterContext();
|
int ctx = xd.GetIntraInterContext();
|
||||||
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
@@ -525,7 +537,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
return isInter;
|
return isInter;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||||
{
|
{
|
||||||
@@ -547,6 +558,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
mvRefList[refMvCount] = mv;
|
mvRefList[refMvCount] = mv;
|
||||||
refMvCount++;
|
refMvCount++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,7 +617,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
// This function searches the neighborhood of a given MB/SB
|
// This function searches the neighborhood of a given MB/SB
|
||||||
// to try and find candidate reference vectors.
|
// to try and find candidate reference vectors.
|
||||||
private static unsafe int DecFindMvRefs(
|
private static int DecFindMvRefs(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
@@ -627,7 +639,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
bool earlyBreak = mode != PredictionMode.NearMv;
|
bool earlyBreak = mode != PredictionMode.NearMv;
|
||||||
|
|
||||||
// Blank the reference vector list
|
// Blank the reference vector list
|
||||||
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
mvRefList[..Constants.MaxMvRefCandidates].Clear();
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (isSub8X8 != 0)
|
if (isSub8X8 != 0)
|
||||||
@@ -805,7 +817,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
switch (block)
|
switch (block)
|
||||||
{
|
{
|
||||||
case 0: bestSub8x8 = mvList[refmvCount - 1]; break;
|
case 0:
|
||||||
|
bestSub8x8 = mvList[refmvCount - 1];
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
@@ -848,7 +862,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid block index."); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid block index.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,7 +899,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
bool allowHP = cm.AllowHighPrecisionMv;
|
bool allowHP = cm.AllowHighPrecisionMv;
|
||||||
Array2<Mv> bestRefMvs = new Array2<Mv>();
|
Array2<Mv> bestRefMvs = new();
|
||||||
int refr, isCompound;
|
int refr, isCompound;
|
||||||
byte interModeCtx;
|
byte interModeCtx;
|
||||||
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
||||||
@@ -898,6 +914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,11 +957,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int num4X4H = 1 << xd.BmodeBlocksHl;
|
int num4X4H = 1 << xd.BmodeBlocksHl;
|
||||||
int idx, idy;
|
int idx, idy;
|
||||||
PredictionMode bMode = 0;
|
PredictionMode bMode = 0;
|
||||||
Array2<Mv> bestSub8x8 = new Array2<Mv>();
|
Array2<Mv> bestSub8x8 = new();
|
||||||
const uint invalidMv = 0x80008000;
|
const uint InvalidMv = 0x80008000;
|
||||||
// Initialize the 2nd element as even though it won't be used meaningfully
|
// Initialize the 2nd element as even though it won't be used meaningfully
|
||||||
// if isCompound is false.
|
// if isCompound is false.
|
||||||
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = invalidMv;
|
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = InvalidMv;
|
||||||
for (idy = 0; idy < 2; idy += num4X4H)
|
for (idy = 0; idy < 2; idy += num4X4H)
|
||||||
{
|
{
|
||||||
for (idx = 0; idx < 2; idx += num4X4W)
|
for (idx = 0; idx < 2; idx += num4X4W)
|
||||||
@@ -1026,12 +1043,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
return leftMi.Value.GetYMode(b + 1);
|
return leftMi.Value.GetYMode(b + 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Assert(b == 1 || b == 3);
|
Debug.Assert(b == 1 || b == 3);
|
||||||
|
|
||||||
return curMi.Value.Bmi[b - 1].Mode;
|
return curMi.Value.Bmi[b - 1].Mode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
||||||
{
|
{
|
||||||
@@ -1044,12 +1060,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
return aboveMi.Value.GetYMode(b + 2);
|
return aboveMi.Value.GetYMode(b + 2);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Assert(b == 2 || b == 3);
|
Debug.Assert(b == 2 || b == 3);
|
||||||
|
|
||||||
return curMi.Value.Bmi[b - 2].Mode;
|
return curMi.Value.Bmi[b - 2].Mode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetYModeProbs(
|
private static ReadOnlySpan<byte> GetYModeProbs(
|
||||||
ref Vp9EntropyProbs fc,
|
ref Vp9EntropyProbs fc,
|
||||||
@@ -1060,6 +1075,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
||||||
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
||||||
|
|
||||||
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
|||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
@@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
public bool IsHardwareAccelerated => false;
|
public bool IsHardwareAccelerated => false;
|
||||||
|
|
||||||
private readonly MemoryAllocator _allocator = new MemoryAllocator();
|
private readonly MemoryAllocator _allocator = new();
|
||||||
|
|
||||||
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Constants.EightTapSmooth,
|
Constants.EightTapSmooth,
|
||||||
Constants.EightTap,
|
Constants.EightTap,
|
||||||
Constants.EightTapSharp,
|
Constants.EightTapSharp,
|
||||||
Constants.Bilinear
|
Constants.Bilinear,
|
||||||
};
|
};
|
||||||
|
|
||||||
public unsafe bool Decode(
|
public unsafe bool Decode(
|
||||||
@@ -30,24 +29,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ReadOnlySpan<Vp9MvRef> mvsIn,
|
ReadOnlySpan<Vp9MvRef> mvsIn,
|
||||||
Span<Vp9MvRef> mvsOut)
|
Span<Vp9MvRef> mvsOut)
|
||||||
{
|
{
|
||||||
Vp9Common cm = new Vp9Common();
|
Vp9Common cm = new()
|
||||||
|
{
|
||||||
|
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
|
||||||
|
IntraOnly = pictureInfo.IntraOnly,
|
||||||
|
|
||||||
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
Width = output.Width,
|
||||||
cm.IntraOnly = pictureInfo.IntraOnly;
|
Height = output.Height,
|
||||||
|
SubsamplingX = 1,
|
||||||
|
SubsamplingY = 1,
|
||||||
|
|
||||||
cm.Width = output.Width;
|
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
|
||||||
cm.Height = output.Height;
|
|
||||||
cm.SubsamplingX = 1;
|
|
||||||
cm.SubsamplingY = 1;
|
|
||||||
|
|
||||||
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
|
RefFrameSignBias = pictureInfo.RefFrameSignBias,
|
||||||
|
|
||||||
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
|
BaseQindex = pictureInfo.BaseQIndex,
|
||||||
|
YDcDeltaQ = pictureInfo.YDcDeltaQ,
|
||||||
cm.BaseQindex = pictureInfo.BaseQIndex;
|
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
|
||||||
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
|
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
|
||||||
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
|
};
|
||||||
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
|
|
||||||
|
|
||||||
cm.Mb.Lossless = pictureInfo.Lossless;
|
cm.Mb.Lossless = pictureInfo.Lossless;
|
||||||
cm.Mb.Bd = 8;
|
cm.Mb.Bd = 8;
|
||||||
|
@@ -17,9 +17,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
|
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
|
||||||
{
|
{
|
||||||
const int maxNeighbors = 2;
|
const int MaxNeighbors = 2;
|
||||||
|
|
||||||
return (1 + tokenCache[neighbors[maxNeighbors * c + 0]] + tokenCache[neighbors[maxNeighbors * c + 1]]) >> 1;
|
return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadCoeff(
|
private static int ReadCoeff(
|
||||||
@@ -57,13 +57,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int band, c = 0;
|
int band, c = 0;
|
||||||
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
||||||
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
||||||
ReadOnlySpan<byte> bandTranslate = Luts.get_band_translate(txSize);
|
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
|
||||||
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
||||||
int v;
|
int v;
|
||||||
short dqv = dq[0];
|
short dqv = dq[0];
|
||||||
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
||||||
? Luts.Vp9Cat6ProbHigh12
|
? Luts.Vp9Cat6ProbHigh12
|
||||||
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12.Slice(2) : Luts.Vp9Cat6Prob;
|
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
|
||||||
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
||||||
// Keep value, range, and count as locals. The compiler produces better
|
// Keep value, range, and count as locals. The compiler produces better
|
||||||
// results with the locals than using r directly.
|
// results with the locals than using r directly.
|
||||||
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
int val = -1;
|
int val = -1;
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate.Slice(1);
|
bandTranslate = bandTranslate[1..];
|
||||||
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
@@ -107,11 +107,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
|
|
||||||
return c; // Zero tokens at the end (no eob token)
|
return c; // Zero tokens at the end (no eob token)
|
||||||
}
|
}
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate.Slice(1);
|
bandTranslate = bandTranslate[1..];
|
||||||
prob = ref coefProbs[band][ctx];
|
prob = ref coefProbs[band][ctx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +197,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +238,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
||||||
int eob;
|
int eob;
|
||||||
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
|
Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
|
||||||
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
|
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
|
||||||
int ctx;
|
int ctx;
|
||||||
int ctxShiftA = 0;
|
int ctxShiftA = 0;
|
||||||
int ctxShiftL = 0;
|
int ctxShiftL = 0;
|
||||||
|
@@ -117,6 +117,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +262,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
// of this range for invalid/corrupt VP9 streams.
|
// of this range for invalid/corrupt VP9 streams.
|
||||||
Debug.Assert(short.MinValue <= input);
|
Debug.Assert(short.MinValue <= input);
|
||||||
Debug.Assert(input <= short.MaxValue);
|
Debug.Assert(input <= short.MaxValue);
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
public static byte ClipPixelAdd(byte dest, long trans)
|
public static byte ClipPixelAdd(byte dest, long trans)
|
||||||
{
|
{
|
||||||
trans = WrapLow(trans);
|
trans = WrapLow(trans);
|
||||||
|
|
||||||
return BitUtils.ClipPixel(dest + (int)trans);
|
return BitUtils.ClipPixel(dest + (int)trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +79,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd)
|
public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd)
|
||||||
{
|
{
|
||||||
trans = HighbdWrapLow(trans, bd);
|
trans = HighbdWrapLow(trans, bd);
|
||||||
|
|
||||||
return BitUtils.ClipPixelHighbd(dest + (int)trans, bd);
|
return BitUtils.ClipPixelHighbd(dest + (int)trans, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +87,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
private static long DctConstRoundShift(long input)
|
private static long DctConstRoundShift(long input)
|
||||||
{
|
{
|
||||||
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
|
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +119,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
op[1] = WrapLow(b1);
|
op[1] = WrapLow(b1);
|
||||||
op[2] = WrapLow(c1);
|
op[2] = WrapLow(c1);
|
||||||
op[3] = WrapLow(d1);
|
op[3] = WrapLow(d1);
|
||||||
ip = ip.Slice(4);
|
ip = ip[4..];
|
||||||
op = op.Slice(4);
|
op = op[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<int> ip2 = output;
|
Span<int> ip2 = output;
|
||||||
@@ -138,8 +142,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1));
|
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1));
|
||||||
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
|
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
|
||||||
|
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,8 +171,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
|
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
|
||||||
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
|
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
|
||||||
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
|
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +186,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
if ((x0 | x1 | x2 | x3) == 0)
|
if ((x0 | x1 | x2 | x3) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,8 +252,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct4(input, outptr);
|
Idct4(input, outptr);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -282,7 +287,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[1] = ClipPixelAdd(dest[1], a1);
|
dest[1] = ClipPixelAdd(dest[1], a1);
|
||||||
dest[2] = ClipPixelAdd(dest[2], a1);
|
dest[2] = ClipPixelAdd(dest[2], a1);
|
||||||
dest[3] = ClipPixelAdd(dest[3], a1);
|
dest[3] = ClipPixelAdd(dest[3], a1);
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +305,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,8 +440,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct8(input, outptr);
|
Idct8(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -464,15 +470,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows
|
// First transform rows
|
||||||
// Only first 4 row has non-zero coefs
|
// Only first 4 row has non-zero coefs
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct8(input, outptr);
|
Idct8(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -506,7 +512,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,7 +539,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,8 +867,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -889,15 +896,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -925,15 +932,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -967,7 +974,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1365,11 +1372,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outptr.Slice(0, 32).Fill(0);
|
outptr[..32].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -1397,15 +1404,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 16x16 has non-zero coeff
|
// Only upper-left 16x16 has non-zero coeff
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
Idct32(input, outptr);
|
Idct32(input, outptr);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -1433,15 +1440,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 8x8 has non-zero coeff
|
// Only upper-left 8x8 has non-zero coeff
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct32(input, outptr);
|
Idct32(input, outptr);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -1476,7 +1483,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1508,8 +1515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
op[1] = HighbdWrapLow(b1, bd);
|
op[1] = HighbdWrapLow(b1, bd);
|
||||||
op[2] = HighbdWrapLow(c1, bd);
|
op[2] = HighbdWrapLow(c1, bd);
|
||||||
op[3] = HighbdWrapLow(d1, bd);
|
op[3] = HighbdWrapLow(d1, bd);
|
||||||
ip = ip.Slice(4);
|
ip = ip[4..];
|
||||||
op = op.Slice(4);
|
op = op[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadOnlySpan<int> ip2 = output;
|
ReadOnlySpan<int> ip2 = output;
|
||||||
@@ -1531,8 +1538,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd);
|
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd);
|
||||||
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
|
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
|
||||||
|
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1560,8 +1567,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd);
|
dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd);
|
||||||
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
|
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
|
||||||
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
|
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1576,13 +1583,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 4) != 0)
|
if (DetectInvalidHighbdInput(input, 4) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3) == 0)
|
if ((x0 | x1 | x2 | x3) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1619,7 +1628,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 4) != 0)
|
if (DetectInvalidHighbdInput(input, 4) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1653,8 +1663,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct4(input, outptr, bd);
|
HighbdIdct4(input, outptr, bd);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -1688,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
|
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
|
||||||
dest[2] = HighbdClipPixelAdd(dest[2], a1, bd);
|
dest[2] = HighbdClipPixelAdd(dest[2], a1, bd);
|
||||||
dest[3] = HighbdClipPixelAdd(dest[3], a1, bd);
|
dest[3] = HighbdClipPixelAdd(dest[3], a1, bd);
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,13 +1717,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 8) != 0)
|
if (DetectInvalidHighbdInput(input, 8) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1786,7 +1798,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 8) != 0)
|
if (DetectInvalidHighbdInput(input, 8) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1845,8 +1858,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct8(input, outptr, bd);
|
HighbdIdct8(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -1874,15 +1887,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows
|
// First transform rows
|
||||||
// Only first 4 row has non-zero coefs
|
// Only first 4 row has non-zero coefs
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct8(input, outptr, bd);
|
HighbdIdct8(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -1901,7 +1914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd)
|
public static void Vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
long a1;
|
long a1;
|
||||||
@@ -1916,7 +1929,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1940,16 +1953,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int x13 = input[12];
|
int x13 = input[12];
|
||||||
int x14 = input[1];
|
int x14 = input[1];
|
||||||
int x15 = input[14];
|
int x15 = input[14];
|
||||||
|
|
||||||
if (DetectInvalidHighbdInput(input, 16) != 0)
|
if (DetectInvalidHighbdInput(input, 16) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,7 +2121,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 16) != 0)
|
if (DetectInvalidHighbdInput(input, 16) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2283,8 +2300,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -2312,15 +2329,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -2336,7 +2353,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (j = 0; j < 16; ++j)
|
for (j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||||
destT = destT.Slice(stride);
|
destT = destT[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2350,15 +2367,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
@@ -2392,7 +2409,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2406,7 +2423,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (DetectInvalidHighbdInput(input, 32) != 0)
|
if (DetectInvalidHighbdInput(input, 32) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 32).Fill(0);
|
output[..32].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2797,11 +2815,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outptr.Slice(0, 32).Fill(0);
|
outptr[..32].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -2829,15 +2847,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 16x16 has non-zero coeff
|
// Only upper-left 16x16 has non-zero coeff
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct32(input, outptr, bd);
|
HighbdIdct32(input, outptr, bd);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -2853,7 +2871,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
for (j = 0; j < 32; ++j)
|
for (j = 0; j < 32; ++j)
|
||||||
{
|
{
|
||||||
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||||
destT = destT.Slice(stride);
|
destT = destT[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2867,15 +2885,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 8x8 has non-zero coeff
|
// Only upper-left 8x8 has non-zero coeff
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct32(input, outptr, bd);
|
HighbdIdct32(input, outptr, bd);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -2910,7 +2928,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
||||||
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
||||||
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
||||||
|
|
||||||
return (byte)clippedProb;
|
return (byte)clippedProb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,10 +27,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||||
private static readonly uint[] CountToUpdateFactor = new uint[]
|
private static readonly uint[] _countToUpdateFactor = {
|
||||||
{
|
|
||||||
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
|
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
|
||||||
70, 76, 83, 89, 96, 102, 108, 115, 121, 128
|
70, 76, 83, 89, 96, 102, 108, 115, 121, 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int ModeMvCountSat = 20;
|
private const int ModeMvCountSat = 20;
|
||||||
@@ -44,8 +44,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint count = Math.Min(den, ModeMvCountSat);
|
uint count = Math.Min(den, ModeMvCountSat);
|
||||||
uint factor = CountToUpdateFactor[(int)count];
|
uint factor = _countToUpdateFactor[(int)count];
|
||||||
byte prob = GetProb(ct0, den);
|
byte prob = GetProb(ct0, den);
|
||||||
|
|
||||||
return WeightedProb(preProb, prob, (int)factor);
|
return WeightedProb(preProb, prob, (int)factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int r = tree[i + 1];
|
int r = tree[i + 1];
|
||||||
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||||
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
||||||
|
|
||||||
return leftCount + rightCount;
|
return leftCount + rightCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,8 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
{
|
{
|
||||||
internal struct Reader
|
internal struct Reader
|
||||||
{
|
{
|
||||||
private static readonly byte[] Norm = new byte[]
|
private static readonly byte[] _norm = {
|
||||||
{
|
|
||||||
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
@@ -17,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
};
|
};
|
||||||
private const int BdValueSize = sizeof(ulong) * 8;
|
private const int BdValueSize = sizeof(ulong) * 8;
|
||||||
|
|
||||||
@@ -44,6 +43,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Count = -8;
|
Count = -8;
|
||||||
Range = 255;
|
Range = 255;
|
||||||
Fill();
|
Fill();
|
||||||
|
|
||||||
return ReadBit() != 0; // Marker bit
|
return ReadBit() != 0; // Marker bit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||||
nv = bigEndianValues >> (BdValueSize - bits);
|
nv = bigEndianValues >> (BdValueSize - bits);
|
||||||
count += bits;
|
count += bits;
|
||||||
buffer = buffer.Slice(bits >> 3);
|
buffer = buffer[(bits >> 3)..];
|
||||||
value = Value | (nv << (shift & 0x7));
|
value = Value | (nv << (shift & 0x7));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
{
|
{
|
||||||
count += 8;
|
count += 8;
|
||||||
value |= (ulong)buffer[0] << shift;
|
value |= (ulong)buffer[0] << shift;
|
||||||
buffer = buffer.Slice(1);
|
buffer = buffer[1..];
|
||||||
shift -= 8;
|
shift -= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Count = count;
|
Count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasError()
|
public readonly bool HasError()
|
||||||
{
|
{
|
||||||
// Check if we have reached the end of the buffer.
|
// Check if we have reached the end of the buffer.
|
||||||
//
|
//
|
||||||
@@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
@@ -181,7 +181,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
||||||
{
|
{
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -i;
|
return -i;
|
||||||
@@ -203,10 +202,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
if (value >= bigsplit)
|
if (value >= bigsplit)
|
||||||
{
|
{
|
||||||
range = range - split;
|
range -= split;
|
||||||
value = value - bigsplit;
|
value -= bigsplit;
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
@@ -215,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
range = split;
|
range = split;
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
|
@@ -32,12 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht4 = new Transform2D[]
|
private static readonly Transform2D[] _iht4 = {
|
||||||
{
|
new(Idct4, Idct4), // DCT_DCT = 0
|
||||||
new Transform2D(Idct4, Idct4), // DCT_DCT = 0
|
new(Iadst4, Idct4), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst4, Idct4), // ADST_DCT = 1
|
new(Idct4, Iadst4), // DCT_ADST = 2
|
||||||
new Transform2D(Idct4, Iadst4), // DCT_ADST = 2
|
new(Iadst4, Iadst4), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst4, Iadst4) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
@@ -51,9 +50,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Iht4[txType].Rows(input, outptr);
|
_iht4[txType].Rows(input, outptr);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
@@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[j * 4 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Iht4[txType].Cols(tempIn, tempOut);
|
_iht4[txType].Cols(tempIn, tempOut);
|
||||||
for (j = 0; j < 4; ++j)
|
for (j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
||||||
@@ -72,12 +71,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht8 = new Transform2D[]
|
private static readonly Transform2D[] _iht8 = {
|
||||||
{
|
new(Idct8, Idct8), // DCT_DCT = 0
|
||||||
new Transform2D(Idct8, Idct8), // DCT_DCT = 0
|
new(Iadst8, Idct8), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst8, Idct8), // ADST_DCT = 1
|
new(Idct8, Iadst8), // DCT_ADST = 2
|
||||||
new Transform2D(Idct8, Iadst8), // DCT_ADST = 2
|
new(Iadst8, Iadst8), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst8, Iadst8) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
@@ -87,14 +85,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
Transform2D ht = Iht8[txType];
|
Transform2D ht = _iht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
@@ -113,12 +111,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht16 = new Transform2D[]
|
private static readonly Transform2D[] _iht16 = {
|
||||||
{
|
new(Idct16, Idct16), // DCT_DCT = 0
|
||||||
new Transform2D(Idct16, Idct16), // DCT_DCT = 0
|
new(Iadst16, Idct16), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst16, Idct16), // ADST_DCT = 1
|
new(Idct16, Iadst16), // DCT_ADST = 2
|
||||||
new Transform2D(Idct16, Iadst16), // DCT_ADST = 2
|
new(Iadst16, Iadst16), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst16, Iadst16) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
@@ -128,14 +125,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
Transform2D ht = Iht16[txType];
|
Transform2D ht = _iht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -283,12 +280,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighbdIht4 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highbdIht4 = {
|
||||||
{
|
new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
@@ -302,9 +298,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIht4[txType].Rows(input, outptr, bd);
|
_highbdIht4[txType].Rows(input, outptr, bd);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
@@ -315,7 +311,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[j * 4 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
HighbdIht4[txType].Cols(tempIn, tempOut, bd);
|
_highbdIht4[txType].Cols(tempIn, tempOut, bd);
|
||||||
for (j = 0; j < 4; ++j)
|
for (j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
||||||
@@ -323,12 +319,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht8 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highIht8 = {
|
||||||
{
|
new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
@@ -338,14 +333,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
HighbdTransform2D ht = HighIht8[txType];
|
HighbdTransform2D ht = _highIht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = output.Slice(8);
|
outptr = output[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
@@ -364,12 +359,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht16 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highIht16 = {
|
||||||
{
|
new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
@@ -379,14 +373,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
HighbdTransform2D ht = HighIht16[txType];
|
HighbdTransform2D ht = _highIht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = output.Slice(16);
|
outptr = output[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
@@ -440,7 +434,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// DC only DCT coefficient
|
// DC only DCT coefficient
|
||||||
if (eob == 1)
|
if (eob == 1)
|
||||||
{
|
{
|
||||||
vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
||||||
}
|
}
|
||||||
else if (eob <= 12)
|
else if (eob <= 12)
|
||||||
{
|
{
|
||||||
|
@@ -30,8 +30,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// 10101010
|
// 10101010
|
||||||
//
|
//
|
||||||
// A loopfilter should be applied to every other 8x8 horizontally.
|
// A loopfilter should be applied to every other 8x8 horizontally.
|
||||||
private static readonly ulong[] Left64X64TxformMask = new ulong[]
|
private static readonly ulong[] _left64X64TxformMask = {
|
||||||
{
|
|
||||||
0xffffffffffffffffUL, // TX_4X4
|
0xffffffffffffffffUL, // TX_4X4
|
||||||
0xffffffffffffffffUL, // TX_8x8
|
0xffffffffffffffffUL, // TX_8x8
|
||||||
0x5555555555555555UL, // TX_16x16
|
0x5555555555555555UL, // TX_16x16
|
||||||
@@ -55,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// 00000000
|
// 00000000
|
||||||
//
|
//
|
||||||
// A loopfilter should be applied to every other 4 the row vertically.
|
// A loopfilter should be applied to every other 4 the row vertically.
|
||||||
private static readonly ulong[] Above64X64TxformMask = new ulong[]
|
private static readonly ulong[] _above64X64TxformMask = {
|
||||||
{
|
|
||||||
0xffffffffffffffffUL, // TX_4X4
|
0xffffffffffffffffUL, // TX_4X4
|
||||||
0xffffffffffffffffUL, // TX_8x8
|
0xffffffffffffffffUL, // TX_8x8
|
||||||
0x00ff00ff00ff00ffUL, // TX_16x16
|
0x00ff00ff00ff00ffUL, // TX_16x16
|
||||||
@@ -78,8 +76,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// 00000000
|
// 00000000
|
||||||
// 00000000
|
// 00000000
|
||||||
// 00000000
|
// 00000000
|
||||||
private static readonly ulong[] LeftPredictionMask = new ulong[]
|
private static readonly ulong[] _leftPredictionMask = {
|
||||||
{
|
|
||||||
0x0000000000000001UL, // BLOCK_4X4,
|
0x0000000000000001UL, // BLOCK_4X4,
|
||||||
0x0000000000000001UL, // BLOCK_4X8,
|
0x0000000000000001UL, // BLOCK_4X8,
|
||||||
0x0000000000000001UL, // BLOCK_8X4,
|
0x0000000000000001UL, // BLOCK_8X4,
|
||||||
@@ -96,8 +93,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit mask to shift and set for each prediction size.
|
// 64 bit mask to shift and set for each prediction size.
|
||||||
private static readonly ulong[] AbovePredictionMask = new ulong[]
|
private static readonly ulong[] _abovePredictionMask = {
|
||||||
{
|
|
||||||
0x0000000000000001UL, // BLOCK_4X4
|
0x0000000000000001UL, // BLOCK_4X4
|
||||||
0x0000000000000001UL, // BLOCK_4X8
|
0x0000000000000001UL, // BLOCK_4X8
|
||||||
0x0000000000000001UL, // BLOCK_8X4
|
0x0000000000000001UL, // BLOCK_8X4
|
||||||
@@ -116,8 +112,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// 64 bit mask to shift and set for each prediction size. A bit is set for
|
// 64 bit mask to shift and set for each prediction size. A bit is set for
|
||||||
// each 8x8 block that would be in the left most block of the given block
|
// each 8x8 block that would be in the left most block of the given block
|
||||||
// size in the 64x64 block.
|
// size in the 64x64 block.
|
||||||
private static readonly ulong[] SizeMask = new ulong[]
|
private static readonly ulong[] _sizeMask = {
|
||||||
{
|
|
||||||
0x0000000000000001UL, // BLOCK_4X4
|
0x0000000000000001UL, // BLOCK_4X4
|
||||||
0x0000000000000001UL, // BLOCK_4X8
|
0x0000000000000001UL, // BLOCK_4X8
|
||||||
0x0000000000000001UL, // BLOCK_8X4
|
0x0000000000000001UL, // BLOCK_8X4
|
||||||
@@ -134,20 +129,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
};
|
};
|
||||||
|
|
||||||
// These are used for masking the left and above borders.
|
// These are used for masking the left and above borders.
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private const ulong LeftBorder = 0x1111111111111111UL;
|
private const ulong LeftBorder = 0x1111111111111111UL;
|
||||||
private const ulong AboveBorder = 0x000000ff000000ffUL;
|
private const ulong AboveBorder = 0x000000ff000000ffUL;
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
// 16 bit masks for uv transform sizes.
|
// 16 bit masks for uv transform sizes.
|
||||||
private static readonly ushort[] Left64X64TxformMaskUv = new ushort[]
|
private static readonly ushort[] _left64X64TxformMaskUv = {
|
||||||
{
|
|
||||||
0xffff, // TX_4X4
|
0xffff, // TX_4X4
|
||||||
0xffff, // TX_8x8
|
0xffff, // TX_8x8
|
||||||
0x5555, // TX_16x16
|
0x5555, // TX_16x16
|
||||||
0x1111, // TX_32x32
|
0x1111, // TX_32x32
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly ushort[] Above64X64TxformMaskUv = new ushort[]
|
private static readonly ushort[] _above64X64TxformMaskUv = {
|
||||||
{
|
|
||||||
0xffff, // TX_4X4
|
0xffff, // TX_4X4
|
||||||
0xffff, // TX_8x8
|
0xffff, // TX_8x8
|
||||||
0x0f0f, // TX_16x16
|
0x0f0f, // TX_16x16
|
||||||
@@ -155,8 +150,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 16 bit left mask to shift and set for each uv prediction size.
|
// 16 bit left mask to shift and set for each uv prediction size.
|
||||||
private static readonly ushort[] LeftPredictionMaskUv = new ushort[]
|
private static readonly ushort[] _leftPredictionMaskUv = {
|
||||||
{
|
|
||||||
0x0001, // BLOCK_4X4,
|
0x0001, // BLOCK_4X4,
|
||||||
0x0001, // BLOCK_4X8,
|
0x0001, // BLOCK_4X8,
|
||||||
0x0001, // BLOCK_8X4,
|
0x0001, // BLOCK_8X4,
|
||||||
@@ -173,8 +167,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 16 bit above mask to shift and set for uv each prediction size.
|
// 16 bit above mask to shift and set for uv each prediction size.
|
||||||
private static readonly ushort[] AbovePredictionMaskUv = new ushort[]
|
private static readonly ushort[] _abovePredictionMaskUv = {
|
||||||
{
|
|
||||||
0x0001, // BLOCK_4X4
|
0x0001, // BLOCK_4X4
|
||||||
0x0001, // BLOCK_4X8
|
0x0001, // BLOCK_4X8
|
||||||
0x0001, // BLOCK_8X4
|
0x0001, // BLOCK_8X4
|
||||||
@@ -191,8 +184,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit mask to shift and set for each uv prediction size
|
// 64 bit mask to shift and set for each uv prediction size
|
||||||
private static readonly ushort[] SizeMaskUv = new ushort[]
|
private static readonly ushort[] _sizeMaskUv = {
|
||||||
{
|
|
||||||
0x0001, // BLOCK_4X4
|
0x0001, // BLOCK_4X4
|
||||||
0x0001, // BLOCK_4X8
|
0x0001, // BLOCK_4X8
|
||||||
0x0001, // BLOCK_8X4
|
0x0001, // BLOCK_8X4
|
||||||
@@ -208,18 +200,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
0xffff, // BLOCK_64X64
|
0xffff, // BLOCK_64X64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private const ushort LeftBorderUv = 0x1111;
|
private const ushort LeftBorderUv = 0x1111;
|
||||||
private const ushort AboveBorderUv = 0x000f;
|
private const ushort AboveBorderUv = 0x000f;
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
private static readonly int[] ModeLfLut = new int[]
|
private static readonly int[] _modeLfLut = {
|
||||||
{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
|
||||||
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0)
|
1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi)
|
private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi)
|
||||||
{
|
{
|
||||||
return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][ModeLfLut[(int)mi.Mode]];
|
return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][_modeLfLut[(int)mi.Mode]];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol)
|
private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol)
|
||||||
@@ -229,12 +222,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
|
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
|
||||||
// or greater area.
|
// or greater area.
|
||||||
private static readonly byte[][] FirstBlockIn16x16 = new byte[][]
|
private static readonly byte[][] _firstBlockIn16X16 = {
|
||||||
{
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function sets up the bit masks for a block represented
|
// This function sets up the bit masks for a block represented
|
||||||
@@ -257,22 +249,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int colInSb = (miCol & 7);
|
int colInSb = (miCol & 7);
|
||||||
int shiftY = colInSb + (rowInSb << 3);
|
int shiftY = colInSb + (rowInSb << 3);
|
||||||
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
|
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
|
||||||
int buildUv = FirstBlockIn16x16[rowInSb][colInSb];
|
int buildUv = _firstBlockIn16X16[rowInSb][colInSb];
|
||||||
|
|
||||||
if (filterLevel == 0)
|
if (filterLevel == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = shiftY;
|
int index = shiftY;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < bh; i++)
|
for (i = 0; i < bh; i++)
|
||||||
{
|
{
|
||||||
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel);
|
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel);
|
||||||
index += 8;
|
index += 8;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// These set 1 in the current block size for the block size edges.
|
// These set 1 in the current block size for the block size edges.
|
||||||
// For instance if the block size is 32x16, we'll set:
|
// For instance if the block size is 32x16, we'll set:
|
||||||
@@ -286,13 +276,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
//
|
//
|
||||||
// U and V set things on a 16 bit scale.
|
// U and V set things on a 16 bit scale.
|
||||||
//
|
//
|
||||||
aboveY |= AbovePredictionMask[(int)blockSize] << shiftY;
|
aboveY |= _abovePredictionMask[(int)blockSize] << shiftY;
|
||||||
leftY |= LeftPredictionMask[(int)blockSize] << shiftY;
|
leftY |= _leftPredictionMask[(int)blockSize] << shiftY;
|
||||||
|
|
||||||
if (buildUv != 0)
|
if (buildUv != 0)
|
||||||
{
|
{
|
||||||
aboveUv |= (ushort)(AbovePredictionMaskUv[(int)blockSize] << shiftUv);
|
aboveUv |= (ushort)(_abovePredictionMaskUv[(int)blockSize] << shiftUv);
|
||||||
leftUv |= (ushort)(LeftPredictionMaskUv[(int)blockSize] << shiftUv);
|
leftUv |= (ushort)(_leftPredictionMaskUv[(int)blockSize] << shiftUv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the block has no coefficients and is not intra we skip applying
|
// If the block has no coefficients and is not intra we skip applying
|
||||||
@@ -305,13 +295,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// Add a mask for the transform size. The transform size mask is set to
|
// Add a mask for the transform size. The transform size mask is set to
|
||||||
// be correct for a 64x64 prediction block size. Mask to match the size of
|
// be correct for a 64x64 prediction block size. Mask to match the size of
|
||||||
// the block we are working on and then shift it into place.
|
// the block we are working on and then shift it into place.
|
||||||
aboveY |= (SizeMask[(int)blockSize] & Above64X64TxformMask[(int)txSizeY]) << shiftY;
|
aboveY |= (_sizeMask[(int)blockSize] & _above64X64TxformMask[(int)txSizeY]) << shiftY;
|
||||||
leftY |= (SizeMask[(int)blockSize] & Left64X64TxformMask[(int)txSizeY]) << shiftY;
|
leftY |= (_sizeMask[(int)blockSize] & _left64X64TxformMask[(int)txSizeY]) << shiftY;
|
||||||
|
|
||||||
if (buildUv != 0)
|
if (buildUv != 0)
|
||||||
{
|
{
|
||||||
aboveUv |= (ushort)((SizeMaskUv[(int)blockSize] & Above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
aboveUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
||||||
leftUv |= (ushort)((SizeMaskUv[(int)blockSize] & Left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
leftUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to determine what to do with the internal 4x4 block boundaries. These
|
// Try to determine what to do with the internal 4x4 block boundaries. These
|
||||||
@@ -319,12 +309,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// internal ones can be skipped and don't depend on the prediction block size.
|
// internal ones can be skipped and don't depend on the prediction block size.
|
||||||
if (txSizeY == TxSize.Tx4x4)
|
if (txSizeY == TxSize.Tx4x4)
|
||||||
{
|
{
|
||||||
int4X4Y |= SizeMask[(int)blockSize] << shiftY;
|
int4X4Y |= _sizeMask[(int)blockSize] << shiftY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildUv != 0 && txSizeUv == TxSize.Tx4x4)
|
if (buildUv != 0 && txSizeUv == TxSize.Tx4x4)
|
||||||
{
|
{
|
||||||
int4X4Uv |= (ushort)((SizeMaskUv[(int)blockSize] & 0xffff) << shiftUv);
|
int4X4Uv |= (ushort)((_sizeMaskUv[(int)blockSize] & 0xffff) << shiftUv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ctx = 1;
|
ctx = 1;
|
||||||
}
|
}
|
||||||
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +171,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +264,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,6 +386,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,8 +9,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
public const int MinQ = 0;
|
public const int MinQ = 0;
|
||||||
public const int MaxQ = 255;
|
public const int MaxQ = 255;
|
||||||
|
|
||||||
private static readonly short[] DcQlookup = new short[]
|
private static readonly short[] _dcQlookup = {
|
||||||
{
|
|
||||||
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
|
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
|
||||||
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
|
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
|
||||||
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
||||||
@@ -32,8 +31,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
1184, 1232, 1282, 1336,
|
1184, 1232, 1282, 1336,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup10 = new short[]
|
private static readonly short[] _dcQlookup10 = {
|
||||||
{
|
|
||||||
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
|
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
|
||||||
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
||||||
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
|
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
|
||||||
@@ -56,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup12 = new short[]
|
private static readonly short[] _dcQlookup12 = {
|
||||||
{
|
|
||||||
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
|
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
|
||||||
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
|
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
|
||||||
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
|
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
|
||||||
@@ -84,8 +81,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
19718, 20521, 21387,
|
19718, 20521, 21387,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup = new short[]
|
private static readonly short[] _acQlookup = {
|
||||||
{
|
|
||||||
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
||||||
@@ -108,8 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup10 = new short[]
|
private static readonly short[] _acQlookup10 = {
|
||||||
{
|
|
||||||
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
|
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
|
||||||
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
||||||
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
|
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
|
||||||
@@ -132,8 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup12 = new short[]
|
private static readonly short[] _acQlookup12 = {
|
||||||
{
|
|
||||||
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
|
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
|
||||||
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
|
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
|
||||||
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
|
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
|
||||||
@@ -164,11 +158,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (bitDepth)
|
switch (bitDepth)
|
||||||
{
|
{
|
||||||
case BitDepth.Bits8: return DcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits8:
|
||||||
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10:
|
||||||
|
return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
|
case BitDepth.Bits12:
|
||||||
|
return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,11 +175,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (bitDepth)
|
switch (bitDepth)
|
||||||
{
|
{
|
||||||
case BitDepth.Bits8: return AcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits8:
|
||||||
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10:
|
||||||
|
return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
|
case BitDepth.Bits12:
|
||||||
|
return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,12 +194,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
||||||
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
||||||
|
|
||||||
return Math.Clamp(segQIndex, 0, MaxQ);
|
return Math.Clamp(segQIndex, 0, MaxQ);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return baseQIndex;
|
return baseQIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@@ -84,16 +84,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
||||||
{
|
{
|
||||||
Mv res = new Mv()
|
return new Mv
|
||||||
{
|
{
|
||||||
Row = (short)RoundMvCompQ4(
|
Row = (short)RoundMvCompQ4(
|
||||||
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
|
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
|
||||||
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
|
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
|
||||||
Col = (short)RoundMvCompQ4(
|
Col = (short)RoundMvCompQ4(
|
||||||
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
|
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
|
||||||
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col)
|
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col),
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int RoundMvCompQ2(int value)
|
private static int RoundMvCompQ2(int value)
|
||||||
@@ -103,16 +102,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
||||||
{
|
{
|
||||||
Mv res = new Mv()
|
return new Mv
|
||||||
{
|
{
|
||||||
Row = (short)RoundMvCompQ2(
|
Row = (short)RoundMvCompQ2(
|
||||||
mi.Bmi[block0].Mv[idx].Row +
|
mi.Bmi[block0].Mv[idx].Row +
|
||||||
mi.Bmi[block1].Mv[idx].Row),
|
mi.Bmi[block1].Mv[idx].Row),
|
||||||
Col = (short)RoundMvCompQ2(
|
Col = (short)RoundMvCompQ2(
|
||||||
mi.Bmi[block0].Mv[idx].Col +
|
mi.Bmi[block0].Mv[idx].Col +
|
||||||
mi.Bmi[block1].Mv[idx].Col)
|
mi.Bmi[block1].Mv[idx].Col),
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
||||||
@@ -124,10 +122,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int spelRight = spelLeft - SubpelShifts;
|
int spelRight = spelLeft - SubpelShifts;
|
||||||
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
||||||
int spelBottom = spelTop - SubpelShifts;
|
int spelBottom = spelTop - SubpelShifts;
|
||||||
Mv clampedMv = new Mv()
|
Mv clampedMv = new()
|
||||||
{
|
{
|
||||||
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
||||||
Col = (short)(srcMv.Col * (1 << (1 - ssX)))
|
Col = (short)(srcMv.Col * (1 << (1 - ssX))),
|
||||||
};
|
};
|
||||||
|
|
||||||
Debug.Assert(ssX <= 1);
|
Debug.Assert(ssX <= 1);
|
||||||
@@ -145,14 +143,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
||||||
{
|
{
|
||||||
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
||||||
Mv res = new Mv();
|
Mv res = new();
|
||||||
switch (ssIdx)
|
switch (ssIdx)
|
||||||
{
|
{
|
||||||
case 0: res = mi.Bmi[block].Mv[refr]; break;
|
case 0:
|
||||||
case 1: res = MiMvPredQ2(ref mi, refr, block, block + 2); break;
|
res = mi.Bmi[block].Mv[refr];
|
||||||
case 2: res = MiMvPredQ2(ref mi, refr, block, block + 1); break;
|
break;
|
||||||
case 3: res = MiMvPredQ4(ref mi, refr); break;
|
case 1:
|
||||||
default: Debug.Assert(ssIdx <= 3 && ssIdx >= 0); break;
|
res = MiMvPredQ2(ref mi, refr, block, block + 2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
res = MiMvPredQ2(ref mi, refr, block, block + 1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
res = MiMvPredQ4(ref mi, refr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -161,6 +169,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
||||||
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
||||||
|
|
||||||
return y * stride + x;
|
return y * stride + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,8 +7,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
internal static class ReconIntra
|
internal static class ReconIntra
|
||||||
{
|
{
|
||||||
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[]
|
public static readonly TxType[] IntraModeToTxTypeLookup = {
|
||||||
{
|
|
||||||
TxType.DctDct, // DC
|
TxType.DctDct, // DC
|
||||||
TxType.AdstDct, // V
|
TxType.AdstDct, // V
|
||||||
TxType.DctAdst, // H
|
TxType.DctAdst, // H
|
||||||
@@ -18,7 +17,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
TxType.DctAdst, // D153
|
TxType.DctAdst, // D153
|
||||||
TxType.DctAdst, // D207
|
TxType.DctAdst, // D207
|
||||||
TxType.AdstDct, // D63
|
TxType.AdstDct, // D63
|
||||||
TxType.AdstAdst // TM
|
TxType.AdstAdst, // TM
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int NeedLeft = 1 << 1;
|
private const int NeedLeft = 1 << 1;
|
||||||
@@ -41,230 +40,226 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][] _pred = new IntraPredFn[][]
|
private static readonly unsafe IntraPredFn[][] _pred = {
|
||||||
{
|
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
VPredictor4x4,
|
VPredictor4x4,
|
||||||
VPredictor8x8,
|
VPredictor8x8,
|
||||||
VPredictor16x16,
|
VPredictor16x16,
|
||||||
VPredictor32x32
|
VPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
HPredictor4x4,
|
HPredictor4x4,
|
||||||
HPredictor8x8,
|
HPredictor8x8,
|
||||||
HPredictor16x16,
|
HPredictor16x16,
|
||||||
HPredictor32x32
|
HPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D45Predictor4x4,
|
D45Predictor4x4,
|
||||||
D45Predictor8x8,
|
D45Predictor8x8,
|
||||||
D45Predictor16x16,
|
D45Predictor16x16,
|
||||||
D45Predictor32x32
|
D45Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D135Predictor4x4,
|
D135Predictor4x4,
|
||||||
D135Predictor8x8,
|
D135Predictor8x8,
|
||||||
D135Predictor16x16,
|
D135Predictor16x16,
|
||||||
D135Predictor32x32
|
D135Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D117Predictor4x4,
|
D117Predictor4x4,
|
||||||
D117Predictor8x8,
|
D117Predictor8x8,
|
||||||
D117Predictor16x16,
|
D117Predictor16x16,
|
||||||
D117Predictor32x32
|
D117Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D153Predictor4x4,
|
D153Predictor4x4,
|
||||||
D153Predictor8x8,
|
D153Predictor8x8,
|
||||||
D153Predictor16x16,
|
D153Predictor16x16,
|
||||||
D153Predictor32x32
|
D153Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D207Predictor4x4,
|
D207Predictor4x4,
|
||||||
D207Predictor8x8,
|
D207Predictor8x8,
|
||||||
D207Predictor16x16,
|
D207Predictor16x16,
|
||||||
D207Predictor32x32
|
D207Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D63Predictor4x4,
|
D63Predictor4x4,
|
||||||
D63Predictor8x8,
|
D63Predictor8x8,
|
||||||
D63Predictor16x16,
|
D63Predictor16x16,
|
||||||
D63Predictor32x32
|
D63Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
TMPredictor4x4,
|
TMPredictor4x4,
|
||||||
TMPredictor8x8,
|
TMPredictor8x8,
|
||||||
TMPredictor16x16,
|
TMPredictor16x16,
|
||||||
TMPredictor32x32
|
TMPredictor32x32,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][]
|
private static readonly unsafe IntraPredFn[][][] _dcPred = {
|
||||||
{
|
new[]
|
||||||
new IntraPredFn[][]
|
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
Dc128Predictor4x4,
|
Dc128Predictor4x4,
|
||||||
Dc128Predictor8x8,
|
Dc128Predictor8x8,
|
||||||
Dc128Predictor16x16,
|
Dc128Predictor16x16,
|
||||||
Dc128Predictor32x32
|
Dc128Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcTopPredictor4x4,
|
DcTopPredictor4x4,
|
||||||
DcTopPredictor8x8,
|
DcTopPredictor8x8,
|
||||||
DcTopPredictor16x16,
|
DcTopPredictor16x16,
|
||||||
DcTopPredictor32x32
|
DcTopPredictor32x32,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new IntraPredFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcLeftPredictor4x4,
|
DcLeftPredictor4x4,
|
||||||
DcLeftPredictor8x8,
|
DcLeftPredictor8x8,
|
||||||
DcLeftPredictor16x16,
|
DcLeftPredictor16x16,
|
||||||
DcLeftPredictor32x32
|
DcLeftPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcPredictor4x4,
|
DcPredictor4x4,
|
||||||
DcPredictor8x8,
|
DcPredictor8x8,
|
||||||
DcPredictor16x16,
|
DcPredictor16x16,
|
||||||
DcPredictor32x32
|
DcPredictor32x32,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][] _predHigh = new IntraHighPredFn[][]
|
private static readonly unsafe IntraHighPredFn[][] _predHigh = {
|
||||||
{
|
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdVPredictor4x4,
|
HighbdVPredictor4x4,
|
||||||
HighbdVPredictor8x8,
|
HighbdVPredictor8x8,
|
||||||
HighbdVPredictor16x16,
|
HighbdVPredictor16x16,
|
||||||
HighbdVPredictor32x32
|
HighbdVPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdHPredictor4x4,
|
HighbdHPredictor4x4,
|
||||||
HighbdHPredictor8x8,
|
HighbdHPredictor8x8,
|
||||||
HighbdHPredictor16x16,
|
HighbdHPredictor16x16,
|
||||||
HighbdHPredictor32x32
|
HighbdHPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD45Predictor4x4,
|
HighbdD45Predictor4x4,
|
||||||
HighbdD45Predictor8x8,
|
HighbdD45Predictor8x8,
|
||||||
HighbdD45Predictor16x16,
|
HighbdD45Predictor16x16,
|
||||||
HighbdD45Predictor32x32
|
HighbdD45Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD135Predictor4x4,
|
HighbdD135Predictor4x4,
|
||||||
HighbdD135Predictor8x8,
|
HighbdD135Predictor8x8,
|
||||||
HighbdD135Predictor16x16,
|
HighbdD135Predictor16x16,
|
||||||
HighbdD135Predictor32x32
|
HighbdD135Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD117Predictor4x4,
|
HighbdD117Predictor4x4,
|
||||||
HighbdD117Predictor8x8,
|
HighbdD117Predictor8x8,
|
||||||
HighbdD117Predictor16x16,
|
HighbdD117Predictor16x16,
|
||||||
HighbdD117Predictor32x32
|
HighbdD117Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD153Predictor4x4,
|
HighbdD153Predictor4x4,
|
||||||
HighbdD153Predictor8x8,
|
HighbdD153Predictor8x8,
|
||||||
HighbdD153Predictor16x16,
|
HighbdD153Predictor16x16,
|
||||||
HighbdD153Predictor32x32
|
HighbdD153Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD207Predictor4x4,
|
HighbdD207Predictor4x4,
|
||||||
HighbdD207Predictor8x8,
|
HighbdD207Predictor8x8,
|
||||||
HighbdD207Predictor16x16,
|
HighbdD207Predictor16x16,
|
||||||
HighbdD207Predictor32x32
|
HighbdD207Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD63Predictor4x4,
|
HighbdD63Predictor4x4,
|
||||||
HighbdD63Predictor8x8,
|
HighbdD63Predictor8x8,
|
||||||
HighbdD63Predictor16x16,
|
HighbdD63Predictor16x16,
|
||||||
HighbdD63Predictor32x32
|
HighbdD63Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdTMPredictor4x4,
|
HighbdTMPredictor4x4,
|
||||||
HighbdTMPredictor8x8,
|
HighbdTMPredictor8x8,
|
||||||
HighbdTMPredictor16x16,
|
HighbdTMPredictor16x16,
|
||||||
HighbdTMPredictor32x32
|
HighbdTMPredictor32x32,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][]
|
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
|
||||||
{
|
new[]
|
||||||
new IntraHighPredFn[][]
|
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDc128Predictor4x4,
|
HighbdDc128Predictor4x4,
|
||||||
HighbdDc128Predictor8x8,
|
HighbdDc128Predictor8x8,
|
||||||
HighbdDc128Predictor16x16,
|
HighbdDc128Predictor16x16,
|
||||||
HighbdDc128Predictor32x32
|
HighbdDc128Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcTopPredictor4x4,
|
HighbdDcTopPredictor4x4,
|
||||||
HighbdDcTopPredictor8x8,
|
HighbdDcTopPredictor8x8,
|
||||||
HighbdDcTopPredictor16x16,
|
HighbdDcTopPredictor16x16,
|
||||||
HighbdDcTopPredictor32x32
|
HighbdDcTopPredictor32x32,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcLeftPredictor4x4,
|
HighbdDcLeftPredictor4x4,
|
||||||
HighbdDcLeftPredictor8x8,
|
HighbdDcLeftPredictor8x8,
|
||||||
HighbdDcLeftPredictor16x16,
|
HighbdDcLeftPredictor16x16,
|
||||||
HighbdDcLeftPredictor32x32
|
HighbdDcLeftPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcPredictor4x4,
|
HighbdDcPredictor4x4,
|
||||||
HighbdDcPredictor8x8,
|
HighbdDcPredictor8x8,
|
||||||
HighbdDcPredictor16x16,
|
HighbdDcPredictor16x16,
|
||||||
HighbdDcPredictor32x32
|
HighbdDcPredictor32x32,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe void BuildIntraPredictorsHigh(
|
private static unsafe void BuildIntraPredictorsHigh(
|
||||||
@@ -741,6 +736,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
plane);
|
plane);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BuildIntraPredictors(
|
BuildIntraPredictors(
|
||||||
|
@@ -16,6 +16,6 @@
|
|||||||
Block64x32 = 11,
|
Block64x32 = 11,
|
||||||
Block64x64 = 12,
|
Block64x64 = 12,
|
||||||
BlockSizes = 13,
|
BlockSizes = 13,
|
||||||
BlockInvalid = BlockSizes
|
BlockInvalid = BlockSizes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
internal enum FrameType
|
internal enum FrameType
|
||||||
{
|
{
|
||||||
KeyFrame = 0,
|
KeyFrame = 0,
|
||||||
InterFrame = 1
|
InterFrame = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
// passed it can be loaded into vector registers.
|
// passed it can be loaded into vector registers.
|
||||||
internal struct LoopFilterThresh
|
internal struct LoopFilterThresh
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public Array16<byte> Mblim;
|
public Array16<byte> Mblim;
|
||||||
public Array16<byte> Lim;
|
public Array16<byte> Lim;
|
||||||
public Array16<byte> HevThr;
|
public Array16<byte> HevThr;
|
||||||
|
@@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
|
|
||||||
public Ptr<InternalErrorInfo> ErrorInfo;
|
public Ptr<InternalErrorInfo> ErrorInfo;
|
||||||
|
|
||||||
public int GetPredContextSegId()
|
public readonly int GetPredContextSegId()
|
||||||
{
|
{
|
||||||
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
||||||
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
||||||
@@ -62,14 +62,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
return aboveSip + leftSip;
|
return aboveSip + leftSip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetSkipContext()
|
public readonly int GetSkipContext()
|
||||||
{
|
{
|
||||||
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
||||||
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
||||||
|
|
||||||
return aboveSkip + leftSkip;
|
return aboveSkip + leftSkip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetPredContextSwitchableInterp()
|
public readonly int GetPredContextSwitchableInterp()
|
||||||
{
|
{
|
||||||
// Note:
|
// Note:
|
||||||
// The mode info data structure has a one element border above and to the
|
// The mode info data structure has a one element border above and to the
|
||||||
@@ -103,15 +104,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
// 1 - intra/inter, inter/intra
|
// 1 - intra/inter, inter/intra
|
||||||
// 2 - intra/--, --/intra
|
// 2 - intra/--, --/intra
|
||||||
// 3 - intra/intra
|
// 3 - intra/intra
|
||||||
public int GetIntraInterContext()
|
public readonly int GetIntraInterContext()
|
||||||
{
|
{
|
||||||
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{ // Both edges available
|
||||||
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
||||||
}
|
}
|
||||||
else if (!AboveMi.IsNull || !LeftMi.IsNull)
|
|
||||||
|
if (!AboveMi.IsNull || !LeftMi.IsNull)
|
||||||
{ // One edge available
|
{ // One edge available
|
||||||
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
||||||
}
|
}
|
||||||
@@ -122,7 +125,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
// The mode info data structure has a one element border above and to the
|
// The mode info data structure has a one element border above and to the
|
||||||
// left of the entries corresponding to real blocks.
|
// left of the entries corresponding to real blocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
public int GetTxSizeContext()
|
public readonly int GetTxSizeContext()
|
||||||
{
|
{
|
||||||
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
||||||
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
||||||
|
@@ -32,10 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
|
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
||||||
{
|
{
|
||||||
Debug.Assert(SbType < BlockSize.Block8x8 ||
|
Debug.Assert(SbType < BlockSize.Block8x8 ||
|
||||||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
|
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
|
||||||
|
|
||||||
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
|
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,9 +50,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
return RefFrame[1] > Constants.IntraFrame;
|
return RefFrame[1] > Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly int[][] IdxNColumnToSubblock = new int[][]
|
private static readonly int[][] _idxNColumnToSubblock = {
|
||||||
{
|
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
|
||||||
new int[] { 1, 2 }, new int[] { 1, 3 }, new int[] { 3, 2 }, new int[] { 3, 3 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function returns either the appropriate sub block or block's mv
|
// This function returns either the appropriate sub block or block's mv
|
||||||
@@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
|
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
|
||||||
{
|
{
|
||||||
return blockIdx >= 0 && SbType < BlockSize.Block8x8
|
return blockIdx >= 0 && SbType < BlockSize.Block8x8
|
||||||
? Bmi[IdxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
? Bmi[_idxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
||||||
: Mv[whichMv];
|
: Mv[whichMv];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
BothNew = 4,
|
BothNew = 4,
|
||||||
IntraPlusNonIntra = 5,
|
IntraPlusNonIntra = 5,
|
||||||
BothIntra = 6,
|
BothIntra = 6,
|
||||||
InvalidCase = 9
|
InvalidCase = 9,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,13 +51,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool UseMvHp()
|
public readonly bool UseMvHp()
|
||||||
{
|
{
|
||||||
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
||||||
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
|
return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool MvJointVertical(MvJointType type)
|
public static bool MvJointVertical(MvJointType type)
|
||||||
@@ -121,19 +121,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MvJointType GetMvJoint()
|
private readonly MvJointType GetMvJoint()
|
||||||
{
|
{
|
||||||
if (Row == 0)
|
if (Row == 0)
|
||||||
{
|
{
|
||||||
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
||||||
{
|
{
|
||||||
if (!counts.IsNull)
|
if (!counts.IsNull)
|
||||||
{
|
{
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
PartitionVert,
|
PartitionVert,
|
||||||
PartitionSplit,
|
PartitionSplit,
|
||||||
PartitionTypes,
|
PartitionTypes,
|
||||||
PartitionInvalid = PartitionTypes
|
PartitionInvalid = PartitionTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,6 @@
|
|||||||
{
|
{
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Uv = 1,
|
Uv = 1,
|
||||||
PlaneTypes
|
PlaneTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,6 @@
|
|||||||
NearMv = 11,
|
NearMv = 11,
|
||||||
ZeroMv = 12,
|
ZeroMv = 12,
|
||||||
NewMv = 13,
|
NewMv = 13,
|
||||||
MbModeCount = 14
|
MbModeCount = 14,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,6 @@
|
|||||||
SingleReference = 0,
|
SingleReference = 0,
|
||||||
CompoundReference = 1,
|
CompoundReference = 1,
|
||||||
ReferenceModeSelect = 2,
|
ReferenceModeSelect = 2,
|
||||||
ReferenceModes = 3
|
ReferenceModes = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,244 +38,236 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
int h,
|
int h,
|
||||||
int bd);
|
int bd);
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ConvolveCopy,
|
ConvolveCopy,
|
||||||
ConvolveAvg
|
ConvolveAvg,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8Vert,
|
Convolve8Vert,
|
||||||
Convolve8AvgVert
|
Convolve8AvgVert,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8Horiz,
|
Convolve8Horiz,
|
||||||
Convolve8AvgHoriz
|
Convolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8,
|
Convolve8,
|
||||||
Convolve8Avg
|
Convolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictX16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledVert,
|
ScaledVert,
|
||||||
ScaledAvgVert
|
ScaledAvgVert,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledVert,
|
ScaledVert,
|
||||||
ScaledAvgVert
|
ScaledAvgVert,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictY16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledHoriz,
|
ScaledHoriz,
|
||||||
ScaledAvgHoriz
|
ScaledAvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledHoriz,
|
ScaledHoriz,
|
||||||
ScaledAvgHoriz
|
ScaledAvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predict = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolveCopy,
|
HighbdConvolveCopy,
|
||||||
HighbdConvolveAvg
|
HighbdConvolveAvg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
},
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public int XScaleFP; // Horizontal fixed point scale factor
|
public int XScaleFP; // Horizontal fixed point scale factor
|
||||||
@@ -283,18 +275,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
public int XStepQ4;
|
public int XStepQ4;
|
||||||
public int YStepQ4;
|
public int YStepQ4;
|
||||||
|
|
||||||
public int ScaleValueX(int val)
|
public readonly int ScaleValueX(int val)
|
||||||
{
|
{
|
||||||
return IsScaled() ? ScaledX(val) : val;
|
return IsScaled() ? ScaledX(val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ScaleValueY(int val)
|
public readonly int ScaleValueY(int val)
|
||||||
{
|
{
|
||||||
return IsScaled() ? ScaledY(val) : val;
|
return IsScaled() ? ScaledY(val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void InterPredict(
|
public readonly unsafe void InterPredict(
|
||||||
int horiz,
|
int horiz,
|
||||||
int vert,
|
int vert,
|
||||||
int avg,
|
int avg,
|
||||||
@@ -315,12 +307,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// No scaling in x direction. Must always scale in the y direction.
|
||||||
PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -328,18 +320,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// No scaling in the y direction. Must always scale in the x direction.
|
||||||
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Must always scale in both directions.
|
// Must always scale in both directions.
|
||||||
Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void HighbdInterPredict(
|
public readonly unsafe void HighbdInterPredict(
|
||||||
int horiz,
|
int horiz,
|
||||||
int vert,
|
int vert,
|
||||||
int avg,
|
int avg,
|
||||||
@@ -361,12 +353,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// No scaling in x direction. Must always scale in the y direction.
|
||||||
HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -374,22 +366,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// No scaling in the y direction. Must always scale in the x direction.
|
||||||
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Must always scale in both directions.
|
// Must always scale in both directions.
|
||||||
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledX(int val)
|
private readonly int ScaledX(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * XScaleFP >> RefScaleShift);
|
return (int)((long)val * XScaleFP >> RefScaleShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledY(int val)
|
private readonly int ScaledY(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * YScaleFP >> RefScaleShift);
|
return (int)((long)val * YScaleFP >> RefScaleShift);
|
||||||
}
|
}
|
||||||
@@ -407,20 +399,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
{
|
{
|
||||||
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
||||||
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
||||||
Mv32 res = new Mv32()
|
Mv32 res = new()
|
||||||
{
|
{
|
||||||
Row = ScaledY(mv.Row) + yOffQ4,
|
Row = ScaledY(mv.Row) + yOffQ4,
|
||||||
Col = ScaledX(mv.Col) + xOffQ4
|
Col = ScaledX(mv.Col) + xOffQ4,
|
||||||
};
|
};
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsValidScale()
|
public readonly bool IsValidScale()
|
||||||
{
|
{
|
||||||
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsScaled()
|
public readonly bool IsScaled()
|
||||||
{
|
{
|
||||||
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
||||||
}
|
}
|
||||||
@@ -439,6 +432,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
{
|
{
|
||||||
XScaleFP = RefInvalidScale;
|
XScaleFP = RefInvalidScale;
|
||||||
YScaleFP = RefInvalidScale;
|
YScaleFP = RefInvalidScale;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,6 @@
|
|||||||
SegLvlAltLf = 1, // Use alternate loop filter value...
|
SegLvlAltLf = 1, // Use alternate loop filter value...
|
||||||
SegLvlRefFrame = 2, // Optional Segment reference frame
|
SegLvlRefFrame = 2, // Optional Segment reference frame
|
||||||
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
||||||
SegLvlMax = 4 // Number of features supported
|
SegLvlMax = 4, // Number of features supported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,8 +6,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
{
|
{
|
||||||
internal struct Segmentation
|
internal struct Segmentation
|
||||||
{
|
{
|
||||||
private static readonly int[] SegFeatureDataSigned = new int[] { 1, 1, 0, 0 };
|
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
|
||||||
private static readonly int[] SegFeatureDataMax = new int[] { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
||||||
|
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
public bool UpdateMap;
|
public bool UpdateMap;
|
||||||
@@ -26,8 +26,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
|
|
||||||
public void ClearAllSegFeatures()
|
public void ClearAllSegFeatures()
|
||||||
{
|
{
|
||||||
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Clear();
|
||||||
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Clear();
|
||||||
AqAvOffset = 0;
|
AqAvOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,21 +38,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
|
|
||||||
internal static int FeatureDataMax(SegLvlFeatures featureId)
|
internal static int FeatureDataMax(SegLvlFeatures featureId)
|
||||||
{
|
{
|
||||||
return SegFeatureDataMax[(int)featureId];
|
return _segFeatureDataMax[(int)featureId];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
|
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
|
||||||
{
|
{
|
||||||
return SegFeatureDataSigned[(int)featureId];
|
return _segFeatureDataSigned[(int)featureId];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
|
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
|
||||||
{
|
{
|
||||||
Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]);
|
Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]);
|
||||||
if (segData < 0)
|
if (segData < 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0);
|
Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0);
|
||||||
Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]);
|
Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FeatureData[segmentId][(int)featureId] = (short)segData;
|
FeatureData[segmentId][(int)featureId] = (short)segData;
|
||||||
|
@@ -11,11 +11,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
public ArrayPtr<byte> UBuffer;
|
public ArrayPtr<byte> UBuffer;
|
||||||
public ArrayPtr<byte> VBuffer;
|
public ArrayPtr<byte> VBuffer;
|
||||||
|
|
||||||
public unsafe Plane YPlane => new Plane((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
public readonly unsafe Plane YPlane => new((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
||||||
public unsafe Plane UPlane => new Plane((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
public readonly unsafe Plane UPlane => new((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
||||||
public unsafe Plane VPlane => new Plane((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
public readonly unsafe Plane VPlane => new((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
||||||
|
|
||||||
public FrameField Field => FrameField.Progressive;
|
public readonly FrameField Field => FrameField.Progressive;
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
public int Height { get; }
|
public int Height { get; }
|
||||||
@@ -27,29 +27,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
public int UvAlignedWidth { get; }
|
public int UvAlignedWidth { get; }
|
||||||
public int UvAlignedHeight { get; }
|
public int UvAlignedHeight { get; }
|
||||||
public int UvStride { get; }
|
public int UvStride { get; }
|
||||||
public bool HighBd => false;
|
|
||||||
|
public bool HighBd { get; }
|
||||||
|
|
||||||
private readonly IntPtr _pointer;
|
private readonly IntPtr _pointer;
|
||||||
|
|
||||||
public Surface(int width, int height)
|
public Surface(int width, int height)
|
||||||
{
|
{
|
||||||
const int border = 32;
|
HighBd = false;
|
||||||
const int ssX = 1;
|
|
||||||
const int ssY = 1;
|
const int Border = 32;
|
||||||
const bool highbd = false;
|
const int SsX = 1;
|
||||||
|
const int SsY = 1;
|
||||||
|
|
||||||
int alignedWidth = (width + 7) & ~7;
|
int alignedWidth = (width + 7) & ~7;
|
||||||
int alignedHeight = (height + 7) & ~7;
|
int alignedHeight = (height + 7) & ~7;
|
||||||
int yStride = ((alignedWidth + 2 * border) + 31) & ~31;
|
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
|
||||||
int yplaneSize = (alignedHeight + 2 * border) * yStride;
|
int yplaneSize = (alignedHeight + 2 * Border) * yStride;
|
||||||
int uvWidth = alignedWidth >> ssX;
|
int uvWidth = alignedWidth >> SsX;
|
||||||
int uvHeight = alignedHeight >> ssY;
|
int uvHeight = alignedHeight >> SsY;
|
||||||
int uvStride = yStride >> ssX;
|
int uvStride = yStride >> SsX;
|
||||||
int uvBorderW = border >> ssX;
|
int uvBorderW = Border >> SsX;
|
||||||
int uvBorderH = border >> ssY;
|
int uvBorderH = Border >> SsY;
|
||||||
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
|
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
|
||||||
|
|
||||||
int frameSize = (highbd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
int frameSize = (HighBd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
||||||
|
|
||||||
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
||||||
_pointer = pointer;
|
_pointer = pointer;
|
||||||
@@ -58,23 +60,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
AlignedWidth = alignedWidth;
|
AlignedWidth = alignedWidth;
|
||||||
AlignedHeight = alignedHeight;
|
AlignedHeight = alignedHeight;
|
||||||
Stride = yStride;
|
Stride = yStride;
|
||||||
UvWidth = (width + ssX) >> ssX;
|
UvWidth = (width + SsX) >> SsX;
|
||||||
UvHeight = (height + ssY) >> ssY;
|
UvHeight = (height + SsY) >> SsY;
|
||||||
UvAlignedWidth = uvWidth;
|
UvAlignedWidth = uvWidth;
|
||||||
UvAlignedHeight = uvHeight;
|
UvAlignedHeight = uvHeight;
|
||||||
UvStride = uvStride;
|
UvStride = uvStride;
|
||||||
|
|
||||||
ArrayPtr<byte> NewPlane(int start, int size, int border)
|
ArrayPtr<byte> NewPlane(int start, int size, int planeBorder)
|
||||||
{
|
{
|
||||||
return new ArrayPtr<byte>(pointer + start + border, size - border);
|
return new ArrayPtr<byte>(pointer + start + planeBorder, size - planeBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
YBuffer = NewPlane(0, yplaneSize, (border * yStride) + border);
|
YBuffer = NewPlane(0, yplaneSize, (Border * yStride) + Border);
|
||||||
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||||
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public readonly void Dispose()
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(_pointer);
|
Marshal.FreeHGlobal(_pointer);
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
{
|
{
|
||||||
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
|
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
|
||||||
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
|
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
|
||||||
|
|
||||||
return Math.Min(offset, mis);
|
return Math.Min(offset, mis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
|
|
||||||
// Checks that the given miRow, miCol and search point
|
// Checks that the given miRow, miCol and search point
|
||||||
// are inside the borders of the tile.
|
// are inside the borders of the tile.
|
||||||
public bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
|
public readonly bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
|
||||||
{
|
{
|
||||||
return !(miRow + miPos.Row < 0 ||
|
return !(miRow + miPos.Row < 0 ||
|
||||||
miCol + miPos.Col < MiColStart ||
|
miCol + miPos.Col < MiColStart ||
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
Allow16X16 = 2, // Allow block transform size up to 16x16
|
Allow16X16 = 2, // Allow block transform size up to 16x16
|
||||||
Allow32X32 = 3, // Allow block transform size up to 32x32
|
Allow32X32 = 3, // Allow block transform size up to 32x32
|
||||||
TxModeSelect = 4, // Transform specified for each block
|
TxModeSelect = 4, // Transform specified for each block
|
||||||
TxModes = 5
|
TxModes = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,6 @@
|
|||||||
Tx8x8 = 1, // 8x8 transform
|
Tx8x8 = 1, // 8x8 transform
|
||||||
Tx16x16 = 2, // 16x16 transform
|
Tx16x16 = 2, // 16x16 transform
|
||||||
Tx32x32 = 3, // 32x32 transform
|
Tx32x32 = 3, // 32x32 transform
|
||||||
TxSizes = 4
|
TxSizes = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,6 @@
|
|||||||
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
||||||
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
||||||
AdstAdst = 3, // ADST in both directions
|
AdstAdst = 3, // ADST in both directions
|
||||||
TxTypes = 4
|
TxTypes = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
public ArrayPtr<sbyte> AboveSegContext;
|
public ArrayPtr<sbyte> AboveSegContext;
|
||||||
public ArrayPtr<sbyte> AboveContext;
|
public ArrayPtr<sbyte> AboveContext;
|
||||||
|
|
||||||
public bool FrameIsIntraOnly()
|
public readonly bool FrameIsIntraOnly()
|
||||||
{
|
{
|
||||||
return FrameType == FrameType.KeyFrame || IntraOnly;
|
return FrameType == FrameType.KeyFrame || IntraOnly;
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FreeTileWorkerData(MemoryAllocator allocator)
|
public readonly void FreeTileWorkerData(MemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
allocator.Free(TileWorkerData);
|
allocator.Free(TileWorkerData);
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPartitionProbs(ref MacroBlockD xd)
|
private readonly void SetPartitionProbs(ref MacroBlockD xd)
|
||||||
{
|
{
|
||||||
xd.PartitionProbs = FrameIsIntraOnly()
|
xd.PartitionProbs = FrameIsIntraOnly()
|
||||||
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
|
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
|
||||||
@@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
|
|
||||||
public void SetupSegmentationDequant()
|
public void SetupSegmentationDequant()
|
||||||
{
|
{
|
||||||
const BitDepth bitDepth = BitDepth.Bits8; // TODO: Configurable
|
const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
|
||||||
// Build y/uv dequant values based on segmentation.
|
// Build y/uv dequant values based on segmentation.
|
||||||
if (Seg.Enabled)
|
if (Seg.Enabled)
|
||||||
{
|
{
|
||||||
@@ -301,10 +301,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
for (i = 0; i < Constants.MaxSegments; ++i)
|
for (i = 0; i < Constants.MaxSegments; ++i)
|
||||||
{
|
{
|
||||||
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
|
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
|
||||||
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
|
||||||
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -312,10 +312,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
|||||||
int qIndex = BaseQindex;
|
int qIndex = BaseQindex;
|
||||||
// When segmentation is disabled, only the first value is used. The
|
// When segmentation is disabled, only the first value is used. The
|
||||||
// remaining are don't cares.
|
// remaining are don't cares.
|
||||||
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
|
||||||
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
Greater,
|
Greater,
|
||||||
NotEqual,
|
NotEqual,
|
||||||
GreaterOrEqual,
|
GreaterOrEqual,
|
||||||
Always
|
Always,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
// Generic types.
|
// Generic types.
|
||||||
Float,
|
Float,
|
||||||
Sint,
|
Sint,
|
||||||
Uint
|
Uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AttributeTypeExtensions
|
static class AttributeTypeExtensions
|
||||||
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
AttributeType.Float => "vec4",
|
AttributeType.Float => "vec4",
|
||||||
AttributeType.Sint => "ivec4",
|
AttributeType.Sint => "ivec4",
|
||||||
AttributeType.Uint => "uvec4",
|
AttributeType.Uint => "uvec4",
|
||||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
AttributeType.Float => AggregateType.FP32,
|
AttributeType.Float => AggregateType.FP32,
|
||||||
AttributeType.Sint => AggregateType.S32,
|
AttributeType.Sint => AggregateType.S32,
|
||||||
AttributeType.Uint => AggregateType.U32,
|
AttributeType.Uint => AggregateType.U32,
|
||||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffer is written to.
|
/// Buffer is written to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Write = 1 << 0
|
Write = 1 << 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -244,16 +244,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetTfLayout(TransformFeedbackOutput tfOutput)
|
|
||||||
{
|
|
||||||
if (tfOutput.Valid)
|
|
||||||
{
|
|
||||||
return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) ";
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
|
public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
|
||||||
{
|
{
|
||||||
foreach (AstOperand decl in function.Locals)
|
foreach (AstOperand decl in function.Locals)
|
||||||
@@ -294,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
|
AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
|
||||||
AggregateType.Vector4 | AggregateType.S32 => "ivec4",
|
AggregateType.Vector4 | AggregateType.S32 => "ivec4",
|
||||||
AggregateType.Vector4 | AggregateType.U32 => "uvec4",
|
AggregateType.Vector4 | AggregateType.U32 => "uvec4",
|
||||||
_ => throw new ArgumentException($"Invalid variable type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid variable type \"{type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
string layout = buffer.Layout switch
|
string layout = buffer.Layout switch
|
||||||
{
|
{
|
||||||
BufferLayout.Std140 => "std140",
|
BufferLayout.Std140 => "std140",
|
||||||
_ => "std430"
|
_ => "std430",
|
||||||
};
|
};
|
||||||
|
|
||||||
string set = string.Empty;
|
string set = string.Empty;
|
||||||
@@ -507,7 +497,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{
|
{
|
||||||
PixelImap.Constant => "flat ",
|
PixelImap.Constant => "flat ",
|
||||||
PixelImap.ScreenLinear => "noperspective ",
|
PixelImap.ScreenLinear => "noperspective ",
|
||||||
_ => string.Empty
|
_ => string.Empty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,7 +514,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
2 => "vec2",
|
2 => "vec2",
|
||||||
3 => "vec3",
|
3 => "vec3",
|
||||||
4 => "vec4",
|
4 => "vec4",
|
||||||
_ => "float"
|
_ => "float",
|
||||||
};
|
};
|
||||||
|
|
||||||
context.AppendLine($"layout (location = {attr}) in {type} {name};");
|
context.AppendLine($"layout (location = {attr}) in {type} {name};");
|
||||||
@@ -611,7 +601,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
2 => "vec2",
|
2 => "vec2",
|
||||||
3 => "vec3",
|
3 => "vec3",
|
||||||
4 => "vec4",
|
4 => "vec4",
|
||||||
_ => "float"
|
_ => "float",
|
||||||
};
|
};
|
||||||
|
|
||||||
string xfb = string.Empty;
|
string xfb = string.Empty;
|
||||||
@@ -647,7 +637,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{
|
{
|
||||||
AttributeType.Sint => "ivec4",
|
AttributeType.Sint => "ivec4",
|
||||||
AttributeType.Uint => "uvec4",
|
AttributeType.Uint => "uvec4",
|
||||||
_ => "vec4"
|
_ => "vec4",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)
|
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)
|
||||||
|
@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
public static string Generate(StructuredProgramInfo info, ShaderConfig config)
|
public static string Generate(StructuredProgramInfo info, ShaderConfig config)
|
||||||
{
|
{
|
||||||
CodeGenContext context = new CodeGenContext(info, config);
|
CodeGenContext context = new(info, config);
|
||||||
|
|
||||||
Declarations.Declare(context, info);
|
Declarations.Declare(context, info);
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
|
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
|
||||||
{
|
{
|
||||||
AstBlockVisitor visitor = new AstBlockVisitor(block);
|
AstBlockVisitor visitor = new(block);
|
||||||
|
|
||||||
visitor.BlockEntered += (sender, e) =>
|
visitor.BlockEntered += (sender, e) =>
|
||||||
{
|
{
|
||||||
@@ -96,7 +96,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
|
context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
|
default:
|
||||||
|
throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.EnterScope();
|
context.EnterScope();
|
||||||
|
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
_infoTable = new InstInfo[(int)Instruction.Count];
|
_infoTable = new InstInfo[(int)Instruction.Count];
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
|
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
|
||||||
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
|
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
|
||||||
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
|
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
|
||||||
@@ -125,6 +126,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
|
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
|
||||||
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
|
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
|
||||||
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
|
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
|
||||||
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
|
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
|
||||||
@@ -163,7 +165,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
// If the node isn't a operation, then it can only be a operand,
|
// If the node isn't a operation, then it can only be a operand,
|
||||||
// and those never needs to be surrounded in parenthesis.
|
// and those never needs to be surrounded in parenthesis.
|
||||||
if (!(node is AstOperation operation))
|
if (node is not AstOperation operation)
|
||||||
{
|
{
|
||||||
// This is sort of a special case, if this is a negative constant,
|
// This is sort of a special case, if this is a negative constant,
|
||||||
// and it is consumed by a unary operation, we need to put on the parenthesis,
|
// and it is consumed by a unary operation, we need to put on the parenthesis,
|
||||||
@@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
private static bool IsNegativeConst(IAstNode node)
|
private static bool IsNegativeConst(IAstNode node)
|
||||||
{
|
{
|
||||||
if (!(node is AstOperand operand))
|
if (node is not AstOperand operand)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.StructuredIr;
|
|||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
||||||
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
||||||
|
|
||||||
@@ -49,7 +48,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
if (texOp.Inst == Instruction.ImageAtomic)
|
if (texOp.Inst == Instruction.ImageAtomic)
|
||||||
{
|
{
|
||||||
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch {
|
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch
|
||||||
|
{
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
TextureFlags.Add => "imageAtomicAdd",
|
TextureFlags.Add => "imageAtomicAdd",
|
||||||
TextureFlags.Minimum => "imageAtomicMin",
|
TextureFlags.Minimum => "imageAtomicMin",
|
||||||
TextureFlags.Maximum => "imageAtomicMax",
|
TextureFlags.Maximum => "imageAtomicMax",
|
||||||
@@ -61,6 +62,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
TextureFlags.Swap => "imageAtomicExchange",
|
TextureFlags.Swap => "imageAtomicExchange",
|
||||||
TextureFlags.CAS => "imageAtomicCompSwap",
|
TextureFlags.CAS => "imageAtomicCompSwap",
|
||||||
_ => "imageAtomicAdd",
|
_ => "imageAtomicAdd",
|
||||||
|
#pragma warning restore IDE0055
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
AggregateType.S32 => NumberFormatter.FormatInt(0),
|
AggregateType.S32 => NumberFormatter.FormatInt(0),
|
||||||
AggregateType.U32 => NumberFormatter.FormatUint(0),
|
AggregateType.U32 => NumberFormatter.FormatUint(0),
|
||||||
_ => NumberFormatter.FormatFloat(0)
|
_ => NumberFormatter.FormatFloat(0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
AggregateType.S32 => "i",
|
AggregateType.S32 => "i",
|
||||||
AggregateType.U32 => "u",
|
AggregateType.U32 => "u",
|
||||||
_ => string.Empty
|
_ => string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
Append($"{prefix}vec4({string.Join(", ", cElems)})");
|
Append($"{prefix}vec4({string.Join(", ", cElems)})");
|
||||||
@@ -159,7 +161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
|
TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
|
||||||
TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
|
TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
|
||||||
_ => Src(type)
|
_ => Src(type),
|
||||||
};
|
};
|
||||||
|
|
||||||
Append(value);
|
Append(value);
|
||||||
@@ -584,7 +586,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
{
|
{
|
||||||
case StorageKind.ConstantBuffer:
|
case StorageKind.ConstantBuffer:
|
||||||
case StorageKind.StorageBuffer:
|
case StorageKind.StorageBuffer:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -594,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
? context.Config.Properties.ConstantBuffers[binding]
|
? context.Config.Properties.ConstantBuffers[binding]
|
||||||
: context.Config.Properties.StorageBuffers[binding];
|
: context.Config.Properties.StorageBuffers[binding];
|
||||||
|
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -606,7 +608,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
case StorageKind.LocalMemory:
|
case StorageKind.LocalMemory:
|
||||||
case StorageKind.SharedMemory:
|
case StorageKind.SharedMemory:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -623,7 +625,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
case StorageKind.InputPerPatch:
|
case StorageKind.InputPerPatch:
|
||||||
case StorageKind.Output:
|
case StorageKind.Output:
|
||||||
case StorageKind.OutputPerPatch:
|
case StorageKind.OutputPerPatch:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -636,7 +638,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||||
{
|
{
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
|
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||||
enum InstType
|
enum InstType
|
||||||
{
|
{
|
||||||
OpNullary = Op | 0,
|
OpNullary = Op | 0,
|
||||||
@@ -28,6 +30,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
Atomic = 1 << 11,
|
Atomic = 1 << 11,
|
||||||
Special = 1 << 12,
|
Special = 1 << 12,
|
||||||
|
|
||||||
ArityMask = 0xff
|
ArityMask = 0xff,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
|
IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
|
||||||
IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
|
IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
|
||||||
IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
|
IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
|
||||||
_ => (null, AggregateType.Invalid)
|
_ => (null, AggregateType.Invalid),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{
|
{
|
||||||
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
||||||
|
|
||||||
private Dictionary<AstOperand, string> _locals;
|
private readonly Dictionary<AstOperand, string> _locals;
|
||||||
|
|
||||||
public OperandManager()
|
public OperandManager()
|
||||||
{
|
{
|
||||||
@@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
|
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
|
||||||
OperandType.LocalVariable => _locals[operand],
|
OperandType.LocalVariable => _locals[operand],
|
||||||
OperandType.Undefined => DefaultNames.UndefinedName,
|
OperandType.Undefined => DefaultNames.UndefinedName,
|
||||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,11 +95,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
return _stagePrefixes[index];
|
return _stagePrefixes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char GetSwizzleMask(int value)
|
|
||||||
{
|
|
||||||
return "xyzw"[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetArgumentName(int argIndex)
|
public static string GetArgumentName(int argIndex)
|
||||||
{
|
{
|
||||||
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
|
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
|
||||||
@@ -119,12 +113,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{
|
{
|
||||||
case StorageKind.ConstantBuffer:
|
case StorageKind.ConstantBuffer:
|
||||||
case StorageKind.StorageBuffer:
|
case StorageKind.StorageBuffer:
|
||||||
if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
if (operation.GetSource(0) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
if (operation.GetSource(1) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -138,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
case StorageKind.LocalMemory:
|
case StorageKind.LocalMemory:
|
||||||
case StorageKind.SharedMemory:
|
case StorageKind.SharedMemory:
|
||||||
if (!(operation.GetSource(0) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
if (operation.GetSource(0) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -153,7 +147,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
case StorageKind.InputPerPatch:
|
case StorageKind.InputPerPatch:
|
||||||
case StorageKind.Output:
|
case StorageKind.Output:
|
||||||
case StorageKind.OutputPerPatch:
|
case StorageKind.OutputPerPatch:
|
||||||
if (!(operation.GetSource(0) is AstOperand varId) || varId.Type != OperandType.Constant)
|
if (operation.GetSource(0) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -166,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||||
{
|
{
|
||||||
if (!(operation.GetSource(1) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
if (operation.GetSource(1) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
|
@@ -38,18 +38,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{
|
{
|
||||||
switch (dstType)
|
switch (dstType)
|
||||||
{
|
{
|
||||||
case AggregateType.Bool: return $"(floatBitsToInt({expr}) != 0)";
|
case AggregateType.Bool:
|
||||||
case AggregateType.S32: return $"floatBitsToInt({expr})";
|
return $"(floatBitsToInt({expr}) != 0)";
|
||||||
case AggregateType.U32: return $"floatBitsToUint({expr})";
|
case AggregateType.S32:
|
||||||
|
return $"floatBitsToInt({expr})";
|
||||||
|
case AggregateType.U32:
|
||||||
|
return $"floatBitsToUint({expr})";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dstType == AggregateType.FP32)
|
else if (dstType == AggregateType.FP32)
|
||||||
{
|
{
|
||||||
switch (srcType)
|
switch (srcType)
|
||||||
{
|
{
|
||||||
case AggregateType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
|
case AggregateType.Bool:
|
||||||
case AggregateType.S32: return $"intBitsToFloat({expr})";
|
return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
|
||||||
case AggregateType.U32: return $"uintBitsToFloat({expr})";
|
case AggregateType.S32:
|
||||||
|
return $"intBitsToFloat({expr})";
|
||||||
|
case AggregateType.U32:
|
||||||
|
return $"uintBitsToFloat({expr})";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (srcType == AggregateType.Bool)
|
else if (srcType == AggregateType.Bool)
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
|
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using Spv.Generator;
|
using Spv.Generator;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using static Spv.Specification;
|
using static Spv.Specification;
|
||||||
|
using Instruction = Spv.Generator.Instruction;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
{
|
{
|
||||||
using IrConsts = IntermediateRepresentation.IrConsts;
|
|
||||||
using IrOperandType = IntermediateRepresentation.OperandType;
|
using IrOperandType = IntermediateRepresentation.OperandType;
|
||||||
|
|
||||||
partial class CodeGenContext : Module
|
partial class CodeGenContext : Module
|
||||||
@@ -36,15 +37,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>();
|
public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>();
|
||||||
|
|
||||||
public StructuredFunction CurrentFunction { get; set; }
|
public StructuredFunction CurrentFunction { get; set; }
|
||||||
private readonly Dictionary<AstOperand, Instruction> _locals = new Dictionary<AstOperand, Instruction>();
|
private readonly Dictionary<AstOperand, Instruction> _locals = new();
|
||||||
private readonly Dictionary<int, Instruction[]> _localForArgs = new Dictionary<int, Instruction[]>();
|
private readonly Dictionary<int, Instruction[]> _localForArgs = new();
|
||||||
private readonly Dictionary<int, Instruction> _funcArgs = new Dictionary<int, Instruction>();
|
private readonly Dictionary<int, Instruction> _funcArgs = new();
|
||||||
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new Dictionary<int, (StructuredFunction, Instruction)>();
|
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
|
||||||
|
|
||||||
private class BlockState
|
private class BlockState
|
||||||
{
|
{
|
||||||
private int _entryCount;
|
private int _entryCount;
|
||||||
private readonly List<Instruction> _labels = new List<Instruction>();
|
private readonly List<Instruction> _labels = new();
|
||||||
|
|
||||||
public Instruction GetNextLabel(CodeGenContext context)
|
public Instruction GetNextLabel(CodeGenContext context)
|
||||||
{
|
{
|
||||||
@@ -67,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<AstBlock, BlockState> _labels = new Dictionary<AstBlock, BlockState>();
|
private readonly Dictionary<AstBlock, BlockState> _labels = new();
|
||||||
|
|
||||||
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
|
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
|
||||||
|
|
||||||
@@ -98,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
InputTopology.LinesAdjacency => 2,
|
InputTopology.LinesAdjacency => 2,
|
||||||
InputTopology.Triangles => 3,
|
InputTopology.Triangles => 3,
|
||||||
InputTopology.TrianglesAdjacency => 3,
|
InputTopology.TrianglesAdjacency => 3,
|
||||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\".")
|
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +223,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
IrOperandType.Constant => GetConstant(type, operand),
|
IrOperandType.Constant => GetConstant(type, operand),
|
||||||
IrOperandType.LocalVariable => GetLocal(type, operand),
|
IrOperandType.LocalVariable => GetLocal(type, operand),
|
||||||
IrOperandType.Undefined => GetUndefined(type),
|
IrOperandType.Undefined => GetUndefined(type),
|
||||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +260,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AggregateType.Bool => ConstantFalse(TypeBool()),
|
AggregateType.Bool => ConstantFalse(TypeBool()),
|
||||||
AggregateType.FP32 => Constant(TypeFP32(), 0f),
|
AggregateType.FP32 => Constant(TypeFP32(), 0f),
|
||||||
AggregateType.FP64 => Constant(TypeFP64(), 0d),
|
AggregateType.FP64 => Constant(TypeFP64(), 0d),
|
||||||
_ => Constant(GetType(type), 0)
|
_ => Constant(GetType(type), 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)),
|
AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)),
|
||||||
AggregateType.S32 => Constant(TypeS32(), operand.Value),
|
AggregateType.S32 => Constant(TypeS32(), operand.Value),
|
||||||
AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value),
|
AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value),
|
||||||
_ => throw new ArgumentException($"Invalid type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid type \"{type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AggregateType.Vector2 => 2,
|
AggregateType.Vector2 => 2,
|
||||||
AggregateType.Vector3 => 3,
|
AggregateType.Vector3 => 3,
|
||||||
AggregateType.Vector4 => 4,
|
AggregateType.Vector4 => 4,
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
|
return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
|
||||||
@@ -342,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AggregateType.FP64 => TypeFP64(),
|
AggregateType.FP64 => TypeFP64(),
|
||||||
AggregateType.S32 => TypeS32(),
|
AggregateType.S32 => TypeS32(),
|
||||||
AggregateType.U32 => TypeU32(),
|
AggregateType.U32 => TypeU32(),
|
||||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
|
||||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using Spv.Generator;
|
using Spv.Generator;
|
||||||
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
static class Declarations
|
static class Declarations
|
||||||
{
|
{
|
||||||
private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
private static readonly string[] _stagePrefixes = { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
||||||
|
|
||||||
public static void DeclareParameters(CodeGenContext context, StructuredFunction function)
|
public static void DeclareParameters(CodeGenContext context, StructuredFunction function)
|
||||||
{
|
{
|
||||||
@@ -107,7 +106,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
|
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
|
||||||
{
|
{
|
||||||
HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>();
|
HashSet<SpvInstruction> decoratedTypes = new();
|
||||||
|
|
||||||
foreach (BufferDefinition buffer in buffers)
|
foreach (BufferDefinition buffer in buffers)
|
||||||
{
|
{
|
||||||
@@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
SamplerType.Texture3D => Dim.Dim3D,
|
SamplerType.Texture3D => Dim.Dim3D,
|
||||||
SamplerType.TextureCube => Dim.Cube,
|
SamplerType.TextureCube => Dim.Cube,
|
||||||
SamplerType.TextureBuffer => Dim.Buffer,
|
SamplerType.TextureBuffer => Dim.Buffer,
|
||||||
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\".")
|
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\"."),
|
||||||
};
|
};
|
||||||
|
|
||||||
var imageType = context.TypeImage(
|
var imageType = context.TypeImage(
|
||||||
@@ -282,7 +281,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
SamplerType.Texture3D => Dim.Dim3D,
|
SamplerType.Texture3D => Dim.Dim3D,
|
||||||
SamplerType.TextureCube => Dim.Cube,
|
SamplerType.TextureCube => Dim.Cube,
|
||||||
SamplerType.TextureBuffer => Dim.Buffer,
|
SamplerType.TextureBuffer => Dim.Buffer,
|
||||||
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\".")
|
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2,
|
TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2,
|
||||||
TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui,
|
TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui,
|
||||||
TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f,
|
TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f,
|
||||||
_ => throw new ArgumentException($"Invalid texture format \"{format}\".")
|
_ => throw new ArgumentException($"Invalid texture format \"{format}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
(_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
(_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
||||||
AggregateType elemType = varType & AggregateType.ElementTypeMask;
|
AggregateType elemType = varType & AggregateType.ElementTypeMask;
|
||||||
|
|
||||||
if (elemType == AggregateType.S32 || elemType == AggregateType.U32)
|
if (elemType is AggregateType.S32 or AggregateType.U32)
|
||||||
{
|
{
|
||||||
iq = PixelImap.Constant;
|
iq = PixelImap.Constant;
|
||||||
}
|
}
|
||||||
@@ -410,7 +409,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
2 => AggregateType.Vector2,
|
2 => AggregateType.Vector2,
|
||||||
3 => AggregateType.Vector3,
|
3 => AggregateType.Vector3,
|
||||||
4 => AggregateType.Vector4,
|
4 => AggregateType.Vector4,
|
||||||
_ => AggregateType.Invalid
|
_ => AggregateType.Invalid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +419,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput))
|
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput))
|
||||||
{
|
{
|
||||||
int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32;
|
int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32;
|
||||||
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), (LiteralInteger)arraySize));
|
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize));
|
||||||
|
|
||||||
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
@@ -542,7 +541,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
private static string GetStagePrefix(ShaderStage stage)
|
private static string GetStagePrefix(ShaderStage stage)
|
||||||
{
|
{
|
||||||
return StagePrefixes[(int)stage];
|
return _stagePrefixes[(int)stage];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation,
|
ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation,
|
||||||
ShaderStage.Geometry => ExecutionModel.Geometry,
|
ShaderStage.Geometry => ExecutionModel.Geometry,
|
||||||
ShaderStage.Fragment => ExecutionModel.Fragment,
|
ShaderStage.Fragment => ExecutionModel.Fragment,
|
||||||
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\".")
|
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,12 +21,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
MemorySemanticsMask.UniformMemory |
|
MemorySemanticsMask.UniformMemory |
|
||||||
MemorySemanticsMask.AcquireRelease;
|
MemorySemanticsMask.AcquireRelease;
|
||||||
|
|
||||||
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] InstTable;
|
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] _instTable;
|
||||||
|
|
||||||
static Instructions()
|
static Instructions()
|
||||||
{
|
{
|
||||||
InstTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
|
_instTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Add(Instruction.Absolute, GenerateAbsolute);
|
Add(Instruction.Absolute, GenerateAbsolute);
|
||||||
Add(Instruction.Add, GenerateAdd);
|
Add(Instruction.Add, GenerateAdd);
|
||||||
Add(Instruction.AtomicAdd, GenerateAtomicAdd);
|
Add(Instruction.AtomicAdd, GenerateAtomicAdd);
|
||||||
@@ -141,16 +142,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
Add(Instruction.VoteAll, GenerateVoteAll);
|
Add(Instruction.VoteAll, GenerateVoteAll);
|
||||||
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
|
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
|
||||||
Add(Instruction.VoteAny, GenerateVoteAny);
|
Add(Instruction.VoteAny, GenerateVoteAny);
|
||||||
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler)
|
private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler)
|
||||||
{
|
{
|
||||||
InstTable[(int)(inst & Instruction.Mask)] = handler;
|
_instTable[(int)(inst & Instruction.Mask)] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OperationResult Generate(CodeGenContext context, AstOperation operation)
|
public static OperationResult Generate(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
var handler = InstTable[(int)(operation.Inst & Instruction.Mask)];
|
var handler = _instTable[(int)(operation.Inst & Instruction.Mask)];
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
{
|
{
|
||||||
return handler(context, operation);
|
return handler(context, operation);
|
||||||
@@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
Debug.Assert(funcId.Type == OperandType.Constant);
|
Debug.Assert(funcId.Type == OperandType.Constant);
|
||||||
|
|
||||||
(var function, var spvFunc) = context.GetFunction(funcId.Value);
|
var (function, spvFunc) = context.GetFunction(funcId.Value);
|
||||||
|
|
||||||
var args = new SpvInstruction[operation.SourcesCount - 1];
|
var args = new SpvInstruction[operation.SourcesCount - 1];
|
||||||
var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
|
var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
|
||||||
@@ -625,11 +627,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = Src(AggregateType.S32);
|
Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
@@ -657,9 +657,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
SpvInstruction value = Src(componentType);
|
SpvInstruction value = Src(componentType);
|
||||||
|
|
||||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
(SpvInstruction imageType, SpvInstruction imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||||
|
|
||||||
var image = context.Load(imageType, imageVariable);
|
context.Load(imageType, imageVariable);
|
||||||
|
|
||||||
SpvInstruction resultType = context.GetType(componentType);
|
SpvInstruction resultType = context.GetType(componentType);
|
||||||
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
|
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
|
||||||
@@ -714,11 +714,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = Src(AggregateType.S32);
|
Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
@@ -744,7 +742,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
pCoords = Src(AggregateType.S32);
|
pCoords = Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||||
|
|
||||||
var image = context.Load(imageType, imageVariable);
|
var image = context.Load(imageType, imageVariable);
|
||||||
var imageComponentType = context.GetType(componentType);
|
var imageComponentType = context.GetType(componentType);
|
||||||
@@ -778,11 +776,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = Src(AggregateType.S32);
|
Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
@@ -833,7 +829,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
|
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
|
||||||
|
|
||||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||||
|
|
||||||
var image = context.Load(imageType, imageVariable);
|
var image = context.Load(imageType, imageVariable);
|
||||||
|
|
||||||
@@ -886,11 +882,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = Src(AggregateType.S32);
|
Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pCount = texOp.Type.GetDimensions();
|
int pCount = texOp.Type.GetDimensions();
|
||||||
@@ -916,7 +910,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||||
|
|
||||||
(_, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
var (_, sampledImageType, sampledImageVariable) = context.Samplers[meta];
|
||||||
|
|
||||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||||
|
|
||||||
@@ -973,7 +967,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
loopBlock = loopBlock.Parent;
|
loopBlock = loopBlock.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
(var loopTarget, var continueTarget) = context.LoopTargets[loopBlock];
|
(_, SpvInstruction continueTarget) = context.LoopTargets[loopBlock];
|
||||||
|
|
||||||
context.Branch(continueTarget);
|
context.Branch(continueTarget);
|
||||||
|
|
||||||
@@ -1307,11 +1301,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = Src(AggregateType.S32);
|
Src(AggregateType.S32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
@@ -1395,7 +1387,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
derivatives = new[]
|
derivatives = new[]
|
||||||
{
|
{
|
||||||
AssembleDerivativesVector(coordsCount), // dPdx
|
AssembleDerivativesVector(coordsCount), // dPdx
|
||||||
AssembleDerivativesVector(coordsCount) // dPdy
|
AssembleDerivativesVector(coordsCount), // dPdy
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,7 +1437,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AssembleOffsetVector(coordsCount),
|
AssembleOffsetVector(coordsCount),
|
||||||
AssembleOffsetVector(coordsCount),
|
AssembleOffsetVector(coordsCount),
|
||||||
AssembleOffsetVector(coordsCount),
|
AssembleOffsetVector(coordsCount),
|
||||||
AssembleOffsetVector(coordsCount)
|
AssembleOffsetVector(coordsCount),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1521,7 +1513,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||||
|
|
||||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
var (imageType, sampledImageType, sampledImageVariable) = context.Samplers[meta];
|
||||||
|
|
||||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||||
|
|
||||||
@@ -1595,16 +1587,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
SpvInstruction index = null;
|
|
||||||
|
|
||||||
if (isIndexed)
|
if (isIndexed)
|
||||||
{
|
{
|
||||||
index = context.GetS32(texOp.GetSource(0));
|
context.GetS32(texOp.GetSource(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||||
|
|
||||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
(SpvInstruction imageType, SpvInstruction sampledImageType, SpvInstruction sampledImageVariable) = context.Samplers[meta];
|
||||||
|
|
||||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||||
image = context.Image(imageType, image);
|
image = context.Image(imageType, image);
|
||||||
@@ -1809,12 +1799,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
case StorageKind.ConstantBuffer:
|
case StorageKind.ConstantBuffer:
|
||||||
case StorageKind.StorageBuffer:
|
case StorageKind.StorageBuffer:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(operation.GetSource(srcIndex) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -1833,7 +1823,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
case StorageKind.LocalMemory:
|
case StorageKind.LocalMemory:
|
||||||
case StorageKind.SharedMemory:
|
case StorageKind.SharedMemory:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -1856,7 +1846,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
case StorageKind.InputPerPatch:
|
case StorageKind.InputPerPatch:
|
||||||
case StorageKind.Output:
|
case StorageKind.Output:
|
||||||
case StorageKind.OutputPerPatch:
|
case StorageKind.OutputPerPatch:
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -1869,7 +1859,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||||
{
|
{
|
||||||
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||||
}
|
}
|
||||||
@@ -1964,7 +1954,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
|
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
|
||||||
{
|
{
|
||||||
(_, var varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
var (_, varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
||||||
varType &= AggregateType.ElementTypeMask;
|
varType &= AggregateType.ElementTypeMask;
|
||||||
|
|
||||||
var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable);
|
var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable);
|
||||||
|
@@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
|
IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
|
||||||
IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
|
IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
|
||||||
IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
|
IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
|
||||||
_ => (default, AggregateType.Invalid)
|
_ => (default, AggregateType.Invalid),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
IoVariable.TessellationLevelOuter => 4,
|
IoVariable.TessellationLevelOuter => 4,
|
||||||
IoVariable.ViewportMask => 1,
|
IoVariable.ViewportMask => 1,
|
||||||
IoVariable.UserDefined => MaxAttributes,
|
IoVariable.UserDefined => MaxAttributes,
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,9 +75,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
case IoVariable.PointCoord:
|
case IoVariable.PointCoord:
|
||||||
case IoVariable.ViewportMask:
|
case IoVariable.ViewportMask:
|
||||||
return !isOutput &&
|
return !isOutput &&
|
||||||
(stage == ShaderStage.TessellationControl ||
|
stage is ShaderStage.TessellationControl or ShaderStage.TessellationEvaluation or ShaderStage.Geometry;
|
||||||
stage == ShaderStage.TessellationEvaluation ||
|
|
||||||
stage == ShaderStage.Geometry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
readonly struct OperationResult
|
readonly struct OperationResult
|
||||||
{
|
{
|
||||||
public static OperationResult Invalid => new OperationResult(AggregateType.Invalid, null);
|
public static OperationResult Invalid => new(AggregateType.Invalid, null);
|
||||||
|
|
||||||
public AggregateType Type { get; }
|
public AggregateType Type { get; }
|
||||||
public Instruction Value { get; }
|
public Instruction Value { get; }
|
||||||
|
@@ -17,15 +17,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
// Resource pools for Spirv generation. Note: Increase count when more threads are being used.
|
// Resource pools for Spirv generation. Note: Increase count when more threads are being used.
|
||||||
private const int GeneratorPoolCount = 1;
|
private const int GeneratorPoolCount = 1;
|
||||||
private static ObjectPool<SpvInstructionPool> InstructionPool;
|
private static readonly ObjectPool<SpvInstructionPool> _instructionPool;
|
||||||
private static ObjectPool<SpvLiteralIntegerPool> IntegerPool;
|
private static readonly ObjectPool<SpvLiteralIntegerPool> _integerPool;
|
||||||
private static object PoolLock;
|
private static readonly object _poolLock;
|
||||||
|
|
||||||
static SpirvGenerator()
|
static SpirvGenerator()
|
||||||
{
|
{
|
||||||
InstructionPool = new (() => new SpvInstructionPool(), GeneratorPoolCount);
|
_instructionPool = new(() => new SpvInstructionPool(), GeneratorPoolCount);
|
||||||
IntegerPool = new (() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
|
_integerPool = new(() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
|
||||||
PoolLock = new object();
|
_poolLock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
private const HelperFunctionsMask NeedsInvocationIdMask =
|
private const HelperFunctionsMask NeedsInvocationIdMask =
|
||||||
@@ -40,13 +40,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
SpvInstructionPool instPool;
|
SpvInstructionPool instPool;
|
||||||
SpvLiteralIntegerPool integerPool;
|
SpvLiteralIntegerPool integerPool;
|
||||||
|
|
||||||
lock (PoolLock)
|
lock (_poolLock)
|
||||||
{
|
{
|
||||||
instPool = InstructionPool.Allocate();
|
instPool = _instructionPool.Allocate();
|
||||||
integerPool = IntegerPool.Allocate();
|
integerPool = _integerPool.Allocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGenContext context = new CodeGenContext(info, config, instPool, integerPool);
|
CodeGenContext context = new(info, config, instPool, integerPool);
|
||||||
|
|
||||||
context.AddCapability(Capability.GroupNonUniformBallot);
|
context.AddCapability(Capability.GroupNonUniformBallot);
|
||||||
context.AddCapability(Capability.GroupNonUniformShuffle);
|
context.AddCapability(Capability.GroupNonUniformShuffle);
|
||||||
@@ -133,10 +133,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
byte[] result = context.Generate();
|
byte[] result = context.Generate();
|
||||||
|
|
||||||
lock (PoolLock)
|
lock (_poolLock)
|
||||||
{
|
{
|
||||||
InstructionPool.Release(instPool);
|
_instructionPool.Release(instPool);
|
||||||
IntegerPool.Release(integerPool);
|
_integerPool.Release(integerPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
|
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
|
||||||
{
|
{
|
||||||
(var function, var spvFunc) = context.GetFunction(funcIndex);
|
var (function, spvFunc) = context.GetFunction(funcIndex);
|
||||||
|
|
||||||
context.CurrentFunction = function;
|
context.CurrentFunction = function;
|
||||||
context.AddFunction(spvFunc);
|
context.AddFunction(spvFunc);
|
||||||
@@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
Generate(context, function.MainBlock);
|
Generate(context, function.MainBlock);
|
||||||
|
|
||||||
// Functions must always end with a return.
|
// Functions must always end with a return.
|
||||||
if (!(function.MainBlock.Last is AstOperation operation) ||
|
if (function.MainBlock.Last is not AstOperation operation ||
|
||||||
(operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard))
|
(operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard))
|
||||||
{
|
{
|
||||||
context.Return();
|
context.Return();
|
||||||
@@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency,
|
InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency,
|
||||||
InputTopology.Triangles => ExecutionMode.Triangles,
|
InputTopology.Triangles => ExecutionMode.Triangles,
|
||||||
InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency,
|
InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency,
|
||||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\".")
|
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\"."),
|
||||||
});
|
});
|
||||||
|
|
||||||
context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive);
|
context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive);
|
||||||
@@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
OutputTopology.PointList => ExecutionMode.OutputPoints,
|
OutputTopology.PointList => ExecutionMode.OutputPoints,
|
||||||
OutputTopology.LineStrip => ExecutionMode.OutputLineStrip,
|
OutputTopology.LineStrip => ExecutionMode.OutputLineStrip,
|
||||||
OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip,
|
OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip,
|
||||||
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".")
|
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\"."),
|
||||||
});
|
});
|
||||||
|
|
||||||
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
|
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
|
||||||
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
private static void Generate(CodeGenContext context, AstBlock block)
|
private static void Generate(CodeGenContext context, AstBlock block)
|
||||||
{
|
{
|
||||||
AstBlockVisitor visitor = new AstBlockVisitor(block);
|
AstBlockVisitor visitor = new(block);
|
||||||
|
|
||||||
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
|
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
|
||||||
|
|
||||||
@@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
// if the condition is true.
|
// if the condition is true.
|
||||||
AstBlock mergeBlock = e.Block.Parent;
|
AstBlock mergeBlock = e.Block.Parent;
|
||||||
|
|
||||||
(var loopTarget, var continueTarget) = loopTargets[e.Block];
|
var (loopTarget, continueTarget) = loopTargets[e.Block];
|
||||||
|
|
||||||
context.Branch(continueTarget);
|
context.Branch(continueTarget);
|
||||||
context.AddLabel(continueTarget);
|
context.AddLabel(continueTarget);
|
||||||
|
@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
if (OpCodes.Count != 0)
|
if (OpCodes.Count != 0)
|
||||||
{
|
{
|
||||||
return OpCodes[OpCodes.Count - 1];
|
return OpCodes[^1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
|
@@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Decoders
|
namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
@@ -12,8 +11,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
||||||
{
|
{
|
||||||
Queue<DecodedFunction> functionsQueue = new Queue<DecodedFunction>();
|
Queue<DecodedFunction> functionsQueue = new();
|
||||||
Dictionary<ulong, DecodedFunction> functionsVisited = new Dictionary<ulong, DecodedFunction>();
|
Dictionary<ulong, DecodedFunction> functionsVisited = new();
|
||||||
|
|
||||||
DecodedFunction EnqueueFunction(ulong address)
|
DecodedFunction EnqueueFunction(ulong address)
|
||||||
{
|
{
|
||||||
@@ -30,9 +29,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
||||||
{
|
{
|
||||||
List<Block> blocks = new List<Block>();
|
List<Block> blocks = new();
|
||||||
Queue<Block> workQueue = new Queue<Block>();
|
Queue<Block> workQueue = new();
|
||||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
Dictionary<ulong, Block> visited = new();
|
||||||
|
|
||||||
Block GetBlock(ulong blkAddress)
|
Block GetBlock(ulong blkAddress)
|
||||||
{
|
{
|
||||||
@@ -273,12 +272,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
int offset;
|
int offset;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
bool isStore = false;
|
bool isStore = false;
|
||||||
bool indexed = false;
|
bool indexed;
|
||||||
bool perPatch = false;
|
bool perPatch = false;
|
||||||
|
|
||||||
if (name == InstName.Ast)
|
if (name == InstName.Ast)
|
||||||
{
|
{
|
||||||
InstAst opAst = new InstAst(opCode);
|
InstAst opAst = new(opCode);
|
||||||
count = (int)opAst.AlSize + 1;
|
count = (int)opAst.AlSize + 1;
|
||||||
offset = opAst.Imm11;
|
offset = opAst.Imm11;
|
||||||
indexed = opAst.Phys;
|
indexed = opAst.Phys;
|
||||||
@@ -287,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
}
|
}
|
||||||
else if (name == InstName.Ald)
|
else if (name == InstName.Ald)
|
||||||
{
|
{
|
||||||
InstAld opAld = new InstAld(opCode);
|
InstAld opAld = new(opCode);
|
||||||
count = (int)opAld.AlSize + 1;
|
count = (int)opAld.AlSize + 1;
|
||||||
offset = opAld.Imm11;
|
offset = opAld.Imm11;
|
||||||
indexed = opAld.Phys;
|
indexed = opAld.Phys;
|
||||||
@@ -296,7 +295,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
}
|
}
|
||||||
else /* if (name == InstName.Ipa) */
|
else /* if (name == InstName.Ipa) */
|
||||||
{
|
{
|
||||||
InstIpa opIpa = new InstIpa(opCode);
|
InstIpa opIpa = new(opCode);
|
||||||
offset = opIpa.Imm10;
|
offset = opIpa.Imm10;
|
||||||
indexed = opIpa.Idx;
|
indexed = opIpa.Idx;
|
||||||
}
|
}
|
||||||
@@ -370,7 +369,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
private static bool IsUnconditional(ref InstOp op)
|
private static bool IsUnconditional(ref InstOp op)
|
||||||
{
|
{
|
||||||
InstConditional condOp = new InstConditional(op.RawOpCode);
|
InstConditional condOp = new(op.RawOpCode);
|
||||||
|
|
||||||
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
|
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
|
||||||
{
|
{
|
||||||
@@ -391,9 +390,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
||||||
{
|
{
|
||||||
HashSet<ulong> visited = new HashSet<ulong>();
|
HashSet<ulong> visited = new();
|
||||||
|
|
||||||
InstBrx opBrx = new InstBrx(lastOp.RawOpCode);
|
InstBrx opBrx = new(lastOp.RawOpCode);
|
||||||
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
||||||
|
|
||||||
// An indirect branch could go anywhere,
|
// An indirect branch could go anywhere,
|
||||||
@@ -437,7 +436,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
|
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
|
||||||
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
|
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
|
||||||
|
|
||||||
HashSet<Block> visited = new HashSet<Block>();
|
HashSet<Block> visited = new();
|
||||||
|
|
||||||
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
|
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
|
||||||
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
|
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
|
||||||
@@ -507,7 +506,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
|
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
|
||||||
{
|
{
|
||||||
Queue<BlockLocation> toVisit = new Queue<BlockLocation>();
|
Queue<BlockLocation> toVisit = new();
|
||||||
toVisit.Enqueue(location);
|
toVisit.Enqueue(location);
|
||||||
visited.Add(location.Block);
|
visited.Add(location.Block);
|
||||||
|
|
||||||
@@ -554,10 +553,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
Brk,
|
Brk,
|
||||||
Cont,
|
Cont,
|
||||||
Sync
|
Sync,
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PathBlockState
|
private readonly struct PathBlockState
|
||||||
{
|
{
|
||||||
public Block Block { get; }
|
public Block Block { get; }
|
||||||
|
|
||||||
@@ -565,13 +564,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
PopPushOp,
|
PopPushOp,
|
||||||
PushBranchOp
|
PushBranchOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
private RestoreType _restoreType;
|
private readonly RestoreType _restoreType;
|
||||||
|
|
||||||
private ulong _restoreValue;
|
private readonly ulong _restoreValue;
|
||||||
private MergeType _restoreMergeType;
|
private readonly MergeType _restoreMergeType;
|
||||||
|
|
||||||
public bool ReturningFromVisit => _restoreType != RestoreType.None;
|
public bool ReturningFromVisit => _restoreType != RestoreType.None;
|
||||||
|
|
||||||
@@ -622,9 +621,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
Block target = blocks[pushOp.GetAbsoluteAddress()];
|
Block target = blocks[pushOp.GetAbsoluteAddress()];
|
||||||
|
|
||||||
Stack<PathBlockState> workQueue = new Stack<PathBlockState>();
|
Stack<PathBlockState> workQueue = new();
|
||||||
HashSet<Block> visited = new HashSet<Block>();
|
HashSet<Block> visited = new();
|
||||||
Stack<(ulong, MergeType)> branchStack = new Stack<(ulong, MergeType)>();
|
Stack<(ulong, MergeType)> branchStack = new();
|
||||||
|
|
||||||
void Push(PathBlockState pbs)
|
void Push(PathBlockState pbs)
|
||||||
{
|
{
|
||||||
@@ -759,7 +758,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
InstName.Pbk => MergeType.Brk,
|
InstName.Pbk => MergeType.Brk,
|
||||||
InstName.Pcnt => MergeType.Cont,
|
InstName.Pcnt => MergeType.Cont,
|
||||||
_ => MergeType.Sync
|
_ => MergeType.Sync,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +768,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
InstName.Brk => MergeType.Brk,
|
InstName.Brk => MergeType.Brk,
|
||||||
InstName.Cont => MergeType.Cont,
|
InstName.Cont => MergeType.Cont,
|
||||||
_ => MergeType.Sync
|
_ => MergeType.Sync,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
Tex = 1 << 12,
|
Tex = 1 << 12,
|
||||||
TexB = 1 << 13,
|
TexB = 1 << 13,
|
||||||
Bra = 1 << 14,
|
Bra = 1 << 14,
|
||||||
NoPred = 1 << 15
|
NoPred = 1 << 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -24,13 +24,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TableEntry[] _opCodes;
|
private static readonly TableEntry[] _opCodes;
|
||||||
|
|
||||||
static InstTable()
|
static InstTable()
|
||||||
{
|
{
|
||||||
_opCodes = new TableEntry[1 << EncodingBits];
|
_opCodes = new TableEntry[1 << EncodingBits];
|
||||||
|
|
||||||
#region Instructions
|
#region Instructions
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
|
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
|
||||||
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra);
|
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra);
|
||||||
Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc);
|
Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc);
|
||||||
@@ -325,6 +326,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
|
Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
|
||||||
Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
|
#pragma warning restore IDE0055
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +359,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
xMask = ~xMask;
|
xMask = ~xMask;
|
||||||
|
|
||||||
TableEntry entry = new TableEntry(name, emitter, props, xBits);
|
TableEntry entry = new(name, emitter, props, xBits);
|
||||||
|
|
||||||
for (int index = 0; index < (1 << xBits); index++)
|
for (int index = 0; index < (1 << xBits); index++)
|
||||||
{
|
{
|
||||||
|
@@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
Lines,
|
Lines,
|
||||||
LinesAdjacency,
|
LinesAdjacency,
|
||||||
Triangles,
|
Triangles,
|
||||||
TrianglesAdjacency
|
TrianglesAdjacency,
|
||||||
}
|
}
|
||||||
|
|
||||||
static class InputTopologyExtensions
|
static class InputTopologyExtensions
|
||||||
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
InputTopology.LinesAdjacency => "lines_adjacency",
|
InputTopology.LinesAdjacency => "lines_adjacency",
|
||||||
InputTopology.Triangles => "triangles",
|
InputTopology.Triangles => "triangles",
|
||||||
InputTopology.TrianglesAdjacency => "triangles_adjacency",
|
InputTopology.TrianglesAdjacency => "triangles_adjacency",
|
||||||
_ => "points"
|
_ => "points",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
InputTopology.LinesAdjacency => 2,
|
InputTopology.LinesAdjacency => 2,
|
||||||
InputTopology.Triangles or
|
InputTopology.Triangles or
|
||||||
InputTopology.TrianglesAdjacency => 3,
|
InputTopology.TrianglesAdjacency => 3,
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Instructions
|
namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
@@ -21,10 +20,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
Tessellation = TessellationControl | TessellationEvaluation,
|
Tessellation = TessellationControl | TessellationEvaluation,
|
||||||
VertexTessellationGeometry = Vertex | Tessellation | Geometry,
|
VertexTessellationGeometry = Vertex | Tessellation | Geometry,
|
||||||
TessellationGeometryFragment = Tessellation | Geometry | Fragment,
|
TessellationGeometryFragment = Tessellation | Geometry | Fragment,
|
||||||
AllGraphics = Vertex | Tessellation | Geometry | Fragment
|
AllGraphics = Vertex | Tessellation | Geometry | Fragment,
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct AttributeEntry
|
private readonly struct AttributeEntry
|
||||||
{
|
{
|
||||||
public int BaseOffset { get; }
|
public int BaseOffset { get; }
|
||||||
public AggregateType Type { get; }
|
public AggregateType Type { get; }
|
||||||
@@ -344,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
AggregateType.Vector2 => 2,
|
AggregateType.Vector2 => 2,
|
||||||
AggregateType.Vector3 => 3,
|
AggregateType.Vector3 => 3,
|
||||||
AggregateType.Vector4 => 4,
|
AggregateType.Vector4 => 4,
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,350 +7,350 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
{
|
{
|
||||||
public static void AtomCas(EmitterContext context)
|
public static void AtomCas(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstAtomCas op = context.GetOp<InstAtomCas>();
|
context.GetOp<InstAtomCas>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AtomsCas(EmitterContext context)
|
public static void AtomsCas(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstAtomsCas op = context.GetOp<InstAtomsCas>();
|
context.GetOp<InstAtomsCas>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void B2r(EmitterContext context)
|
public static void B2r(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstB2r op = context.GetOp<InstB2r>();
|
context.GetOp<InstB2r>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Bpt(EmitterContext context)
|
public static void Bpt(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstBpt op = context.GetOp<InstBpt>();
|
context.GetOp<InstBpt>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cctl(EmitterContext context)
|
public static void Cctl(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCctl op = context.GetOp<InstCctl>();
|
context.GetOp<InstCctl>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cctll(EmitterContext context)
|
public static void Cctll(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCctll op = context.GetOp<InstCctll>();
|
context.GetOp<InstCctll>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cctlt(EmitterContext context)
|
public static void Cctlt(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCctlt op = context.GetOp<InstCctlt>();
|
context.GetOp<InstCctlt>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cs2r(EmitterContext context)
|
public static void Cs2r(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCs2r op = context.GetOp<InstCs2r>();
|
context.GetOp<InstCs2r>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FchkR(EmitterContext context)
|
public static void FchkR(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstFchkR op = context.GetOp<InstFchkR>();
|
context.GetOp<InstFchkR>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FchkI(EmitterContext context)
|
public static void FchkI(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstFchkI op = context.GetOp<InstFchkI>();
|
context.GetOp<InstFchkI>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FchkC(EmitterContext context)
|
public static void FchkC(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstFchkC op = context.GetOp<InstFchkC>();
|
context.GetOp<InstFchkC>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Getcrsptr(EmitterContext context)
|
public static void Getcrsptr(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstGetcrsptr op = context.GetOp<InstGetcrsptr>();
|
context.GetOp<InstGetcrsptr>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Getlmembase(EmitterContext context)
|
public static void Getlmembase(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstGetlmembase op = context.GetOp<InstGetlmembase>();
|
context.GetOp<InstGetlmembase>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ide(EmitterContext context)
|
public static void Ide(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstIde op = context.GetOp<InstIde>();
|
context.GetOp<InstIde>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void IdpR(EmitterContext context)
|
public static void IdpR(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstIdpR op = context.GetOp<InstIdpR>();
|
context.GetOp<InstIdpR>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void IdpC(EmitterContext context)
|
public static void IdpC(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstIdpC op = context.GetOp<InstIdpC>();
|
context.GetOp<InstIdpC>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImadspR(EmitterContext context)
|
public static void ImadspR(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstImadspR op = context.GetOp<InstImadspR>();
|
context.GetOp<InstImadspR>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImadspI(EmitterContext context)
|
public static void ImadspI(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstImadspI op = context.GetOp<InstImadspI>();
|
context.GetOp<InstImadspI>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImadspC(EmitterContext context)
|
public static void ImadspC(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstImadspC op = context.GetOp<InstImadspC>();
|
context.GetOp<InstImadspC>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImadspRc(EmitterContext context)
|
public static void ImadspRc(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstImadspRc op = context.GetOp<InstImadspRc>();
|
context.GetOp<InstImadspRc>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Jcal(EmitterContext context)
|
public static void Jcal(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstJcal op = context.GetOp<InstJcal>();
|
context.GetOp<InstJcal>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Jmp(EmitterContext context)
|
public static void Jmp(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstJmp op = context.GetOp<InstJmp>();
|
context.GetOp<InstJmp>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Jmx(EmitterContext context)
|
public static void Jmx(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstJmx op = context.GetOp<InstJmx>();
|
context.GetOp<InstJmx>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ld(EmitterContext context)
|
public static void Ld(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstLd op = context.GetOp<InstLd>();
|
context.GetOp<InstLd>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Lepc(EmitterContext context)
|
public static void Lepc(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstLepc op = context.GetOp<InstLepc>();
|
context.GetOp<InstLepc>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Longjmp(EmitterContext context)
|
public static void Longjmp(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstLongjmp op = context.GetOp<InstLongjmp>();
|
context.GetOp<InstLongjmp>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pexit(EmitterContext context)
|
public static void Pexit(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPexit op = context.GetOp<InstPexit>();
|
context.GetOp<InstPexit>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pixld(EmitterContext context)
|
public static void Pixld(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPixld op = context.GetOp<InstPixld>();
|
context.GetOp<InstPixld>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Plongjmp(EmitterContext context)
|
public static void Plongjmp(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPlongjmp op = context.GetOp<InstPlongjmp>();
|
context.GetOp<InstPlongjmp>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pret(EmitterContext context)
|
public static void Pret(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPret op = context.GetOp<InstPret>();
|
context.GetOp<InstPret>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrmtR(EmitterContext context)
|
public static void PrmtR(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPrmtR op = context.GetOp<InstPrmtR>();
|
context.GetOp<InstPrmtR>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrmtI(EmitterContext context)
|
public static void PrmtI(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPrmtI op = context.GetOp<InstPrmtI>();
|
context.GetOp<InstPrmtI>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrmtC(EmitterContext context)
|
public static void PrmtC(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPrmtC op = context.GetOp<InstPrmtC>();
|
context.GetOp<InstPrmtC>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrmtRc(EmitterContext context)
|
public static void PrmtRc(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPrmtRc op = context.GetOp<InstPrmtRc>();
|
context.GetOp<InstPrmtRc>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void R2b(EmitterContext context)
|
public static void R2b(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstR2b op = context.GetOp<InstR2b>();
|
context.GetOp<InstR2b>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ram(EmitterContext context)
|
public static void Ram(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstRam op = context.GetOp<InstRam>();
|
context.GetOp<InstRam>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Rtt(EmitterContext context)
|
public static void Rtt(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstRtt op = context.GetOp<InstRtt>();
|
context.GetOp<InstRtt>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sam(EmitterContext context)
|
public static void Sam(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSam op = context.GetOp<InstSam>();
|
context.GetOp<InstSam>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Setcrsptr(EmitterContext context)
|
public static void Setcrsptr(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSetcrsptr op = context.GetOp<InstSetcrsptr>();
|
context.GetOp<InstSetcrsptr>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Setlmembase(EmitterContext context)
|
public static void Setlmembase(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSetlmembase op = context.GetOp<InstSetlmembase>();
|
context.GetOp<InstSetlmembase>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void St(EmitterContext context)
|
public static void St(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSt op = context.GetOp<InstSt>();
|
context.GetOp<InstSt>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction St is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction St is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Stp(EmitterContext context)
|
public static void Stp(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstStp op = context.GetOp<InstStp>();
|
context.GetOp<InstStp>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Txa(EmitterContext context)
|
public static void Txa(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstTxa op = context.GetOp<InstTxa>();
|
context.GetOp<InstTxa>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vabsdiff(EmitterContext context)
|
public static void Vabsdiff(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVabsdiff op = context.GetOp<InstVabsdiff>();
|
context.GetOp<InstVabsdiff>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vabsdiff4(EmitterContext context)
|
public static void Vabsdiff4(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVabsdiff4 op = context.GetOp<InstVabsdiff4>();
|
context.GetOp<InstVabsdiff4>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vadd(EmitterContext context)
|
public static void Vadd(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVadd op = context.GetOp<InstVadd>();
|
context.GetOp<InstVadd>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Votevtg(EmitterContext context)
|
public static void Votevtg(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVotevtg op = context.GetOp<InstVotevtg>();
|
context.GetOp<InstVotevtg>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vset(EmitterContext context)
|
public static void Vset(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVset op = context.GetOp<InstVset>();
|
context.GetOp<InstVset>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vshl(EmitterContext context)
|
public static void Vshl(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVshl op = context.GetOp<InstVshl>();
|
context.GetOp<InstVshl>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Vshr(EmitterContext context)
|
public static void Vshr(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstVshr op = context.GetOp<InstVshr>();
|
context.GetOp<InstVshr>();
|
||||||
|
|
||||||
context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented.");
|
context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented.");
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
|||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
IDstFmt.S16 => short.MinValue,
|
IDstFmt.S16 => short.MinValue,
|
||||||
IDstFmt.U32 => uint.MinValue,
|
IDstFmt.U32 => uint.MinValue,
|
||||||
IDstFmt.S32 => int.MinValue,
|
IDstFmt.S32 => int.MinValue,
|
||||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
IDstFmt.S16 => short.MaxValue,
|
IDstFmt.S16 => short.MaxValue,
|
||||||
IDstFmt.U32 => uint.MaxValue,
|
IDstFmt.U32 => uint.MaxValue,
|
||||||
IDstFmt.S32 => int.MaxValue,
|
IDstFmt.S32 => int.MaxValue,
|
||||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
ISrcDstFmt.S16 => short.MinValue,
|
ISrcDstFmt.S16 => short.MinValue,
|
||||||
ISrcDstFmt.U32 => uint.MinValue,
|
ISrcDstFmt.U32 => uint.MinValue,
|
||||||
ISrcDstFmt.S32 => int.MinValue,
|
ISrcDstFmt.S32 => int.MinValue,
|
||||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
ISrcDstFmt.S16 => short.MaxValue,
|
ISrcDstFmt.S16 => short.MaxValue,
|
||||||
ISrcDstFmt.U32 => uint.MaxValue,
|
ISrcDstFmt.U32 => uint.MaxValue,
|
||||||
ISrcDstFmt.S32 => int.MaxValue,
|
ISrcDstFmt.S32 => int.MaxValue,
|
||||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
BoolOp.And => context.BitwiseAnd(input, pred),
|
BoolOp.And => context.BitwiseAnd(input, pred),
|
||||||
BoolOp.Or => context.BitwiseOr(input, pred),
|
BoolOp.Or => context.BitwiseOr(input, pred),
|
||||||
BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
|
BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
|
||||||
_ => input
|
_ => input,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8),
|
VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8),
|
||||||
VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16),
|
VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16),
|
||||||
VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16),
|
VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16),
|
||||||
_ => src
|
_ => src,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
for (int index = 0; index < (int)op.AlSize + 1; index++)
|
for (int index = 0; index < (int)op.AlSize + 1; index++)
|
||||||
{
|
{
|
||||||
Register rd = new Register(op.Dest + index, RegisterType.Gpr);
|
Register rd = new(op.Dest + index, RegisterType.Gpr);
|
||||||
|
|
||||||
if (rd.IsRZ)
|
if (rd.IsRZ)
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Register rd = new Register(op.SrcB + index, RegisterType.Gpr);
|
Register rd = new(op.SrcB + index, RegisterType.Gpr);
|
||||||
|
|
||||||
if (op.Phys)
|
if (op.Phys)
|
||||||
{
|
{
|
||||||
|
@@ -22,7 +22,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static void Depbar(EmitterContext context)
|
public static void Depbar(EmitterContext context)
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0059 // Remove unnecessary value assignment
|
||||||
InstDepbar op = context.GetOp<InstDepbar>();
|
InstDepbar op = context.GetOp<InstDepbar>();
|
||||||
|
#pragma warning restore IDE0059
|
||||||
|
|
||||||
// No operation.
|
// No operation.
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Graphics.Shader.Decoders;
|
using Ryujinx.Graphics.Shader.Decoders;
|
||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
@@ -80,7 +79,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
Ccc.Oft => GetVF(),
|
Ccc.Oft => GetVF(),
|
||||||
Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()),
|
Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()),
|
||||||
Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())),
|
Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())),
|
||||||
_ => Const(defaultCond)
|
_ => Const(defaultCond),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
|||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
@@ -140,7 +139,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()),
|
IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()),
|
||||||
IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()),
|
IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()),
|
||||||
IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()),
|
IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()),
|
||||||
_ => srcB
|
_ => srcB,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
RoundMode2.Floor => context.FPFloor(srcB, fpType),
|
RoundMode2.Floor => context.FPFloor(srcB, fpType),
|
||||||
RoundMode2.Ceil => context.FPCeiling(srcB, fpType),
|
RoundMode2.Ceil => context.FPCeiling(srcB, fpType),
|
||||||
RoundMode2.Trunc => context.FPTruncate(srcB, fpType),
|
RoundMode2.Trunc => context.FPTruncate(srcB, fpType),
|
||||||
_ => srcB
|
_ => srcB,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isSignedInt)
|
if (!isSignedInt)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Graphics.Shader.Decoders;
|
using Ryujinx.Graphics.Shader.Decoders;
|
||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
@@ -458,7 +457,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
MultiplyScale.M2 => ConstF(2f),
|
MultiplyScale.M2 => ConstF(2f),
|
||||||
MultiplyScale.M4 => ConstF(4f),
|
MultiplyScale.M4 => ConstF(4f),
|
||||||
MultiplyScale.M8 => ConstF(8f),
|
MultiplyScale.M8 => ConstF(8f),
|
||||||
_ => ConstF(1f) // Invalid, behave as if it had no scale.
|
_ => ConstF(1f), // Invalid, behave as if it had no scale.
|
||||||
};
|
};
|
||||||
|
|
||||||
if (scaleConst.AsFloat() == 1f)
|
if (scaleConst.AsFloat() == 1f)
|
||||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
|||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
@@ -546,20 +545,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Instruction inst;
|
var inst = (cond & ~FComp.Nan) switch
|
||||||
|
|
||||||
switch (cond & ~FComp.Nan)
|
|
||||||
{
|
{
|
||||||
case FComp.Lt: inst = Instruction.CompareLess; break;
|
FComp.Lt => Instruction.CompareLess,
|
||||||
case FComp.Eq: inst = Instruction.CompareEqual; break;
|
FComp.Eq => Instruction.CompareEqual,
|
||||||
case FComp.Le: inst = Instruction.CompareLessOrEqual; break;
|
FComp.Le => Instruction.CompareLessOrEqual,
|
||||||
case FComp.Gt: inst = Instruction.CompareGreater; break;
|
FComp.Gt => Instruction.CompareGreater,
|
||||||
case FComp.Ne: inst = Instruction.CompareNotEqual; break;
|
FComp.Ne => Instruction.CompareNotEqual,
|
||||||
case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break;
|
FComp.Ge => Instruction.CompareGreaterOrEqual,
|
||||||
|
_ => throw new ArgumentException($"Unexpected condition \"{cond}\"."),
|
||||||
default: throw new ArgumentException($"Unexpected condition \"{cond}\".");
|
};
|
||||||
}
|
|
||||||
|
|
||||||
res = context.Add(inst | fpType, Local(), srcA, srcB);
|
res = context.Add(inst | fpType, Local(), srcA, srcB);
|
||||||
|
|
||||||
if ((cond & FComp.Nan) != 0)
|
if ((cond & FComp.Nan) != 0)
|
||||||
|
@@ -3,8 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
|||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Instructions
|
namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
@@ -13,14 +11,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
{
|
{
|
||||||
public static void Bra(EmitterContext context)
|
public static void Bra(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstBra op = context.GetOp<InstBra>();
|
context.GetOp<InstBra>();
|
||||||
|
|
||||||
EmitBranch(context, context.CurrBlock.Successors[^1].Address);
|
EmitBranch(context, context.CurrBlock.Successors[^1].Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Brk(EmitterContext context)
|
public static void Brk(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstBrk op = context.GetOp<InstBrk>();
|
context.GetOp<InstBrk>();
|
||||||
|
|
||||||
EmitBrkContSync(context);
|
EmitBrkContSync(context);
|
||||||
}
|
}
|
||||||
@@ -123,7 +121,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static void Cal(EmitterContext context)
|
public static void Cal(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCal op = context.GetOp<InstCal>();
|
context.GetOp<InstCal>();
|
||||||
|
|
||||||
DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress());
|
DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress());
|
||||||
|
|
||||||
@@ -147,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static void Cont(EmitterContext context)
|
public static void Cont(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstCont op = context.GetOp<InstCont>();
|
context.GetOp<InstCont>();
|
||||||
|
|
||||||
EmitBrkContSync(context);
|
EmitBrkContSync(context);
|
||||||
}
|
}
|
||||||
@@ -185,28 +183,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static void Kil(EmitterContext context)
|
public static void Kil(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstKil op = context.GetOp<InstKil>();
|
context.GetOp<InstKil>();
|
||||||
|
|
||||||
context.Discard();
|
context.Discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pbk(EmitterContext context)
|
public static void Pbk(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPbk op = context.GetOp<InstPbk>();
|
context.GetOp<InstPbk>();
|
||||||
|
|
||||||
EmitPbkPcntSsy(context);
|
EmitPbkPcntSsy(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pcnt(EmitterContext context)
|
public static void Pcnt(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstPcnt op = context.GetOp<InstPcnt>();
|
context.GetOp<InstPcnt>();
|
||||||
|
|
||||||
EmitPbkPcntSsy(context);
|
EmitPbkPcntSsy(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ret(EmitterContext context)
|
public static void Ret(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstRet op = context.GetOp<InstRet>();
|
context.GetOp<InstRet>();
|
||||||
|
|
||||||
if (context.IsNonMain)
|
if (context.IsNonMain)
|
||||||
{
|
{
|
||||||
@@ -220,14 +218,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static void Ssy(EmitterContext context)
|
public static void Ssy(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSsy op = context.GetOp<InstSsy>();
|
context.GetOp<InstSsy>();
|
||||||
|
|
||||||
EmitPbkPcntSsy(context);
|
EmitPbkPcntSsy(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sync(EmitterContext context)
|
public static void Sync(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSync op = context.GetOp<InstSync>();
|
context.GetOp<InstSync>();
|
||||||
|
|
||||||
EmitBrkContSync(context);
|
EmitBrkContSync(context);
|
||||||
}
|
}
|
||||||
@@ -275,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
private static void EmitBranch(EmitterContext context, ulong address)
|
private static void EmitBranch(EmitterContext context, ulong address)
|
||||||
{
|
{
|
||||||
InstOp op = context.CurrOp;
|
InstOp op = context.CurrOp;
|
||||||
InstConditional opCond = new InstConditional(op.RawOpCode);
|
InstConditional opCond = new(op.RawOpCode);
|
||||||
|
|
||||||
// If we're branching to the next instruction, then the branch
|
// If we're branching to the next instruction, then the branch
|
||||||
// is useless and we can ignore it.
|
// is useless and we can ignore it.
|
||||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
|||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Instructions
|
namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
@@ -111,7 +110,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
return new Operand[]
|
return new Operand[]
|
||||||
{
|
{
|
||||||
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
||||||
ConstF((float)Unsafe.As<ushort, Half>(ref high))
|
ConstF((float)Unsafe.As<ushort, Half>(ref high)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
return new Operand[]
|
return new Operand[]
|
||||||
{
|
{
|
||||||
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
||||||
ConstF((float)Unsafe.As<ushort, Half>(ref high))
|
ConstF((float)Unsafe.As<ushort, Half>(ref high)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,42 +138,37 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle)
|
public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle)
|
||||||
{
|
{
|
||||||
switch (swizzle)
|
return swizzle switch
|
||||||
{
|
{
|
||||||
case HalfSwizzle.F16:
|
HalfSwizzle.F16 => new Operand[]
|
||||||
return new Operand[]
|
|
||||||
{
|
{
|
||||||
context.UnpackHalf2x16Low (src),
|
context.UnpackHalf2x16Low (src),
|
||||||
context.UnpackHalf2x16High(src)
|
context.UnpackHalf2x16High(src),
|
||||||
};
|
},
|
||||||
|
HalfSwizzle.F32 => new Operand[] { src, src },
|
||||||
case HalfSwizzle.F32: return new Operand[] { src, src };
|
HalfSwizzle.H0H0 => new Operand[]
|
||||||
|
|
||||||
case HalfSwizzle.H0H0:
|
|
||||||
return new Operand[]
|
|
||||||
{
|
{
|
||||||
context.UnpackHalf2x16Low(src),
|
context.UnpackHalf2x16Low(src),
|
||||||
context.UnpackHalf2x16Low(src)
|
context.UnpackHalf2x16Low(src),
|
||||||
};
|
},
|
||||||
|
HalfSwizzle.H1H1 => new Operand[]
|
||||||
case HalfSwizzle.H1H1:
|
|
||||||
return new Operand[]
|
|
||||||
{
|
{
|
||||||
context.UnpackHalf2x16High(src),
|
context.UnpackHalf2x16High(src),
|
||||||
context.UnpackHalf2x16High(src)
|
context.UnpackHalf2x16High(src),
|
||||||
|
},
|
||||||
|
_ => throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd)
|
public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd)
|
||||||
{
|
{
|
||||||
switch (swizzle)
|
switch (swizzle)
|
||||||
{
|
{
|
||||||
case OFmt.F16: return context.PackHalf2x16(results[0], results[1]);
|
case OFmt.F16:
|
||||||
|
return context.PackHalf2x16(results[0], results[1]);
|
||||||
|
|
||||||
case OFmt.F32: return results[0];
|
case OFmt.F32:
|
||||||
|
return results[0];
|
||||||
|
|
||||||
case OFmt.MrgH0:
|
case OFmt.MrgH0:
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user