diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs index 6ee6c93e..7b0f17d1 100644 --- a/Ryujinx.Graphics/Gal/GalPipelineState.cs +++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs @@ -34,6 +34,7 @@ public GalCullFace CullFace; public bool DepthTestEnabled; + public bool DepthWriteEnabled; public GalComparisonOp DepthFunc; public bool StencilTestEnabled; diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index cf856a15..20e92ff2 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -85,6 +85,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL CullFace = GalCullFace.Back, DepthTestEnabled = false, + DepthWriteEnabled = true, DepthFunc = GalComparisonOp.Less, StencilTestEnabled = false, @@ -138,19 +139,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved - //if (New.FrontFace != O.FrontFace) + //if (New.FrontFace != Old.FrontFace) //{ // GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace)); //} - //if (New.CullFaceEnabled != O.CullFaceEnabled) + //if (New.CullFaceEnabled != Old.CullFaceEnabled) //{ // Enable(EnableCap.CullFace, New.CullFaceEnabled); //} //if (New.CullFaceEnabled) //{ - // if (New.CullFace != O.CullFace) + // if (New.CullFace != Old.CullFace) // { // GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace)); // } @@ -161,6 +162,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL Enable(EnableCap.DepthTest, New.DepthTestEnabled); } + if (New.DepthWriteEnabled != Old.DepthWriteEnabled) + { + Rasterizer.DepthWriteEnabled = New.DepthWriteEnabled; + + GL.DepthMask(New.DepthWriteEnabled); + } + if (New.DepthTestEnabled) { if (New.DepthFunc != Old.DepthFunc) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index ebfba63d..a74aee07 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -5,6 +5,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLRasterizer : IGalRasterizer { + public bool DepthWriteEnabled { set; private get; } + private int[] VertexBuffers; private OGLCachedResource VboCache; @@ -28,6 +30,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL IboCache = new OGLCachedResource(GL.DeleteBuffer); IndexBuffer = new IbInfo(); + + DepthWriteEnabled = true; } public void LockCaches() @@ -49,6 +53,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL float Depth, int Stencil) { + //OpenGL needs glDepthMask to be enabled to clear it + if (!DepthWriteEnabled) + { + GL.DepthMask(true); + } + GL.ColorMask( Flags.HasFlag(GalClearBufferFlags.ColorRed), Flags.HasFlag(GalClearBufferFlags.ColorGreen), @@ -68,6 +78,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL } GL.ColorMask(true, true, true, true); + + if (!DepthWriteEnabled) + { + GL.DepthMask(false); + } } public bool IsVboCached(long Key, long DataSize) diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs index a1d0ec80..b19f3063 100644 --- a/Ryujinx.Graphics/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/NvGpuEngine3d.cs @@ -209,7 +209,7 @@ namespace Ryujinx.Graphics private void SetFrameBuffer(GalPipelineState State) { - State.FramebufferSrgb = (ReadRegister(NvGpuEngine3dReg.FrameBufferSrgb) & 1) != 0; + State.FramebufferSrgb = ReadRegisterBool(NvGpuEngine3dReg.FrameBufferSrgb); State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX); State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY); @@ -227,7 +227,7 @@ namespace Ryujinx.Graphics GalMemoryLayout Layout = (GalMemoryLayout)((BlockDim >> 12) & 1); //? - bool ZetaEnable = (ReadRegister(NvGpuEngine3dReg.ZetaEnable) & 1) != 0; + bool ZetaEnable = ReadRegisterBool(NvGpuEngine3dReg.ZetaEnable); if (VA == 0 || ZetaFormat == 0 || !ZetaEnable) { @@ -352,7 +352,7 @@ namespace Ryujinx.Graphics private void SetCullFace(GalPipelineState State) { - State.CullFaceEnabled = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0; + State.CullFaceEnabled = ReadRegisterBool(NvGpuEngine3dReg.CullFaceEnable); if (State.CullFaceEnabled) { @@ -362,7 +362,9 @@ namespace Ryujinx.Graphics private void SetDepth(GalPipelineState State) { - State.DepthTestEnabled = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0; + State.DepthTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthTestEnable); + + State.DepthWriteEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthWriteEnable); if (State.DepthTestEnabled) { @@ -372,7 +374,7 @@ namespace Ryujinx.Graphics private void SetStencil(GalPipelineState State) { - State.StencilTestEnabled = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0; + State.StencilTestEnabled = ReadRegisterBool(NvGpuEngine3dReg.StencilEnable); if (State.StencilTestEnabled) { @@ -397,11 +399,11 @@ namespace Ryujinx.Graphics private void SetAlphaBlending(GalPipelineState State) { //TODO: Support independent blend properly. - State.BlendEnabled = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0; + State.BlendEnabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable); if (State.BlendEnabled) { - State.BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0; + State.BlendSeparateAlpha = ReadRegisterBool(NvGpuEngine3dReg.IBlendNSeparateAlpha); State.BlendEquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb); State.BlendFuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb); @@ -414,7 +416,7 @@ namespace Ryujinx.Graphics private void SetPrimitiveRestart(GalPipelineState State) { - State.PrimitiveRestartEnabled = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0; + State.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable); if (State.PrimitiveRestartEnabled) { @@ -424,7 +426,7 @@ namespace Ryujinx.Graphics private void SetRenderTargets() { - bool SeparateFragData = (ReadRegister(NvGpuEngine3dReg.RTSeparateFragData) & 1) != 0; + bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData); if (SeparateFragData) { @@ -635,7 +637,7 @@ namespace Ryujinx.Graphics int VertexDivisor = ReadRegister(NvGpuEngine3dReg.VertexArrayNDivisor + Index * 4); - bool Instanced = (ReadRegister(NvGpuEngine3dReg.VertexArrayNInstance + Index) & 1) != 0; + bool Instanced = ReadRegisterBool(NvGpuEngine3dReg.VertexArrayNInstance + Index); int Stride = Control & 0xfff; @@ -845,6 +847,11 @@ namespace Ryujinx.Graphics return BitConverter.Int32BitsToSingle(ReadRegister(Reg)); } + private bool ReadRegisterBool(NvGpuEngine3dReg Reg) + { + return (ReadRegister(Reg) & 1) != 0; + } + private void WriteRegister(NvGpuEngine3dReg Reg, int Value) { Registers[(int)Reg] = Value; diff --git a/Ryujinx.Graphics/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/NvGpuEngine3dReg.cs index 3abcf6f5..418e5b6b 100644 --- a/Ryujinx.Graphics/NvGpuEngine3dReg.cs +++ b/Ryujinx.Graphics/NvGpuEngine3dReg.cs @@ -35,6 +35,7 @@ namespace Ryujinx.Graphics ZetaArrayMode = 0x48c, DepthTestEnable = 0x4b3, IBlendEnable = 0x4b9, + DepthWriteEnable = 0x4ba, DepthTestFunction = 0x4c3, BlendSeparateAlpha = 0x4cf, BlendEquationRgb = 0x4d0, diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs index 7d3dde49..18a179fb 100644 --- a/Ryujinx.Graphics/Texture/ImageUtils.cs +++ b/Ryujinx.Graphics/Texture/ImageUtils.cs @@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Texture { GalTextureFormat.G8R8, GalImageFormat.G8R8 | Snorm | Unorm | Sint | Uint }, { GalTextureFormat.R16, GalImageFormat.R16 | Snorm | Unorm | Sint | Uint | Sfloat }, { GalTextureFormat.R8, GalImageFormat.R8 | Snorm | Unorm | Sint | Uint }, - { GalTextureFormat.R16G16, GalImageFormat.R16G16 | Snorm }, + { GalTextureFormat.R16G16, GalImageFormat.R16G16 | Snorm | Sfloat }, { GalTextureFormat.R32, GalImageFormat.R32 | Sint | Uint | Sfloat }, { GalTextureFormat.A4B4G4R4, GalImageFormat.A4B4G4R4 | Unorm }, { GalTextureFormat.A1B5G5R5, GalImageFormat.A1R5G5B5 | Unorm },