aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-11-01 01:22:24 -0300
committerGitHub <noreply@github.com>2018-11-01 01:22:24 -0300
commit44c1cf3fe5a3886f34251f93fbcfc3b9c8f0e164 (patch)
tree257771bfe3360c9be09717e8f9466bcc2999a555
parent1e7ea76f148660ff403938f3f84376879901e3ff (diff)
Implment common and independent blend properly (fixes #458) (#485)
* Implment common and independent blend properly * Nits
-rw-r--r--Ryujinx.Graphics/Gal/GalBlendEquation.cs8
-rw-r--r--Ryujinx.Graphics/Gal/GalBlendFactor.cs21
-rw-r--r--Ryujinx.Graphics/Gal/GalPipelineState.cs50
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs154
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs203
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3d.cs65
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3dReg.cs4
7 files changed, 383 insertions, 122 deletions
diff --git a/Ryujinx.Graphics/Gal/GalBlendEquation.cs b/Ryujinx.Graphics/Gal/GalBlendEquation.cs
index 7fd4ba5f..7757faae 100644
--- a/Ryujinx.Graphics/Gal/GalBlendEquation.cs
+++ b/Ryujinx.Graphics/Gal/GalBlendEquation.cs
@@ -6,6 +6,12 @@ namespace Ryujinx.Graphics.Gal
FuncSubtract = 2,
FuncReverseSubtract = 3,
Min = 4,
- Max = 5
+ Max = 5,
+
+ FuncAddGl = 0x8006,
+ FuncSubtractGl = 0x8007,
+ FuncReverseSubtractGl = 0x8008,
+ MinGl = 0x800a,
+ MaxGl = 0x800b
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalBlendFactor.cs b/Ryujinx.Graphics/Gal/GalBlendFactor.cs
index 001aaaec..f70b0501 100644
--- a/Ryujinx.Graphics/Gal/GalBlendFactor.cs
+++ b/Ryujinx.Graphics/Gal/GalBlendFactor.cs
@@ -21,6 +21,25 @@ namespace Ryujinx.Graphics.Gal
OneMinusConstantColor = 0x62,
ConstantAlpha = 0x63,
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
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs
index f50f1032..793fb395 100644
--- a/Ryujinx.Graphics/Gal/GalPipelineState.cs
+++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs
@@ -1,8 +1,8 @@
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,
Green = true,
@@ -10,7 +10,7 @@
Alpha = true
};
- public static ColorMaskRgba Default => _Default;
+ public static ColorMaskState Default => _Default;
public bool Red;
public bool Green;
@@ -18,6 +18,32 @@
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 const int Stages = 5;
@@ -65,17 +91,11 @@
public GalStencilOp StencilFrontOpZPass;
public uint StencilFrontMask;
- public bool BlendEnabled;
- public bool BlendSeparateAlpha;
- public GalBlendEquation BlendEquationRgb;
- public GalBlendFactor BlendFuncSrcRgb;
- public GalBlendFactor BlendFuncDstRgb;
- public GalBlendEquation BlendEquationAlpha;
- public GalBlendFactor BlendFuncSrcAlpha;
- public GalBlendFactor BlendFuncDstAlpha;
+ public bool BlendIndependent;
+ public BlendState[] Blends;
- public bool ColorMaskCommon;
- public ColorMaskRgba[] ColorMasks;
+ public bool ColorMaskCommon;
+ public ColorMaskState[] ColorMasks;
public bool PrimitiveRestartEnabled;
public uint PrimitiveRestartIndex;
@@ -89,7 +109,9 @@
ConstBufferKeys[Stage] = new long[ConstBuffersPerStage];
}
- ColorMasks = new ColorMaskRgba[RenderTargetsCount];
+ Blends = new BlendState[RenderTargetsCount];
+
+ ColorMasks = new ColorMaskState[RenderTargetsCount];
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index 6b3d4fd6..49165101 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -47,34 +47,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
{
- //Looks like the GPU can take it's own values (described in GalComparisonOp) and OpenGL values alike
- if ((int)Func >= (int)DepthFunction.Never &&
- (int)Func <= (int)DepthFunction.Always)
+ return (DepthFunction)GetFunc(Func);
+ }
+
+ public static StencilFunction GetStencilFunc(GalComparisonOp Func)
+ {
+ return (StencilFunction)GetFunc(Func);
+ }
+
+ private static All GetFunc(GalComparisonOp Func)
+ {
+ if ((int)Func >= (int)All.Never &&
+ (int)Func <= (int)All.Always)
{
- return (DepthFunction)Func;
+ return (All)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;
+ 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 StencilFunction GetStencilFunc(GalComparisonOp Func)
- {
- //OGL comparison values match, it's just an enum cast
- return (StencilFunction)GetDepthFunc(Func);
- }
-
public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
{
switch (Format)
@@ -282,11 +285,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
switch (BlendEquation)
{
- case GalBlendEquation.FuncAdd: return BlendEquationMode.FuncAdd;
- case GalBlendEquation.FuncSubtract: return BlendEquationMode.FuncSubtract;
- case GalBlendEquation.FuncReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
- case GalBlendEquation.Min: return BlendEquationMode.Min;
- case GalBlendEquation.Max: return BlendEquationMode.Max;
+ case GalBlendEquation.FuncAdd:
+ case GalBlendEquation.FuncAddGl:
+ return BlendEquationMode.FuncAdd;
+
+ 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!");
@@ -296,27 +313,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
switch (BlendFactor)
{
- case GalBlendFactor.Zero: return BlendingFactor.Zero;
- case GalBlendFactor.One: return BlendingFactor.One;
- case GalBlendFactor.SrcColor: return BlendingFactor.SrcColor;
- case GalBlendFactor.OneMinusSrcColor: return BlendingFactor.OneMinusSrcColor;
- case GalBlendFactor.DstColor: return BlendingFactor.DstColor;
- case GalBlendFactor.OneMinusDstColor: return BlendingFactor.OneMinusDstColor;
- case GalBlendFactor.SrcAlpha: return BlendingFactor.SrcAlpha;
- case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactor.OneMinusSrcAlpha;
- case GalBlendFactor.DstAlpha: return BlendingFactor.DstAlpha;
- case GalBlendFactor.OneMinusDstAlpha: return BlendingFactor.OneMinusDstAlpha;
- case GalBlendFactor.OneMinusConstantColor: return BlendingFactor.OneMinusConstantColor;
- case GalBlendFactor.ConstantAlpha: return BlendingFactor.ConstantAlpha;
- case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactor.OneMinusConstantAlpha;
- case GalBlendFactor.SrcAlphaSaturate: return BlendingFactor.SrcAlphaSaturate;
- case GalBlendFactor.Src1Color: return BlendingFactor.Src1Color;
- case GalBlendFactor.OneMinusSrc1Color: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color;
- case GalBlendFactor.Src1Alpha: return BlendingFactor.Src1Alpha;
- case GalBlendFactor.OneMinusSrc1Alpha: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha;
+ case GalBlendFactor.Zero:
+ case GalBlendFactor.ZeroGl:
+ return BlendingFactor.Zero;
+
+ case GalBlendFactor.One:
+ case GalBlendFactor.OneGl:
+ return BlendingFactor.One;
+
+ case GalBlendFactor.SrcColor:
+ case GalBlendFactor.SrcColorGl:
+ return BlendingFactor.SrcColor;
+
+ case GalBlendFactor.OneMinusSrcColor:
+ case GalBlendFactor.OneMinusSrcColorGl:
+ return BlendingFactor.OneMinusSrcColor;
+
+ case GalBlendFactor.DstColor:
+ 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.ConstantColorG80:
+ case GalBlendFactor.ConstantColorGl:
return BlendingFactor.ConstantColor;
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
index 6e1cabba..e81cf8a3 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
@@ -121,15 +121,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
StencilFrontOpZPass = GalStencilOp.Keep,
StencilFrontMask = UInt32.MaxValue,
- BlendEnabled = false,
- BlendSeparateAlpha = false,
-
- BlendEquationRgb = 0,
- BlendFuncSrcRgb = GalBlendFactor.One,
- BlendFuncDstRgb = GalBlendFactor.Zero,
- BlendEquationAlpha = 0,
- BlendFuncSrcAlpha = GalBlendFactor.One,
- BlendFuncDstAlpha = GalBlendFactor.Zero,
+ BlendIndependent = false,
PrimitiveRestartEnabled = false,
PrimitiveRestartIndex = 0
@@ -137,7 +129,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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++)
+ {
+ SetBlendState(Index, New.Blends[Index], Old.Blends[Index]);
+ }
}
-
- if (New.BlendEnabled)
+ else
{
- if (New.BlendSeparateAlpha)
+ if (New.BlendIndependent != Old.BlendIndependent)
{
- 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));
- }
+ SetAllBlendState(New.Blends[0]);
}
else
{
- if (New.BlendEquationRgb != Old.BlendEquationRgb)
- {
- GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
- }
-
- if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
- New.BlendFuncDstRgb != Old.BlendFuncDstRgb)
- {
- GL.BlendFunc(
- OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
- OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb));
- }
+ SetBlendState(New.Blends[0], Old.Blends[0]);
}
}
@@ -357,6 +324,136 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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)
{
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()
{
Old.DepthWriteEnabled = true;
@@ -647,7 +756,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void ResetColorMask(int Index)
{
- Old.ColorMasks[Index] = ColorMaskRgba.Default;
+ Old.ColorMasks[Index] = ColorMaskState.Default;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs
index 618d7d9f..f4a45347 100644
--- a/Ryujinx.Graphics/NvGpuEngine3d.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3d.cs
@@ -407,22 +407,59 @@ namespace Ryujinx.Graphics
private void SetBlending(GalPipelineState State)
{
- //TODO: Support independent blend properly.
- State.BlendEnabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
+ bool BlendIndependent = ReadRegisterBool(NvGpuEngine3dReg.BlendIndependent);
- 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);
+
+ if (State.Blends[Index].Enabled)
+ {
+ State.Blends[Index].SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.IBlendNSeparateAlpha + Index * 8);
+
+ State.Blends[Index].EquationRgb = ReadBlendEquation(NvGpuEngine3dReg.IBlendNEquationRgb + Index * 8);
+ 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);
- State.BlendEquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb);
- State.BlendFuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb);
- State.BlendFuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb);
- State.BlendEquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha);
- State.BlendFuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
- State.BlendFuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
+ 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)
{
bool ColorMaskCommon = ReadRegisterBool(NvGpuEngine3dReg.ColorMaskCommon);
@@ -514,10 +551,8 @@ namespace Ryujinx.Graphics
{
if (TextureHandle == 0)
{
- //TODO: Is this correct?
- //Some games like puyo puyo will have 0 handles.
- //It may be just normal behaviour or a bug caused by sync issues.
- //The game does initialize the value properly after through.
+ //FIXME: Some games like puyo puyo will use handles with the value 0.
+ //This is a bug, most likely caused by sync issues.
return;
}
@@ -603,7 +638,7 @@ namespace Ryujinx.Graphics
if (IndexEntrySize > 4)
{
- throw new InvalidOperationException();
+ throw new InvalidOperationException("Invalid index entry size \"" + IndexEntrySize + "\"!");
}
if (IndexCount != 0)
diff --git a/Ryujinx.Graphics/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
index 6c522eac..bd61602b 100644
--- a/Ryujinx.Graphics/NvGpuEngine3dReg.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
@@ -37,7 +37,7 @@ namespace Ryujinx.Graphics
ZetaVert = 0x48b,
ZetaArrayMode = 0x48c,
DepthTestEnable = 0x4b3,
- IBlendEnable = 0x4b9,
+ BlendIndependent = 0x4b9,
DepthWriteEnable = 0x4ba,
DepthTestFunction = 0x4c3,
BlendSeparateAlpha = 0x4cf,
@@ -47,7 +47,7 @@ namespace Ryujinx.Graphics
BlendEquationAlpha = 0x4d3,
BlendFuncSrcAlpha = 0x4d4,
BlendFuncDstAlpha = 0x4d6,
- BlendEnableMaster = 0x4d7,
+ BlendEnable = 0x4d7,
IBlendNEnable = 0x4d8,
StencilEnable = 0x4e0,
StencilFrontOpFail = 0x4e1,