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 }