diff options
author | gdkchan <gab.dark.100@gmail.com> | 2021-11-10 15:37:49 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-10 15:37:49 -0300 |
commit | 611bec6e44effa90554c95ed1fe4dd4812893947 (patch) | |
tree | 679e67c1253f88c3ceef9a98a6109ebede39e352 /Ryujinx.Graphics.OpenGL/Pipeline.cs | |
parent | bc00a251dd14f7cce4023a42bb76d23165755006 (diff) |
Implement DrawTexture functionality (#2747)
* Implement DrawTexture functionality
* Non-NVIDIA support
* Disable some features that should not affect draw texture (slow path)
* Remove space from shader source
* Match 2D engine names
* Fix resolution scale and add missing XML docs
* Disable transform feedback for draw texture fallback
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Pipeline.cs')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Pipeline.cs | 128 |
1 files changed, 115 insertions, 13 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index d0a509b4..aafc4db8 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -12,6 +12,8 @@ namespace Ryujinx.Graphics.OpenGL { class Pipeline : IPipeline, IDisposable { + private readonly DrawTextureEmulation _drawTexture; + internal ulong DrawCount { get; private set; } private Program _program; @@ -29,6 +31,12 @@ namespace Ryujinx.Graphics.OpenGL private int _stencilFrontMask; private bool _depthMask; + private bool _depthTestEnable; + private bool _stencilTestEnable; + private bool _cullEnable; + + private float[] _viewportArray = Array.Empty<float>(); + private double[] _depthRangeArray = Array.Empty<double>(); private int _boundDrawFramebuffer; private int _boundReadFramebuffer; @@ -47,6 +55,7 @@ namespace Ryujinx.Graphics.OpenGL private Vector4<float>[] _renderScale = new Vector4<float>[65]; private TextureBase _unit0Texture; + private Sampler _unit0Sampler; private FrontFaceDirection _frontFace; private ClipOrigin _clipOrigin; @@ -67,6 +76,7 @@ namespace Ryujinx.Graphics.OpenGL internal Pipeline() { + _drawTexture = new DrawTextureEmulation(); _rasterizerDiscard = false; _clipOrigin = ClipOrigin.LowerLeft; _clipDepthMode = ClipDepthMode.NegativeOneToOne; @@ -544,6 +554,91 @@ namespace Ryujinx.Graphics.OpenGL } } + public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) + { + if (texture is TextureView view && sampler is Sampler samp) + { + if (HwCapabilities.SupportsDrawTexture) + { + GL.NV.DrawTexture( + view.Handle, + samp.Handle, + dstRegion.X1, + dstRegion.Y1, + dstRegion.X2, + dstRegion.Y2, + 0, + srcRegion.X1 / view.Width, + srcRegion.Y1 / view.Height, + srcRegion.X2 / view.Width, + srcRegion.Y2 / view.Height); + } + else + { + static void Disable(EnableCap cap, bool enabled) + { + if (enabled) + { + GL.Disable(cap); + } + } + + static void Enable(EnableCap cap, bool enabled) + { + if (enabled) + { + GL.Enable(cap); + } + } + + Disable(EnableCap.CullFace, _cullEnable); + Disable(EnableCap.StencilTest, _stencilTestEnable); + Disable(EnableCap.DepthTest, _depthTestEnable); + + if (_depthMask) + { + GL.DepthMask(false); + } + + if (_tfEnabled) + { + GL.EndTransformFeedback(); + } + + _drawTexture.Draw( + view, + samp, + dstRegion.X1, + dstRegion.Y1, + dstRegion.X2, + dstRegion.Y2, + srcRegion.X1 / view.Width, + srcRegion.Y1 / view.Height, + srcRegion.X2 / view.Width, + srcRegion.Y2 / view.Height); + + _program?.Bind(); + _unit0Sampler?.Bind(0); + + GL.ViewportArray(0, 1, _viewportArray); + + Enable(EnableCap.CullFace, _cullEnable); + Enable(EnableCap.StencilTest, _stencilTestEnable); + Enable(EnableCap.DepthTest, _depthTestEnable); + + if (_depthMask) + { + GL.DepthMask(true); + } + + if (_tfEnabled) + { + GL.BeginTransformFeedback(_tfTopology); + } + } + } + } + public void EndTransformFeedback() { GL.EndTransformFeedback(); @@ -754,10 +849,13 @@ namespace Ryujinx.Graphics.OpenGL GL.DepthMask(depthTest.WriteEnable); _depthMask = depthTest.WriteEnable; + _depthTestEnable = depthTest.TestEnable; } public void SetFaceCulling(bool enable, Face face) { + _cullEnable = enable; + if (!enable) { GL.Disable(EnableCap.CullFace); @@ -994,7 +1092,14 @@ namespace Ryujinx.Graphics.OpenGL return; } - ((Sampler)sampler).Bind(binding); + Sampler samp = (Sampler)sampler; + + if (binding == 0) + { + _unit0Sampler = samp; + } + + samp.Bind(binding); } public void SetScissor(int index, bool enable, int x, int y, int width, int height) @@ -1023,6 +1128,8 @@ namespace Ryujinx.Graphics.OpenGL public void SetStencilTest(StencilTestDescriptor stencilTest) { + _stencilTestEnable = stencilTest.TestEnable; + if (!stencilTest.TestEnable) { GL.Disable(EnableCap.StencilTest); @@ -1152,9 +1259,11 @@ namespace Ryujinx.Graphics.OpenGL public void SetViewports(int first, ReadOnlySpan<Viewport> viewports) { - float[] viewportArray = new float[viewports.Length * 4]; + Array.Resize(ref _viewportArray, viewports.Length * 4); + Array.Resize(ref _depthRangeArray, viewports.Length * 2); - double[] depthRangeArray = new double[viewports.Length * 2]; + float[] viewportArray = _viewportArray; + double[] depthRangeArray = _depthRangeArray; for (int index = 0; index < viewports.Length; index++) { @@ -1186,7 +1295,6 @@ namespace Ryujinx.Graphics.OpenGL SetOrigin(flipY ? ClipOrigin.UpperLeft : ClipOrigin.LowerLeft); GL.ViewportArray(first, viewports.Length, viewportArray); - GL.DepthRangeArray(first, viewports.Length, depthRangeArray); } @@ -1307,10 +1415,7 @@ namespace Ryujinx.Graphics.OpenGL private void PrepareForDispatch() { - if (_unit0Texture != null) - { - _unit0Texture.Bind(0); - } + _unit0Texture?.Bind(0); } private void PreDraw() @@ -1318,11 +1423,7 @@ namespace Ryujinx.Graphics.OpenGL DrawCount++; _vertexArray.Validate(); - - if (_unit0Texture != null) - { - _unit0Texture.Bind(0); - } + _unit0Texture?.Bind(0); } private void PostDraw() @@ -1438,6 +1539,7 @@ namespace Ryujinx.Graphics.OpenGL _activeConditionalRender?.ReleaseHostAccess(); _framebuffer?.Dispose(); _vertexArray?.Dispose(); + _drawTexture.Dispose(); } } } |