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
This commit is contained in:
gdkchan 2018-10-13 23:54:14 -03:00 committed by GitHub
parent 894459fcd7
commit 72317d7777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 12 deletions

View file

@ -26,6 +26,7 @@
public GalComparisonOp DepthFunc; public GalComparisonOp DepthFunc;
public bool StencilTestEnabled; public bool StencilTestEnabled;
public bool StencilTwoSideEnabled;
public GalComparisonOp StencilBackFuncFunc; public GalComparisonOp StencilBackFuncFunc;
public int StencilBackFuncRef; public int StencilBackFuncRef;
@ -52,6 +53,11 @@
public GalBlendFactor BlendFuncSrcAlpha; public GalBlendFactor BlendFuncSrcAlpha;
public GalBlendFactor BlendFuncDstAlpha; public GalBlendFactor BlendFuncDstAlpha;
public bool ColorMaskR;
public bool ColorMaskG;
public bool ColorMaskB;
public bool ColorMaskA;
public bool PrimitiveRestartEnabled; public bool PrimitiveRestartEnabled;
public uint PrimitiveRestartIndex; public uint PrimitiveRestartIndex;

View file

@ -195,6 +195,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Enable(EnableCap.StencilTest, New.StencilTestEnabled); Enable(EnableCap.StencilTest, New.StencilTestEnabled);
} }
if (New.StencilTwoSideEnabled != Old.StencilTwoSideEnabled)
{
Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
}
if (New.StencilTestEnabled) if (New.StencilTestEnabled)
{ {
if (New.StencilBackFuncFunc != Old.StencilBackFuncFunc || 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) if (New.PrimitiveRestartEnabled != Old.PrimitiveRestartEnabled)
{ {
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled); Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);

View file

@ -360,7 +360,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclSsy() private void PrintDeclSsy()
{ {
SB.AppendLine("uint " + GlslDecl.SsyCursorName + "= 0;"); SB.AppendLine("uint " + GlslDecl.SsyCursorName + " = 0;");
SB.AppendLine("uint " + GlslDecl.SsyStackName + "[" + GlslDecl.SsyStackSize + "];" + Environment.NewLine); SB.AppendLine("uint " + GlslDecl.SsyStackName + "[" + GlslDecl.SsyStackSize + "];" + Environment.NewLine);
} }

View file

@ -585,6 +585,7 @@ namespace Ryujinx.Graphics.Gal.Shader
bool AbsA = OpCode.Read(46); bool AbsA = OpCode.Read(46);
bool NegA = OpCode.Read(48); bool NegA = OpCode.Read(48);
bool AbsB = OpCode.Read(49); bool AbsB = OpCode.Read(49);
bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB; ShaderIrNode OperA = OpCode.Gpr8(), OperB;
@ -603,12 +604,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fadd, OperA, OperB); 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) private static void EmitFmul(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{ {
bool NegB = OpCode.Read(48); bool NegB = OpCode.Read(48);
bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB; ShaderIrNode OperA = OpCode.Gpr8(), OperB;
@ -625,13 +627,14 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB); 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) private static void EmitFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{ {
bool NegB = OpCode.Read(48); bool NegB = OpCode.Read(48);
bool NegC = OpCode.Read(49); bool NegC = OpCode.Read(49);
bool Sat = OpCode.Read(50);
ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC; ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC;
@ -658,7 +661,7 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC); 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) private static void EmitIadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)

View file

@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
static class ShaderDecodeHelper 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) public static ShaderIrNode GetAluFabsFneg(ShaderIrNode Node, bool Abs, bool Neg)
{ {
return GetAluFneg(GetAluFabs(Node, Abs), Neg); return GetAluFneg(GetAluFabs(Node, Abs), Neg);
@ -17,6 +20,11 @@ namespace Ryujinx.Graphics.Gal.Shader
return Neg ? new ShaderIrOp(ShaderIrInst.Fneg, Node) : Node; 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) public static ShaderIrNode GetAluIabsIneg(ShaderIrNode Node, bool Abs, bool Neg)
{ {
return GetAluIneg(GetAluIabs(Node, Abs), Neg); return GetAluIneg(GetAluIabs(Node, Abs), Neg);

View file

@ -97,7 +97,8 @@ namespace Ryujinx.Graphics
SetCullFace(State); SetCullFace(State);
SetDepth(State); SetDepth(State);
SetStencil(State); SetStencil(State);
SetAlphaBlending(State); SetBlending(State);
SetColorMask(State);
SetPrimitiveRestart(State); SetPrimitiveRestart(State);
for (int FbIndex = 0; FbIndex < 8; FbIndex++) 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. //TODO: Support independent blend properly.
State.BlendEnabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable); 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) private void SetPrimitiveRestart(GalPipelineState State)
{ {
State.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable); State.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable);

View file

@ -78,6 +78,7 @@ namespace Ryujinx.Graphics
CullFaceEnable = 0x646, CullFaceEnable = 0x646,
FrontFace = 0x647, FrontFace = 0x647,
CullFace = 0x648, CullFace = 0x648,
ColorMask = 0x680,
QueryAddress = 0x6c0, QueryAddress = 0x6c0,
QuerySequence = 0x6c2, QuerySequence = 0x6c2,
QueryControl = 0x6c3, QueryControl = 0x6c3,

View file

@ -235,18 +235,23 @@ namespace Ryujinx.Graphics.Texture
int BytesPerPixel = Desc.BytesPerPixel; 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 Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{ {
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); int OutOffs = Y * Pitch;
CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel); for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
OutOffs += BytesPerPixel; CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
OutOffs += BytesPerPixel;
}
} }
return Data; return Data;