AreaScalingFilter.cs
1 using OpenTK.Graphics.OpenGL; 2 using Ryujinx.Common; 3 using Ryujinx.Graphics.GAL; 4 using Ryujinx.Graphics.OpenGL.Image; 5 using System; 6 using static Ryujinx.Graphics.OpenGL.Effects.ShaderHelper; 7 8 namespace Ryujinx.Graphics.OpenGL.Effects 9 { 10 internal class AreaScalingFilter : IScalingFilter 11 { 12 private readonly OpenGLRenderer _renderer; 13 private int _inputUniform; 14 private int _outputUniform; 15 private int _srcX0Uniform; 16 private int _srcX1Uniform; 17 private int _srcY0Uniform; 18 private int _scalingShaderProgram; 19 private int _srcY1Uniform; 20 private int _dstX0Uniform; 21 private int _dstX1Uniform; 22 private int _dstY0Uniform; 23 private int _dstY1Uniform; 24 25 public float Level { get; set; } 26 27 public AreaScalingFilter(OpenGLRenderer renderer) 28 { 29 Initialize(); 30 31 _renderer = renderer; 32 } 33 34 public void Dispose() 35 { 36 if (_scalingShaderProgram != 0) 37 { 38 GL.DeleteProgram(_scalingShaderProgram); 39 } 40 } 41 42 private void Initialize() 43 { 44 var scalingShader = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/area_scaling.glsl"); 45 46 _scalingShaderProgram = CompileProgram(scalingShader, ShaderType.ComputeShader); 47 48 _inputUniform = GL.GetUniformLocation(_scalingShaderProgram, "Source"); 49 _outputUniform = GL.GetUniformLocation(_scalingShaderProgram, "imgOutput"); 50 51 _srcX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX0"); 52 _srcX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX1"); 53 _srcY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY0"); 54 _srcY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY1"); 55 _dstX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX0"); 56 _dstX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX1"); 57 _dstY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY0"); 58 _dstY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY1"); 59 } 60 61 public void Run( 62 TextureView view, 63 TextureView destinationTexture, 64 int width, 65 int height, 66 Extents2D source, 67 Extents2D destination) 68 { 69 int previousProgram = GL.GetInteger(GetPName.CurrentProgram); 70 int previousUnit = GL.GetInteger(GetPName.ActiveTexture); 71 GL.ActiveTexture(TextureUnit.Texture0); 72 int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D); 73 74 GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); 75 76 int threadGroupWorkRegionDim = 16; 77 int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; 78 int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; 79 80 // Scaling pass 81 GL.UseProgram(_scalingShaderProgram); 82 view.Bind(0); 83 GL.Uniform1(_inputUniform, 0); 84 GL.Uniform1(_outputUniform, 0); 85 GL.Uniform1(_srcX0Uniform, (float)source.X1); 86 GL.Uniform1(_srcX1Uniform, (float)source.X2); 87 GL.Uniform1(_srcY0Uniform, (float)source.Y1); 88 GL.Uniform1(_srcY1Uniform, (float)source.Y2); 89 GL.Uniform1(_dstX0Uniform, (float)destination.X1); 90 GL.Uniform1(_dstX1Uniform, (float)destination.X2); 91 GL.Uniform1(_dstY0Uniform, (float)destination.Y1); 92 GL.Uniform1(_dstY1Uniform, (float)destination.Y2); 93 GL.DispatchCompute(dispatchX, dispatchY, 1); 94 95 GL.UseProgram(previousProgram); 96 GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); 97 98 (_renderer.Pipeline as Pipeline).RestoreImages1And2(); 99 100 GL.ActiveTexture(TextureUnit.Texture0); 101 GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); 102 103 GL.ActiveTexture((TextureUnit)previousUnit); 104 } 105 } 106 }