mirror of
https://github.com/GreemDev/Ryujinx
synced 2024-12-23 04:16:32 +01:00
* Implment common and independent blend properly * Nits
This commit is contained in:
parent
1e7ea76f14
commit
44c1cf3fe5
7 changed files with 389 additions and 128 deletions
|
@ -6,6 +6,12 @@ namespace Ryujinx.Graphics.Gal
|
||||||
FuncSubtract = 2,
|
FuncSubtract = 2,
|
||||||
FuncReverseSubtract = 3,
|
FuncReverseSubtract = 3,
|
||||||
Min = 4,
|
Min = 4,
|
||||||
Max = 5
|
Max = 5,
|
||||||
|
|
||||||
|
FuncAddGl = 0x8006,
|
||||||
|
FuncSubtractGl = 0x8007,
|
||||||
|
FuncReverseSubtractGl = 0x8008,
|
||||||
|
MinGl = 0x800a,
|
||||||
|
MaxGl = 0x800b
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,6 +21,25 @@ namespace Ryujinx.Graphics.Gal
|
||||||
OneMinusConstantColor = 0x62,
|
OneMinusConstantColor = 0x62,
|
||||||
ConstantAlpha = 0x63,
|
ConstantAlpha = 0x63,
|
||||||
OneMinusConstantAlpha = 0x64,
|
OneMinusConstantAlpha = 0x64,
|
||||||
ConstantColorG80 = 0xc001
|
|
||||||
|
ZeroGl = 0x4000,
|
||||||
|
OneGl = 0x4001,
|
||||||
|
SrcColorGl = 0x4300,
|
||||||
|
OneMinusSrcColorGl = 0x4301,
|
||||||
|
SrcAlphaGl = 0x4302,
|
||||||
|
OneMinusSrcAlphaGl = 0x4303,
|
||||||
|
DstAlphaGl = 0x4304,
|
||||||
|
OneMinusDstAlphaGl = 0x4305,
|
||||||
|
DstColorGl = 0x4306,
|
||||||
|
OneMinusDstColorGl = 0x4307,
|
||||||
|
SrcAlphaSaturateGl = 0x4308,
|
||||||
|
ConstantColorGl = 0xc001,
|
||||||
|
OneMinusConstantColorGl = 0xc002,
|
||||||
|
ConstantAlphaGl = 0xc003,
|
||||||
|
OneMinusConstantAlphaGl = 0xc004,
|
||||||
|
Src1ColorGl = 0xc900,
|
||||||
|
OneMinusSrc1ColorGl = 0xc901,
|
||||||
|
Src1AlphaGl = 0xc902,
|
||||||
|
OneMinusSrc1AlphaGl = 0xc903
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
namespace Ryujinx.Graphics.Gal
|
namespace Ryujinx.Graphics.Gal
|
||||||
{
|
{
|
||||||
public struct ColorMaskRgba
|
public struct ColorMaskState
|
||||||
{
|
{
|
||||||
private static readonly ColorMaskRgba _Default = new ColorMaskRgba()
|
private static readonly ColorMaskState _Default = new ColorMaskState()
|
||||||
{
|
{
|
||||||
Red = true,
|
Red = true,
|
||||||
Green = true,
|
Green = true,
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
Alpha = true
|
Alpha = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ColorMaskRgba Default => _Default;
|
public static ColorMaskState Default => _Default;
|
||||||
|
|
||||||
public bool Red;
|
public bool Red;
|
||||||
public bool Green;
|
public bool Green;
|
||||||
|
@ -18,6 +18,32 @@
|
||||||
public bool Alpha;
|
public bool Alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct BlendState
|
||||||
|
{
|
||||||
|
private static readonly BlendState _Default = new BlendState()
|
||||||
|
{
|
||||||
|
Enabled = false,
|
||||||
|
SeparateAlpha = false,
|
||||||
|
EquationRgb = 0,
|
||||||
|
FuncSrcRgb = GalBlendFactor.One,
|
||||||
|
FuncDstRgb = GalBlendFactor.Zero,
|
||||||
|
EquationAlpha = 0,
|
||||||
|
FuncSrcAlpha = GalBlendFactor.One,
|
||||||
|
FuncDstAlpha = GalBlendFactor.Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
public static BlendState Default => _Default;
|
||||||
|
|
||||||
|
public bool Enabled;
|
||||||
|
public bool SeparateAlpha;
|
||||||
|
public GalBlendEquation EquationRgb;
|
||||||
|
public GalBlendFactor FuncSrcRgb;
|
||||||
|
public GalBlendFactor FuncDstRgb;
|
||||||
|
public GalBlendEquation EquationAlpha;
|
||||||
|
public GalBlendFactor FuncSrcAlpha;
|
||||||
|
public GalBlendFactor FuncDstAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
public class GalPipelineState
|
public class GalPipelineState
|
||||||
{
|
{
|
||||||
public const int Stages = 5;
|
public const int Stages = 5;
|
||||||
|
@ -65,17 +91,11 @@
|
||||||
public GalStencilOp StencilFrontOpZPass;
|
public GalStencilOp StencilFrontOpZPass;
|
||||||
public uint StencilFrontMask;
|
public uint StencilFrontMask;
|
||||||
|
|
||||||
public bool BlendEnabled;
|
public bool BlendIndependent;
|
||||||
public bool BlendSeparateAlpha;
|
public BlendState[] Blends;
|
||||||
public GalBlendEquation BlendEquationRgb;
|
|
||||||
public GalBlendFactor BlendFuncSrcRgb;
|
|
||||||
public GalBlendFactor BlendFuncDstRgb;
|
|
||||||
public GalBlendEquation BlendEquationAlpha;
|
|
||||||
public GalBlendFactor BlendFuncSrcAlpha;
|
|
||||||
public GalBlendFactor BlendFuncDstAlpha;
|
|
||||||
|
|
||||||
public bool ColorMaskCommon;
|
public bool ColorMaskCommon;
|
||||||
public ColorMaskRgba[] ColorMasks;
|
public ColorMaskState[] ColorMasks;
|
||||||
|
|
||||||
public bool PrimitiveRestartEnabled;
|
public bool PrimitiveRestartEnabled;
|
||||||
public uint PrimitiveRestartIndex;
|
public uint PrimitiveRestartIndex;
|
||||||
|
@ -89,7 +109,9 @@
|
||||||
ConstBufferKeys[Stage] = new long[ConstBuffersPerStage];
|
ConstBufferKeys[Stage] = new long[ConstBuffersPerStage];
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorMasks = new ColorMaskRgba[RenderTargetsCount];
|
Blends = new BlendState[RenderTargetsCount];
|
||||||
|
|
||||||
|
ColorMasks = new ColorMaskState[RenderTargetsCount];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -47,32 +47,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
|
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
|
||||||
{
|
{
|
||||||
//Looks like the GPU can take it's own values (described in GalComparisonOp) and OpenGL values alike
|
return (DepthFunction)GetFunc(Func);
|
||||||
if ((int)Func >= (int)DepthFunction.Never &&
|
|
||||||
(int)Func <= (int)DepthFunction.Always)
|
|
||||||
{
|
|
||||||
return (DepthFunction)Func;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Func)
|
|
||||||
{
|
|
||||||
case GalComparisonOp.Never: return DepthFunction.Never;
|
|
||||||
case GalComparisonOp.Less: return DepthFunction.Less;
|
|
||||||
case GalComparisonOp.Equal: return DepthFunction.Equal;
|
|
||||||
case GalComparisonOp.Lequal: return DepthFunction.Lequal;
|
|
||||||
case GalComparisonOp.Greater: return DepthFunction.Greater;
|
|
||||||
case GalComparisonOp.NotEqual: return DepthFunction.Notequal;
|
|
||||||
case GalComparisonOp.Gequal: return DepthFunction.Gequal;
|
|
||||||
case GalComparisonOp.Always: return DepthFunction.Always;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Func) + " \"" + Func + "\" is not valid!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StencilFunction GetStencilFunc(GalComparisonOp Func)
|
public static StencilFunction GetStencilFunc(GalComparisonOp Func)
|
||||||
{
|
{
|
||||||
//OGL comparison values match, it's just an enum cast
|
return (StencilFunction)GetFunc(Func);
|
||||||
return (StencilFunction)GetDepthFunc(Func);
|
}
|
||||||
|
|
||||||
|
private static All GetFunc(GalComparisonOp Func)
|
||||||
|
{
|
||||||
|
if ((int)Func >= (int)All.Never &&
|
||||||
|
(int)Func <= (int)All.Always)
|
||||||
|
{
|
||||||
|
return (All)Func;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Func)
|
||||||
|
{
|
||||||
|
case GalComparisonOp.Never: return All.Never;
|
||||||
|
case GalComparisonOp.Less: return All.Less;
|
||||||
|
case GalComparisonOp.Equal: return All.Equal;
|
||||||
|
case GalComparisonOp.Lequal: return All.Lequal;
|
||||||
|
case GalComparisonOp.Greater: return All.Greater;
|
||||||
|
case GalComparisonOp.NotEqual: return All.Notequal;
|
||||||
|
case GalComparisonOp.Gequal: return All.Gequal;
|
||||||
|
case GalComparisonOp.Always: return All.Always;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException(nameof(Func) + " \"" + Func + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
|
public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
|
||||||
|
@ -282,11 +285,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
switch (BlendEquation)
|
switch (BlendEquation)
|
||||||
{
|
{
|
||||||
case GalBlendEquation.FuncAdd: return BlendEquationMode.FuncAdd;
|
case GalBlendEquation.FuncAdd:
|
||||||
case GalBlendEquation.FuncSubtract: return BlendEquationMode.FuncSubtract;
|
case GalBlendEquation.FuncAddGl:
|
||||||
case GalBlendEquation.FuncReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
|
return BlendEquationMode.FuncAdd;
|
||||||
case GalBlendEquation.Min: return BlendEquationMode.Min;
|
|
||||||
case GalBlendEquation.Max: return BlendEquationMode.Max;
|
case GalBlendEquation.FuncSubtract:
|
||||||
|
case GalBlendEquation.FuncSubtractGl:
|
||||||
|
return BlendEquationMode.FuncSubtract;
|
||||||
|
|
||||||
|
case GalBlendEquation.FuncReverseSubtract:
|
||||||
|
case GalBlendEquation.FuncReverseSubtractGl:
|
||||||
|
return BlendEquationMode.FuncReverseSubtract;
|
||||||
|
|
||||||
|
case GalBlendEquation.Min:
|
||||||
|
case GalBlendEquation.MinGl:
|
||||||
|
return BlendEquationMode.Min;
|
||||||
|
|
||||||
|
case GalBlendEquation.Max:
|
||||||
|
case GalBlendEquation.MaxGl:
|
||||||
|
return BlendEquationMode.Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(BlendEquation) + " \"" + BlendEquation + "\" is not valid!");
|
throw new ArgumentException(nameof(BlendEquation) + " \"" + BlendEquation + "\" is not valid!");
|
||||||
|
@ -296,27 +313,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
switch (BlendFactor)
|
switch (BlendFactor)
|
||||||
{
|
{
|
||||||
case GalBlendFactor.Zero: return BlendingFactor.Zero;
|
case GalBlendFactor.Zero:
|
||||||
case GalBlendFactor.One: return BlendingFactor.One;
|
case GalBlendFactor.ZeroGl:
|
||||||
case GalBlendFactor.SrcColor: return BlendingFactor.SrcColor;
|
return BlendingFactor.Zero;
|
||||||
case GalBlendFactor.OneMinusSrcColor: return BlendingFactor.OneMinusSrcColor;
|
|
||||||
case GalBlendFactor.DstColor: return BlendingFactor.DstColor;
|
case GalBlendFactor.One:
|
||||||
case GalBlendFactor.OneMinusDstColor: return BlendingFactor.OneMinusDstColor;
|
case GalBlendFactor.OneGl:
|
||||||
case GalBlendFactor.SrcAlpha: return BlendingFactor.SrcAlpha;
|
return BlendingFactor.One;
|
||||||
case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactor.OneMinusSrcAlpha;
|
|
||||||
case GalBlendFactor.DstAlpha: return BlendingFactor.DstAlpha;
|
case GalBlendFactor.SrcColor:
|
||||||
case GalBlendFactor.OneMinusDstAlpha: return BlendingFactor.OneMinusDstAlpha;
|
case GalBlendFactor.SrcColorGl:
|
||||||
case GalBlendFactor.OneMinusConstantColor: return BlendingFactor.OneMinusConstantColor;
|
return BlendingFactor.SrcColor;
|
||||||
case GalBlendFactor.ConstantAlpha: return BlendingFactor.ConstantAlpha;
|
|
||||||
case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactor.OneMinusConstantAlpha;
|
case GalBlendFactor.OneMinusSrcColor:
|
||||||
case GalBlendFactor.SrcAlphaSaturate: return BlendingFactor.SrcAlphaSaturate;
|
case GalBlendFactor.OneMinusSrcColorGl:
|
||||||
case GalBlendFactor.Src1Color: return BlendingFactor.Src1Color;
|
return BlendingFactor.OneMinusSrcColor;
|
||||||
case GalBlendFactor.OneMinusSrc1Color: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color;
|
|
||||||
case GalBlendFactor.Src1Alpha: return BlendingFactor.Src1Alpha;
|
case GalBlendFactor.DstColor:
|
||||||
case GalBlendFactor.OneMinusSrc1Alpha: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha;
|
case GalBlendFactor.DstColorGl:
|
||||||
|
return BlendingFactor.DstColor;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusDstColor:
|
||||||
|
case GalBlendFactor.OneMinusDstColorGl:
|
||||||
|
return BlendingFactor.OneMinusDstColor;
|
||||||
|
|
||||||
|
case GalBlendFactor.SrcAlpha:
|
||||||
|
case GalBlendFactor.SrcAlphaGl:
|
||||||
|
return BlendingFactor.SrcAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusSrcAlpha:
|
||||||
|
case GalBlendFactor.OneMinusSrcAlphaGl:
|
||||||
|
return BlendingFactor.OneMinusSrcAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.DstAlpha:
|
||||||
|
case GalBlendFactor.DstAlphaGl:
|
||||||
|
return BlendingFactor.DstAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusDstAlpha:
|
||||||
|
case GalBlendFactor.OneMinusDstAlphaGl:
|
||||||
|
return BlendingFactor.OneMinusDstAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusConstantColor:
|
||||||
|
case GalBlendFactor.OneMinusConstantColorGl:
|
||||||
|
return BlendingFactor.OneMinusConstantColor;
|
||||||
|
|
||||||
|
case GalBlendFactor.ConstantAlpha:
|
||||||
|
case GalBlendFactor.ConstantAlphaGl:
|
||||||
|
return BlendingFactor.ConstantAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusConstantAlpha:
|
||||||
|
case GalBlendFactor.OneMinusConstantAlphaGl:
|
||||||
|
return BlendingFactor.OneMinusConstantAlpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.SrcAlphaSaturate:
|
||||||
|
case GalBlendFactor.SrcAlphaSaturateGl:
|
||||||
|
return BlendingFactor.SrcAlphaSaturate;
|
||||||
|
|
||||||
|
case GalBlendFactor.Src1Color:
|
||||||
|
case GalBlendFactor.Src1ColorGl:
|
||||||
|
return BlendingFactor.Src1Color;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusSrc1Color:
|
||||||
|
case GalBlendFactor.OneMinusSrc1ColorGl:
|
||||||
|
return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color;
|
||||||
|
|
||||||
|
case GalBlendFactor.Src1Alpha:
|
||||||
|
case GalBlendFactor.Src1AlphaGl:
|
||||||
|
return BlendingFactor.Src1Alpha;
|
||||||
|
|
||||||
|
case GalBlendFactor.OneMinusSrc1Alpha:
|
||||||
|
case GalBlendFactor.OneMinusSrc1AlphaGl:
|
||||||
|
return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha;
|
||||||
|
|
||||||
case GalBlendFactor.ConstantColor:
|
case GalBlendFactor.ConstantColor:
|
||||||
case GalBlendFactor.ConstantColorG80:
|
case GalBlendFactor.ConstantColorGl:
|
||||||
return BlendingFactor.ConstantColor;
|
return BlendingFactor.ConstantColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,15 +121,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
StencilFrontOpZPass = GalStencilOp.Keep,
|
StencilFrontOpZPass = GalStencilOp.Keep,
|
||||||
StencilFrontMask = UInt32.MaxValue,
|
StencilFrontMask = UInt32.MaxValue,
|
||||||
|
|
||||||
BlendEnabled = false,
|
BlendIndependent = false,
|
||||||
BlendSeparateAlpha = false,
|
|
||||||
|
|
||||||
BlendEquationRgb = 0,
|
|
||||||
BlendFuncSrcRgb = GalBlendFactor.One,
|
|
||||||
BlendFuncDstRgb = GalBlendFactor.Zero,
|
|
||||||
BlendEquationAlpha = 0,
|
|
||||||
BlendFuncSrcAlpha = GalBlendFactor.One,
|
|
||||||
BlendFuncDstAlpha = GalBlendFactor.Zero,
|
|
||||||
|
|
||||||
PrimitiveRestartEnabled = false,
|
PrimitiveRestartEnabled = false,
|
||||||
PrimitiveRestartIndex = 0
|
PrimitiveRestartIndex = 0
|
||||||
|
@ -137,7 +129,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
{
|
{
|
||||||
Old.ColorMasks[Index] = ColorMaskRgba.Default;
|
Old.Blends[Index] = BlendState.Default;
|
||||||
|
|
||||||
|
Old.ColorMasks[Index] = ColorMaskState.Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,49 +262,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.BlendEnabled != Old.BlendEnabled)
|
if (New.BlendIndependent)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.Blend, New.BlendEnabled);
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
}
|
|
||||||
|
|
||||||
if (New.BlendEnabled)
|
|
||||||
{
|
{
|
||||||
if (New.BlendSeparateAlpha)
|
SetBlendState(Index, New.Blends[Index], Old.Blends[Index]);
|
||||||
{
|
|
||||||
if (New.BlendEquationRgb != Old.BlendEquationRgb ||
|
|
||||||
New.BlendEquationAlpha != Old.BlendEquationAlpha)
|
|
||||||
{
|
|
||||||
GL.BlendEquationSeparate(
|
|
||||||
OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb),
|
|
||||||
OGLEnumConverter.GetBlendEquation(New.BlendEquationAlpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
|
|
||||||
New.BlendFuncDstRgb != Old.BlendFuncDstRgb ||
|
|
||||||
New.BlendFuncSrcAlpha != Old.BlendFuncSrcAlpha ||
|
|
||||||
New.BlendFuncDstAlpha != Old.BlendFuncDstAlpha)
|
|
||||||
{
|
|
||||||
GL.BlendFuncSeparate(
|
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
|
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb),
|
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcAlpha),
|
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstAlpha));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (New.BlendEquationRgb != Old.BlendEquationRgb)
|
if (New.BlendIndependent != Old.BlendIndependent)
|
||||||
{
|
{
|
||||||
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
|
SetAllBlendState(New.Blends[0]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
|
|
||||||
New.BlendFuncDstRgb != Old.BlendFuncDstRgb)
|
|
||||||
{
|
{
|
||||||
GL.BlendFunc(
|
SetBlendState(New.Blends[0], Old.Blends[0]);
|
||||||
OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
|
|
||||||
OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +324,136 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Old = New;
|
Old = New;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetAllBlendState(BlendState New)
|
||||||
|
{
|
||||||
|
Enable(EnableCap.Blend, New.Enabled);
|
||||||
|
|
||||||
|
if (New.Enabled)
|
||||||
|
{
|
||||||
|
if (New.SeparateAlpha)
|
||||||
|
{
|
||||||
|
GL.BlendEquationSeparate(
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
|
|
||||||
|
GL.BlendFuncSeparate(
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
|
|
||||||
|
GL.BlendFunc(
|
||||||
|
OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetBlendState(BlendState New, BlendState Old)
|
||||||
|
{
|
||||||
|
if (New.Enabled != Old.Enabled)
|
||||||
|
{
|
||||||
|
Enable(EnableCap.Blend, New.Enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.Enabled)
|
||||||
|
{
|
||||||
|
if (New.SeparateAlpha)
|
||||||
|
{
|
||||||
|
if (New.EquationRgb != Old.EquationRgb ||
|
||||||
|
New.EquationAlpha != Old.EquationAlpha)
|
||||||
|
{
|
||||||
|
GL.BlendEquationSeparate(
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
||||||
|
New.FuncDstRgb != Old.FuncDstRgb ||
|
||||||
|
New.FuncSrcAlpha != Old.FuncSrcAlpha ||
|
||||||
|
New.FuncDstAlpha != Old.FuncDstAlpha)
|
||||||
|
{
|
||||||
|
GL.BlendFuncSeparate(
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (New.EquationRgb != Old.EquationRgb)
|
||||||
|
{
|
||||||
|
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
||||||
|
New.FuncDstRgb != Old.FuncDstRgb)
|
||||||
|
{
|
||||||
|
GL.BlendFunc(
|
||||||
|
OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetBlendState(int Index, BlendState New, BlendState Old)
|
||||||
|
{
|
||||||
|
if (New.Enabled != Old.Enabled)
|
||||||
|
{
|
||||||
|
Enable(IndexedEnableCap.Blend, Index, New.Enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.Enabled)
|
||||||
|
{
|
||||||
|
if (New.SeparateAlpha)
|
||||||
|
{
|
||||||
|
if (New.EquationRgb != Old.EquationRgb ||
|
||||||
|
New.EquationAlpha != Old.EquationAlpha)
|
||||||
|
{
|
||||||
|
GL.BlendEquationSeparate(
|
||||||
|
Index,
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
|
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
||||||
|
New.FuncDstRgb != Old.FuncDstRgb ||
|
||||||
|
New.FuncSrcAlpha != Old.FuncSrcAlpha ||
|
||||||
|
New.FuncDstAlpha != Old.FuncDstAlpha)
|
||||||
|
{
|
||||||
|
GL.BlendFuncSeparate(
|
||||||
|
Index,
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (New.EquationRgb != Old.EquationRgb)
|
||||||
|
{
|
||||||
|
GL.BlendEquation(Index, OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
||||||
|
New.FuncDstRgb != Old.FuncDstRgb)
|
||||||
|
{
|
||||||
|
GL.BlendFunc(
|
||||||
|
Index,
|
||||||
|
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
|
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void BindConstBuffers(GalPipelineState New)
|
private void BindConstBuffers(GalPipelineState New)
|
||||||
{
|
{
|
||||||
int FreeBinding = OGLShader.ReservedCbufCount;
|
int FreeBinding = OGLShader.ReservedCbufCount;
|
||||||
|
@ -640,6 +737,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Enable(IndexedEnableCap Cap, int Index, bool Enabled)
|
||||||
|
{
|
||||||
|
if (Enabled)
|
||||||
|
{
|
||||||
|
GL.Enable(Cap, Index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.Disable(Cap, Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ResetDepthMask()
|
public void ResetDepthMask()
|
||||||
{
|
{
|
||||||
Old.DepthWriteEnabled = true;
|
Old.DepthWriteEnabled = true;
|
||||||
|
@ -647,7 +756,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void ResetColorMask(int Index)
|
public void ResetColorMask(int Index)
|
||||||
{
|
{
|
||||||
Old.ColorMasks[Index] = ColorMaskRgba.Default;
|
Old.ColorMasks[Index] = ColorMaskState.Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -407,21 +407,58 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
private void SetBlending(GalPipelineState State)
|
private void SetBlending(GalPipelineState State)
|
||||||
{
|
{
|
||||||
//TODO: Support independent blend properly.
|
bool BlendIndependent = ReadRegisterBool(NvGpuEngine3dReg.BlendIndependent);
|
||||||
State.BlendEnabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
|
|
||||||
|
|
||||||
if (State.BlendEnabled)
|
State.BlendIndependent = BlendIndependent;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
{
|
{
|
||||||
State.BlendSeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.IBlendNSeparateAlpha);
|
if (BlendIndependent)
|
||||||
|
{
|
||||||
|
State.Blends[Index].Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable + Index);
|
||||||
|
|
||||||
State.BlendEquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb);
|
if (State.Blends[Index].Enabled)
|
||||||
State.BlendFuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb);
|
{
|
||||||
State.BlendFuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb);
|
State.Blends[Index].SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.IBlendNSeparateAlpha + Index * 8);
|
||||||
State.BlendEquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha);
|
|
||||||
State.BlendFuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
|
State.Blends[Index].EquationRgb = ReadBlendEquation(NvGpuEngine3dReg.IBlendNEquationRgb + Index * 8);
|
||||||
State.BlendFuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
|
State.Blends[Index].FuncSrcRgb = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncSrcRgb + Index * 8);
|
||||||
|
State.Blends[Index].FuncDstRgb = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncDstRgb + Index * 8);
|
||||||
|
State.Blends[Index].EquationAlpha = ReadBlendEquation(NvGpuEngine3dReg.IBlendNEquationAlpha + Index * 8);
|
||||||
|
State.Blends[Index].FuncSrcAlpha = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncSrcAlpha + Index * 8);
|
||||||
|
State.Blends[Index].FuncDstAlpha = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncDstAlpha + Index * 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//It seems that even when independent blend is disabled, the first IBlend enable
|
||||||
|
//register is still set to indicate whenever blend is enabled or not (?).
|
||||||
|
State.Blends[Index].Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
|
||||||
|
|
||||||
|
if (State.Blends[Index].Enabled)
|
||||||
|
{
|
||||||
|
State.Blends[Index].SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.BlendSeparateAlpha);
|
||||||
|
|
||||||
|
State.Blends[Index].EquationRgb = ReadBlendEquation(NvGpuEngine3dReg.BlendEquationRgb);
|
||||||
|
State.Blends[Index].FuncSrcRgb = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncSrcRgb);
|
||||||
|
State.Blends[Index].FuncDstRgb = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncDstRgb);
|
||||||
|
State.Blends[Index].EquationAlpha = ReadBlendEquation(NvGpuEngine3dReg.BlendEquationAlpha);
|
||||||
|
State.Blends[Index].FuncSrcAlpha = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncSrcAlpha);
|
||||||
|
State.Blends[Index].FuncDstAlpha = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncDstAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GalBlendEquation ReadBlendEquation(NvGpuEngine3dReg Register)
|
||||||
|
{
|
||||||
|
return (GalBlendEquation)ReadRegister(Register);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GalBlendFactor ReadBlendFactor(NvGpuEngine3dReg Register)
|
||||||
|
{
|
||||||
|
return (GalBlendFactor)ReadRegister(Register);
|
||||||
|
}
|
||||||
|
|
||||||
private void SetColorMask(GalPipelineState State)
|
private void SetColorMask(GalPipelineState State)
|
||||||
{
|
{
|
||||||
|
@ -514,10 +551,8 @@ namespace Ryujinx.Graphics
|
||||||
{
|
{
|
||||||
if (TextureHandle == 0)
|
if (TextureHandle == 0)
|
||||||
{
|
{
|
||||||
//TODO: Is this correct?
|
//FIXME: Some games like puyo puyo will use handles with the value 0.
|
||||||
//Some games like puyo puyo will have 0 handles.
|
//This is a bug, most likely caused by sync issues.
|
||||||
//It may be just normal behaviour or a bug caused by sync issues.
|
|
||||||
//The game does initialize the value properly after through.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +638,7 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
if (IndexEntrySize > 4)
|
if (IndexEntrySize > 4)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException("Invalid index entry size \"" + IndexEntrySize + "\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IndexCount != 0)
|
if (IndexCount != 0)
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics
|
||||||
ZetaVert = 0x48b,
|
ZetaVert = 0x48b,
|
||||||
ZetaArrayMode = 0x48c,
|
ZetaArrayMode = 0x48c,
|
||||||
DepthTestEnable = 0x4b3,
|
DepthTestEnable = 0x4b3,
|
||||||
IBlendEnable = 0x4b9,
|
BlendIndependent = 0x4b9,
|
||||||
DepthWriteEnable = 0x4ba,
|
DepthWriteEnable = 0x4ba,
|
||||||
DepthTestFunction = 0x4c3,
|
DepthTestFunction = 0x4c3,
|
||||||
BlendSeparateAlpha = 0x4cf,
|
BlendSeparateAlpha = 0x4cf,
|
||||||
|
@ -47,7 +47,7 @@ namespace Ryujinx.Graphics
|
||||||
BlendEquationAlpha = 0x4d3,
|
BlendEquationAlpha = 0x4d3,
|
||||||
BlendFuncSrcAlpha = 0x4d4,
|
BlendFuncSrcAlpha = 0x4d4,
|
||||||
BlendFuncDstAlpha = 0x4d6,
|
BlendFuncDstAlpha = 0x4d6,
|
||||||
BlendEnableMaster = 0x4d7,
|
BlendEnable = 0x4d7,
|
||||||
IBlendNEnable = 0x4d8,
|
IBlendNEnable = 0x4d8,
|
||||||
StencilEnable = 0x4e0,
|
StencilEnable = 0x4e0,
|
||||||
StencilFrontOpFail = 0x4e1,
|
StencilFrontOpFail = 0x4e1,
|
||||||
|
|
Loading…
Reference in a new issue