From f224769c493e80ab2bd9a674be697461749e0b94 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Fri, 10 Jul 2020 18:23:15 +0100 Subject: [PATCH] Implement Logical Operation registers and functionality (#1380) * Implement Logical Operation registers and functionality. * Address Feedback 1 --- Ryujinx.Graphics.GAL/IPipeline.cs | 2 + Ryujinx.Graphics.GAL/LogicalOp.cs | 22 ++++++++++ Ryujinx.Graphics.Gpu/Engine/Methods.cs | 16 ++++++++ Ryujinx.Graphics.Gpu/State/LogicalOpState.cs | 12 ++++++ Ryujinx.Graphics.Gpu/State/MethodOffset.cs | 1 + Ryujinx.Graphics.OpenGL/EnumConversion.cs | 43 ++++++++++++++++++++ Ryujinx.Graphics.OpenGL/Pipeline.cs | 14 +++++++ 7 files changed, 110 insertions(+) create mode 100644 Ryujinx.Graphics.GAL/LogicalOp.cs create mode 100644 Ryujinx.Graphics.Gpu/State/LogicalOpState.cs diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index e365529b..3eb778e0 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.GAL void SetImage(int index, ShaderStage stage, ITexture texture); + void SetLogicOpState(bool enable, LogicalOp op); + void SetOrigin(Origin origin); void SetPointSize(float size); diff --git a/Ryujinx.Graphics.GAL/LogicalOp.cs b/Ryujinx.Graphics.GAL/LogicalOp.cs new file mode 100644 index 00000000..848215d0 --- /dev/null +++ b/Ryujinx.Graphics.GAL/LogicalOp.cs @@ -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 + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 5677c8a0..06298cdf 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -252,6 +252,11 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateBlendState(state); } + if (state.QueryModified(MethodOffset.LogicOpState)) + { + UpdateLogicOpState(state); + } + CommitBindings(); } @@ -875,6 +880,17 @@ namespace Ryujinx.Graphics.Gpu.Engine } } + /// + /// Updates host logical operation state, based on guest state. + /// + /// Current GPU state + public void UpdateLogicOpState(GpuState state) + { + LogicalOpState logicOpState = state.Get(MethodOffset.LogicOpState); + + _context.Renderer.Pipeline.SetLogicOpState(logicOpState.Enable, logicOpState.LogicalOp); + } + /// /// Storage buffer address and size information. /// diff --git a/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs b/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs new file mode 100644 index 00000000..d052a45c --- /dev/null +++ b/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs @@ -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 + } +} diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index 2e0a197e..d7d5d903 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Gpu.State FaceState = 0x646, ViewportTransformEnable = 0x64b, ViewVolumeClipControl = 0x64f, + LogicOpState = 0x671, Clear = 0x674, RtColorMask = 0x680, ReportState = 0x6c0, diff --git a/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/Ryujinx.Graphics.OpenGL/EnumConversion.cs index aebe54fa..a4bd39cc 100644 --- a/Ryujinx.Graphics.OpenGL/EnumConversion.cs +++ b/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -443,5 +443,48 @@ namespace Ryujinx.Graphics.OpenGL 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; + } } } diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 62e5394e..9623c826 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -547,6 +547,20 @@ namespace Ryujinx.Graphics.OpenGL 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) { if ((enables & PolygonModeMask.Point) != 0)