aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-04-19 16:18:30 -0300
committergdkchan <gab.dark.100@gmail.com>2018-04-19 16:18:30 -0300
commit03002f6537e3208e6951bc9092e958985e200c7d (patch)
treee3e4eea4eba155d82168915ad7c3a507e3a20f59
parent33ae6e544bd477da629e3f4ab4925f457ecfbbb7 (diff)
Add SvcSetThreadActivity, tweak SignalProcessWideKey, add fmul32i shader instructions and other small fixes
-rw-r--r--ChocolArm64/AThread.cs10
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs83
-rw-r--r--Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs21
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcHandler.cs3
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThread.cs23
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs13
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs5
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs1
9 files changed, 138 insertions, 23 deletions
diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs
index 62f9d2d3..16804a7c 100644
--- a/ChocolArm64/AThread.cs
+++ b/ChocolArm64/AThread.cs
@@ -54,6 +54,14 @@ namespace ChocolArm64
return true;
}
- public void StopExecution() => ThreadState.Running = false;
+ public void StopExecution()
+ {
+ ThreadState.Running = false;
+ }
+
+ public bool IsCurrentThread()
+ {
+ return Thread.CurrentThread == Work;
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index 1300d218..2f694600 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -15,11 +15,15 @@ namespace Ryujinx.Core.OsHle.Handles
public AutoResetEvent WaitEvent { get; private set; }
+ public bool Active { get; set; }
+
public SchedulerThread(KThread Thread)
{
this.Thread = Thread;
WaitEvent = new AutoResetEvent(false);
+
+ Active = true;
}
public void Dispose()
@@ -98,7 +102,10 @@ namespace Ryujinx.Core.OsHle.Handles
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)
{
lock (SchedLock)
@@ -222,9 +278,7 @@ namespace Ryujinx.Core.OsHle.Handles
public void Resume(KThread Thread)
{
- SchedulerThread SchedThread;
-
- if (!AllThreads.TryGetValue(Thread, out SchedThread))
+ if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
{
throw new InvalidOperationException();
}
@@ -236,18 +290,25 @@ namespace Ryujinx.Core.OsHle.Handles
{
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;
+ }
- PrintDbgThreadInfo(Thread, "entering wait state...");
+ WaitingToRun[Thread.ProcessorId].Push(SchedThread);
- WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+ PrintDbgThreadInfo(Thread, "entering wait state...");
+ }
+ }
+ else
+ {
+ PrintDbgThreadInfo(Thread, "entering inactive wait state...");
}
SchedThread.WaitEvent.WaitOne();
diff --git a/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs
index 91ed9158..f7657376 100644
--- a/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs
+++ b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs
@@ -57,7 +57,7 @@ namespace Ryujinx.Core.OsHle.Kernel
Count = Process.Memory.ReadInt32(CondVarAddress);
- if (Count > 0)
+ if (Result && Count > 0)
{
Process.Memory.WriteInt32(CondVarAddress, Count - 1);
}
@@ -73,10 +73,10 @@ namespace Ryujinx.Core.OsHle.Kernel
{
if (Count < 0)
{
- Process.Memory.WriteInt32(CondVarAddress, WaitingThreads.Count);
-
foreach ((_, AutoResetEvent WaitEvent) in WaitingThreads)
{
+ IncrementCondVarValue();
+
WaitEvent.Set();
}
@@ -84,8 +84,6 @@ namespace Ryujinx.Core.OsHle.Kernel
}
else
{
- Process.Memory.WriteInt32(CondVarAddress, Count);
-
while (WaitingThreads.Count > 0 && Count-- > 0)
{
int HighestPriority = WaitingThreads[0].Thread.Priority;
@@ -101,6 +99,8 @@ namespace Ryujinx.Core.OsHle.Kernel
}
}
+ IncrementCondVarValue();
+
WaitingThreads[HighestPrioIndex].WaitEvent.Set();
WaitingThreads.RemoveAt(HighestPrioIndex);
@@ -111,6 +111,17 @@ namespace Ryujinx.Core.OsHle.Kernel
Process.Scheduler.Yield(Thread);
}
+ private void IncrementCondVarValue()
+ {
+ AcquireCondVarValue();
+
+ int Count = Process.Memory.ReadInt32(CondVarAddress);
+
+ Process.Memory.WriteInt32(CondVarAddress, Count + 1);
+
+ ReleaseCondVarValue();
+ }
+
private void AcquireCondVarValue()
{
if (!OwnsCondVarValue)
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
index fa772988..16ef8697 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
@@ -63,7 +63,8 @@ namespace Ryujinx.Core.OsHle.Kernel
{ 0x25, SvcGetThreadId },
{ 0x26, SvcBreak },
{ 0x27, SvcOutputDebugString },
- { 0x29, SvcGetInfo }
+ { 0x29, SvcGetInfo },
+ { 0x32, SvcSetThreadActivity }
};
this.Ns = Ns;
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index 2534c9d9..06147b28 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -147,7 +147,28 @@ namespace Ryujinx.Core.OsHle.Kernel
}
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);
}
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index 457192dc..d7173bcd 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -193,7 +193,7 @@ namespace Ryujinx.Graphics.Gal.Shader
}
else if (DeclInfo.Name == GlslDecl.FragmentOutputName)
{
- Name = "layout (location = 0) out " + GetDecl(DeclInfo) + ";";
+ Name = "layout (location = 0) out " + GetDecl(DeclInfo) + ";" + Environment.NewLine;
}
else
{
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
index b796ab28..830aeb8c 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
@@ -41,6 +41,16 @@ namespace Ryujinx.Graphics.Gal.Shader
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)
{
EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul);
@@ -212,7 +222,6 @@ namespace Ryujinx.Graphics.Gal.Shader
bool Aa = ((OpCode >> 46) & 1) != 0;
bool Na = ((OpCode >> 48) & 1) != 0;
bool Ab = ((OpCode >> 49) & 1) != 0;
- bool Ad = ((OpCode >> 50) & 1) != 0;
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
@@ -234,8 +243,6 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
- Op = GetAluAbs(Op, Ad);
-
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
index de932dce..efbce20f 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
@@ -70,6 +70,11 @@ namespace Ryujinx.Graphics.Gal.Shader
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)
{
int Value = (int)(OpCode >> 20) & 0x7ffff;
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs
index a234f7f7..762544cb 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs
@@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("001100101xxxxx", ShaderDecode.Ffma_I);
Set("010100011xxxxx", ShaderDecode.Ffma_RC);
Set("010110011xxxxx", ShaderDecode.Ffma_RR);
+ Set("00011110xxxxxx", ShaderDecode.Fmul32i);
Set("0100110001101x", ShaderDecode.Fmul_C);
Set("0011100x01101x", ShaderDecode.Fmul_I);
Set("0101110001101x", ShaderDecode.Fmul_R);