Pipeline state changes
This commit is contained in:
parent
2eb8733fa5
commit
5b49938c9b
7 changed files with 510 additions and 961 deletions
|
@ -1,117 +0,0 @@
|
|||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public struct ColorMaskState
|
||||
{
|
||||
private static readonly ColorMaskState _Default = new ColorMaskState()
|
||||
{
|
||||
Red = true,
|
||||
Green = true,
|
||||
Blue = true,
|
||||
Alpha = true
|
||||
};
|
||||
|
||||
public static ColorMaskState Default => _Default;
|
||||
|
||||
public bool Red;
|
||||
public bool Green;
|
||||
public bool Blue;
|
||||
public bool Alpha;
|
||||
}
|
||||
|
||||
public struct BlendState
|
||||
{
|
||||
private static readonly BlendState _Default = new BlendState()
|
||||
{
|
||||
Enabled = false,
|
||||
SeparateAlpha = false,
|
||||
EquationRgb = GalBlendEquation.FuncAdd,
|
||||
FuncSrcRgb = GalBlendFactor.One,
|
||||
FuncDstRgb = GalBlendFactor.Zero,
|
||||
EquationAlpha = GalBlendEquation.FuncAdd,
|
||||
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;
|
||||
public const int ConstBuffersPerStage = 18;
|
||||
public const int RenderTargetsCount = 8;
|
||||
|
||||
public long[][] ConstBufferKeys;
|
||||
|
||||
public GalVertexBinding[] VertexBindings;
|
||||
|
||||
public bool FramebufferSrgb;
|
||||
|
||||
public float FlipX;
|
||||
public float FlipY;
|
||||
|
||||
public int Instance;
|
||||
|
||||
public GalFrontFace FrontFace;
|
||||
|
||||
public bool CullFaceEnabled;
|
||||
public GalCullFace CullFace;
|
||||
|
||||
public bool DepthTestEnabled;
|
||||
public bool DepthWriteEnabled;
|
||||
public GalComparisonOp DepthFunc;
|
||||
public float DepthRangeNear;
|
||||
public float DepthRangeFar;
|
||||
|
||||
public bool StencilTestEnabled;
|
||||
public bool StencilTwoSideEnabled;
|
||||
|
||||
public GalComparisonOp StencilBackFuncFunc;
|
||||
public int StencilBackFuncRef;
|
||||
public uint StencilBackFuncMask;
|
||||
public GalStencilOp StencilBackOpFail;
|
||||
public GalStencilOp StencilBackOpZFail;
|
||||
public GalStencilOp StencilBackOpZPass;
|
||||
public uint StencilBackMask;
|
||||
|
||||
public GalComparisonOp StencilFrontFuncFunc;
|
||||
public int StencilFrontFuncRef;
|
||||
public uint StencilFrontFuncMask;
|
||||
public GalStencilOp StencilFrontOpFail;
|
||||
public GalStencilOp StencilFrontOpZFail;
|
||||
public GalStencilOp StencilFrontOpZPass;
|
||||
public uint StencilFrontMask;
|
||||
|
||||
public bool BlendIndependent;
|
||||
public BlendState[] Blends;
|
||||
|
||||
public bool ColorMaskCommon;
|
||||
public ColorMaskState[] ColorMasks;
|
||||
|
||||
public bool PrimitiveRestartEnabled;
|
||||
public uint PrimitiveRestartIndex;
|
||||
|
||||
public GalPipelineState()
|
||||
{
|
||||
ConstBufferKeys = new long[Stages][];
|
||||
|
||||
for (int Stage = 0; Stage < Stages; Stage++)
|
||||
{
|
||||
ConstBufferKeys[Stage] = new long[ConstBuffersPerStage];
|
||||
}
|
||||
|
||||
Blends = new BlendState[RenderTargetsCount];
|
||||
|
||||
ColorMasks = new ColorMaskState[RenderTargetsCount];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,83 @@
|
|||
{
|
||||
public interface IGalPipeline
|
||||
{
|
||||
void Bind(GalPipelineState State);
|
||||
void SetFlip(float FlipX, float FlipY, int Instance);
|
||||
|
||||
void ResetDepthMask();
|
||||
void ResetColorMask(int Index);
|
||||
//Depth.
|
||||
void SetDepthMask(bool DepthTestEnabled, bool DepthWriteEnabled);
|
||||
|
||||
void SetDepthFunc(GalComparisonOp DepthFunc);
|
||||
|
||||
void SetDepthRange(float DepthRangeNear, float DepthRangeFar);
|
||||
|
||||
//Stencil.
|
||||
void SetStencilTestEnabled(bool Enabled);
|
||||
|
||||
void SetStencilTest(
|
||||
GalComparisonOp StencilBackFuncFunc,
|
||||
int StencilBackFuncRef,
|
||||
uint StencilBackFuncMask,
|
||||
GalStencilOp StencilBackOpFail,
|
||||
GalStencilOp StencilBackOpZFail,
|
||||
GalStencilOp StencilBackOpZPass,
|
||||
uint StencilBackMask,
|
||||
GalComparisonOp StencilFrontFuncFunc,
|
||||
int StencilFrontFuncRef,
|
||||
uint StencilFrontFuncMask,
|
||||
GalStencilOp StencilFrontOpFail,
|
||||
GalStencilOp StencilFrontOpZFail,
|
||||
GalStencilOp StencilFrontOpZPass,
|
||||
uint StencilFrontMask);
|
||||
|
||||
//Blend.
|
||||
void SetBlendEnabled(bool Enabled);
|
||||
|
||||
void SetBlendEnabled(int Index, bool Enabled);
|
||||
|
||||
void SetBlend(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb);
|
||||
|
||||
void SetBlend(
|
||||
int Index,
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb);
|
||||
|
||||
void SetBlendSeparate(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha);
|
||||
|
||||
void SetBlendSeparate(
|
||||
int Index,
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha);
|
||||
|
||||
//Color mask.
|
||||
void SetColorMask(bool RedMask, bool GreenMask, bool BlueMask, bool AlphaMask);
|
||||
|
||||
void SetColorMask(
|
||||
int Index,
|
||||
bool RedMask,
|
||||
bool GreenMask,
|
||||
bool BlueMask,
|
||||
bool AlphaMask);
|
||||
|
||||
//Primitive restart.
|
||||
void SetPrimitiveRestartEnabled(bool Enabled);
|
||||
void SetPrimitiveRestartIndex(int Index);
|
||||
|
||||
void SetFramebufferSrgb(bool Enabled);
|
||||
|
||||
void BindConstBuffers(long[][] ConstBufferKeys);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ namespace Ryujinx.Graphics.Gal
|
|||
{
|
||||
public interface IGalRenderTarget
|
||||
{
|
||||
bool FramebufferSrgb { get; set; }
|
||||
|
||||
void Bind();
|
||||
|
||||
void BindColor(long Key, int Attachment);
|
||||
|
|
|
@ -1,468 +1,211 @@
|
|||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLPipeline : IGalPipeline
|
||||
{
|
||||
private static Dictionary<GalVertexAttribSize, int> AttribElements =
|
||||
new Dictionary<GalVertexAttribSize, int>()
|
||||
private OGLConstBuffer Buffer;
|
||||
private OGLShader Shader;
|
||||
|
||||
private float FlipX;
|
||||
private float FlipY;
|
||||
private int Instance;
|
||||
|
||||
public OGLPipeline(OGLConstBuffer Buffer, OGLShader Shader)
|
||||
{
|
||||
{ GalVertexAttribSize._32_32_32_32, 4 },
|
||||
{ GalVertexAttribSize._32_32_32, 3 },
|
||||
{ GalVertexAttribSize._16_16_16_16, 4 },
|
||||
{ GalVertexAttribSize._32_32, 2 },
|
||||
{ GalVertexAttribSize._16_16_16, 3 },
|
||||
{ GalVertexAttribSize._8_8_8_8, 4 },
|
||||
{ GalVertexAttribSize._16_16, 2 },
|
||||
{ GalVertexAttribSize._32, 1 },
|
||||
{ GalVertexAttribSize._8_8_8, 3 },
|
||||
{ GalVertexAttribSize._8_8, 2 },
|
||||
{ GalVertexAttribSize._16, 1 },
|
||||
{ GalVertexAttribSize._8, 1 },
|
||||
{ GalVertexAttribSize._10_10_10_2, 4 },
|
||||
{ GalVertexAttribSize._11_11_10, 3 }
|
||||
};
|
||||
this.Buffer = Buffer;
|
||||
this.Shader = Shader;
|
||||
}
|
||||
|
||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> FloatAttribTypes =
|
||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||
public void SetFlip(float FlipX, float FlipY, int Instance)
|
||||
{
|
||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16, VertexAttribPointerType.HalfFloat }
|
||||
};
|
||||
|
||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> SignedAttribTypes =
|
||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||
{
|
||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
|
||||
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
|
||||
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
|
||||
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
|
||||
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
|
||||
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
|
||||
{ GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
|
||||
{ GalVertexAttribSize._32, VertexAttribPointerType.Int },
|
||||
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
|
||||
{ GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
|
||||
{ GalVertexAttribSize._16, VertexAttribPointerType.Short },
|
||||
{ GalVertexAttribSize._8, VertexAttribPointerType.Byte },
|
||||
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int2101010Rev }
|
||||
};
|
||||
|
||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> UnsignedAttribTypes =
|
||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||
{
|
||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.UnsignedInt },
|
||||
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.UnsignedInt },
|
||||
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.UnsignedShort },
|
||||
{ GalVertexAttribSize._32_32, VertexAttribPointerType.UnsignedInt },
|
||||
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.UnsignedShort },
|
||||
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.UnsignedByte },
|
||||
{ GalVertexAttribSize._16_16, VertexAttribPointerType.UnsignedShort },
|
||||
{ GalVertexAttribSize._32, VertexAttribPointerType.UnsignedInt },
|
||||
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.UnsignedByte },
|
||||
{ GalVertexAttribSize._8_8, VertexAttribPointerType.UnsignedByte },
|
||||
{ GalVertexAttribSize._16, VertexAttribPointerType.UnsignedShort },
|
||||
{ GalVertexAttribSize._8, VertexAttribPointerType.UnsignedByte },
|
||||
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.UnsignedInt2101010Rev },
|
||||
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
||||
};
|
||||
|
||||
private GalPipelineState Old;
|
||||
|
||||
private OGLConstBuffer Buffer;
|
||||
private OGLRenderTarget RenderTarget;
|
||||
private OGLRasterizer Rasterizer;
|
||||
private OGLShader Shader;
|
||||
|
||||
private int VaoHandle;
|
||||
|
||||
public OGLPipeline(
|
||||
OGLConstBuffer Buffer,
|
||||
OGLRenderTarget RenderTarget,
|
||||
OGLRasterizer Rasterizer,
|
||||
OGLShader Shader)
|
||||
{
|
||||
this.Buffer = Buffer;
|
||||
this.RenderTarget = RenderTarget;
|
||||
this.Rasterizer = Rasterizer;
|
||||
this.Shader = Shader;
|
||||
|
||||
//These values match OpenGL's defaults
|
||||
Old = new GalPipelineState
|
||||
if (FlipX != this.FlipX ||
|
||||
FlipY != this.FlipY ||
|
||||
Instance != this.Instance)
|
||||
{
|
||||
FrontFace = GalFrontFace.CCW,
|
||||
this.FlipX = FlipX;
|
||||
this.FlipY = FlipY;
|
||||
this.Instance = Instance;
|
||||
|
||||
CullFaceEnabled = false,
|
||||
CullFace = GalCullFace.Back,
|
||||
|
||||
DepthTestEnabled = false,
|
||||
DepthWriteEnabled = true,
|
||||
DepthFunc = GalComparisonOp.Less,
|
||||
DepthRangeNear = 0,
|
||||
DepthRangeFar = 1,
|
||||
|
||||
StencilTestEnabled = false,
|
||||
|
||||
StencilBackFuncFunc = GalComparisonOp.Always,
|
||||
StencilBackFuncRef = 0,
|
||||
StencilBackFuncMask = UInt32.MaxValue,
|
||||
StencilBackOpFail = GalStencilOp.Keep,
|
||||
StencilBackOpZFail = GalStencilOp.Keep,
|
||||
StencilBackOpZPass = GalStencilOp.Keep,
|
||||
StencilBackMask = UInt32.MaxValue,
|
||||
|
||||
StencilFrontFuncFunc = GalComparisonOp.Always,
|
||||
StencilFrontFuncRef = 0,
|
||||
StencilFrontFuncMask = UInt32.MaxValue,
|
||||
StencilFrontOpFail = GalStencilOp.Keep,
|
||||
StencilFrontOpZFail = GalStencilOp.Keep,
|
||||
StencilFrontOpZPass = GalStencilOp.Keep,
|
||||
StencilFrontMask = UInt32.MaxValue,
|
||||
|
||||
BlendIndependent = false,
|
||||
|
||||
PrimitiveRestartEnabled = false,
|
||||
PrimitiveRestartIndex = 0
|
||||
};
|
||||
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
{
|
||||
Old.Blends[Index] = BlendState.Default;
|
||||
|
||||
Old.ColorMasks[Index] = ColorMaskState.Default;
|
||||
Shader.SetExtraData(FlipX, FlipY, Instance);
|
||||
}
|
||||
}
|
||||
|
||||
public void Bind(GalPipelineState New)
|
||||
public void SetDepthMask(bool DepthTestEnabled, bool DepthWriteEnabled)
|
||||
{
|
||||
BindConstBuffers(New);
|
||||
Enable(EnableCap.DepthTest, DepthTestEnabled);
|
||||
|
||||
BindVertexLayout(New);
|
||||
|
||||
if (New.FramebufferSrgb != Old.FramebufferSrgb)
|
||||
{
|
||||
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
|
||||
|
||||
RenderTarget.FramebufferSrgb = New.FramebufferSrgb;
|
||||
}
|
||||
|
||||
if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance)
|
||||
{
|
||||
Shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
|
||||
}
|
||||
|
||||
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
|
||||
|
||||
//if (New.FrontFace != Old.FrontFace)
|
||||
//{
|
||||
// GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace));
|
||||
//}
|
||||
|
||||
//if (New.CullFaceEnabled != Old.CullFaceEnabled)
|
||||
//{
|
||||
// Enable(EnableCap.CullFace, New.CullFaceEnabled);
|
||||
//}
|
||||
|
||||
//if (New.CullFaceEnabled)
|
||||
//{
|
||||
// if (New.CullFace != Old.CullFace)
|
||||
// {
|
||||
// GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace));
|
||||
// }
|
||||
//}
|
||||
|
||||
if (New.DepthTestEnabled != Old.DepthTestEnabled)
|
||||
{
|
||||
Enable(EnableCap.DepthTest, New.DepthTestEnabled);
|
||||
}
|
||||
|
||||
if (New.DepthWriteEnabled != Old.DepthWriteEnabled)
|
||||
{
|
||||
GL.DepthMask(New.DepthWriteEnabled);
|
||||
}
|
||||
|
||||
if (New.DepthTestEnabled)
|
||||
{
|
||||
if (New.DepthFunc != Old.DepthFunc)
|
||||
{
|
||||
GL.DepthFunc(OGLEnumConverter.GetDepthFunc(New.DepthFunc));
|
||||
}
|
||||
}
|
||||
|
||||
if (New.DepthRangeNear != Old.DepthRangeNear ||
|
||||
New.DepthRangeFar != Old.DepthRangeFar)
|
||||
{
|
||||
GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
|
||||
}
|
||||
|
||||
if (New.StencilTestEnabled != Old.StencilTestEnabled)
|
||||
{
|
||||
Enable(EnableCap.StencilTest, New.StencilTestEnabled);
|
||||
}
|
||||
|
||||
if (New.StencilTwoSideEnabled != Old.StencilTwoSideEnabled)
|
||||
{
|
||||
Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
|
||||
}
|
||||
|
||||
if (New.StencilTestEnabled)
|
||||
{
|
||||
if (New.StencilBackFuncFunc != Old.StencilBackFuncFunc ||
|
||||
New.StencilBackFuncRef != Old.StencilBackFuncRef ||
|
||||
New.StencilBackFuncMask != Old.StencilBackFuncMask)
|
||||
{
|
||||
GL.StencilFuncSeparate(
|
||||
StencilFace.Back,
|
||||
OGLEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
|
||||
New.StencilBackFuncRef,
|
||||
New.StencilBackFuncMask);
|
||||
}
|
||||
|
||||
if (New.StencilBackOpFail != Old.StencilBackOpFail ||
|
||||
New.StencilBackOpZFail != Old.StencilBackOpZFail ||
|
||||
New.StencilBackOpZPass != Old.StencilBackOpZPass)
|
||||
{
|
||||
GL.StencilOpSeparate(
|
||||
StencilFace.Back,
|
||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpFail),
|
||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpZFail),
|
||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpZPass));
|
||||
}
|
||||
|
||||
if (New.StencilBackMask != Old.StencilBackMask)
|
||||
{
|
||||
GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
|
||||
}
|
||||
|
||||
if (New.StencilFrontFuncFunc != Old.StencilFrontFuncFunc ||
|
||||
New.StencilFrontFuncRef != Old.StencilFrontFuncRef ||
|
||||
New.StencilFrontFuncMask != Old.StencilFrontFuncMask)
|
||||
{
|
||||
GL.StencilFuncSeparate(
|
||||
StencilFace.Front,
|
||||
OGLEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
|
||||
New.StencilFrontFuncRef,
|
||||
New.StencilFrontFuncMask);
|
||||
}
|
||||
|
||||
if (New.StencilFrontOpFail != Old.StencilFrontOpFail ||
|
||||
New.StencilFrontOpZFail != Old.StencilFrontOpZFail ||
|
||||
New.StencilFrontOpZPass != Old.StencilFrontOpZPass)
|
||||
{
|
||||
GL.StencilOpSeparate(
|
||||
StencilFace.Front,
|
||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpFail),
|
||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
|
||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
|
||||
}
|
||||
|
||||
if (New.StencilFrontMask != Old.StencilFrontMask)
|
||||
{
|
||||
GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (New.BlendIndependent)
|
||||
{
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
{
|
||||
SetBlendState(Index, New.Blends[Index], Old.Blends[Index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (New.BlendIndependent != Old.BlendIndependent)
|
||||
{
|
||||
SetAllBlendState(New.Blends[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBlendState(New.Blends[0], Old.Blends[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (New.ColorMaskCommon)
|
||||
{
|
||||
if (New.ColorMaskCommon != Old.ColorMaskCommon || !New.ColorMasks[0].Equals(Old.ColorMasks[0]))
|
||||
{
|
||||
GL.ColorMask(
|
||||
New.ColorMasks[0].Red,
|
||||
New.ColorMasks[0].Green,
|
||||
New.ColorMasks[0].Blue,
|
||||
New.ColorMasks[0].Alpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
{
|
||||
if (!New.ColorMasks[Index].Equals(Old.ColorMasks[Index]))
|
||||
{
|
||||
GL.ColorMask(
|
||||
Index,
|
||||
New.ColorMasks[Index].Red,
|
||||
New.ColorMasks[Index].Green,
|
||||
New.ColorMasks[Index].Blue,
|
||||
New.ColorMasks[Index].Alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (New.PrimitiveRestartEnabled != Old.PrimitiveRestartEnabled)
|
||||
{
|
||||
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
|
||||
}
|
||||
|
||||
if (New.PrimitiveRestartEnabled)
|
||||
{
|
||||
if (New.PrimitiveRestartIndex != Old.PrimitiveRestartIndex)
|
||||
{
|
||||
GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Old = New;
|
||||
GL.DepthMask(DepthWriteEnabled);
|
||||
}
|
||||
|
||||
private void SetAllBlendState(BlendState New)
|
||||
public void SetDepthFunc(GalComparisonOp DepthFunc)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
GL.DepthFunc(OGLEnumConverter.GetDepthFunc(DepthFunc));
|
||||
}
|
||||
|
||||
private void SetBlendState(BlendState New, BlendState Old)
|
||||
public void SetDepthRange(float DepthRangeNear, float DepthRangeFar)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
GL.DepthRange(DepthRangeNear, DepthRangeFar);
|
||||
}
|
||||
|
||||
private void SetBlendState(int Index, BlendState New, BlendState Old)
|
||||
public void SetStencilTestEnabled(bool Enabled)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Enable(EnableCap.StencilTest, Enabled);
|
||||
}
|
||||
|
||||
private void BindConstBuffers(GalPipelineState New)
|
||||
public void SetStencilTest(
|
||||
GalComparisonOp StencilBackFuncFunc,
|
||||
int StencilBackFuncRef,
|
||||
uint StencilBackFuncMask,
|
||||
GalStencilOp StencilBackOpFail,
|
||||
GalStencilOp StencilBackOpZFail,
|
||||
GalStencilOp StencilBackOpZPass,
|
||||
uint StencilBackMask,
|
||||
GalComparisonOp StencilFrontFuncFunc,
|
||||
int StencilFrontFuncRef,
|
||||
uint StencilFrontFuncMask,
|
||||
GalStencilOp StencilFrontOpFail,
|
||||
GalStencilOp StencilFrontOpZFail,
|
||||
GalStencilOp StencilFrontOpZPass,
|
||||
uint StencilFrontMask)
|
||||
{
|
||||
GL.StencilFuncSeparate(
|
||||
StencilFace.Back,
|
||||
OGLEnumConverter.GetStencilFunc(StencilBackFuncFunc),
|
||||
StencilBackFuncRef,
|
||||
StencilBackFuncMask);
|
||||
|
||||
GL.StencilOpSeparate(
|
||||
StencilFace.Back,
|
||||
OGLEnumConverter.GetStencilOp(StencilBackOpFail),
|
||||
OGLEnumConverter.GetStencilOp(StencilBackOpZFail),
|
||||
OGLEnumConverter.GetStencilOp(StencilBackOpZPass));
|
||||
|
||||
GL.StencilMaskSeparate(StencilFace.Back, StencilBackMask);
|
||||
|
||||
GL.StencilFuncSeparate(
|
||||
StencilFace.Front,
|
||||
OGLEnumConverter.GetStencilFunc(StencilFrontFuncFunc),
|
||||
StencilFrontFuncRef,
|
||||
StencilFrontFuncMask);
|
||||
|
||||
GL.StencilOpSeparate(
|
||||
StencilFace.Front,
|
||||
OGLEnumConverter.GetStencilOp(StencilFrontOpFail),
|
||||
OGLEnumConverter.GetStencilOp(StencilFrontOpZFail),
|
||||
OGLEnumConverter.GetStencilOp(StencilFrontOpZPass));
|
||||
|
||||
GL.StencilMaskSeparate(StencilFace.Front, StencilFrontMask);
|
||||
}
|
||||
|
||||
public void SetBlendEnabled(bool Enabled)
|
||||
{
|
||||
Enable(EnableCap.Blend, Enabled);
|
||||
}
|
||||
|
||||
public void SetBlendEnabled(int Index, bool Enabled)
|
||||
{
|
||||
Enable(IndexedEnableCap.Blend, Index, Enabled);
|
||||
}
|
||||
|
||||
public void SetBlend(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb)
|
||||
{
|
||||
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(EquationRgb));
|
||||
|
||||
GL.BlendFunc(
|
||||
OGLEnumConverter.GetBlendFactor(FuncSrcRgb),
|
||||
OGLEnumConverter.GetBlendFactor(FuncDstRgb));
|
||||
}
|
||||
|
||||
public void SetBlend(
|
||||
int Index,
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb)
|
||||
{
|
||||
GL.BlendEquation(Index, OGLEnumConverter.GetBlendEquation(EquationRgb));
|
||||
|
||||
GL.BlendFunc(
|
||||
Index,
|
||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(FuncSrcRgb),
|
||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstRgb));
|
||||
}
|
||||
|
||||
public void SetBlendSeparate(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha)
|
||||
{
|
||||
GL.BlendEquationSeparate(
|
||||
OGLEnumConverter.GetBlendEquation(EquationRgb),
|
||||
OGLEnumConverter.GetBlendEquation(EquationAlpha));
|
||||
|
||||
GL.BlendFuncSeparate(
|
||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(FuncSrcRgb),
|
||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstRgb),
|
||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(FuncSrcAlpha),
|
||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstAlpha));
|
||||
}
|
||||
|
||||
public void SetBlendSeparate(
|
||||
int Index,
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha)
|
||||
{
|
||||
GL.BlendEquationSeparate(
|
||||
Index,
|
||||
OGLEnumConverter.GetBlendEquation(EquationRgb),
|
||||
OGLEnumConverter.GetBlendEquation(EquationAlpha));
|
||||
|
||||
GL.BlendFuncSeparate(
|
||||
Index,
|
||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(FuncSrcRgb),
|
||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstRgb),
|
||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(FuncSrcAlpha),
|
||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstAlpha));
|
||||
}
|
||||
|
||||
public void SetColorMask(bool RedMask, bool GreenMask, bool BlueMask, bool AlphaMask)
|
||||
{
|
||||
GL.ColorMask(RedMask, GreenMask, BlueMask, AlphaMask);
|
||||
}
|
||||
|
||||
public void SetColorMask(
|
||||
int Index,
|
||||
bool RedMask,
|
||||
bool GreenMask,
|
||||
bool BlueMask,
|
||||
bool AlphaMask)
|
||||
{
|
||||
GL.ColorMask(Index, RedMask, GreenMask, BlueMask, AlphaMask);
|
||||
}
|
||||
|
||||
public void SetPrimitiveRestartEnabled(bool Enabled)
|
||||
{
|
||||
Enable(EnableCap.PrimitiveRestart, Enabled);
|
||||
}
|
||||
|
||||
public void SetPrimitiveRestartIndex(int Index)
|
||||
{
|
||||
GL.PrimitiveRestartIndex(Index);
|
||||
}
|
||||
|
||||
public void SetFramebufferSrgb(bool Enabled)
|
||||
{
|
||||
Enable(EnableCap.FramebufferSrgb, Enabled);
|
||||
}
|
||||
|
||||
public void BindConstBuffers(long[][] ConstBufferKeys)
|
||||
{
|
||||
int FreeBinding = OGLShader.ReservedCbufCount;
|
||||
|
||||
|
@ -472,7 +215,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
foreach (ShaderDeclInfo DeclInfo in Stage.ConstBufferUsage)
|
||||
{
|
||||
long Key = New.ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf];
|
||||
long Key = ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf];
|
||||
|
||||
if (Key != 0 && Buffer.TryGetUbo(Key, out int UboHandle))
|
||||
{
|
||||
|
@ -491,251 +234,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
BindIfNotNull(Shader.Current.Fragment);
|
||||
}
|
||||
|
||||
private void BindVertexLayout(GalPipelineState New)
|
||||
{
|
||||
foreach (GalVertexBinding Binding in New.VertexBindings)
|
||||
{
|
||||
if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VaoHandle == 0)
|
||||
{
|
||||
VaoHandle = GL.GenVertexArray();
|
||||
|
||||
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend
|
||||
//if you want to use it, move this line out of the if
|
||||
GL.BindVertexArray(VaoHandle);
|
||||
}
|
||||
|
||||
foreach (GalVertexAttrib Attrib in Binding.Attribs)
|
||||
{
|
||||
//Skip uninitialized attributes.
|
||||
if (Attrib.Size == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
bool Unsigned =
|
||||
Attrib.Type == GalVertexAttribType.Unorm ||
|
||||
Attrib.Type == GalVertexAttribType.Uint ||
|
||||
Attrib.Type == GalVertexAttribType.Uscaled;
|
||||
|
||||
bool Normalize =
|
||||
Attrib.Type == GalVertexAttribType.Snorm ||
|
||||
Attrib.Type == GalVertexAttribType.Unorm;
|
||||
|
||||
VertexAttribPointerType Type = 0;
|
||||
|
||||
if (Attrib.Type == GalVertexAttribType.Float)
|
||||
{
|
||||
Type = GetType(FloatAttribTypes, Attrib);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unsigned)
|
||||
{
|
||||
Type = GetType(UnsignedAttribTypes, Attrib);
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = GetType(SignedAttribTypes, Attrib);
|
||||
}
|
||||
}
|
||||
|
||||
if (!AttribElements.TryGetValue(Attrib.Size, out int Size))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid attribute size \"" + Attrib.Size + "\"!");
|
||||
}
|
||||
|
||||
int Offset = Attrib.Offset;
|
||||
|
||||
if (Binding.Stride != 0)
|
||||
{
|
||||
GL.EnableVertexAttribArray(Attrib.Index);
|
||||
|
||||
if (Attrib.Type == GalVertexAttribType.Sint ||
|
||||
Attrib.Type == GalVertexAttribType.Uint)
|
||||
{
|
||||
IntPtr Pointer = new IntPtr(Offset);
|
||||
|
||||
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
|
||||
|
||||
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Binding.Stride, Pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.DisableVertexAttribArray(Attrib.Index);
|
||||
|
||||
SetConstAttrib(Attrib);
|
||||
}
|
||||
|
||||
if (Binding.Instanced && Binding.Divisor != 0)
|
||||
{
|
||||
GL.VertexAttribDivisor(Attrib.Index, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.VertexAttribDivisor(Attrib.Index, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> Dict, GalVertexAttrib Attrib)
|
||||
{
|
||||
if (!Dict.TryGetValue(Attrib.Size, out VertexAttribPointerType Type))
|
||||
{
|
||||
ThrowUnsupportedAttrib(Attrib);
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
private unsafe static void SetConstAttrib(GalVertexAttrib Attrib)
|
||||
{
|
||||
if (Attrib.Size == GalVertexAttribSize._10_10_10_2 ||
|
||||
Attrib.Size == GalVertexAttribSize._11_11_10)
|
||||
{
|
||||
ThrowUnsupportedAttrib(Attrib);
|
||||
}
|
||||
|
||||
fixed (byte* Ptr = Attrib.Data)
|
||||
{
|
||||
if (Attrib.Type == GalVertexAttribType.Unorm)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (ushort*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (uint*)Ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Snorm)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (sbyte*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (short*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (int*)Ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Uint)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (ushort*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (uint*)Ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Sint)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (sbyte*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (short*)Ptr);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (int*)Ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Float)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4(Attrib.Index, (float*)Ptr);
|
||||
break;
|
||||
|
||||
default: ThrowUnsupportedAttrib(Attrib); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ThrowUnsupportedAttrib(GalVertexAttrib Attrib)
|
||||
{
|
||||
throw new NotImplementedException("Unsupported size \"" + Attrib.Size + "\" on type \"" + Attrib.Type + "\"!");
|
||||
}
|
||||
|
||||
private void Enable(EnableCap Cap, bool Enabled)
|
||||
{
|
||||
if (Enabled)
|
||||
|
@ -759,15 +257,5 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
GL.Disable(Cap, Index);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetDepthMask()
|
||||
{
|
||||
Old.DepthWriteEnabled = true;
|
||||
}
|
||||
|
||||
public void ResetColorMask(int Index)
|
||||
{
|
||||
Old.ColorMasks[Index] = ColorMaskState.Default;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
private const int NativeWidth = 1280;
|
||||
private const int NativeHeight = 720;
|
||||
|
||||
private const int RenderTargetsCount = GalPipelineState.RenderTargetsCount;
|
||||
private const int RenderTargetsCount = 8;
|
||||
|
||||
private struct Rect
|
||||
{
|
||||
|
|
|
@ -31,11 +31,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
Shader = new OGLShader(Buffer as OGLConstBuffer);
|
||||
|
||||
Pipeline = new OGLPipeline(
|
||||
Buffer as OGLConstBuffer,
|
||||
RenderTarget as OGLRenderTarget,
|
||||
Rasterizer as OGLRasterizer,
|
||||
Shader as OGLShader);
|
||||
Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Shader as OGLShader);
|
||||
|
||||
ActionsQueue = new ConcurrentQueue<Action>();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
{
|
||||
class NvGpuEngine3d : INvGpuEngine
|
||||
{
|
||||
private const int RenderTargetsCount = 8;
|
||||
|
||||
public int[] Registers { get; private set; }
|
||||
|
||||
private NvGpu Gpu;
|
||||
|
@ -24,6 +26,18 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
|
||||
private ConstBuffer[][] ConstBuffers;
|
||||
|
||||
[Flags]
|
||||
private enum PipelineState
|
||||
{
|
||||
Depth = 1 << 0,
|
||||
Stencil = 1 << 1,
|
||||
Blend = 1 << 2,
|
||||
ColorMask = 1 << 3,
|
||||
PrimRestart = 1 << 4
|
||||
}
|
||||
|
||||
private PipelineState DirtyState;
|
||||
|
||||
private int CurrentInstance = 0;
|
||||
|
||||
public NvGpuEngine3d(NvGpu Gpu)
|
||||
|
@ -61,9 +75,9 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
//FIXME: Is this correct?
|
||||
WriteRegister(NvGpuEngine3dReg.ColorMaskN, 0x1111);
|
||||
|
||||
WriteRegister(NvGpuEngine3dReg.FrameBufferSrgb, 1);
|
||||
Gpu.Renderer.RenderTarget.FramebufferSrgb = true;
|
||||
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
for (int Index = 0; Index < RenderTargetsCount; Index++)
|
||||
{
|
||||
WriteRegister(NvGpuEngine3dReg.IBlendNEquationRgb + Index * 8, (int)GalBlendEquation.FuncAdd);
|
||||
WriteRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb + Index * 8, (int)GalBlendFactor.One);
|
||||
|
@ -90,16 +104,40 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
{
|
||||
LockCaches();
|
||||
|
||||
GalPipelineState State = new GalPipelineState();
|
||||
if ((DirtyState & PipelineState.Depth) == 0)
|
||||
{
|
||||
DirtyState |= PipelineState.Depth;
|
||||
|
||||
SetFrameBuffer(State);
|
||||
SetFrontFace(State);
|
||||
SetCullFace(State);
|
||||
SetDepth(State);
|
||||
SetStencil(State);
|
||||
SetBlending(State);
|
||||
SetColorMask(State);
|
||||
SetPrimitiveRestart(State);
|
||||
UpdateDepth();
|
||||
}
|
||||
|
||||
if ((DirtyState & PipelineState.Stencil) == 0)
|
||||
{
|
||||
DirtyState |= PipelineState.Stencil;
|
||||
|
||||
UpdateStencil();
|
||||
}
|
||||
|
||||
if ((DirtyState & PipelineState.Blend) == 0)
|
||||
{
|
||||
DirtyState |= PipelineState.Blend;
|
||||
|
||||
UpdateBlend();
|
||||
}
|
||||
|
||||
if ((DirtyState & PipelineState.ColorMask) == 0)
|
||||
{
|
||||
DirtyState |= PipelineState.ColorMask;
|
||||
|
||||
UpdateColorMask();
|
||||
}
|
||||
|
||||
if ((DirtyState & PipelineState.PrimRestart) == 0)
|
||||
{
|
||||
DirtyState |= PipelineState.PrimRestart;
|
||||
|
||||
UpdatePrimRestart();
|
||||
}
|
||||
|
||||
for (int FbIndex = 0; FbIndex < 8; FbIndex++)
|
||||
{
|
||||
|
@ -114,11 +152,11 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
|
||||
Gpu.Renderer.Shader.BindProgram();
|
||||
|
||||
UploadTextures(Vmm, State, Keys);
|
||||
UploadConstBuffers(Vmm, State, Keys);
|
||||
UploadVertexArrays(Vmm, State);
|
||||
UploadTextures(Vmm, Keys);
|
||||
UploadConstBuffers(Vmm, Keys);
|
||||
UploadVertexArrays(Vmm);
|
||||
|
||||
DispatchRender(Vmm, State);
|
||||
DispatchRender(Vmm);
|
||||
|
||||
UnlockCaches();
|
||||
}
|
||||
|
@ -162,8 +200,8 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
|
||||
Gpu.Renderer.Rasterizer.ClearBuffers(Flags, Attachment, Red, Green, Blue, Alpha, Depth, Stencil);
|
||||
|
||||
Gpu.Renderer.Pipeline.ResetDepthMask();
|
||||
Gpu.Renderer.Pipeline.ResetColorMask(Attachment);
|
||||
DirtyState &= ~PipelineState.Depth;
|
||||
DirtyState &= ~PipelineState.ColorMask;
|
||||
}
|
||||
|
||||
private void SetFrameBuffer(NvGpuVmm Vmm, int FbIndex)
|
||||
|
@ -211,23 +249,6 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
Gpu.Renderer.RenderTarget.SetViewport(FbIndex, VpX, VpY, VpW, VpH);
|
||||
}
|
||||
|
||||
private void SetFrameBuffer(GalPipelineState State)
|
||||
{
|
||||
State.FramebufferSrgb = ReadRegisterBool(NvGpuEngine3dReg.FrameBufferSrgb);
|
||||
|
||||
State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
|
||||
State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
|
||||
|
||||
int ScreenYControl = ReadRegister(NvGpuEngine3dReg.ScreenYControl);
|
||||
|
||||
bool NegateY = (ScreenYControl & 1) != 0;
|
||||
|
||||
if (NegateY)
|
||||
{
|
||||
State.FlipY = -State.FlipY;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetZeta(NvGpuVmm Vmm)
|
||||
{
|
||||
long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);
|
||||
|
@ -338,115 +359,174 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
throw new ArgumentOutOfRangeException(nameof(Program));
|
||||
}
|
||||
|
||||
private void SetFrontFace(GalPipelineState State)
|
||||
private void SetDepth(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
|
||||
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
|
||||
WriteRegister(MethCall);
|
||||
|
||||
GalFrontFace FrontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace);
|
||||
|
||||
//Flipping breaks facing. Flipping front facing too fixes it
|
||||
if (SignX != SignY)
|
||||
{
|
||||
switch (FrontFace)
|
||||
{
|
||||
case GalFrontFace.CW: FrontFace = GalFrontFace.CCW; break;
|
||||
case GalFrontFace.CCW: FrontFace = GalFrontFace.CW; break;
|
||||
}
|
||||
}
|
||||
|
||||
State.FrontFace = FrontFace;
|
||||
DirtyState &= ~PipelineState.Depth;
|
||||
}
|
||||
|
||||
private void SetCullFace(GalPipelineState State)
|
||||
private void SetStencil(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
State.CullFaceEnabled = ReadRegisterBool(NvGpuEngine3dReg.CullFaceEnable);
|
||||
WriteRegister(MethCall);
|
||||
|
||||
if (State.CullFaceEnabled)
|
||||
DirtyState &= ~PipelineState.Stencil;
|
||||
}
|
||||
|
||||
private void SetBlend(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
WriteRegister(MethCall);
|
||||
|
||||
DirtyState &= ~PipelineState.Blend;
|
||||
}
|
||||
|
||||
private void SetColorMask(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
WriteRegister(MethCall);
|
||||
|
||||
DirtyState &= ~PipelineState.ColorMask;
|
||||
}
|
||||
|
||||
private void SetPrimRestart(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
WriteRegister(MethCall);
|
||||
|
||||
DirtyState &= ~PipelineState.PrimRestart;
|
||||
}
|
||||
|
||||
private void SetFramebufferSrgb(NvGpuVmm Vmm, GpuMethodCall MethCall)
|
||||
{
|
||||
bool FramebufferSrgb = ReadRegisterBool(NvGpuEngine3dReg.FrameBufferSrgb);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetFramebufferSrgb(FramebufferSrgb);
|
||||
|
||||
Gpu.Renderer.RenderTarget.FramebufferSrgb = FramebufferSrgb;
|
||||
}
|
||||
|
||||
private void UpdateDepth()
|
||||
{
|
||||
bool DepthTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthTestEnable);
|
||||
bool DepthWriteEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthWriteEnable);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetDepthMask(DepthTestEnabled, DepthWriteEnabled);
|
||||
|
||||
if (DepthTestEnabled)
|
||||
{
|
||||
State.CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace);
|
||||
GalComparisonOp DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetDepthFunc(DepthFunc);
|
||||
}
|
||||
|
||||
if (DepthTestEnabled || DepthWriteEnabled)
|
||||
{
|
||||
float DepthRangeNear = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNNear);
|
||||
float DepthRangeFar = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNFar);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetDepthRange(DepthRangeNear, DepthRangeFar);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDepth(GalPipelineState State)
|
||||
private void UpdateStencil()
|
||||
{
|
||||
State.DepthTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthTestEnable);
|
||||
bool StencilTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.StencilEnable);
|
||||
|
||||
State.DepthWriteEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthWriteEnable);
|
||||
Gpu.Renderer.Pipeline.SetStencilTestEnabled(StencilTestEnabled);
|
||||
|
||||
if (State.DepthTestEnabled)
|
||||
if (StencilTestEnabled)
|
||||
{
|
||||
State.DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
|
||||
}
|
||||
|
||||
State.DepthRangeNear = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNNear);
|
||||
State.DepthRangeFar = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNFar);
|
||||
}
|
||||
|
||||
private void SetStencil(GalPipelineState State)
|
||||
{
|
||||
State.StencilTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.StencilEnable);
|
||||
|
||||
if (State.StencilTestEnabled)
|
||||
{
|
||||
State.StencilBackFuncFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilBackFuncFunc);
|
||||
State.StencilBackFuncRef = ReadRegister(NvGpuEngine3dReg.StencilBackFuncRef);
|
||||
State.StencilBackFuncMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilBackFuncMask);
|
||||
State.StencilBackOpFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpFail);
|
||||
State.StencilBackOpZFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZFail);
|
||||
State.StencilBackOpZPass = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZPass);
|
||||
State.StencilBackMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilBackMask);
|
||||
|
||||
State.StencilFrontFuncFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncFunc);
|
||||
State.StencilFrontFuncRef = ReadRegister(NvGpuEngine3dReg.StencilFrontFuncRef);
|
||||
State.StencilFrontFuncMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncMask);
|
||||
State.StencilFrontOpFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpFail);
|
||||
State.StencilFrontOpZFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZFail);
|
||||
State.StencilFrontOpZPass = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZPass);
|
||||
State.StencilFrontMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilFrontMask);
|
||||
Gpu.Renderer.Pipeline.SetStencilTest(
|
||||
(GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilBackFuncFunc),
|
||||
ReadRegister(NvGpuEngine3dReg.StencilBackFuncRef),
|
||||
(uint)ReadRegister(NvGpuEngine3dReg.StencilBackFuncMask),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpFail),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZFail),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZPass),
|
||||
(uint)ReadRegister(NvGpuEngine3dReg.StencilBackMask),
|
||||
(GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncFunc),
|
||||
ReadRegister(NvGpuEngine3dReg.StencilFrontFuncRef),
|
||||
(uint)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncMask),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpFail),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZFail),
|
||||
(GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZPass),
|
||||
(uint)ReadRegister(NvGpuEngine3dReg.StencilFrontMask));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBlending(GalPipelineState State)
|
||||
private void UpdateBlend()
|
||||
{
|
||||
bool BlendIndependent = ReadRegisterBool(NvGpuEngine3dReg.BlendIndependent);
|
||||
|
||||
State.BlendIndependent = BlendIndependent;
|
||||
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
if (BlendIndependent)
|
||||
{
|
||||
if (BlendIndependent)
|
||||
for (int Index = 0; Index < RenderTargetsCount; Index++)
|
||||
{
|
||||
State.Blends[Index].Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable + Index);
|
||||
bool Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable + Index);
|
||||
|
||||
if (State.Blends[Index].Enabled)
|
||||
Gpu.Renderer.Pipeline.SetBlendEnabled(Index, Enabled);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
State.Blends[Index].SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.IBlendNSeparateAlpha + Index * 8);
|
||||
bool 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);
|
||||
GalBlendEquation EquationRgb = ReadBlendEquation(NvGpuEngine3dReg.IBlendNEquationRgb + Index * 8);
|
||||
GalBlendFactor FuncSrcRgb = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncSrcRgb + Index * 8);
|
||||
GalBlendFactor FuncDstRgb = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncDstRgb + Index * 8);
|
||||
|
||||
if (SeparateAlpha)
|
||||
{
|
||||
GalBlendEquation EquationAlpha = ReadBlendEquation(NvGpuEngine3dReg.IBlendNEquationAlpha + Index * 8);
|
||||
GalBlendFactor FuncSrcAlpha = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncSrcAlpha + Index * 8);
|
||||
GalBlendFactor FuncDstAlpha = ReadBlendFactor (NvGpuEngine3dReg.IBlendNFuncDstAlpha + Index * 8);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetBlendSeparate(
|
||||
Index,
|
||||
EquationRgb,
|
||||
FuncSrcRgb,
|
||||
FuncDstRgb,
|
||||
EquationAlpha,
|
||||
FuncSrcAlpha,
|
||||
FuncDstAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gpu.Renderer.Pipeline.SetBlend(Index, EquationRgb, FuncSrcRgb, FuncDstRgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
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 (?).
|
||||
bool Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetBlendEnabled(Enabled);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
//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);
|
||||
bool SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.BlendSeparateAlpha);
|
||||
|
||||
if (State.Blends[Index].Enabled)
|
||||
GalBlendEquation EquationRgb = ReadBlendEquation(NvGpuEngine3dReg.BlendEquationRgb);
|
||||
GalBlendFactor FuncSrcRgb = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncSrcRgb);
|
||||
GalBlendFactor FuncDstRgb = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncDstRgb);
|
||||
|
||||
if (SeparateAlpha)
|
||||
{
|
||||
State.Blends[Index].SeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.BlendSeparateAlpha);
|
||||
GalBlendEquation EquationAlpha = ReadBlendEquation(NvGpuEngine3dReg.BlendEquationAlpha);
|
||||
GalBlendFactor FuncSrcAlpha = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncSrcAlpha);
|
||||
GalBlendFactor FuncDstAlpha = ReadBlendFactor (NvGpuEngine3dReg.BlendFuncDstAlpha);
|
||||
|
||||
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);
|
||||
Gpu.Renderer.Pipeline.SetBlendSeparate(
|
||||
EquationRgb,
|
||||
FuncSrcRgb,
|
||||
FuncDstRgb,
|
||||
EquationAlpha,
|
||||
FuncSrcAlpha,
|
||||
FuncDstAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gpu.Renderer.Pipeline.SetBlend(EquationRgb, FuncSrcRgb, FuncDstRgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -462,30 +542,48 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
return (GalBlendFactor)ReadRegister(Register);
|
||||
}
|
||||
|
||||
private void SetColorMask(GalPipelineState State)
|
||||
private void UpdateColorMask()
|
||||
{
|
||||
bool ColorMaskCommon = ReadRegisterBool(NvGpuEngine3dReg.ColorMaskCommon);
|
||||
|
||||
State.ColorMaskCommon = ColorMaskCommon;
|
||||
|
||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||
if (ColorMaskCommon)
|
||||
{
|
||||
int ColorMask = ReadRegister(NvGpuEngine3dReg.ColorMaskN + (ColorMaskCommon ? 0 : Index));
|
||||
int ColorMask = ReadRegister(NvGpuEngine3dReg.ColorMaskN);
|
||||
|
||||
State.ColorMasks[Index].Red = ((ColorMask >> 0) & 0xf) != 0;
|
||||
State.ColorMasks[Index].Green = ((ColorMask >> 4) & 0xf) != 0;
|
||||
State.ColorMasks[Index].Blue = ((ColorMask >> 8) & 0xf) != 0;
|
||||
State.ColorMasks[Index].Alpha = ((ColorMask >> 12) & 0xf) != 0;
|
||||
bool RedMask = ((ColorMask >> 0) & 0xf) != 0;
|
||||
bool GreenMask = ((ColorMask >> 4) & 0xf) != 0;
|
||||
bool BlueMask = ((ColorMask >> 8) & 0xf) != 0;
|
||||
bool AlphaMask = ((ColorMask >> 12) & 0xf) != 0;
|
||||
|
||||
Gpu.Renderer.Pipeline.SetColorMask(RedMask, GreenMask, BlueMask, AlphaMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int Index = 0; Index < RenderTargetsCount; Index++)
|
||||
{
|
||||
int ColorMask = ReadRegister(NvGpuEngine3dReg.ColorMaskN + Index);
|
||||
|
||||
bool RedMask = ((ColorMask >> 0) & 0xf) != 0;
|
||||
bool GreenMask = ((ColorMask >> 4) & 0xf) != 0;
|
||||
bool BlueMask = ((ColorMask >> 8) & 0xf) != 0;
|
||||
bool AlphaMask = ((ColorMask >> 12) & 0xf) != 0;
|
||||
|
||||
Gpu.Renderer.Pipeline.SetColorMask(Index, RedMask, GreenMask, BlueMask, AlphaMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPrimitiveRestart(GalPipelineState State)
|
||||
private void UpdatePrimRestart()
|
||||
{
|
||||
State.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable);
|
||||
bool PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable);
|
||||
|
||||
if (State.PrimitiveRestartEnabled)
|
||||
Gpu.Renderer.Pipeline.SetPrimitiveRestartEnabled(PrimitiveRestartEnabled);
|
||||
|
||||
if (PrimitiveRestartEnabled)
|
||||
{
|
||||
State.PrimitiveRestartIndex = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
|
||||
int Index = ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
|
||||
|
||||
Gpu.Renderer.Pipeline.SetPrimitiveRestartIndex(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,7 +615,7 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
}
|
||||
}
|
||||
|
||||
private void UploadTextures(NvGpuVmm Vmm, GalPipelineState State, long[] Keys)
|
||||
private void UploadTextures(NvGpuVmm Vmm, long[] Keys)
|
||||
{
|
||||
long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
|
||||
|
||||
|
@ -609,10 +707,14 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
return (Key, Image, Sampler);
|
||||
}
|
||||
|
||||
private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State, long[] Keys)
|
||||
private void UploadConstBuffers(NvGpuVmm Vmm, long[] Keys)
|
||||
{
|
||||
long[][] ConstBufferKeys = new long[6][];
|
||||
|
||||
for (int Stage = 0; Stage < Keys.Length; Stage++)
|
||||
{
|
||||
ConstBufferKeys[Stage] = new long[18];
|
||||
|
||||
foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.Shader.GetConstBufferUsage(Keys[Stage]))
|
||||
{
|
||||
ConstBuffer Cb = ConstBuffers[Stage][DeclInfo.Cbuf];
|
||||
|
@ -636,13 +738,16 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
}
|
||||
}
|
||||
|
||||
State.ConstBufferKeys[Stage][DeclInfo.Cbuf] = Key;
|
||||
ConstBufferKeys[Stage][DeclInfo.Cbuf] = Key;
|
||||
}
|
||||
}
|
||||
|
||||
Gpu.Renderer.Pipeline.BindConstBuffers(ConstBufferKeys);
|
||||
}
|
||||
|
||||
private void UploadVertexArrays(NvGpuVmm Vmm, GalPipelineState State)
|
||||
private void UploadVertexArrays(NvGpuVmm Vmm)
|
||||
{
|
||||
//Upload index buffers.
|
||||
long IbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress);
|
||||
|
||||
long IboKey = Vmm.GetPhysicalAddress(IbPosition);
|
||||
|
@ -750,8 +855,6 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
Attribs[ArrayIndex].Add(new GalVertexAttrib(Attr, IsConst, Offset, Data, Size, Type, IsRgba));
|
||||
}
|
||||
|
||||
State.VertexBindings = new GalVertexBinding[32];
|
||||
|
||||
for (int Index = 0; Index < 32; Index++)
|
||||
{
|
||||
if (Attribs[Index] == null)
|
||||
|
@ -805,17 +908,10 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, Vmm.ReadBytes(VbPosition, VbSize));
|
||||
}
|
||||
}
|
||||
|
||||
State.VertexBindings[Index].Enabled = true;
|
||||
State.VertexBindings[Index].Stride = Stride;
|
||||
State.VertexBindings[Index].VboKey = VboKey;
|
||||
State.VertexBindings[Index].Instanced = Instanced;
|
||||
State.VertexBindings[Index].Divisor = VertexDivisor;
|
||||
State.VertexBindings[Index].Attribs = Attribs[Index].ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void DispatchRender(NvGpuVmm Vmm, GalPipelineState State)
|
||||
private void DispatchRender(NvGpuVmm Vmm)
|
||||
{
|
||||
int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount);
|
||||
int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl);
|
||||
|
@ -839,9 +935,19 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
CurrentInstance = 0;
|
||||
}
|
||||
|
||||
State.Instance = CurrentInstance;
|
||||
float FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
|
||||
float FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
|
||||
|
||||
Gpu.Renderer.Pipeline.Bind(State);
|
||||
int ScreenYControl = ReadRegister(NvGpuEngine3dReg.ScreenYControl);
|
||||
|
||||
bool NegateY = (ScreenYControl & 1) != 0;
|
||||
|
||||
if (NegateY)
|
||||
{
|
||||
FlipY = -FlipY;
|
||||
}
|
||||
|
||||
Gpu.Renderer.Pipeline.SetFlip(FlipX, FlipY, CurrentInstance);
|
||||
|
||||
Gpu.Renderer.RenderTarget.Bind();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue