Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
90432946ac | |||
9bad71afbf | |||
923089a298 | |||
d9aa15eb24 | |||
12c89a61f9 | |||
f5235fff29 |
@ -157,6 +157,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Add(X86Instruction.Paddd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Palignr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pand, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pandn, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
@ -239,6 +240,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Add(X86Instruction.Rsqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Sar, new InstructionInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Setcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstructionFlags.Reg8Dest));
|
||||
Add(X86Instruction.Sha256Msg1, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cc, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Msg2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cd, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Rnds2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cb, InstructionFlags.None));
|
||||
Add(X86Instruction.Shl, new InstructionInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shr, new InstructionInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shufpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
|
@ -12,21 +12,28 @@ namespace ARMeilleure.CodeGen.X86
|
||||
return;
|
||||
}
|
||||
|
||||
(_, _, int ecx, int edx) = X86Base.CpuId(0x00000001, 0x00000000);
|
||||
(int maxNum, _, _, _) = X86Base.CpuId(0x00000000, 0x00000000);
|
||||
|
||||
FeatureInfoEdx = (FeatureFlagsEdx)edx;
|
||||
FeatureInfoEcx = (FeatureFlagsEcx)ecx;
|
||||
(_, _, int ecx1, int edx1) = X86Base.CpuId(0x00000001, 0x00000000);
|
||||
FeatureInfo1Edx = (FeatureFlags1Edx)edx1;
|
||||
FeatureInfo1Ecx = (FeatureFlags1Ecx)ecx1;
|
||||
|
||||
if (maxNum >= 7)
|
||||
{
|
||||
(_, int ebx7, _, _) = X86Base.CpuId(0x00000007, 0x00000000);
|
||||
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FeatureFlagsEdx
|
||||
public enum FeatureFlags1Edx
|
||||
{
|
||||
Sse = 1 << 25,
|
||||
Sse2 = 1 << 26
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FeatureFlagsEcx
|
||||
public enum FeatureFlags1Ecx
|
||||
{
|
||||
Sse3 = 1 << 0,
|
||||
Pclmulqdq = 1 << 1,
|
||||
@ -40,21 +47,31 @@ namespace ARMeilleure.CodeGen.X86
|
||||
F16c = 1 << 29
|
||||
}
|
||||
|
||||
public static FeatureFlagsEdx FeatureInfoEdx { get; }
|
||||
public static FeatureFlagsEcx FeatureInfoEcx { get; }
|
||||
[Flags]
|
||||
public enum FeatureFlags7Ebx
|
||||
{
|
||||
Avx2 = 1 << 5,
|
||||
Sha = 1 << 29
|
||||
}
|
||||
|
||||
public static bool SupportsSse => FeatureInfoEdx.HasFlag(FeatureFlagsEdx.Sse);
|
||||
public static bool SupportsSse2 => FeatureInfoEdx.HasFlag(FeatureFlagsEdx.Sse2);
|
||||
public static bool SupportsSse3 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse3);
|
||||
public static bool SupportsPclmulqdq => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Pclmulqdq);
|
||||
public static bool SupportsSsse3 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Ssse3);
|
||||
public static bool SupportsFma => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Fma);
|
||||
public static bool SupportsSse41 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse41);
|
||||
public static bool SupportsSse42 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse42);
|
||||
public static bool SupportsPopcnt => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Popcnt);
|
||||
public static bool SupportsAesni => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Aes);
|
||||
public static bool SupportsAvx => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Avx);
|
||||
public static bool SupportsF16c => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.F16c);
|
||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
|
||||
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
|
||||
|
||||
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
|
||||
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
|
||||
public static bool SupportsSse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse3);
|
||||
public static bool SupportsPclmulqdq => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Pclmulqdq);
|
||||
public static bool SupportsSsse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Ssse3);
|
||||
public static bool SupportsFma => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Fma);
|
||||
public static bool SupportsSse41 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse41);
|
||||
public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
|
||||
public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
|
||||
public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
|
||||
public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx);
|
||||
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
||||
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
|
||||
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
|
||||
|
||||
public static bool ForceLegacySse { get; set; }
|
||||
|
||||
|
@ -82,6 +82,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddw, new IntrinsicInfo(X86Instruction.Paddw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Palignr, new IntrinsicInfo(X86Instruction.Palignr, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Pand, new IntrinsicInfo(X86Instruction.Pand, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pandn, new IntrinsicInfo(X86Instruction.Pandn, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pavgb, new IntrinsicInfo(X86Instruction.Pavgb, IntrinsicType.Binary));
|
||||
@ -151,6 +152,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Add(Intrinsic.X86Roundss, new IntrinsicInfo(X86Instruction.Roundss, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Rsqrtps, new IntrinsicInfo(X86Instruction.Rsqrtps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Rsqrtss, new IntrinsicInfo(X86Instruction.Rsqrtss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sha256Msg1, new IntrinsicInfo(X86Instruction.Sha256Msg1, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Msg2, new IntrinsicInfo(X86Instruction.Sha256Msg2, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Rnds2, new IntrinsicInfo(X86Instruction.Sha256Rnds2, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Shufpd, new IntrinsicInfo(X86Instruction.Shufpd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Shufps, new IntrinsicInfo(X86Instruction.Shufps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Sqrtpd, new IntrinsicInfo(X86Instruction.Sqrtpd, IntrinsicType.Unary));
|
||||
|
@ -308,11 +308,13 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
case Instruction.Extended:
|
||||
{
|
||||
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
|
||||
node.Intrinsic == Intrinsic.X86Blendvps ||
|
||||
node.Intrinsic == Intrinsic.X86Pblendvb;
|
||||
|
||||
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
||||
if ((node.Intrinsic == Intrinsic.X86Blendvpd ||
|
||||
node.Intrinsic == Intrinsic.X86Blendvps ||
|
||||
node.Intrinsic == Intrinsic.X86Pblendvb) &&
|
||||
!HardwareCapabilities.SupportsVexEncoding)
|
||||
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
||||
if ((isBlend && !HardwareCapabilities.SupportsVexEncoding) || node.Intrinsic == Intrinsic.X86Sha256Rnds2)
|
||||
{
|
||||
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
|
||||
|
||||
|
@ -98,6 +98,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Paddd,
|
||||
Paddq,
|
||||
Paddw,
|
||||
Palignr,
|
||||
Pand,
|
||||
Pandn,
|
||||
Pavgb,
|
||||
@ -180,6 +181,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Rsqrtss,
|
||||
Sar,
|
||||
Setcc,
|
||||
Sha256Msg1,
|
||||
Sha256Msg2,
|
||||
Sha256Rnds2,
|
||||
Shl,
|
||||
Shr,
|
||||
Shufpd,
|
||||
|
@ -100,7 +100,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, d, n, m, part2: false);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
@ -113,7 +113,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, n, d, m, part2: true);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
@ -125,7 +125,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), d, n);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256su0(context, d, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
@ -138,7 +138,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256su1(context, d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVecA32(op.Qn);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, d, n, m, part2: false);
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
@ -30,7 +30,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVecA32(op.Qn);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, n, d, m, part2: true);
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand d = GetVecA32(op.Qd);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), d, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256su0(context, d, m);
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand n = GetVecA32(op.Qn);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), d, n, m);
|
||||
Operand res = InstEmitSimdHashHelper.EmitSha256su1(context, d, n, m);
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
56
ARMeilleure/Instructions/InstEmitSimdHashHelper.cs
Normal file
56
ARMeilleure/Instructions/InstEmitSimdHashHelper.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class InstEmitSimdHashHelper
|
||||
{
|
||||
public static Operand EmitSha256h(ArmEmitterContext context, Operand x, Operand y, Operand w, bool part2)
|
||||
{
|
||||
if (Optimizations.UseSha)
|
||||
{
|
||||
Operand src1 = context.AddIntrinsic(Intrinsic.X86Shufps, y, x, Const(0xbb));
|
||||
Operand src2 = context.AddIntrinsic(Intrinsic.X86Shufps, y, x, Const(0x11));
|
||||
Operand w2 = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, w, w);
|
||||
|
||||
Operand round2 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src1, src2, w);
|
||||
Operand round4 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src2, round2, w2);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Shufps, round4, round2, Const(part2 ? 0x11 : 0xbb));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
String method = part2 ? nameof(SoftFallback.HashUpper) : nameof(SoftFallback.HashLower);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(method), x, y, w);
|
||||
}
|
||||
|
||||
public static Operand EmitSha256su0(ArmEmitterContext context, Operand x, Operand y)
|
||||
{
|
||||
if (Optimizations.UseSha)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Sha256Msg1, x, y);
|
||||
}
|
||||
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), x, y);
|
||||
}
|
||||
|
||||
public static Operand EmitSha256su1(ArmEmitterContext context, Operand x, Operand y, Operand z)
|
||||
{
|
||||
if (Optimizations.UseSha && Optimizations.UseSsse3)
|
||||
{
|
||||
Operand extr = context.AddIntrinsic(Intrinsic.X86Palignr, z, y, Const(4));
|
||||
Operand tmp = context.AddIntrinsic(Intrinsic.X86Paddd, extr, x);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Sha256Msg2, tmp, z);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
@ -1129,7 +1129,7 @@ namespace ARMeilleure.Instructions
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||
}
|
||||
|
||||
public static V128 HashUpper(V128 hash_efgh, V128 hash_abcd, V128 wk)
|
||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
X86Paddd,
|
||||
X86Paddq,
|
||||
X86Paddw,
|
||||
X86Palignr,
|
||||
X86Pand,
|
||||
X86Pandn,
|
||||
X86Pavgb,
|
||||
@ -140,6 +141,9 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
X86Roundss,
|
||||
X86Rsqrtps,
|
||||
X86Rsqrtss,
|
||||
X86Sha256Msg1,
|
||||
X86Sha256Msg2,
|
||||
X86Sha256Rnds2,
|
||||
X86Shufpd,
|
||||
X86Shufps,
|
||||
X86Sqrtpd,
|
||||
|
@ -21,6 +21,7 @@ namespace ARMeilleure
|
||||
public static bool UseFmaIfAvailable { get; set; } = true;
|
||||
public static bool UseAesniIfAvailable { get; set; } = true;
|
||||
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
|
||||
public static bool UseShaIfAvailable { get; set; } = true;
|
||||
|
||||
public static bool ForceLegacySse
|
||||
{
|
||||
@ -40,5 +41,6 @@ namespace ARMeilleure
|
||||
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
|
||||
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
|
||||
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
|
||||
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 3439; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 3585; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
@ -946,9 +946,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
return BitConverter.IsLittleEndian;
|
||||
}
|
||||
|
||||
private static ulong GetFeatureInfo()
|
||||
private static FeatureInfo GetFeatureInfo()
|
||||
{
|
||||
return (ulong)HardwareCapabilities.FeatureInfoEdx << 32 | (uint)HardwareCapabilities.FeatureInfoEcx;
|
||||
return new FeatureInfo(
|
||||
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
||||
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ebx);
|
||||
}
|
||||
|
||||
private static byte GetMemoryManagerMode()
|
||||
@ -968,7 +971,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return osPlatform;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 50*/)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 54*/)]
|
||||
private struct OuterHeader
|
||||
{
|
||||
public ulong Magic;
|
||||
@ -976,7 +979,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
public uint CacheFileVersion;
|
||||
|
||||
public bool Endianness;
|
||||
public ulong FeatureInfo;
|
||||
public FeatureInfo FeatureInfo;
|
||||
public byte MemoryManagerMode;
|
||||
public uint OSPlatform;
|
||||
|
||||
@ -999,6 +1002,9 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 12*/)]
|
||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
|
||||
private struct InnerHeader
|
||||
{
|
||||
|
@ -131,56 +131,56 @@
|
||||
<MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="en_US"
|
||||
Header="American English" />
|
||||
CommandParameter="de_DE"
|
||||
Header="Deutsch" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="pt_BR"
|
||||
Header="Brazilian Portuguese" />
|
||||
CommandParameter="en_US"
|
||||
Header="English (US)" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="es_ES"
|
||||
Header="Castilian Spanish" />
|
||||
Header="Español (ES)" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="fr_FR"
|
||||
Header="French" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="de_DE"
|
||||
Header="German" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="el_GR"
|
||||
Header="Greek" />
|
||||
Header="Français" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="it_IT"
|
||||
Header="Italian" />
|
||||
Header="Italiano" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ja_JP"
|
||||
Header="Japanese" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ko_KR"
|
||||
Header="Korean" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ru_RU"
|
||||
Header="Russian" />
|
||||
CommandParameter="pt_BR"
|
||||
Header="Português (BR)" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="tr_TR"
|
||||
Header="Turkish" />
|
||||
Header="Türkçe" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="el_GR"
|
||||
Header="Ελληνικά" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ru_RU"
|
||||
Header="Русский" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="zh_CN"
|
||||
Header="Simplified Chinese" />
|
||||
Header="简体中文" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="zh_TW"
|
||||
Header="Traditional Chinese (Taiwan)" />
|
||||
Header="繁體中文" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ja_JP"
|
||||
Header="日本語" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ko_KR"
|
||||
Header="한국어" />
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem
|
||||
|
@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
|
||||
void SetData(ReadOnlySpan<byte> data);
|
||||
void SetData(ReadOnlySpan<byte> data, int layer, int level);
|
||||
void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region);
|
||||
void SetStorage(BufferRange buffer);
|
||||
void Release();
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
TextureSetDataCommand.Run(ref GetCommand<TextureSetDataCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetDataSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
TextureSetDataSliceCommand.Run(ref GetCommand<TextureSetDataSliceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetDataSliceRegion] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
TextureSetDataSliceRegionCommand.Run(ref GetCommand<TextureSetDataSliceRegionCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetStorage] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
TextureSetStorageCommand.Run(ref GetCommand<TextureSetStorageCommand>(memory), threaded, renderer);
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
TextureRelease,
|
||||
TextureSetData,
|
||||
TextureSetDataSlice,
|
||||
TextureSetDataSliceRegion,
|
||||
TextureSetStorage,
|
||||
|
||||
WindowPresent,
|
||||
|
@ -0,0 +1,31 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
|
||||
{
|
||||
struct TextureSetDataSliceRegionCommand : IGALCommand
|
||||
{
|
||||
public CommandType CommandType => CommandType.TextureSetDataSliceRegion;
|
||||
private TableRef<ThreadedTexture> _texture;
|
||||
private TableRef<byte[]> _data;
|
||||
private int _layer;
|
||||
private int _level;
|
||||
private Rectangle<int> _region;
|
||||
|
||||
public void Set(TableRef<ThreadedTexture> texture, TableRef<byte[]> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
_texture = texture;
|
||||
_data = data;
|
||||
_layer = layer;
|
||||
_level = level;
|
||||
_region = region;
|
||||
}
|
||||
|
||||
public static void Run(ref TextureSetDataSliceRegionCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
ThreadedTexture texture = command._texture.Get(threaded);
|
||||
texture.Base.SetData(new ReadOnlySpan<byte>(command._data.Get(threaded)), command._layer, command._level, command._region);
|
||||
}
|
||||
}
|
||||
}
|
@ -119,6 +119,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level, region);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetStorage(BufferRange buffer)
|
||||
{
|
||||
_renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer);
|
||||
|
@ -224,7 +224,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
xCount,
|
||||
yCount,
|
||||
dstLinear,
|
||||
dst.MemoryLayout);
|
||||
dst.MemoryLayout.UnpackGobBlocksInY(),
|
||||
dst.MemoryLayout.UnpackGobBlocksInZ());
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
private int _dstHeight;
|
||||
private int _dstStride;
|
||||
private int _dstGobBlocksInY;
|
||||
private int _dstGobBlocksInZ;
|
||||
private int _lineLengthIn;
|
||||
private int _lineCount;
|
||||
|
||||
@ -117,6 +118,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
_dstHeight = (int)state.SetDstHeight;
|
||||
_dstStride = (int)state.PitchOut;
|
||||
_dstGobBlocksInY = 1 << (int)state.SetDstBlockSizeHeight;
|
||||
_dstGobBlocksInZ = 1 << (int)state.SetDstBlockSizeDepth;
|
||||
_lineLengthIn = (int)state.LineLengthIn;
|
||||
_lineCount = (int)state.LineCount;
|
||||
|
||||
@ -176,6 +178,31 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Verify if the destination X/Y and width/height are taken into account
|
||||
// for linear texture transfers. If not, we can use the fast path for that aswell.
|
||||
// Right now the copy code at the bottom assumes that it is used on both which might be incorrect.
|
||||
if (!_isLinear)
|
||||
{
|
||||
var target = memoryManager.Physical.TextureCache.FindTexture(
|
||||
memoryManager,
|
||||
_dstGpuVa,
|
||||
1,
|
||||
_dstStride,
|
||||
_dstHeight,
|
||||
_lineLengthIn,
|
||||
_lineCount,
|
||||
_isLinear,
|
||||
_dstGobBlocksInY,
|
||||
_dstGobBlocksInZ);
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
target.SetData(data, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var dstCalculator = new OffsetCalculator(
|
||||
_dstWidth,
|
||||
_dstHeight,
|
||||
|
@ -761,6 +761,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
_hasData = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uploads new texture data to the host GPU for a specific layer/level and 2D sub-region.
|
||||
/// </summary>
|
||||
/// <param name="data">New data</param>
|
||||
/// <param name="layer">Target layer</param>
|
||||
/// <param name="level">Target level</param>
|
||||
/// <param name="region">Target sub-region of the texture to update</param>
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
BlacklistScale();
|
||||
|
||||
HostTexture.SetData(data, layer, level, region);
|
||||
|
||||
_currentData = null;
|
||||
|
||||
_hasData = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts texture data to a format and layout that is supported by the host GPU.
|
||||
/// </summary>
|
||||
|
@ -905,7 +905,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <param name="xCount">Number of pixels to be copied per line</param>
|
||||
/// <param name="yCount">Number of lines to be copied</param>
|
||||
/// <param name="linear">True if the texture has a linear layout, false otherwise</param>
|
||||
/// <param name="memoryLayout">If <paramref name="linear"/> is false, should have the memory layout, otherwise ignored</param>
|
||||
/// <param name="gobBlocksInY">If <paramref name="linear"/> is false, the amount of GOB blocks in the Y axis</param>
|
||||
/// <param name="gobBlocksInZ">If <paramref name="linear"/> is false, the amount of GOB blocks in the Z axis</param>
|
||||
/// <returns>A matching texture, or null if there is no match</returns>
|
||||
public Texture FindTexture(
|
||||
MemoryManager memoryManager,
|
||||
@ -916,7 +917,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
int xCount,
|
||||
int yCount,
|
||||
bool linear,
|
||||
MemoryLayout memoryLayout)
|
||||
int gobBlocksInY,
|
||||
int gobBlocksInZ)
|
||||
{
|
||||
ulong address = memoryManager.Translate(gpuVa);
|
||||
|
||||
@ -955,8 +957,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
bool sizeMatch = xCount * bpp == texture.Info.Width * format.BytesPerPixel && height == texture.Info.Height;
|
||||
bool formatMatch = !texture.Info.IsLinear &&
|
||||
texture.Info.GobBlocksInY == memoryLayout.UnpackGobBlocksInY() &&
|
||||
texture.Info.GobBlocksInZ == memoryLayout.UnpackGobBlocksInZ();
|
||||
texture.Info.GobBlocksInY == gobBlocksInY &&
|
||||
texture.Info.GobBlocksInZ == gobBlocksInZ;
|
||||
|
||||
match = sizeMatch && formatMatch;
|
||||
}
|
||||
|
@ -58,6 +58,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetStorage(BufferRange buffer)
|
||||
{
|
||||
if (_buffer != BufferHandle.Null &&
|
||||
|
@ -1,4 +1,5 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
|
||||
@ -385,7 +386,34 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
int width = Math.Max(Info.Width >> level, 1);
|
||||
int height = Math.Max(Info.Height >> level, 1);
|
||||
|
||||
ReadFrom2D((IntPtr)ptr, layer, level, width, height);
|
||||
ReadFrom2D((IntPtr)ptr, layer, level, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
if (Format == Format.S8UintD24Unorm)
|
||||
{
|
||||
data = FormatConverter.ConvertS8D24ToD24S8(data);
|
||||
}
|
||||
|
||||
int wInBlocks = BitUtils.DivRoundUp(region.Width, Info.BlockWidth);
|
||||
int hInBlocks = BitUtils.DivRoundUp(region.Height, Info.BlockHeight);
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
ReadFrom2D(
|
||||
(IntPtr)ptr,
|
||||
layer,
|
||||
level,
|
||||
region.X,
|
||||
region.Y,
|
||||
region.Width,
|
||||
region.Height,
|
||||
BitUtils.AlignUp(wInBlocks * Info.BytesPerPixel, 4) * hInBlocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,15 +425,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
|
||||
public void ReadFromPbo2D(int offset, int layer, int level, int width, int height)
|
||||
{
|
||||
ReadFrom2D(IntPtr.Zero + offset, layer, level, width, height);
|
||||
ReadFrom2D(IntPtr.Zero + offset, layer, level, 0, 0, width, height);
|
||||
}
|
||||
|
||||
private void ReadFrom2D(IntPtr data, int layer, int level, int width, int height)
|
||||
private void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height)
|
||||
{
|
||||
int mipSize = Info.GetMipSize2D(level);
|
||||
|
||||
ReadFrom2D(data, layer, level, x, y, width, height, mipSize);
|
||||
}
|
||||
|
||||
private void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height, int mipSize)
|
||||
{
|
||||
TextureTarget target = Target.Convert();
|
||||
|
||||
int mipSize = Info.GetMipSize2D(level);
|
||||
|
||||
Bind(target, 0);
|
||||
|
||||
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
|
||||
@ -418,7 +451,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.CompressedTexSubImage1D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
x,
|
||||
width,
|
||||
format.PixelFormat,
|
||||
mipSize,
|
||||
@ -429,7 +462,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.TexSubImage1D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
x,
|
||||
width,
|
||||
format.PixelFormat,
|
||||
format.PixelType,
|
||||
@ -443,7 +476,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.CompressedTexSubImage2D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
x,
|
||||
layer,
|
||||
width,
|
||||
1,
|
||||
@ -456,7 +489,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.TexSubImage2D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
x,
|
||||
layer,
|
||||
width,
|
||||
1,
|
||||
@ -472,8 +505,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.CompressedTexSubImage2D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
@ -485,8 +518,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.TexSubImage2D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
@ -503,8 +536,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.CompressedTexSubImage3D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
layer,
|
||||
width,
|
||||
height,
|
||||
@ -518,8 +551,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.TexSubImage3D(
|
||||
target,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
layer,
|
||||
width,
|
||||
height,
|
||||
@ -536,8 +569,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.CompressedTexSubImage2D(
|
||||
TextureTarget.TextureCubeMapPositiveX + layer,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
@ -549,8 +582,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.TexSubImage2D(
|
||||
TextureTarget.TextureCubeMapPositiveX + layer,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
|
@ -98,6 +98,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetStorage(BufferRange buffer)
|
||||
{
|
||||
if (_bufferHandle == buffer.Handle &&
|
||||
|
@ -819,7 +819,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value;
|
||||
var image = GetImage().Get(cbs).Value;
|
||||
|
||||
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, x, y, width, height);
|
||||
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, 0, 0, x, y, width, height);
|
||||
}
|
||||
|
||||
bufferHolder.WaitForFences();
|
||||
@ -893,7 +893,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
SetData(data, layer, level, 1, 1, singleSlice: true);
|
||||
}
|
||||
|
||||
private void SetData(ReadOnlySpan<byte> data, int layer, int level, int layers, int levels, bool singleSlice)
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
SetData(data, layer, level, 1, 1, singleSlice: true, region);
|
||||
}
|
||||
|
||||
private void SetData(ReadOnlySpan<byte> data, int layer, int level, int layers, int levels, bool singleSlice, Rectangle<int>? region = null)
|
||||
{
|
||||
int bufferDataLength = GetBufferDataLength(data.Length);
|
||||
|
||||
@ -917,7 +922,25 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value;
|
||||
var image = imageAuto.Get(cbs).Value;
|
||||
|
||||
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, bufferDataLength, false, layer, level, layers, levels, singleSlice);
|
||||
if (region.HasValue)
|
||||
{
|
||||
CopyFromOrToBuffer(
|
||||
cbs.CommandBuffer,
|
||||
buffer,
|
||||
image,
|
||||
bufferDataLength,
|
||||
false,
|
||||
layer,
|
||||
level,
|
||||
region.Value.X,
|
||||
region.Value.Y,
|
||||
region.Value.Width,
|
||||
region.Value.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, bufferDataLength, false, layer, level, layers, levels, singleSlice);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetBufferDataLength(int length)
|
||||
@ -1059,6 +1082,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Image image,
|
||||
int size,
|
||||
bool to,
|
||||
int dstLayer,
|
||||
int dstLevel,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
@ -1071,13 +1096,21 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
|
||||
}
|
||||
|
||||
var sl = new ImageSubresourceLayers(aspectFlags, (uint)FirstLevel, (uint)FirstLayer, 1);
|
||||
var sl = new ImageSubresourceLayers(aspectFlags, (uint)(FirstLevel + dstLevel), (uint)(FirstLayer + dstLayer), 1);
|
||||
|
||||
var extent = new Extent3D((uint)width, (uint)height, 1);
|
||||
|
||||
int rowLengthAlignment = Info.BlockWidth;
|
||||
|
||||
// We expect all data being written into the texture to have a stride aligned by 4.
|
||||
if (!to && Info.BytesPerPixel < 4)
|
||||
{
|
||||
rowLengthAlignment = 4 / Info.BytesPerPixel;
|
||||
}
|
||||
|
||||
var region = new BufferImageCopy(
|
||||
0,
|
||||
(uint)AlignUpNpot(width, Info.BlockWidth),
|
||||
(uint)AlignUpNpot(width, rowLengthAlignment),
|
||||
(uint)AlignUpNpot(height, Info.BlockHeight),
|
||||
sl,
|
||||
new Offset3D(x, y, 0),
|
||||
|
@ -14,11 +14,14 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
|
||||
private ParentalControlFlagValue _parentalControlFlag;
|
||||
private int[] _ratingAge;
|
||||
|
||||
#pragma warning disable CS0414
|
||||
// TODO: Find where they are set.
|
||||
private bool _restrictionEnabled = false;
|
||||
private bool _featuresRestriction = false;
|
||||
private bool _freeCommunicationEnabled = false;
|
||||
private bool _stereoVisionRestrictionConfigurable = true;
|
||||
private bool _stereoVisionRestriction = false;
|
||||
#pragma warning restore CS0414
|
||||
|
||||
public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag)
|
||||
{
|
||||
@ -88,13 +91,22 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
|
||||
return ResultCode.FreeCommunicationDisabled;
|
||||
}
|
||||
|
||||
// NOTE: This sets an internal field to true. Usage have to be determined.
|
||||
_freeCommunicationEnabled = true;
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServicePctl);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(1017)] // 10.0.0+
|
||||
// EndFreeCommunication()
|
||||
public ResultCode EndFreeCommunication(ServiceCtx context)
|
||||
{
|
||||
_freeCommunicationEnabled = false;
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(1013)] // 4.0.0+
|
||||
// ConfirmStereoVisionPermission()
|
||||
public ResultCode ConfirmStereoVisionPermission(ServiceCtx context)
|
||||
|
@ -219,9 +219,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
int fdsCount = context.RequestData.ReadInt32();
|
||||
int timeout = context.RequestData.ReadInt32();
|
||||
|
||||
(ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x21();
|
||||
(ulong inputBufferPosition, ulong inputBufferSize) = context.Request.GetBufferType0x21();
|
||||
(ulong outputBufferPosition, ulong outputBufferSize) = context.Request.GetBufferType0x22();
|
||||
|
||||
if (timeout < -1 || fdsCount < 0 || (ulong)(fdsCount * 8) > bufferSize)
|
||||
if (timeout < -1 || fdsCount < 0 || (ulong)(fdsCount * 8) > inputBufferSize)
|
||||
{
|
||||
return WriteBsdResult(context, -1, LinuxError.EINVAL);
|
||||
}
|
||||
@ -230,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
|
||||
for (int i = 0; i < fdsCount; i++)
|
||||
{
|
||||
PollEventData pollEventData = context.Memory.Read<PollEventData>(bufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()));
|
||||
PollEventData pollEventData = context.Memory.Read<PollEventData>(inputBufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()));
|
||||
|
||||
IFileDescriptor fileDescriptor = _context.RetrieveFileDescriptor(pollEventData.SocketFd);
|
||||
|
||||
@ -277,7 +278,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
{
|
||||
bool IsUnexpectedLinuxError(LinuxError error)
|
||||
{
|
||||
return errno != LinuxError.SUCCESS && errno != LinuxError.ETIMEDOUT;
|
||||
return error != LinuxError.SUCCESS && error != LinuxError.ETIMEDOUT;
|
||||
}
|
||||
|
||||
// Hybrid approach
|
||||
@ -332,7 +333,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
// TODO: Spanify
|
||||
for (int i = 0; i < fdsCount; i++)
|
||||
{
|
||||
context.Memory.Write(bufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()), events[i].Data);
|
||||
context.Memory.Write(outputBufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()), events[i].Data);
|
||||
}
|
||||
|
||||
return WriteBsdResult(context, updateCount, errno);
|
||||
|
@ -253,7 +253,7 @@ namespace Ryujinx.HLE.Loaders.Mods
|
||||
|
||||
if (tokens[1][0] == '"')
|
||||
{
|
||||
var patch = Encoding.ASCII.GetBytes(tokens[1].Trim('"'));
|
||||
var patch = Encoding.ASCII.GetBytes(tokens[1].Trim('"') + "\0");
|
||||
patches.Add((uint)offset, patch);
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user