aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-10-13 23:54:14 -0300
committerGitHub <noreply@github.com>2018-10-13 23:54:14 -0300
commit72317d777734155881081d5989aabd80146e1197 (patch)
treef8f570f6b7561c9853fcb7427101067773d69215
parent894459fcd7797b1e38f2448797d83856d11b6e23 (diff)
Add support for saturation on some shader instructions, fix ReadTexture alignment and add ColorMask support (#451)
* Add support for saturation on some shader instructions, fix ReadTexture alignment * Add ColorMask support, other tweaks
-rw-r--r--Ryujinx.Graphics/Gal/GalPipelineState.cs6
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs17
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs9
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs8
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3d.cs15
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3dReg.cs1
-rw-r--r--Ryujinx.Graphics/Texture/ImageUtils.cs17
8 files changed, 63 insertions, 12 deletions
diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs
index 8837eb8c..1bfe2684 100644
--- a/Ryujinx.Graphics/Gal/GalPipelineState.cs
+++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs
@@ -26,6 +26,7 @@
public GalComparisonOp DepthFunc;
public bool StencilTestEnabled;
+ public bool StencilTwoSideEnabled;
public GalComparisonOp StencilBackFuncFunc;
public int StencilBackFuncRef;
@@ -52,6 +53,11 @@
public GalBlendFactor BlendFuncSrcAlpha;
public GalBlendFactor BlendFuncDstAlpha;
+ public bool ColorMaskR;
+ public bool ColorMaskG;
+ public bool ColorMaskB;
+ public bool ColorMaskA;
+
public bool PrimitiveRestartEnabled;
public uint PrimitiveRestartIndex;
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
index 96da17f8..b7825996 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
@@ -195,6 +195,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Enable(EnableCap.StencilTest, New.StencilTestEnabled);
}
+ if (New.StencilTwoSideEnabled != Old.StencilTwoSideEnabled)
+ {
+ Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
+ }
+
if (New.StencilTestEnabled)
{
if (New.StencilBackFuncFunc != Old.StencilBackFuncFunc ||
@@ -298,6 +303,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
+ if (New.ColorMaskR != Old.ColorMaskR ||
+ New.ColorMaskG != Old.ColorMaskG ||
+ New.ColorMaskB != Old.ColorMaskB ||
+ New.ColorMaskA != Old.ColorMaskA)
+ {
+ GL.ColorMask(
+ New.ColorMaskR,
+ New.ColorMaskG,
+ New.ColorMaskB,
+ New.ColorMaskA);
+ }
+
if (New.PrimitiveRestartEnabled != Old.PrimitiveRestartEnabled)
{
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index 11f04449..d0f9223b 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -360,7 +360,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclSsy()
{
- SB.AppendLine("uint " + GlslDecl.SsyCursorName + "= 0;");
+ SB.AppendLine("uint " + GlslDecl.SsyCursorName + " = 0;");
SB.AppendLine("uint " + GlslDecl.SsyStackName + "[" + GlslDecl.SsyStackSize + "];" + Environment.NewLine);
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
index 0a3c0da9..d4a76bc9 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
@@ -585,6 +585,7 @@ namespace Ryujinx.Graphics.Gal.Shader
bool AbsA = OpCode.Read(46);
bool NegA = OpCode.Read(48);
bool AbsB = OpCode.Read(49);
+ bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB;
@@ -603,12 +604,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fadd, OperA, OperB);
- Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
+ Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat))));
}
private static void EmitFmul(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegB = OpCode.Read(48);
+ bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB;
@@ -625,13 +627,14 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB);
- Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
+ Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat))));
}
private static void EmitFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegB = OpCode.Read(48);
bool NegC = OpCode.Read(49);
+ bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC;
@@ -658,7 +661,7 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC);
- Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
+ Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat))));
}
private static void EmitIadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
index ebacd53a..d07bcd91 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
@@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal.Shader
{
static class ShaderDecodeHelper
{
+ private static readonly ShaderIrOperImmf ImmfZero = new ShaderIrOperImmf(0);
+ private static readonly ShaderIrOperImmf ImmfOne = new ShaderIrOperImmf(1);
+
public static ShaderIrNode GetAluFabsFneg(ShaderIrNode Node, bool Abs, bool Neg)
{
return GetAluFneg(GetAluFabs(Node, Abs), Neg);
@@ -17,6 +20,11 @@ namespace Ryujinx.Graphics.Gal.Shader
return Neg ? new ShaderIrOp(ShaderIrInst.Fneg, Node) : Node;
}
+ public static ShaderIrNode GetAluFsat(ShaderIrNode Node, bool Sat)
+ {
+ return Sat ? new ShaderIrOp(ShaderIrInst.Fclamp, Node, ImmfZero, ImmfOne) : Node;
+ }
+
public static ShaderIrNode GetAluIabsIneg(ShaderIrNode Node, bool Abs, bool Neg)
{
return GetAluIneg(GetAluIabs(Node, Abs), Neg);
diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs
index 3dd7746d..a2a96928 100644
--- a/Ryujinx.Graphics/NvGpuEngine3d.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3d.cs
@@ -97,7 +97,8 @@ namespace Ryujinx.Graphics
SetCullFace(State);
SetDepth(State);
SetStencil(State);
- SetAlphaBlending(State);
+ SetBlending(State);
+ SetColorMask(State);
SetPrimitiveRestart(State);
for (int FbIndex = 0; FbIndex < 8; FbIndex++)
@@ -403,7 +404,7 @@ namespace Ryujinx.Graphics
}
}
- private void SetAlphaBlending(GalPipelineState State)
+ private void SetBlending(GalPipelineState State)
{
//TODO: Support independent blend properly.
State.BlendEnabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
@@ -421,6 +422,16 @@ namespace Ryujinx.Graphics
}
}
+ private void SetColorMask(GalPipelineState State)
+ {
+ int ColorMask = ReadRegister(NvGpuEngine3dReg.ColorMask);
+
+ State.ColorMaskR = ((ColorMask >> 0) & 0xf) != 0;
+ State.ColorMaskG = ((ColorMask >> 4) & 0xf) != 0;
+ State.ColorMaskB = ((ColorMask >> 8) & 0xf) != 0;
+ State.ColorMaskA = ((ColorMask >> 12) & 0xf) != 0;
+ }
+
private void SetPrimitiveRestart(GalPipelineState State)
{
State.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable);
diff --git a/Ryujinx.Graphics/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
index 418e5b6b..ba211313 100644
--- a/Ryujinx.Graphics/NvGpuEngine3dReg.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
@@ -78,6 +78,7 @@ namespace Ryujinx.Graphics
CullFaceEnable = 0x646,
FrontFace = 0x647,
CullFace = 0x648,
+ ColorMask = 0x680,
QueryAddress = 0x6c0,
QuerySequence = 0x6c2,
QueryControl = 0x6c3,
diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs
index 1b043245..e1f370cd 100644
--- a/Ryujinx.Graphics/Texture/ImageUtils.cs
+++ b/Ryujinx.Graphics/Texture/ImageUtils.cs
@@ -235,18 +235,23 @@ namespace Ryujinx.Graphics.Texture
int BytesPerPixel = Desc.BytesPerPixel;
- int OutOffs = 0;
+ //Note: Each row of the texture needs to be aligned to 4 bytes.
+ int Pitch = (Width * BytesPerPixel + 3) & ~3;
- byte[] Data = new byte[Width * Height * BytesPerPixel];
+ byte[] Data = new byte[Height * Pitch];
for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
{
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
+ int OutOffs = Y * Pitch;
+
+ for (int X = 0; X < Width; X++)
+ {
+ long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
- CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
+ CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
- OutOffs += BytesPerPixel;
+ OutOffs += BytesPerPixel;
+ }
}
return Data;