forked from Mirror/Ryujinx
Implement FIFO semaphore (#1286)
* Implement FIFO semaphore * New enum for FIFO semaphore operation
This commit is contained in:
parent
12cfaf56f0
commit
44d7fcff39
7 changed files with 50 additions and 14 deletions
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
9
Ryujinx.Graphics.Gpu/State/FifoSemaphoreOperation.cs
Normal file
9
Ryujinx.Graphics.Gpu/State/FifoSemaphoreOperation.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Ryujinx.Graphics.Gpu.State
|
||||||
|
{
|
||||||
|
enum FifoSemaphoreOperation
|
||||||
|
{
|
||||||
|
Counter = 0,
|
||||||
|
Acquire = 1,
|
||||||
|
Release = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
|
@ -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;
|
Reference in a new issue