diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-07-05 15:47:29 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-07-05 15:47:29 -0300 |
| commit | 97ca974213ec9564ed4a9c57e998ca726dbbb64f (patch) | |
| tree | 5daf598d267d3ce05f3ef342621e7f93536fa554 /Ryujinx.HLE | |
| parent | c99b2884e4eb9adfb5b893ee84d7678262d19b06 (diff) | |
Implement some GPU features (#209)
* Implement stencil testing
* Implement depth testing
* Implement face culling
* Implement front face
* Comparison functions now take OGL enums too
* Fix front facing when flipping was used
* Add depth and stencil clear values
Diffstat (limited to 'Ryujinx.HLE')
| -rw-r--r-- | Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs | 157 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs | 18 |
2 files changed, 165 insertions, 10 deletions
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index b27f5c14..e0e769d4 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -79,8 +79,10 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Shader.BindProgram(); + SetFrontFace(); SetCullFace(); SetDepth(); + SetStencil(); SetAlphaBlending(); UploadTextures(Vmm, Keys); @@ -173,14 +175,8 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Shader.Bind(Key); } - int RawSX = ReadRegister(NvGpuEngine3dReg.ViewportScaleX); - int RawSY = ReadRegister(NvGpuEngine3dReg.ViewportScaleY); - - float SX = BitConverter.Int32BitsToSingle(RawSX); - float SY = BitConverter.Int32BitsToSingle(RawSY); - - float SignX = MathF.Sign(SX); - float SignY = MathF.Sign(SY); + float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX); + float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY); Gpu.Renderer.Shader.SetFlip(SignX, SignY); @@ -202,14 +198,145 @@ namespace Ryujinx.HLE.Gpu.Engines throw new ArgumentOutOfRangeException(nameof(Program)); } + private void SetFrontFace() + { + float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX); + float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY); + + 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; + } + } + + Gpu.Renderer.Rasterizer.SetFrontFace(FrontFace); + } + private void SetCullFace() { - //TODO. + bool Enable = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0; + + if (Enable) + { + Gpu.Renderer.Rasterizer.EnableCullFace(); + } + else + { + Gpu.Renderer.Rasterizer.DisableCullFace(); + } + + if (!Enable) + { + return; + } + + GalCullFace CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace); + + Gpu.Renderer.Rasterizer.SetCullFace(CullFace); } private void SetDepth() { - //TODO. + float ClearDepth = ReadRegisterFloat(NvGpuEngine3dReg.ClearDepth); + + Gpu.Renderer.Rasterizer.SetClearDepth(ClearDepth); + + bool Enable = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0; + + if (Enable) + { + Gpu.Renderer.Rasterizer.EnableDepthTest(); + } + 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); + + Gpu.Renderer.Rasterizer.SetClearStencil(ClearStencil); + + bool Enable = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0; + + if (Enable) + { + Gpu.Renderer.Rasterizer.EnableStencilTest(); + } + 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() @@ -549,6 +676,11 @@ namespace Ryujinx.HLE.Gpu.Engines ConstBuffers[Stage][Index].Size = ReadRegister(NvGpuEngine3dReg.ConstBufferSize); } + private float GetFlipSign(NvGpuEngine3dReg Reg) + { + return MathF.Sign(ReadRegisterFloat(Reg)); + } + private long MakeInt64From2xInt32(NvGpuEngine3dReg Reg) { return @@ -571,6 +703,11 @@ namespace Ryujinx.HLE.Gpu.Engines return Registers[(int)Reg]; } + private float ReadRegisterFloat(NvGpuEngine3dReg Reg) + { + return BitConverter.Int32BitsToSingle(ReadRegister(Reg)); + } + private void WriteRegister(NvGpuEngine3dReg Reg, int Value) { Registers[(int)Reg] = Value; diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs index 64866ce9..9eb2966d 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs @@ -14,6 +14,11 @@ namespace Ryujinx.HLE.Gpu.Engines ViewportTranslateZ = 0x285, VertexArrayFirst = 0x35d, VertexArrayCount = 0x35e, + ClearDepth = 0x364, + ClearStencil = 0x368, + StencilBackFuncRef = 0x3d5, + StencilBackMask = 0x3d6, + StencilBackFuncMask = 0x3d7, VertexAttribNFormat = 0x458, DepthTestEnable = 0x4b3, IBlendEnable = 0x4b9, @@ -27,9 +32,22 @@ namespace Ryujinx.HLE.Gpu.Engines BlendFuncDstAlpha = 0x4d6, BlendEnableMaster = 0x4d7, IBlendNEnable = 0x4d8, + StencilEnable = 0x4e0, + StencilFrontOpFail = 0x4e1, + StencilFrontOpZFail = 0x4e2, + StencilFrontOpZPass = 0x4e3, + StencilFrontFuncFunc = 0x4e4, + StencilFrontFuncRef = 0x4e5, + StencilFrontFuncMask = 0x4e6, + StencilFrontMask = 0x4e7, VertexArrayElemBase = 0x50d, TexHeaderPoolOffset = 0x55d, TexSamplerPoolOffset = 0x557, + StencilTwoSideEnable = 0x565, + StencilBackOpFail = 0x566, + StencilBackOpZFail = 0x567, + StencilBackOpZPass = 0x568, + StencilBackFuncFunc = 0x569, ShaderAddress = 0x582, VertexBeginGl = 0x586, IndexArrayAddress = 0x5f2, |
