diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-04-25 23:11:26 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-04-25 23:12:26 -0300 |
| commit | a38a72b0622f89897bdcd01b6d00ea6bc142c34f (patch) | |
| tree | 2025cdddaa7ef6769ac69c51eeede0924ffcba5f /Ryujinx.Graphics/Gal | |
| parent | 211f7f69db4d84b82caa3ee62d4ecdfbbd95604d (diff) | |
Some small sync primitive fixes, logging fixes, started to implement the 2D engine on the GPU, fixed DrawArrays, implemented a few more shader instructions, made a start on nvdrv refactor, etc...
Diffstat (limited to 'Ryujinx.Graphics/Gal')
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalRenderer.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs | 25 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 9 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 108 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs | 87 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs | 92 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs | 5 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs | 32 |
9 files changed, 312 insertions, 69 deletions
diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index af88412a..e4aef206 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -44,6 +44,8 @@ namespace Ryujinx.Graphics.Gal void SetViewport(int X, int Y, int Width, int Height); + void GetFrameBufferData(long Tag, Action<byte[]> Callback); + //Rasterizer void ClearBuffers(int RtIndex, GalClearBufferFlags Flags); @@ -51,7 +53,7 @@ namespace Ryujinx.Graphics.Gal void SetIndexArray(byte[] Buffer, GalIndexFormat Format); - void DrawArrays(int VbIndex, GalPrimitiveType PrimType); + void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType); void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs index 05a7288a..8f265f54 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs @@ -270,6 +270,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL } } + public void GetBufferData(long Tag, Action<byte[]> Callback) + { + if (Fbs.TryGetValue(Tag, out FrameBuffer Fb)) + { + GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, Fb.Handle); + + byte[] Data = new byte[Fb.Width * Fb.Height * 4]; + + (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8); + + GL.ReadPixels( + 0, + 0, + Fb.Width, + Fb.Height, + Format, + Type, + Data); + + Callback(Data); + + GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, CurrFbHandle); + } + } + private void SetViewport(Rect Viewport) { GL.Viewport( diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index 9e0d4523..b1504563 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -48,8 +48,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL { public int VaoHandle; public int VboHandle; - - public int PrimCount; } private struct IbInfo @@ -102,8 +100,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL { EnsureVbInitialized(VbIndex); - VertexBuffers[VbIndex].PrimCount = Buffer.Length / Stride; - VbInfo Vb = VertexBuffers[VbIndex]; IntPtr Length = new IntPtr(Buffer.Length); @@ -171,29 +167,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); } - public void DrawArrays(int VbIndex, GalPrimitiveType PrimType) + public void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType) { - VbInfo Vb = VertexBuffers[VbIndex]; - - if (Vb.PrimCount == 0) + if (PrimCount == 0) { return; } + VbInfo Vb = VertexBuffers[VbIndex]; + GL.BindVertexArray(Vb.VaoHandle); - GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), 0, Vb.PrimCount); + GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount); } public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType) { VbInfo Vb = VertexBuffers[VbIndex]; - if (Vb.PrimCount == 0) - { - return; - } - PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType); GL.BindVertexArray(Vb.VaoHandle); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index cf2da91c..f9410573 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -146,6 +146,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue.Enqueue(() => FrameBuffer.SetViewport(X, Y, Width, Height)); } + public void GetFrameBufferData(long Tag, Action<byte[]> Callback) + { + ActionsQueue.Enqueue(() => FrameBuffer.GetBufferData(Tag, Callback)); + } + public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags) { ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags)); @@ -173,14 +178,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Buffer, Format)); } - public void DrawArrays(int VbIndex, GalPrimitiveType PrimType) + public void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType) { if ((uint)VbIndex > 31) { throw new ArgumentOutOfRangeException(nameof(VbIndex)); } - ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(VbIndex, PrimType)); + ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(VbIndex, First, PrimCount, PrimType)); } public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index d7173bcd..c22f5926 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -31,51 +31,53 @@ namespace Ryujinx.Graphics.Gal.Shader { InstsExpr = new Dictionary<ShaderIrInst, GetInstExpr>() { - { ShaderIrInst.And, GetAndExpr }, - { ShaderIrInst.Asr, GetAsrExpr }, - { ShaderIrInst.Band, GetBandExpr }, - { ShaderIrInst.Bnot, GetBnotExpr }, - { ShaderIrInst.Ceil, GetCeilExpr }, - { ShaderIrInst.Ceq, GetCeqExpr }, - { ShaderIrInst.Cge, GetCgeExpr }, - { ShaderIrInst.Cgt, GetCgtExpr }, - { ShaderIrInst.Clamp, GetClampExpr }, - { ShaderIrInst.Cle, GetCleExpr }, - { ShaderIrInst.Clt, GetCltExpr }, - { ShaderIrInst.Cne, GetCneExpr }, - { ShaderIrInst.Exit, GetExitExpr }, - { ShaderIrInst.Fabs, GetFabsExpr }, - { ShaderIrInst.Fadd, GetFaddExpr }, - { ShaderIrInst.Fceq, GetCeqExpr }, - { ShaderIrInst.Fcge, GetCgeExpr }, - { ShaderIrInst.Fcgt, GetCgtExpr }, - { ShaderIrInst.Fcle, GetCleExpr }, - { ShaderIrInst.Fclt, GetCltExpr }, - { ShaderIrInst.Fcne, GetCneExpr }, - { ShaderIrInst.Fcos, GetFcosExpr }, - { ShaderIrInst.Fex2, GetFex2Expr }, - { ShaderIrInst.Ffma, GetFfmaExpr }, - { ShaderIrInst.Flg2, GetFlg2Expr }, - { ShaderIrInst.Floor, GetFloorExpr }, - { ShaderIrInst.Fmul, GetFmulExpr }, - { ShaderIrInst.Fneg, GetFnegExpr }, - { ShaderIrInst.Frcp, GetFrcpExpr }, - { ShaderIrInst.Frsq, GetFrsqExpr }, - { ShaderIrInst.Fsin, GetFsinExpr }, - { ShaderIrInst.Ftos, GetFtosExpr }, - { ShaderIrInst.Ftou, GetFtouExpr }, - { ShaderIrInst.Ipa, GetIpaExpr }, - { ShaderIrInst.Kil, GetKilExpr }, - { ShaderIrInst.Lsr, GetLsrExpr }, - { ShaderIrInst.Not, GetNotExpr }, - { ShaderIrInst.Or, GetOrExpr }, - { ShaderIrInst.Stof, GetStofExpr }, - { ShaderIrInst.Texq, GetTexqExpr }, - { ShaderIrInst.Texs, GetTexsExpr }, - { ShaderIrInst.Trunc, GetTruncExpr }, - { ShaderIrInst.Txlf, GetTxlfExpr }, - { ShaderIrInst.Utof, GetUtofExpr }, - { ShaderIrInst.Xor, GetXorExpr } + { ShaderIrInst.And, GetAndExpr }, + { ShaderIrInst.Asr, GetAsrExpr }, + { ShaderIrInst.Band, GetBandExpr }, + { ShaderIrInst.Bnot, GetBnotExpr }, + { ShaderIrInst.Ceil, GetCeilExpr }, + { ShaderIrInst.Ceq, GetCeqExpr }, + { ShaderIrInst.Cge, GetCgeExpr }, + { ShaderIrInst.Cgt, GetCgtExpr }, + { ShaderIrInst.Clamps, GetClampsExpr }, + { ShaderIrInst.Clampu, GetClampuExpr }, + { ShaderIrInst.Cle, GetCleExpr }, + { ShaderIrInst.Clt, GetCltExpr }, + { ShaderIrInst.Cne, GetCneExpr }, + { ShaderIrInst.Exit, GetExitExpr }, + { ShaderIrInst.Fabs, GetFabsExpr }, + { ShaderIrInst.Fadd, GetFaddExpr }, + { ShaderIrInst.Fceq, GetCeqExpr }, + { ShaderIrInst.Fcge, GetCgeExpr }, + { ShaderIrInst.Fcgt, GetCgtExpr }, + { ShaderIrInst.Fclamp, GetFclampExpr }, + { ShaderIrInst.Fcle, GetCleExpr }, + { ShaderIrInst.Fclt, GetCltExpr }, + { ShaderIrInst.Fcne, GetCneExpr }, + { ShaderIrInst.Fcos, GetFcosExpr }, + { ShaderIrInst.Fex2, GetFex2Expr }, + { ShaderIrInst.Ffma, GetFfmaExpr }, + { ShaderIrInst.Flg2, GetFlg2Expr }, + { ShaderIrInst.Floor, GetFloorExpr }, + { ShaderIrInst.Fmul, GetFmulExpr }, + { ShaderIrInst.Fneg, GetFnegExpr }, + { ShaderIrInst.Frcp, GetFrcpExpr }, + { ShaderIrInst.Frsq, GetFrsqExpr }, + { ShaderIrInst.Fsin, GetFsinExpr }, + { ShaderIrInst.Ftos, GetFtosExpr }, + { ShaderIrInst.Ftou, GetFtouExpr }, + { ShaderIrInst.Ipa, GetIpaExpr }, + { ShaderIrInst.Kil, GetKilExpr }, + { ShaderIrInst.Lsr, GetLsrExpr }, + { ShaderIrInst.Not, GetNotExpr }, + { ShaderIrInst.Or, GetOrExpr }, + { ShaderIrInst.Stof, GetStofExpr }, + { ShaderIrInst.Texq, GetTexqExpr }, + { ShaderIrInst.Texs, GetTexsExpr }, + { ShaderIrInst.Trunc, GetTruncExpr }, + { ShaderIrInst.Txlf, GetTxlfExpr }, + { ShaderIrInst.Utof, GetUtofExpr }, + { ShaderIrInst.Xor, GetXorExpr } }; } @@ -478,7 +480,19 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetCeilExpr(ShaderIrOp Op) => GetUnaryCall(Op, "ceil"); - private string GetClampExpr(ShaderIrOp Op) => GetTernaryCall(Op, "clamp"); + private string GetClampsExpr(ShaderIrOp Op) + { + return "clamp(" + GetOperExpr(Op, Op.OperandA) + ", " + + GetOperExpr(Op, Op.OperandB) + ", " + + GetOperExpr(Op, Op.OperandC) + ")"; + } + + private string GetClampuExpr(ShaderIrOp Op) + { + return "int(clamp(uint(" + GetOperExpr(Op, Op.OperandA) + "), " + + "uint(" + GetOperExpr(Op, Op.OperandB) + "), " + + "uint(" + GetOperExpr(Op, Op.OperandC) + ")))"; + } private string GetCltExpr(ShaderIrOp Op) => GetBinaryExpr(Op, "<"); private string GetCeqExpr(ShaderIrOp Op) => GetBinaryExpr(Op, "=="); @@ -499,6 +513,8 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetFfmaExpr(ShaderIrOp Op) => GetTernaryExpr(Op, "*", "+"); + private string GetFclampExpr(ShaderIrOp Op) => GetTernaryCall(Op, "clamp"); + private string GetFlg2Expr(ShaderIrOp Op) => GetUnaryCall(Op, "log2"); private string GetFloorExpr(ShaderIrOp Op) => GetUnaryCall(Op, "floor"); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs index 830aeb8c..42609bce 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs @@ -66,6 +66,21 @@ namespace Ryujinx.Graphics.Gal.Shader EmitAluBinaryF(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul); } + public static void Fset_C(ShaderIrBlock Block, long OpCode) + { + EmitFset(Block, OpCode, ShaderOper.CR); + } + + public static void Fset_I(ShaderIrBlock Block, long OpCode) + { + EmitFset(Block, OpCode, ShaderOper.Immf); + } + + public static void Fset_R(ShaderIrBlock Block, long OpCode) + { + EmitFset(Block, OpCode, ShaderOper.RR); + } + public static void Fsetp_C(ShaderIrBlock Block, long OpCode) { EmitFsetp(Block, OpCode, ShaderOper.CR); @@ -279,6 +294,78 @@ namespace Ryujinx.Graphics.Gal.Shader Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); } + private static void EmitFset(ShaderIrBlock Block, long OpCode, ShaderOper Oper) + { + EmitSet(Block, OpCode, true, Oper); + } + + private static void EmitIset(ShaderIrBlock Block, long OpCode, ShaderOper Oper) + { + EmitSet(Block, OpCode, false, Oper); + } + + private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper) + { + bool Na = ((OpCode >> 43) & 1) != 0; + bool Ab = ((OpCode >> 44) & 1) != 0; + bool Nb = ((OpCode >> 53) & 1) != 0; + bool Aa = ((OpCode >> 54) & 1) != 0; + + ShaderIrNode OperA = GetOperGpr8(OpCode), OperB; + + switch (Oper) + { + case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; + case ShaderOper.Imm: OperB = GetOperImm19_20 (OpCode); break; + case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break; + case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; + + default: throw new ArgumentException(nameof(Oper)); + } + + ShaderIrInst CmpInst; + + if (IsFloat) + { + OperA = GetAluAbsNeg(OperA, Aa, Na); + OperB = GetAluAbsNeg(OperB, Ab, Nb); + + CmpInst = GetCmpF(OpCode); + } + else + { + CmpInst = GetCmp(OpCode); + } + + ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB); + + ShaderIrInst LopInst = GetBLop(OpCode); + + ShaderIrOperPred PNode = GetOperPred39(OpCode); + + ShaderIrOperImmf Imm0 = new ShaderIrOperImmf(0); + ShaderIrOperImmf Imm1 = new ShaderIrOperImmf(1); + + ShaderIrNode Asg0 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm0); + ShaderIrNode Asg1 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm1); + + if (LopInst != ShaderIrInst.Band || !PNode.IsConst) + { + ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode); + + Asg0 = new ShaderIrCond(Op2, Asg0, Not: true); + Asg1 = new ShaderIrCond(Op2, Asg1, Not: false); + } + else + { + Asg0 = new ShaderIrCond(Op, Asg0, Not: true); + Asg1 = new ShaderIrCond(Op, Asg1, Not: false); + } + + Block.AddNode(GetPredNode(Asg0, OpCode)); + Block.AddNode(GetPredNode(Asg1, OpCode)); + } + private static void EmitFsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper) { EmitSetp(Block, OpCode, true, Oper); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs index 6d30cfed..b9cf02f1 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs @@ -70,6 +70,21 @@ namespace Ryujinx.Graphics.Gal.Shader EmitI2f(Block, OpCode, ShaderOper.RR); } + public static void I2i_C(ShaderIrBlock Block, long OpCode) + { + EmitI2i(Block, OpCode, ShaderOper.CR); + } + + public static void I2i_I(ShaderIrBlock Block, long OpCode) + { + EmitI2i(Block, OpCode, ShaderOper.Imm); + } + + public static void I2i_R(ShaderIrBlock Block, long OpCode) + { + EmitI2i(Block, OpCode, ShaderOper.RR); + } + public static void Mov_C(ShaderIrBlock Block, long OpCode) { ShaderIrOperCbuf Cbuf = GetOperCbuf34(OpCode); @@ -183,7 +198,7 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrOperImmf IMin = new ShaderIrOperImmf(CMin); ShaderIrOperImmf IMax = new ShaderIrOperImmf(CMax); - OperA = new ShaderIrOp(ShaderIrInst.Clamp, OperA, IMin, IMax); + OperA = new ShaderIrOp(ShaderIrInst.Fclamp, OperA, IMin, IMax); } ShaderIrInst Inst = Signed @@ -252,6 +267,81 @@ namespace Ryujinx.Graphics.Gal.Shader Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); } + private static void EmitI2i(ShaderIrBlock Block, long OpCode, ShaderOper Oper) + { + IntType Type = GetIntType(OpCode); + + if (Type == IntType.U64 || + Type == IntType.S64) + { + //TODO: 64-bits support. + //Note: GLSL doesn't support 64-bits integers. + throw new NotImplementedException(); + } + + int Sel = (int)(OpCode >> 41) & 3; + + bool NegA = ((OpCode >> 45) & 1) != 0; + bool AbsA = ((OpCode >> 49) & 1) != 0; + bool SatA = ((OpCode >> 50) & 1) != 0; + + ShaderIrNode OperA; + + switch (Oper) + { + case ShaderOper.CR: OperA = GetOperCbuf34 (OpCode); break; + case ShaderOper.Immf: OperA = GetOperImmf19_20(OpCode); break; + case ShaderOper.RR: OperA = GetOperGpr20 (OpCode); break; + + default: throw new ArgumentException(nameof(Oper)); + } + + OperA = GetAluAbsNeg(OperA, AbsA, NegA); + + bool Signed = Type >= IntType.S8; + + int Shift = Sel * 8; + + int Size = 8 << ((int)Type & 3); + + if (Shift != 0) + { + OperA = new ShaderIrOp(ShaderIrInst.Asr, OperA, new ShaderIrOperImm(Shift)); + } + + if (Size < 32) + { + uint Mask = uint.MaxValue >> (32 - Size); + + if (SatA) + { + uint CMin = 0; + uint CMax = Mask; + + if (Signed) + { + uint HalfMask = Mask >> 1; + + CMin -= HalfMask + 1; + CMax = HalfMask; + } + + ShaderIrOperImm IMin = new ShaderIrOperImm((int)CMin); + ShaderIrOperImm IMax = new ShaderIrOperImm((int)CMax); + + OperA = new ShaderIrOp(Signed + ? ShaderIrInst.Clamps + : ShaderIrInst.Clampu, OperA, IMin, IMax); + } + else + { + OperA = new ShaderIrOp(ShaderIrInst.And, OperA, new ShaderIrOperImm((int)Mask)); + } + } + + Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode)); + } + private static IntType GetIntType(long OpCode) { bool Signed = ((OpCode >> 13) & 1) != 0; diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs index 1b72f647..ce2b98fe 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Gal.Shader F_Start, Ceil, - Clamp, + Fabs, Fadd, Fceq, @@ -22,6 +22,7 @@ namespace Ryujinx.Graphics.Gal.Shader Fcgeu, Fcgt, Fcgtu, + Fclamp, Fcle, Fcleu, Fclt, @@ -53,6 +54,8 @@ namespace Ryujinx.Graphics.Gal.Shader Ceq, Cge, Cgt, + Clamps, + Clampu, Cle, Clt, Cne, diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs index 762544cb..65e24928 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs @@ -6,11 +6,24 @@ namespace Ryujinx.Graphics.Gal.Shader { private const int EncodingBits = 14; - private static ShaderDecodeFunc[] OpCodes; + private class ShaderDecodeEntry + { + public ShaderDecodeFunc Func; + + public int XBits; + + public ShaderDecodeEntry(ShaderDecodeFunc Func, int XBits) + { + this.Func = Func; + this.XBits = XBits; + } + } + + private static ShaderDecodeEntry[] OpCodes; static ShaderOpCodeTable() { - OpCodes = new ShaderDecodeFunc[1 << EncodingBits]; + OpCodes = new ShaderDecodeEntry[1 << EncodingBits]; #region Instructions Set("111000110000xx", ShaderDecode.Exit); @@ -31,12 +44,18 @@ namespace Ryujinx.Graphics.Gal.Shader Set("0100110001101x", ShaderDecode.Fmul_C); Set("0011100x01101x", ShaderDecode.Fmul_I); Set("0101110001101x", ShaderDecode.Fmul_R); + Set("0100100xxxxxxx", ShaderDecode.Fset_C); + Set("0011000xxxxxxx", ShaderDecode.Fset_I); + Set("01011000xxxxxx", ShaderDecode.Fset_R); Set("010010111011xx", ShaderDecode.Fsetp_C); Set("0011011x1011xx", ShaderDecode.Fsetp_I); Set("010110111011xx", ShaderDecode.Fsetp_R); Set("0100110010111x", ShaderDecode.I2f_C); Set("0011100x10111x", ShaderDecode.I2f_I); Set("0101110010111x", ShaderDecode.I2f_R); + Set("0100110011100x", ShaderDecode.I2i_C); + Set("0011100x11100x", ShaderDecode.I2i_I); + Set("0101110011100x", ShaderDecode.I2i_R); Set("11100000xxxxxx", ShaderDecode.Ipa); Set("010010110110xx", ShaderDecode.Isetp_C); Set("0011011x0110xx", ShaderDecode.Isetp_I); @@ -91,6 +110,8 @@ namespace Ryujinx.Graphics.Gal.Shader XMask = ~XMask; + ShaderDecodeEntry Entry = new ShaderDecodeEntry(Func, XBits); + for (int Index = 0; Index < (1 << XBits); Index++) { Value &= XMask; @@ -100,13 +121,16 @@ namespace Ryujinx.Graphics.Gal.Shader Value |= ((Index >> X) & 1) << XPos[X]; } - OpCodes[Value] = Func; + if (OpCodes[Value] == null || OpCodes[Value].XBits > XBits) + { + OpCodes[Value] = Entry; + } } } public static ShaderDecodeFunc GetDecoder(long OpCode) { - return OpCodes[(ulong)OpCode >> (64 - EncodingBits)]; + return OpCodes[(ulong)OpCode >> (64 - EncodingBits)]?.Func; } } }
\ No newline at end of file |
