diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2020-07-07 03:41:07 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-07 04:41:07 +0200 |
| commit | 484eb645ae0611f60fae845ed011ed6115352e06 (patch) | |
| tree | b15972f04dae0b1b6c644cbbbdfcd98856adee15 /Ryujinx.Graphics.OpenGL/Pipeline.cs | |
| parent | 43b78ae157eed5c9436dc19a6d498655891202d8 (diff) | |
Implement Zero-Configuration Resolution Scaling (#1365)
* Initial implementation of Render Target Scaling
Works with most games I have. No GUI option right now, it is hardcoded.
Missing handling for texelFetch operation.
* Realtime Configuration, refactoring.
* texelFetch scaling on fragment shader (WIP)
* Improve Shader-Side changes.
* Fix potential crash when no color/depth bound
* Workaround random uses of textures in compute.
This was blacklisting textures in a few games despite causing no bugs. Will eventually add full support so this doesn't break anything.
* Fix scales oscillating when changing between non-native scales.
* Scaled textures on compute, cleanup, lazier uniform update.
* Cleanup.
* Fix stupidity
* Address Thog Feedback.
* Cover most of GDK's feedback (two comments remain)
* Fix bad rename
* Move IsDepthStencil to FormatExtensions, add docs.
* Fix default config, square texture detection.
* Three final fixes:
- Nearest copy when texture is integer format.
- Texture2D -> Texture3D copy correctly blacklists the texture before trying an unscaled copy (caused driver error)
- Discount small textures.
* Remove scale threshold.
Not needed right now - we'll see if we run into problems.
* All CPU modification blacklists scale.
* Fix comment.
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Pipeline.cs')
| -rw-r--r-- | Ryujinx.Graphics.OpenGL/Pipeline.cs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 6c511e09..62e5394e 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -31,7 +31,12 @@ namespace Ryujinx.Graphics.OpenGL private int _boundDrawFramebuffer; private int _boundReadFramebuffer; + private float[] _fpRenderScale = new float[33]; + private float[] _cpRenderScale = new float[32]; + private TextureBase _unit0Texture; + private TextureBase _rtColor0Texture; + private TextureBase _rtDepthTexture; private ClipOrigin _clipOrigin; private ClipDepthMode _clipDepthMode; @@ -54,6 +59,16 @@ namespace Ryujinx.Graphics.OpenGL { _componentMasks[index] = 0xf; } + + for (int index = 0; index < _fpRenderScale.Length; index++) + { + _fpRenderScale[index] = 1f; + } + + for (int index = 0; index < _cpRenderScale.Length; index++) + { + _cpRenderScale[index] = 1f; + } } public void Barrier() @@ -685,6 +700,8 @@ namespace Ryujinx.Graphics.OpenGL { _program = (Program)program; _program.Bind(); + + SetRenderTargetScale(_fpRenderScale[0]); } public void SetRasterizerDiscard(bool discard) @@ -701,6 +718,16 @@ namespace Ryujinx.Graphics.OpenGL _rasterizerDiscard = discard; } + public void SetRenderTargetScale(float scale) + { + _fpRenderScale[0] = scale; + + if (_program != null && _program.FragmentRenderScaleUniform != -1) + { + GL.Uniform1(_program.FragmentRenderScaleUniform, 1, _fpRenderScale); // Just the first element. + } + } + public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks) { for (int index = 0; index < componentMasks.Length; index++) @@ -715,6 +742,9 @@ namespace Ryujinx.Graphics.OpenGL { EnsureFramebuffer(); + _rtColor0Texture = (TextureBase)colors[0]; + _rtDepthTexture = (TextureBase)depthStencil; + for (int index = 0; index < colors.Length; index++) { TextureView color = (TextureView)colors[index]; @@ -826,6 +856,37 @@ namespace Ryujinx.Graphics.OpenGL { ((TextureBase)texture).Bind(unit); } + + // Update scale factor for bound textures. + + switch (stage) + { + case ShaderStage.Fragment: + if (_program.FragmentRenderScaleUniform != -1) + { + // Only update and send sampled texture scales if the shader uses them. + bool interpolate = false; + float scale = texture.ScaleFactor; + + if (scale != 1) + { + TextureBase activeTarget = _rtColor0Texture ?? _rtDepthTexture; + + if (activeTarget != null && activeTarget.Width / (float)texture.Width == activeTarget.Height / (float)texture.Height) + { + // If the texture's size is a multiple of the sampler size, enable interpolation using gl_FragCoord. (helps "invent" new integer values between scaled pixels) + interpolate = true; + } + } + + _fpRenderScale[index + 1] = interpolate ? -scale : scale; + } + break; + + case ShaderStage.Compute: + _cpRenderScale[index] = texture.ScaleFactor; + break; + } } } @@ -1089,5 +1150,28 @@ namespace Ryujinx.Graphics.OpenGL _framebuffer?.Dispose(); _vertexArray?.Dispose(); } + + public void UpdateRenderScale(ShaderStage stage, int textureCount) + { + if (_program != null) + { + switch (stage) + { + case ShaderStage.Fragment: + if (_program.FragmentRenderScaleUniform != -1) + { + GL.Uniform1(_program.FragmentRenderScaleUniform, textureCount + 1, _fpRenderScale); + } + break; + + case ShaderStage.Compute: + if (_program.ComputeRenderScaleUniform != -1) + { + GL.Uniform1(_program.ComputeRenderScaleUniform, textureCount, _cpRenderScale); + } + break; + } + } + } } } |
