/ src / Ryujinx.Graphics.OpenGL / Effects / FxaaPostProcessingEffect.cs
FxaaPostProcessingEffect.cs
 1  using OpenTK.Graphics.OpenGL;
 2  using Ryujinx.Common;
 3  using Ryujinx.Graphics.OpenGL.Image;
 4  
 5  namespace Ryujinx.Graphics.OpenGL.Effects
 6  {
 7      internal class FxaaPostProcessingEffect : IPostProcessingEffect
 8      {
 9          private readonly OpenGLRenderer _renderer;
10          private int _resolutionUniform;
11          private int _inputUniform;
12          private int _outputUniform;
13          private int _shaderProgram;
14          private TextureStorage _textureStorage;
15  
16          public FxaaPostProcessingEffect(OpenGLRenderer renderer)
17          {
18              Initialize();
19  
20              _renderer = renderer;
21          }
22  
23          public void Dispose()
24          {
25              if (_shaderProgram != 0)
26              {
27                  GL.DeleteProgram(_shaderProgram);
28                  _textureStorage?.Dispose();
29              }
30          }
31  
32          private void Initialize()
33          {
34              _shaderProgram = ShaderHelper.CompileProgram(EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
35  
36              _resolutionUniform = GL.GetUniformLocation(_shaderProgram, "invResolution");
37              _inputUniform = GL.GetUniformLocation(_shaderProgram, "inputTexture");
38              _outputUniform = GL.GetUniformLocation(_shaderProgram, "imgOutput");
39          }
40  
41          public TextureView Run(TextureView view, int width, int height)
42          {
43              if (_textureStorage == null || _textureStorage.Info.Width != view.Width || _textureStorage.Info.Height != view.Height)
44              {
45                  _textureStorage?.Dispose();
46                  _textureStorage = new TextureStorage(_renderer, view.Info);
47                  _textureStorage.CreateDefaultView();
48              }
49  
50              var textureView = _textureStorage.CreateView(view.Info, 0, 0) as TextureView;
51  
52              int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
53              int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
54              GL.ActiveTexture(TextureUnit.Texture0);
55              int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
56  
57              GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
58              GL.UseProgram(_shaderProgram);
59  
60              var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
61              var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
62  
63              view.Bind(0);
64              GL.Uniform1(_inputUniform, 0);
65              GL.Uniform1(_outputUniform, 0);
66              GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
67              GL.DispatchCompute(dispatchX, dispatchY, 1);
68              GL.UseProgram(previousProgram);
69              GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
70  
71              (_renderer.Pipeline as Pipeline).RestoreImages1And2();
72  
73              GL.ActiveTexture(TextureUnit.Texture0);
74              GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
75  
76              GL.ActiveTexture((TextureUnit)previousUnit);
77  
78              return textureView;
79          }
80      }
81  }