Implement FIFO semaphore (#1286)

* Implement FIFO semaphore

* New enum for FIFO semaphore operation
This commit is contained in:
gdkchan 2020-05-29 05:51:10 -03:00 committed by GitHub
parent 12cfaf56f0
commit 44d7fcff39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 14 deletions

View file

@ -1,11 +1,37 @@
using Ryujinx.Graphics.Gpu.State; using Ryujinx.Graphics.Gpu.State;
using System;
using System.Threading; using System.Threading;
namespace Ryujinx.Graphics.Gpu.Engine namespace Ryujinx.Graphics.Gpu.Engine
{ {
partial class Methods partial class Methods
{ {
/// <summary>
/// Writes a GPU counter to guest memory.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="argument">Method call argument</param>
public void Semaphore(GpuState state, int argument)
{
FifoSemaphoreOperation op = (FifoSemaphoreOperation)(argument & 3);
var semaphore = state.Get<SemaphoreState>(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<int>(semaphore.Address.Pack());
}
_context.MemoryAccessor.Write(semaphore.Address.Pack(), value);
_context.AdvanceSequence();
}
/// <summary> /// <summary>
/// Waits for the GPU to be idle. /// Waits for the GPU to be idle.
/// </summary> /// </summary>

View file

@ -21,14 +21,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="argument">Method call argument</param> /// <param name="argument">Method call argument</param>
private void Report(GpuState state, int argument) private void Report(GpuState state, int argument)
{ {
ReportMode mode = (ReportMode)(argument & 3); SemaphoreOperation op = (SemaphoreOperation)(argument & 3);
ReportCounterType type = (ReportCounterType)((argument >> 23) & 0x1f); ReportCounterType type = (ReportCounterType)((argument >> 23) & 0x1f);
switch (mode) switch (op)
{ {
case ReportMode.Release: ReleaseSemaphore(state); break; case SemaphoreOperation.Release: ReleaseSemaphore(state); break;
case ReportMode.Counter: ReportCounter(state, type); break; case SemaphoreOperation.Counter: ReportCounter(state, type); break;
} }
} }
@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="state">Current GPU state</param> /// <param name="state">Current GPU state</param>
private void ReleaseSemaphore(GpuState state) private void ReleaseSemaphore(GpuState state)
{ {
var rs = state.Get<ReportState>(MethodOffset.ReportState); var rs = state.Get<SemaphoreState>(MethodOffset.ReportState);
_context.MemoryAccessor.Write(rs.Address.Pack(), rs.Payload); _context.MemoryAccessor.Write(rs.Address.Pack(), rs.Payload);
@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
CounterData counterData = new CounterData(); CounterData counterData = new CounterData();
var rs = state.Get<ReportState>(MethodOffset.ReportState); var rs = state.Get<SemaphoreState>(MethodOffset.ReportState);
ulong gpuVa = rs.Address.Pack(); ulong gpuVa = rs.Address.Pack();

View file

@ -104,6 +104,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="state">GPU state where the triggers will be registered</param> /// <param name="state">GPU state where the triggers will be registered</param>
public void RegisterCallbacksForFifo(GpuState state) public void RegisterCallbacksForFifo(GpuState state)
{ {
state.RegisterCallback(MethodOffset.Semaphore, Semaphore);
state.RegisterCallback(MethodOffset.FenceAction, FenceAction); state.RegisterCallback(MethodOffset.FenceAction, FenceAction);
state.RegisterCallback(MethodOffset.WaitForIdle, WaitForIdle); state.RegisterCallback(MethodOffset.WaitForIdle, WaitForIdle);
state.RegisterCallback(MethodOffset.SendMacroCodeData, SendMacroCodeData); state.RegisterCallback(MethodOffset.SendMacroCodeData, SendMacroCodeData);
@ -430,7 +431,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
_context.Renderer.Pipeline.SetOrigin(origin); _context.Renderer.Pipeline.SetOrigin(origin);
// The triangle rast flip flag only affects rasterization, the viewport is not flipped. // 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. // but also flips the viewport.
// We negate the effects of flipping the viewport by flipping it again using the viewport swizzle. // We negate the effects of flipping the viewport by flipping it again using the viewport swizzle.
if (origin == Origin.UpperLeft) if (origin == Origin.UpperLeft)

View file

@ -0,0 +1,9 @@
namespace Ryujinx.Graphics.Gpu.State
{
enum FifoSemaphoreOperation
{
Counter = 0,
Acquire = 1,
Release = 2
}
}

View file

@ -8,7 +8,8 @@ namespace Ryujinx.Graphics.Gpu.State
/// </remarks> /// </remarks>
enum MethodOffset enum MethodOffset
{ {
BindChannel = 0x00, BindChannel = 0x0,
Semaphore = 0x4,
FenceValue = 0x1c, FenceValue = 0x1c,
FenceAction = 0x1d, FenceAction = 0x1d,
WaitForIdle = 0x44, WaitForIdle = 0x44,

View file

@ -1,9 +1,9 @@
namespace Ryujinx.Graphics.Gpu.State namespace Ryujinx.Graphics.Gpu.State
{ {
/// <summary> /// <summary>
/// GPU counter report mode. /// GPU semaphore operation.
/// </summary> /// </summary>
enum ReportMode enum SemaphoreOperation
{ {
Release = 0, Release = 0,
Acquire = 1, Acquire = 1,

View file

@ -1,9 +1,9 @@
namespace Ryujinx.Graphics.Gpu.State namespace Ryujinx.Graphics.Gpu.State
{ {
/// <summary> /// <summary>
/// GPU counter report state. /// GPU semaphore state.
/// </summary> /// </summary>
struct ReportState struct SemaphoreState
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public GpuVa Address; public GpuVa Address;