Ver código fonte

Implement Logical Operation registers and functionality (#1380)

* Implement Logical Operation registers and functionality.

* Address Feedback 1
riperiperi 5 anos atrás
pai
commit
f224769c49

+ 2 - 0
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);

+ 22 - 0
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
+    }
+}

+ 16 - 0
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
             }
         }
 
+        /// <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>
         /// Storage buffer address and size information.
         /// </summary>

+ 12 - 0
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
+    }
+}

+ 1 - 0
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,

+ 43 - 0
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;
+        }
     }
 }

+ 14 - 0
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)