diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodFifo.cs b/Ryujinx.Graphics.Gpu/Engine/MethodFifo.cs
index 1c0e72e58d..c1f45941c5 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodFifo.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodFifo.cs
@@ -1,11 +1,37 @@
using Ryujinx.Graphics.Gpu.State;
-using System;
using System.Threading;
namespace Ryujinx.Graphics.Gpu.Engine
{
partial class Methods
{
+ ///
+ /// Writes a GPU counter to guest memory.
+ ///
+ /// Current GPU state
+ /// Method call argument
+ public void Semaphore(GpuState state, int argument)
+ {
+ FifoSemaphoreOperation op = (FifoSemaphoreOperation)(argument & 3);
+
+ var semaphore = state.Get(MethodOffset.Semaphore);
+
+ int value = semaphore.Payload;
+
+ if (op == FifoSemaphoreOperation.Counter)
+ {
+ // TODO: There's much more that should be done here.
+ // NVN only supports the "Accumulate" mode, so we
+ // can't currently guess which bits specify the
+ // reduction operation.
+ value += _context.MemoryAccessor.Read(semaphore.Address.Pack());
+ }
+
+ _context.MemoryAccessor.Write(semaphore.Address.Pack(), value);
+
+ _context.AdvanceSequence();
+ }
+
///
/// Waits for the GPU to be idle.
///
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
index e8efddeaa0..224a4da181 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
@@ -21,14 +21,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// Method call argument
private void Report(GpuState state, int argument)
{
- ReportMode mode = (ReportMode)(argument & 3);
-
+ SemaphoreOperation op = (SemaphoreOperation)(argument & 3);
ReportCounterType type = (ReportCounterType)((argument >> 23) & 0x1f);
- switch (mode)
+ switch (op)
{
- case ReportMode.Release: ReleaseSemaphore(state); break;
- case ReportMode.Counter: ReportCounter(state, type); break;
+ case SemaphoreOperation.Release: ReleaseSemaphore(state); break;
+ case SemaphoreOperation.Counter: ReportCounter(state, type); break;
}
}
@@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// Current GPU state
private void ReleaseSemaphore(GpuState state)
{
- var rs = state.Get(MethodOffset.ReportState);
+ var rs = state.Get(MethodOffset.ReportState);
_context.MemoryAccessor.Write(rs.Address.Pack(), rs.Payload);
@@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
{
CounterData counterData = new CounterData();
- var rs = state.Get(MethodOffset.ReportState);
+ var rs = state.Get(MethodOffset.ReportState);
ulong gpuVa = rs.Address.Pack();
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index d67ce2d111..5957bb624f 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -104,6 +104,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// GPU state where the triggers will be registered
public void RegisterCallbacksForFifo(GpuState state)
{
+ state.RegisterCallback(MethodOffset.Semaphore, Semaphore);
state.RegisterCallback(MethodOffset.FenceAction, FenceAction);
state.RegisterCallback(MethodOffset.WaitForIdle, WaitForIdle);
state.RegisterCallback(MethodOffset.SendMacroCodeData, SendMacroCodeData);
@@ -430,7 +431,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
_context.Renderer.Pipeline.SetOrigin(origin);
// The triangle rast flip flag only affects rasterization, the viewport is not flipped.
- // Setting the origin mode to upper left on the host, however, not onlyy affects rasterization,
+ // Setting the origin mode to upper left on the host, however, not only affects rasterization,
// but also flips the viewport.
// We negate the effects of flipping the viewport by flipping it again using the viewport swizzle.
if (origin == Origin.UpperLeft)
diff --git a/Ryujinx.Graphics.Gpu/State/FifoSemaphoreOperation.cs b/Ryujinx.Graphics.Gpu/State/FifoSemaphoreOperation.cs
new file mode 100644
index 0000000000..a6ccdcfe4d
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/FifoSemaphoreOperation.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ enum FifoSemaphoreOperation
+ {
+ Counter = 0,
+ Acquire = 1,
+ Release = 2
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index b39ff9b5e0..da54a46980 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -8,7 +8,8 @@ namespace Ryujinx.Graphics.Gpu.State
///
enum MethodOffset
{
- BindChannel = 0x00,
+ BindChannel = 0x0,
+ Semaphore = 0x4,
FenceValue = 0x1c,
FenceAction = 0x1d,
WaitForIdle = 0x44,
diff --git a/Ryujinx.Graphics.Gpu/State/ReportMode.cs b/Ryujinx.Graphics.Gpu/State/SemaphoreOperation.cs
similarity index 71%
rename from Ryujinx.Graphics.Gpu/State/ReportMode.cs
rename to Ryujinx.Graphics.Gpu/State/SemaphoreOperation.cs
index 0625f3f610..67f3c127f6 100644
--- a/Ryujinx.Graphics.Gpu/State/ReportMode.cs
+++ b/Ryujinx.Graphics.Gpu/State/SemaphoreOperation.cs
@@ -1,9 +1,9 @@
namespace Ryujinx.Graphics.Gpu.State
{
///
- /// GPU counter report mode.
+ /// GPU semaphore operation.
///
- enum ReportMode
+ enum SemaphoreOperation
{
Release = 0,
Acquire = 1,
diff --git a/Ryujinx.Graphics.Gpu/State/ReportState.cs b/Ryujinx.Graphics.Gpu/State/SemaphoreState.cs
similarity index 80%
rename from Ryujinx.Graphics.Gpu/State/ReportState.cs
rename to Ryujinx.Graphics.Gpu/State/SemaphoreState.cs
index 0c14bfe953..bfc5720a40 100644
--- a/Ryujinx.Graphics.Gpu/State/ReportState.cs
+++ b/Ryujinx.Graphics.Gpu/State/SemaphoreState.cs
@@ -1,9 +1,9 @@
namespace Ryujinx.Graphics.Gpu.State
{
///
- /// GPU counter report state.
+ /// GPU semaphore state.
///
- struct ReportState
+ struct SemaphoreState
{
#pragma warning disable CS0649
public GpuVa Address;