diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs new file mode 100644 index 0000000000..1a8acd4eac --- /dev/null +++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs @@ -0,0 +1,45 @@ +namespace Ryujinx.Graphics.Gal +{ + public struct GalPipelineState + { + public GalFrontFace FrontFace; + + public bool CullFaceEnabled; + public GalCullFace CullFace; + + public bool DepthTestEnabled; + public float DepthClear; + public GalComparisonOp DepthFunc; + + public bool StencilTestEnabled; + public int StencilClear; + + 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 BlendEnabled; + public bool BlendSeparateAlpha; + public GalBlendEquation BlendEquationRgb; + public GalBlendFactor BlendFuncSrcRgb; + public GalBlendFactor BlendFuncDstRgb; + public GalBlendEquation BlendEquationAlpha; + public GalBlendFactor BlendFuncSrcAlpha; + public GalBlendFactor BlendFuncDstAlpha; + + public bool PrimitiveRestartEnabled; + public uint PrimitiveRestartIndex; + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalBlend.cs b/Ryujinx.Graphics/Gal/IGalBlend.cs deleted file mode 100644 index 5c96a49231..0000000000 --- a/Ryujinx.Graphics/Gal/IGalBlend.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Ryujinx.Graphics.Gal -{ - public interface IGalBlend - { - void Enable(); - - void Disable(); - - void Set( - GalBlendEquation Equation, - GalBlendFactor FuncSrc, - GalBlendFactor FuncDst); - - void SetSeparate( - GalBlendEquation EquationRgb, - GalBlendEquation EquationAlpha, - GalBlendFactor FuncSrcRgb, - GalBlendFactor FuncDstRgb, - GalBlendFactor FuncSrcAlpha, - GalBlendFactor FuncDstAlpha); - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalPipeline.cs b/Ryujinx.Graphics/Gal/IGalPipeline.cs new file mode 100644 index 0000000000..1fad7a4ecd --- /dev/null +++ b/Ryujinx.Graphics/Gal/IGalPipeline.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Graphics.Gal +{ + public interface IGalPipeline + { + void Bind(ref GalPipelineState State); + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs index a87d36c38f..7c8f7dabbf 100644 --- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs +++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs @@ -13,40 +13,6 @@ namespace Ryujinx.Graphics.Gal bool IsIboCached(long Key, long DataSize); - void SetFrontFace(GalFrontFace FrontFace); - - void EnableCullFace(); - - void DisableCullFace(); - - void SetCullFace(GalCullFace CullFace); - - void EnableDepthTest(); - - void DisableDepthTest(); - - void SetDepthFunction(GalComparisonOp Func); - - void SetClearDepth(float Depth); - - void EnableStencilTest(); - - void DisableStencilTest(); - - void SetStencilFunction(bool IsFrontFace, GalComparisonOp Func, int Ref, int Mask); - - void SetStencilOp(bool IsFrontFace, GalStencilOp Fail, GalStencilOp ZFail, GalStencilOp ZPass); - - void SetStencilMask(bool IsFrontFace, int Mask); - - void SetClearStencil(int Stencil); - - void EnablePrimitiveRestart(); - - void DisablePrimitiveRestart(); - - void SetPrimitiveRestartIndex(uint Index); - void CreateVbo(long Key, int DataSize, IntPtr HostAddress); void CreateIbo(long Key, int DataSize, IntPtr HostAddress); diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index c6324c4a35..547e348f68 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -8,14 +8,14 @@ namespace Ryujinx.Graphics.Gal void RunActions(); - IGalBlend Blend { get; } - IGalFrameBuffer FrameBuffer { get; } IGalRasterizer Rasterizer { get; } IGalShader Shader { get; } + IGalPipeline Pipeline { get; } + IGalTexture Texture { get; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs deleted file mode 100644 index 7175e3a0ef..0000000000 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs +++ /dev/null @@ -1,49 +0,0 @@ -using OpenTK.Graphics.OpenGL; - -namespace Ryujinx.Graphics.Gal.OpenGL -{ - public class OGLBlend : IGalBlend - { - public void Enable() - { - GL.Enable(EnableCap.Blend); - } - - public void Disable() - { - GL.Disable(EnableCap.Blend); - } - - public void Set( - GalBlendEquation Equation, - GalBlendFactor FuncSrc, - GalBlendFactor FuncDst) - { - GL.BlendEquation( - OGLEnumConverter.GetBlendEquation(Equation)); - - GL.BlendFunc( - OGLEnumConverter.GetBlendFactor(FuncSrc), - OGLEnumConverter.GetBlendFactor(FuncDst)); - } - - public void SetSeparate( - GalBlendEquation EquationRgb, - GalBlendEquation EquationAlpha, - GalBlendFactor FuncSrcRgb, - GalBlendFactor FuncDstRgb, - 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)); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs new file mode 100644 index 0000000000..3ce9251ee4 --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -0,0 +1,240 @@ +using OpenTK.Graphics.OpenGL; +using System; + +namespace Ryujinx.Graphics.Gal.OpenGL +{ + public class OGLPipeline : IGalPipeline + { + private GalPipelineState O; + + public OGLPipeline() + { + //The following values match OpenGL's defaults + O = new GalPipelineState(); + + O.FrontFace = GalFrontFace.CCW; + + O.CullFaceEnabled = false; + O.CullFace = GalCullFace.Back; + + O.DepthTestEnabled = false; + O.DepthClear = 1f; + O.DepthFunc = GalComparisonOp.Less; + + O.StencilTestEnabled = false; + O.StencilClear = 0; + + O.StencilBackFuncFunc = GalComparisonOp.Always; + O.StencilBackFuncRef = 0; + O.StencilBackFuncMask = UInt32.MaxValue; + O.StencilBackOpFail = GalStencilOp.Keep; + O.StencilBackOpZFail = GalStencilOp.Keep; + O.StencilBackOpZPass = GalStencilOp.Keep; + O.StencilBackMask = UInt32.MaxValue; + + O.StencilFrontFuncFunc = GalComparisonOp.Always; + O.StencilFrontFuncRef = 0; + O.StencilFrontFuncMask = UInt32.MaxValue; + O.StencilFrontOpFail = GalStencilOp.Keep; + O.StencilFrontOpZFail = GalStencilOp.Keep; + O.StencilFrontOpZPass = GalStencilOp.Keep; + O.StencilFrontMask = UInt32.MaxValue; + + O.BlendEnabled = false; + O.BlendSeparateAlpha = false; + + O.BlendEquationRgb = 0; + O.BlendFuncSrcRgb = GalBlendFactor.One; + O.BlendFuncDstRgb = GalBlendFactor.Zero; + O.BlendEquationAlpha = 0; + O.BlendFuncSrcAlpha = GalBlendFactor.One; + O.BlendFuncDstAlpha = GalBlendFactor.Zero; + + O.PrimitiveRestartEnabled = false; + O.PrimitiveRestartIndex = 0; + } + + public void Bind(ref GalPipelineState S) + { + // O stands for Other, S from State (current state) + + //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved + + //if (S.FrontFace != O.FrontFace) + //{ + // GL.FrontFace(OGLEnumConverter.GetFrontFace(S.FrontFace)); + //} + + //if (S.CullFaceEnabled != O.CullFaceEnabled) + //{ + // Enable(EnableCap.CullFace, S.CullFaceEnabled); + //} + + //if (S.CullFaceEnabled) + //{ + // if (S.CullFace != O.CullFace) + // { + // GL.CullFace(OGLEnumConverter.GetCullFace(S.CullFace)); + // } + //} + + if (S.DepthTestEnabled != O.DepthTestEnabled) + { + Enable(EnableCap.DepthTest, S.DepthTestEnabled); + } + + if (S.DepthClear != O.DepthClear) + { + GL.ClearDepth(S.DepthClear); + } + + if (S.DepthTestEnabled) + { + if (S.DepthFunc != O.DepthFunc) + { + GL.DepthFunc(OGLEnumConverter.GetDepthFunc(S.DepthFunc)); + } + } + + if (S.StencilTestEnabled != O.StencilTestEnabled) + { + Enable(EnableCap.StencilTest, S.StencilTestEnabled); + } + + if (S.StencilClear != O.StencilClear) + { + GL.ClearStencil(S.StencilClear); + } + + if (S.StencilTestEnabled) + { + if (S.StencilBackFuncFunc != O.StencilBackFuncFunc || + S.StencilBackFuncRef != O.StencilBackFuncRef || + S.StencilBackFuncMask != O.StencilBackFuncMask) + { + GL.StencilFuncSeparate( + StencilFace.Back, + OGLEnumConverter.GetStencilFunc(S.StencilBackFuncFunc), + S.StencilBackFuncRef, + S.StencilBackFuncMask); + } + + if (S.StencilBackOpFail != O.StencilBackOpFail || + S.StencilBackOpZFail != O.StencilBackOpZFail || + S.StencilBackOpZPass != O.StencilBackOpZPass) + { + GL.StencilOpSeparate( + StencilFace.Back, + OGLEnumConverter.GetStencilOp(S.StencilBackOpFail), + OGLEnumConverter.GetStencilOp(S.StencilBackOpZFail), + OGLEnumConverter.GetStencilOp(S.StencilBackOpZPass)); + } + + if (S.StencilBackMask != O.StencilBackMask) + { + GL.StencilMaskSeparate(StencilFace.Back, S.StencilBackMask); + } + + if (S.StencilFrontFuncFunc != O.StencilFrontFuncFunc || + S.StencilFrontFuncRef != O.StencilFrontFuncRef || + S.StencilFrontFuncMask != O.StencilFrontFuncMask) + { + GL.StencilFuncSeparate( + StencilFace.Front, + OGLEnumConverter.GetStencilFunc(S.StencilFrontFuncFunc), + S.StencilFrontFuncRef, + S.StencilFrontFuncMask); + } + + if (S.StencilFrontOpFail != O.StencilFrontOpFail || + S.StencilFrontOpZFail != O.StencilFrontOpZFail || + S.StencilFrontOpZPass != O.StencilFrontOpZPass) + { + GL.StencilOpSeparate( + StencilFace.Front, + OGLEnumConverter.GetStencilOp(S.StencilFrontOpFail), + OGLEnumConverter.GetStencilOp(S.StencilFrontOpZFail), + OGLEnumConverter.GetStencilOp(S.StencilFrontOpZPass)); + } + + if (S.StencilFrontMask != O.StencilFrontMask) + { + GL.StencilMaskSeparate(StencilFace.Front, S.StencilFrontMask); + } + } + + if (S.BlendEnabled != O.BlendEnabled) + { + Enable(EnableCap.Blend, S.BlendEnabled); + } + + if (S.BlendEnabled) + { + if (S.BlendSeparateAlpha) + { + if (S.BlendEquationRgb != O.BlendEquationRgb || + S.BlendEquationAlpha != O.BlendEquationAlpha) + { + GL.BlendEquationSeparate( + OGLEnumConverter.GetBlendEquation(S.BlendEquationRgb), + OGLEnumConverter.GetBlendEquation(S.BlendEquationAlpha)); + } + + if (S.BlendFuncSrcRgb != O.BlendFuncSrcRgb || + S.BlendFuncDstRgb != O.BlendFuncDstRgb || + S.BlendFuncSrcAlpha != O.BlendFuncSrcAlpha || + S.BlendFuncDstAlpha != O.BlendFuncDstAlpha) + { + GL.BlendFuncSeparate( + (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(S.BlendFuncSrcRgb), + (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(S.BlendFuncDstRgb), + (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(S.BlendFuncSrcAlpha), + (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(S.BlendFuncDstAlpha)); + } + } + else + { + if (S.BlendEquationRgb != O.BlendEquationRgb) + { + GL.BlendEquation(OGLEnumConverter.GetBlendEquation(S.BlendEquationRgb)); + } + + if (S.BlendFuncSrcRgb != O.BlendFuncSrcRgb || + S.BlendFuncDstRgb != O.BlendFuncDstRgb) + { + GL.BlendFunc( + OGLEnumConverter.GetBlendFactor(S.BlendFuncSrcRgb), + OGLEnumConverter.GetBlendFactor(S.BlendFuncDstRgb)); + } + } + } + + if (S.PrimitiveRestartEnabled != O.PrimitiveRestartEnabled) + { + Enable(EnableCap.PrimitiveRestart, S.PrimitiveRestartEnabled); + } + + if (S.PrimitiveRestartEnabled) + { + if (S.PrimitiveRestartIndex != O.PrimitiveRestartIndex) + { + GL.PrimitiveRestartIndex(S.PrimitiveRestartIndex); + } + } + + O = S; + } + + private void Enable(EnableCap Cap, bool Enabled) + { + if (Enabled) + { + GL.Enable(Cap); + } + else + { + GL.Disable(Cap); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index c5166b51bf..2c0008d9fa 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -118,99 +118,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL return IboCache.TryGetSize(Key, out long Size) && Size == DataSize; } - public void SetFrontFace(GalFrontFace FrontFace) - { - GL.FrontFace(OGLEnumConverter.GetFrontFace(FrontFace)); - } - - public void EnableCullFace() - { - GL.Enable(EnableCap.CullFace); - } - - public void DisableCullFace() - { - GL.Disable(EnableCap.CullFace); - } - - public void SetCullFace(GalCullFace CullFace) - { - GL.CullFace(OGLEnumConverter.GetCullFace(CullFace)); - } - - public void EnableDepthTest() - { - GL.Enable(EnableCap.DepthTest); - } - - public void DisableDepthTest() - { - GL.Disable(EnableCap.DepthTest); - } - - public void SetDepthFunction(GalComparisonOp Func) - { - GL.DepthFunc(OGLEnumConverter.GetDepthFunc(Func)); - } - - public void SetClearDepth(float Depth) - { - GL.ClearDepth(Depth); - } - - public void EnableStencilTest() - { - GL.Enable(EnableCap.StencilTest); - } - - public void DisableStencilTest() - { - GL.Disable(EnableCap.StencilTest); - } - - public void SetStencilFunction(bool IsFrontFace, GalComparisonOp Func, int Ref, int Mask) - { - GL.StencilFuncSeparate( - IsFrontFace ? StencilFace.Front : StencilFace.Back, - OGLEnumConverter.GetStencilFunc(Func), - Ref, - Mask); - } - - public void SetStencilOp(bool IsFrontFace, GalStencilOp Fail, GalStencilOp ZFail, GalStencilOp ZPass) - { - GL.StencilOpSeparate( - IsFrontFace ? StencilFace.Front : StencilFace.Back, - OGLEnumConverter.GetStencilOp(Fail), - OGLEnumConverter.GetStencilOp(ZFail), - OGLEnumConverter.GetStencilOp(ZPass)); - } - - public void SetStencilMask(bool IsFrontFace, int Mask) - { - GL.StencilMaskSeparate(IsFrontFace ? StencilFace.Front : StencilFace.Back, Mask); - } - - public void SetClearStencil(int Stencil) - { - GL.ClearStencil(Stencil); - } - - public void EnablePrimitiveRestart() - { - GL.Enable(EnableCap.PrimitiveRestart); - } - - public void DisablePrimitiveRestart() - { - GL.Disable(EnableCap.PrimitiveRestart); - } - - public void SetPrimitiveRestartIndex(uint Index) - { - GL.PrimitiveRestartIndex(Index); - } - public void CreateVbo(long Key, int DataSize, IntPtr HostAddress) { int Handle = GL.GenBuffer(); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs index ca70d4f666..c44732ebe7 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs @@ -5,28 +5,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL { public class OGLRenderer : IGalRenderer { - public IGalBlend Blend { get; private set; } - public IGalFrameBuffer FrameBuffer { get; private set; } public IGalRasterizer Rasterizer { get; private set; } public IGalShader Shader { get; private set; } + public IGalPipeline Pipeline { get; private set; } + public IGalTexture Texture { get; private set; } private ConcurrentQueue ActionsQueue; public OGLRenderer() { - Blend = new OGLBlend(); - FrameBuffer = new OGLFrameBuffer(); Rasterizer = new OGLRasterizer(); Shader = new OGLShader(); + Pipeline = new OGLPipeline(); + Texture = new OGLTexture(); ActionsQueue = new ConcurrentQueue(); diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index 3dd0e98e60..8b21ea0715 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -27,6 +27,8 @@ namespace Ryujinx.HLE.Gpu.Engines private List[] UploadedKeys; + private GalPipelineState State; + public NvGpuEngine3d(NvGpu Gpu) { this.Gpu = Gpu; @@ -66,6 +68,8 @@ namespace Ryujinx.HLE.Gpu.Engines { UploadedKeys[i] = new List(); } + + State = new GalPipelineState(); } public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) @@ -90,14 +94,15 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Shader.BindProgram(); - //Note: Uncomment SetFrontFace SetCullFace when flipping issues are solved - //SetFrontFace(); - //SetCullFace(); + SetFrontFace(); + SetCullFace(); SetDepth(); SetStencil(); SetAlphaBlending(); SetPrimitiveRestart(); + Gpu.Renderer.Pipeline.Bind(ref State); + UploadTextures(Vmm, Keys); UploadUniforms(Vmm); UploadVertexArrays(Vmm); @@ -261,195 +266,83 @@ namespace Ryujinx.HLE.Gpu.Engines } } - Gpu.Renderer.Rasterizer.SetFrontFace(FrontFace); + State.FrontFace = FrontFace; } private void SetCullFace() { - bool Enable = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0; + State.CullFaceEnabled = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0; - if (Enable) + if (State.CullFaceEnabled) { - Gpu.Renderer.Rasterizer.EnableCullFace(); + State.CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace); } - else - { - Gpu.Renderer.Rasterizer.DisableCullFace(); - } - - if (!Enable) - { - return; - } - - GalCullFace CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace); - - Gpu.Renderer.Rasterizer.SetCullFace(CullFace); } private void SetDepth() { - float ClearDepth = ReadRegisterFloat(NvGpuEngine3dReg.ClearDepth); + State.DepthTestEnabled = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0; - Gpu.Renderer.Rasterizer.SetClearDepth(ClearDepth); + State.DepthClear = ReadRegisterFloat(NvGpuEngine3dReg.ClearDepth); - bool Enable = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0; - - if (Enable) + if (State.DepthTestEnabled) { - Gpu.Renderer.Rasterizer.EnableDepthTest(); + State.DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction); } - else - { - Gpu.Renderer.Rasterizer.DisableDepthTest(); - } - - if (!Enable) - { - return; - } - - GalComparisonOp Func = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction); - - Gpu.Renderer.Rasterizer.SetDepthFunction(Func); } private void SetStencil() { - int ClearStencil = ReadRegister(NvGpuEngine3dReg.ClearStencil); + State.StencilTestEnabled = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0; - Gpu.Renderer.Rasterizer.SetClearStencil(ClearStencil); - - bool Enable = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0; - - if (Enable) + State.StencilClear = ReadRegister(NvGpuEngine3dReg.ClearStencil); + + if (State.StencilTestEnabled) { - Gpu.Renderer.Rasterizer.EnableStencilTest(); + 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); } - else - { - Gpu.Renderer.Rasterizer.DisableStencilTest(); - } - - if (!Enable) - { - return; - } - - void SetFaceStencil( - bool IsFrontFace, - NvGpuEngine3dReg Func, - NvGpuEngine3dReg FuncRef, - NvGpuEngine3dReg FuncMask, - NvGpuEngine3dReg OpFail, - NvGpuEngine3dReg OpZFail, - NvGpuEngine3dReg OpZPass, - NvGpuEngine3dReg Mask) - { - Gpu.Renderer.Rasterizer.SetStencilFunction( - IsFrontFace, - (GalComparisonOp)ReadRegister(Func), - ReadRegister(FuncRef), - ReadRegister(FuncMask)); - - Gpu.Renderer.Rasterizer.SetStencilOp( - IsFrontFace, - (GalStencilOp)ReadRegister(OpFail), - (GalStencilOp)ReadRegister(OpZFail), - (GalStencilOp)ReadRegister(OpZPass)); - - Gpu.Renderer.Rasterizer.SetStencilMask(IsFrontFace, ReadRegister(Mask)); - } - - SetFaceStencil(false, - NvGpuEngine3dReg.StencilBackFuncFunc, - NvGpuEngine3dReg.StencilBackFuncRef, - NvGpuEngine3dReg.StencilBackFuncMask, - NvGpuEngine3dReg.StencilBackOpFail, - NvGpuEngine3dReg.StencilBackOpZFail, - NvGpuEngine3dReg.StencilBackOpZPass, - NvGpuEngine3dReg.StencilBackMask); - - SetFaceStencil(true, - NvGpuEngine3dReg.StencilFrontFuncFunc, - NvGpuEngine3dReg.StencilFrontFuncRef, - NvGpuEngine3dReg.StencilFrontFuncMask, - NvGpuEngine3dReg.StencilFrontOpFail, - NvGpuEngine3dReg.StencilFrontOpZFail, - NvGpuEngine3dReg.StencilFrontOpZPass, - NvGpuEngine3dReg.StencilFrontMask); } private void SetAlphaBlending() { //TODO: Support independent blend properly. - bool Enable = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0; + State.BlendEnabled = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0; - if (Enable) + if (State.BlendEnabled) { - Gpu.Renderer.Blend.Enable(); - } - else - { - Gpu.Renderer.Blend.Disable(); - } + State.BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0; - if (!Enable) - { - //If blend is not enabled, then the other values have no effect. - //Note that if it is disabled, the register may contain invalid values. - return; - } - - bool BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0; - - GalBlendEquation EquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb); - - GalBlendFactor FuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb); - GalBlendFactor FuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb); - - if (BlendSeparateAlpha) - { - GalBlendEquation EquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha); - - GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha); - GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha); - - Gpu.Renderer.Blend.SetSeparate( - EquationRgb, - EquationAlpha, - FuncSrcRgb, - FuncDstRgb, - FuncSrcAlpha, - FuncDstAlpha); - } - else - { - Gpu.Renderer.Blend.Set(EquationRgb, FuncSrcRgb, FuncDstRgb); + 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); } } private void SetPrimitiveRestart() { - bool Enable = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0; + State.PrimitiveRestartEnabled = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0; - if (Enable) + if (State.PrimitiveRestartEnabled) { - Gpu.Renderer.Rasterizer.EnablePrimitiveRestart(); + State.PrimitiveRestartIndex = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex); } - else - { - Gpu.Renderer.Rasterizer.DisablePrimitiveRestart(); - } - - if (!Enable) - { - return; - } - - uint Index = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex); - - Gpu.Renderer.Rasterizer.SetPrimitiveRestartIndex(Index); } private void UploadTextures(NvGpuVmm Vmm, long[] Keys)