aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs
diff options
context:
space:
mode:
authorZenoArrows <129334871+ZenoArrows@users.noreply.github.com>2024-09-17 20:30:50 +0200
committerGitHub <noreply@github.com>2024-09-17 15:30:50 -0300
commitf39e89ece79436f5058bb58d50a1a4dcd6823f4e (patch)
tree079cd6cd332b1f2691bb13f587789e191ddf2c6d /src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs
parentcf77c011e4f90efd93509c3852350c48f2597344 (diff)
Add area sampling scaler to allow for super-sampled anti-aliasing. (#7304)
* Add area sampling scaler to allow for super-sampled anti-aliasing. * Area scaling filter doesn't have a scaling level. * Add further clarification to the tooltip on how to achieve supersampling. * ShaderHelper: Merge the two CompileProgram functions. * Convert tabs to spaces in area scaling shaders * Fixup Vulkan and OpenGL project files. * AreaScaling: Replace texture() by texelFetch() and use integer vectors. No functional difference, but it cleans up the code a bit. * AreaScaling: Delete unused sharpening level member. Also rename _scale to _sharpeningLevel for clarity and consistency. * AreaScaling: Delete unused scaleX/scaleY uniforms. * AreaScaling: Force the alpha to 1 when storing the pixel. * AreaScaling: Remove left-over sharpening buffer.
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs')
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs b/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs
new file mode 100644
index 00000000..9b19f2f2
--- /dev/null
+++ b/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs
@@ -0,0 +1,106 @@
+using OpenTK.Graphics.OpenGL;
+using Ryujinx.Common;
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.OpenGL.Image;
+using System;
+using static Ryujinx.Graphics.OpenGL.Effects.ShaderHelper;
+
+namespace Ryujinx.Graphics.OpenGL.Effects
+{
+ internal class AreaScalingFilter : IScalingFilter
+ {
+ private readonly OpenGLRenderer _renderer;
+ private int _inputUniform;
+ private int _outputUniform;
+ private int _srcX0Uniform;
+ private int _srcX1Uniform;
+ private int _srcY0Uniform;
+ private int _scalingShaderProgram;
+ private int _srcY1Uniform;
+ private int _dstX0Uniform;
+ private int _dstX1Uniform;
+ private int _dstY0Uniform;
+ private int _dstY1Uniform;
+
+ public float Level { get; set; }
+
+ public AreaScalingFilter(OpenGLRenderer renderer)
+ {
+ Initialize();
+
+ _renderer = renderer;
+ }
+
+ public void Dispose()
+ {
+ if (_scalingShaderProgram != 0)
+ {
+ GL.DeleteProgram(_scalingShaderProgram);
+ }
+ }
+
+ private void Initialize()
+ {
+ var scalingShader = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/area_scaling.glsl");
+
+ _scalingShaderProgram = CompileProgram(scalingShader, ShaderType.ComputeShader);
+
+ _inputUniform = GL.GetUniformLocation(_scalingShaderProgram, "Source");
+ _outputUniform = GL.GetUniformLocation(_scalingShaderProgram, "imgOutput");
+
+ _srcX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX0");
+ _srcX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX1");
+ _srcY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY0");
+ _srcY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY1");
+ _dstX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX0");
+ _dstX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX1");
+ _dstY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY0");
+ _dstY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY1");
+ }
+
+ public void Run(
+ TextureView view,
+ TextureView destinationTexture,
+ int width,
+ int height,
+ Extents2D source,
+ Extents2D destination)
+ {
+ int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
+ int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
+ GL.ActiveTexture(TextureUnit.Texture0);
+ int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
+
+ GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
+
+ int threadGroupWorkRegionDim = 16;
+ int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
+ int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
+
+ // Scaling pass
+ GL.UseProgram(_scalingShaderProgram);
+ view.Bind(0);
+ GL.Uniform1(_inputUniform, 0);
+ GL.Uniform1(_outputUniform, 0);
+ GL.Uniform1(_srcX0Uniform, (float)source.X1);
+ GL.Uniform1(_srcX1Uniform, (float)source.X2);
+ GL.Uniform1(_srcY0Uniform, (float)source.Y1);
+ GL.Uniform1(_srcY1Uniform, (float)source.Y2);
+ GL.Uniform1(_dstX0Uniform, (float)destination.X1);
+ GL.Uniform1(_dstX1Uniform, (float)destination.X2);
+ GL.Uniform1(_dstY0Uniform, (float)destination.Y1);
+ GL.Uniform1(_dstY1Uniform, (float)destination.Y2);
+ GL.DispatchCompute(dispatchX, dispatchY, 1);
+
+ GL.UseProgram(previousProgram);
+ GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
+
+ (_renderer.Pipeline as Pipeline).RestoreImages1And2();
+
+ GL.ActiveTexture(TextureUnit.Texture0);
+ GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
+
+ GL.ActiveTexture((TextureUnit)previousUnit);
+ }
+ }
+}