Implement Logical Operation registers and functionality (#1380)

* Implement Logical Operation registers and functionality.

* Address Feedback 1
This commit is contained in:
riperiperi 2020-07-10 18:23:15 +01:00 committed by GitHub
parent 189c0c9c72
commit f224769c49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 0 deletions

View file

@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.GAL
void SetImage(int index, ShaderStage stage, ITexture texture); void SetImage(int index, ShaderStage stage, ITexture texture);
void SetLogicOpState(bool enable, LogicalOp op);
void SetOrigin(Origin origin); void SetOrigin(Origin origin);
void SetPointSize(float size); void SetPointSize(float size);

View file

@ -0,0 +1,22 @@
namespace Ryujinx.Graphics.GAL
{
public enum LogicalOp
{
Clear = 0x1500,
And = 0x1501,
AndReverse = 0x1502,
Copy = 0x1503,
AndInverted = 0x1504,
Noop = 0x1505,
Xor = 0x1506,
Or = 0x1507,
Nor = 0x1508,
Equiv = 0x1509,
Invert = 0x150A,
OrReverse = 0x150B,
CopyInverted = 0x150C,
OrInverted = 0x150D,
Nand = 0x150E,
Set = 0x150F
}
}

View file

@ -252,6 +252,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateBlendState(state); UpdateBlendState(state);
} }
if (state.QueryModified(MethodOffset.LogicOpState))
{
UpdateLogicOpState(state);
}
CommitBindings(); CommitBindings();
} }
@ -875,6 +880,17 @@ namespace Ryujinx.Graphics.Gpu.Engine
} }
} }
/// <summary>
/// Updates host logical operation state, based on guest state.
/// </summary>
/// <param name="state">Current GPU state</param>
public void UpdateLogicOpState(GpuState state)
{
LogicalOpState logicOpState = state.Get<LogicalOpState>(MethodOffset.LogicOpState);
_context.Renderer.Pipeline.SetLogicOpState(logicOpState.Enable, logicOpState.LogicalOp);
}
/// <summary> /// <summary>
/// Storage buffer address and size information. /// Storage buffer address and size information.
/// </summary> /// </summary>

View file

@ -0,0 +1,12 @@
using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.State
{
struct LogicalOpState
{
#pragma warning disable CS0649
public Boolean32 Enable;
public LogicalOp LogicalOp;
#pragma warning restore CS0649
}
}

View file

@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Gpu.State
FaceState = 0x646, FaceState = 0x646,
ViewportTransformEnable = 0x64b, ViewportTransformEnable = 0x64b,
ViewVolumeClipControl = 0x64f, ViewVolumeClipControl = 0x64f,
LogicOpState = 0x671,
Clear = 0x674, Clear = 0x674,
RtColorMask = 0x680, RtColorMask = 0x680,
ReportState = 0x6c0, ReportState = 0x6c0,

View file

@ -443,5 +443,48 @@ namespace Ryujinx.Graphics.OpenGL
return NvViewportSwizzle.ViewportSwizzlePositiveXNv; return NvViewportSwizzle.ViewportSwizzlePositiveXNv;
} }
public static All Convert(this LogicalOp op)
{
switch (op)
{
case LogicalOp.Clear:
return All.Clear;
case LogicalOp.And:
return All.And;
case LogicalOp.AndReverse:
return All.AndReverse;
case LogicalOp.Copy:
return All.Copy;
case LogicalOp.AndInverted:
return All.AndInverted;
case LogicalOp.Noop:
return All.Noop;
case LogicalOp.Xor:
return All.Xor;
case LogicalOp.Or:
return All.Or;
case LogicalOp.Nor:
return All.Nor;
case LogicalOp.Equiv:
return All.Equiv;
case LogicalOp.Invert:
return All.Invert;
case LogicalOp.OrReverse:
return All.OrReverse;
case LogicalOp.CopyInverted:
return All.CopyInverted;
case LogicalOp.OrInverted:
return All.OrInverted;
case LogicalOp.Nand:
return All.Nand;
case LogicalOp.Set:
return All.Set;
}
Logger.PrintDebug(LogClass.Gpu, $"Invalid {nameof(LogicalOp)} enum value: {op}.");
return All.Never;
}
} }
} }

View file

@ -547,6 +547,20 @@ namespace Ryujinx.Graphics.OpenGL
GL.Enable(IndexedEnableCap.Blend, index); GL.Enable(IndexedEnableCap.Blend, index);
} }
public void SetLogicOpState(bool enable, LogicalOp op)
{
if (enable)
{
GL.Enable(EnableCap.ColorLogicOp);
GL.LogicOp((LogicOp)op.Convert());
}
else
{
GL.Disable(EnableCap.ColorLogicOp);
}
}
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
{ {
if ((enables & PolygonModeMask.Point) != 0) if ((enables & PolygonModeMask.Point) != 0)