Add SvcSetThreadActivity, tweak SignalProcessWideKey, add fmul32i shader instructions and other small fixes
This commit is contained in:
parent
33ae6e544b
commit
03002f6537
9 changed files with 139 additions and 24 deletions
|
@ -54,6 +54,14 @@ namespace ChocolArm64
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopExecution() => ThreadState.Running = false;
|
public void StopExecution()
|
||||||
|
{
|
||||||
|
ThreadState.Running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCurrentThread()
|
||||||
|
{
|
||||||
|
return Thread.CurrentThread == Work;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,11 +15,15 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public AutoResetEvent WaitEvent { get; private set; }
|
public AutoResetEvent WaitEvent { get; private set; }
|
||||||
|
|
||||||
|
public bool Active { get; set; }
|
||||||
|
|
||||||
public SchedulerThread(KThread Thread)
|
public SchedulerThread(KThread Thread)
|
||||||
{
|
{
|
||||||
this.Thread = Thread;
|
this.Thread = Thread;
|
||||||
|
|
||||||
WaitEvent = new AutoResetEvent(false);
|
WaitEvent = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
Active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -98,7 +102,10 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public bool Remove(SchedulerThread SchedThread)
|
public bool Remove(SchedulerThread SchedThread)
|
||||||
{
|
{
|
||||||
return Threads.Remove(SchedThread);
|
lock (Threads)
|
||||||
|
{
|
||||||
|
return Threads.Remove(SchedThread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +187,55 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetThreadActivity(KThread Thread, bool Active)
|
||||||
|
{
|
||||||
|
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SchedLock)
|
||||||
|
{
|
||||||
|
bool OldState = SchedThread.Active;
|
||||||
|
|
||||||
|
SchedThread.Active = Active;
|
||||||
|
|
||||||
|
if (!OldState && Active)
|
||||||
|
{
|
||||||
|
if (ActiveProcessors.Add(Thread.ProcessorId))
|
||||||
|
{
|
||||||
|
RunThread(SchedThread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitingToRun[Thread.ProcessorId].Push(SchedThread);
|
||||||
|
|
||||||
|
PrintDbgThreadInfo(Thread, "entering wait state...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (OldState && !Active)
|
||||||
|
{
|
||||||
|
if (Thread.Thread.IsCurrentThread())
|
||||||
|
{
|
||||||
|
Suspend(Thread.ProcessorId);
|
||||||
|
|
||||||
|
PrintDbgThreadInfo(Thread, "entering inactive wait state...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitingToRun[Thread.ProcessorId].Remove(SchedThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Active && Thread.Thread.IsCurrentThread())
|
||||||
|
{
|
||||||
|
SchedThread.WaitEvent.WaitOne();
|
||||||
|
|
||||||
|
PrintDbgThreadInfo(Thread, "resuming execution...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Suspend(int ProcessorId)
|
public void Suspend(int ProcessorId)
|
||||||
{
|
{
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
|
@ -222,9 +278,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public void Resume(KThread Thread)
|
public void Resume(KThread Thread)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
||||||
|
|
||||||
if (!AllThreads.TryGetValue(Thread, out SchedThread))
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
@ -236,18 +290,25 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
KThread Thread = SchedThread.Thread;
|
KThread Thread = SchedThread.Thread;
|
||||||
|
|
||||||
lock (SchedLock)
|
if (SchedThread.Active)
|
||||||
{
|
{
|
||||||
if (ActiveProcessors.Add(Thread.ProcessorId))
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
PrintDbgThreadInfo(Thread, "resuming execution...");
|
if (ActiveProcessors.Add(Thread.ProcessorId))
|
||||||
|
{
|
||||||
|
PrintDbgThreadInfo(Thread, "resuming execution...");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitingToRun[Thread.ProcessorId].Push(SchedThread);
|
||||||
|
|
||||||
|
PrintDbgThreadInfo(Thread, "entering wait state...");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PrintDbgThreadInfo(Thread, "entering wait state...");
|
else
|
||||||
|
{
|
||||||
WaitingToRun[Thread.ProcessorId].Push(SchedThread);
|
PrintDbgThreadInfo(Thread, "entering inactive wait state...");
|
||||||
}
|
}
|
||||||
|
|
||||||
SchedThread.WaitEvent.WaitOne();
|
SchedThread.WaitEvent.WaitOne();
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
Count = Process.Memory.ReadInt32(CondVarAddress);
|
Count = Process.Memory.ReadInt32(CondVarAddress);
|
||||||
|
|
||||||
if (Count > 0)
|
if (Result && Count > 0)
|
||||||
{
|
{
|
||||||
Process.Memory.WriteInt32(CondVarAddress, Count - 1);
|
Process.Memory.WriteInt32(CondVarAddress, Count - 1);
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,10 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
{
|
{
|
||||||
if (Count < 0)
|
if (Count < 0)
|
||||||
{
|
{
|
||||||
Process.Memory.WriteInt32(CondVarAddress, WaitingThreads.Count);
|
|
||||||
|
|
||||||
foreach ((_, AutoResetEvent WaitEvent) in WaitingThreads)
|
foreach ((_, AutoResetEvent WaitEvent) in WaitingThreads)
|
||||||
{
|
{
|
||||||
|
IncrementCondVarValue();
|
||||||
|
|
||||||
WaitEvent.Set();
|
WaitEvent.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +84,6 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Process.Memory.WriteInt32(CondVarAddress, Count);
|
|
||||||
|
|
||||||
while (WaitingThreads.Count > 0 && Count-- > 0)
|
while (WaitingThreads.Count > 0 && Count-- > 0)
|
||||||
{
|
{
|
||||||
int HighestPriority = WaitingThreads[0].Thread.Priority;
|
int HighestPriority = WaitingThreads[0].Thread.Priority;
|
||||||
|
@ -101,6 +99,8 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IncrementCondVarValue();
|
||||||
|
|
||||||
WaitingThreads[HighestPrioIndex].WaitEvent.Set();
|
WaitingThreads[HighestPrioIndex].WaitEvent.Set();
|
||||||
|
|
||||||
WaitingThreads.RemoveAt(HighestPrioIndex);
|
WaitingThreads.RemoveAt(HighestPrioIndex);
|
||||||
|
@ -111,6 +111,17 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
Process.Scheduler.Yield(Thread);
|
Process.Scheduler.Yield(Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void IncrementCondVarValue()
|
||||||
|
{
|
||||||
|
AcquireCondVarValue();
|
||||||
|
|
||||||
|
int Count = Process.Memory.ReadInt32(CondVarAddress);
|
||||||
|
|
||||||
|
Process.Memory.WriteInt32(CondVarAddress, Count + 1);
|
||||||
|
|
||||||
|
ReleaseCondVarValue();
|
||||||
|
}
|
||||||
|
|
||||||
private void AcquireCondVarValue()
|
private void AcquireCondVarValue()
|
||||||
{
|
{
|
||||||
if (!OwnsCondVarValue)
|
if (!OwnsCondVarValue)
|
||||||
|
|
|
@ -63,7 +63,8 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
{ 0x25, SvcGetThreadId },
|
{ 0x25, SvcGetThreadId },
|
||||||
{ 0x26, SvcBreak },
|
{ 0x26, SvcBreak },
|
||||||
{ 0x27, SvcOutputDebugString },
|
{ 0x27, SvcOutputDebugString },
|
||||||
{ 0x29, SvcGetInfo }
|
{ 0x29, SvcGetInfo },
|
||||||
|
{ 0x32, SvcSetThreadActivity }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Ns = Ns;
|
this.Ns = Ns;
|
||||||
|
|
|
@ -147,7 +147,28 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Warn(LogClass.KernelSvc, $"Tried to GetThreadId on invalid thread handle 0x{Handle:x8}!");
|
Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SvcSetThreadActivity(AThreadState ThreadState)
|
||||||
|
{
|
||||||
|
int Handle = (int)ThreadState.X0;
|
||||||
|
bool Active = (int)ThreadState.X1 != 0;
|
||||||
|
|
||||||
|
KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
|
if (CurrThread != null)
|
||||||
|
{
|
||||||
|
Process.Scheduler.SetThreadActivity(CurrThread, Active);
|
||||||
|
|
||||||
|
ThreadState.X0 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
|
||||||
|
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
}
|
}
|
||||||
else if (DeclInfo.Name == GlslDecl.FragmentOutputName)
|
else if (DeclInfo.Name == GlslDecl.FragmentOutputName)
|
||||||
{
|
{
|
||||||
Name = "layout (location = 0) out " + GetDecl(DeclInfo) + ";";
|
Name = "layout (location = 0) out " + GetDecl(DeclInfo) + ";" + Environment.NewLine;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,6 +41,16 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
EmitAluFfma(Block, OpCode, ShaderOper.RR);
|
EmitAluFfma(Block, OpCode, ShaderOper.RR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fmul32i(ShaderIrBlock Block, long OpCode)
|
||||||
|
{
|
||||||
|
ShaderIrNode OperA = GetOperGpr8 (OpCode);
|
||||||
|
ShaderIrNode OperB = GetOperImmf32_20(OpCode);
|
||||||
|
|
||||||
|
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB);
|
||||||
|
|
||||||
|
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fmul_C(ShaderIrBlock Block, long OpCode)
|
public static void Fmul_C(ShaderIrBlock Block, long OpCode)
|
||||||
{
|
{
|
||||||
EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul);
|
EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul);
|
||||||
|
@ -212,7 +222,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
bool Aa = ((OpCode >> 46) & 1) != 0;
|
bool Aa = ((OpCode >> 46) & 1) != 0;
|
||||||
bool Na = ((OpCode >> 48) & 1) != 0;
|
bool Na = ((OpCode >> 48) & 1) != 0;
|
||||||
bool Ab = ((OpCode >> 49) & 1) != 0;
|
bool Ab = ((OpCode >> 49) & 1) != 0;
|
||||||
bool Ad = ((OpCode >> 50) & 1) != 0;
|
|
||||||
|
|
||||||
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
|
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
|
||||||
|
|
||||||
|
@ -234,8 +243,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
|
ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
|
||||||
|
|
||||||
Op = GetAluAbs(Op, Ad);
|
|
||||||
|
|
||||||
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
|
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,11 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
return new ShaderIrOperImm((int)(OpCode >> 20));
|
return new ShaderIrOperImm((int)(OpCode >> 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ShaderIrOperImmf GetOperImmf32_20(long OpCode)
|
||||||
|
{
|
||||||
|
return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(OpCode >> 20)));
|
||||||
|
}
|
||||||
|
|
||||||
public static ShaderIrOperImm GetOperImm19_20(long OpCode)
|
public static ShaderIrOperImm GetOperImm19_20(long OpCode)
|
||||||
{
|
{
|
||||||
int Value = (int)(OpCode >> 20) & 0x7ffff;
|
int Value = (int)(OpCode >> 20) & 0x7ffff;
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
Set("001100101xxxxx", ShaderDecode.Ffma_I);
|
Set("001100101xxxxx", ShaderDecode.Ffma_I);
|
||||||
Set("010100011xxxxx", ShaderDecode.Ffma_RC);
|
Set("010100011xxxxx", ShaderDecode.Ffma_RC);
|
||||||
Set("010110011xxxxx", ShaderDecode.Ffma_RR);
|
Set("010110011xxxxx", ShaderDecode.Ffma_RR);
|
||||||
|
Set("00011110xxxxxx", ShaderDecode.Fmul32i);
|
||||||
Set("0100110001101x", ShaderDecode.Fmul_C);
|
Set("0100110001101x", ShaderDecode.Fmul_C);
|
||||||
Set("0011100x01101x", ShaderDecode.Fmul_I);
|
Set("0011100x01101x", ShaderDecode.Fmul_I);
|
||||||
Set("0101110001101x", ShaderDecode.Fmul_R);
|
Set("0101110001101x", ShaderDecode.Fmul_R);
|
||||||
|
|
Loading…
Reference in a new issue