aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-07-23 11:21:05 -0300
committerAc_K <Acoustik666@gmail.com>2018-07-23 16:21:05 +0200
commit1344a47c774ab2b7491c59e363e04a499fa432f3 (patch)
treed375e6573a0f314d49e9c867a10232bfce45a449
parented29982f9b0414d42fd75acdcf2182d14174fe90 (diff)
Blit framebuffer without shaders (#229)
* Blit framebuffer without shaders * De-hardcode native size values * Adapt to dehardcoded framebuffers and address feedback * Remove framebuffer rebinding
-rw-r--r--Ryujinx.Graphics/Gal/IGalFrameBuffer.cs2
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl13
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl28
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs278
-rw-r--r--Ryujinx.Graphics/Ryujinx.Graphics.csproj9
-rw-r--r--Ryujinx.HLE/OsHle/Services/Vi/NvFlinger.cs53
6 files changed, 98 insertions, 285 deletions
diff --git a/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs b/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
index 1f62bdb3..c0287ef8 100644
--- a/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
+++ b/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
@@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Gal
void Set(byte[] Data, int Width, int Height);
- void SetTransform(float SX, float SY, float Rotate, float TX, float TY);
+ void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom);
void SetWindowSize(int Width, int Height);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl
deleted file mode 100644
index 74e33bd7..00000000
--- a/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 330 core
-
-precision highp float;
-
-uniform sampler2D tex;
-
-in vec2 tex_coord;
-
-out vec4 out_frag_color;
-
-void main(void) {
- out_frag_color = texture(tex, tex_coord);
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl
deleted file mode 100644
index 35d560c0..00000000
--- a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl
+++ /dev/null
@@ -1,28 +0,0 @@
-#version 330 core
-
-precision highp float;
-
-uniform mat2 transform;
-uniform vec2 window_size;
-uniform vec2 offset;
-
-layout(location = 0) in vec2 in_position;
-layout(location = 1) in vec2 in_tex_coord;
-
-out vec2 tex_coord;
-
-// Have a fixed aspect ratio, fit the image within the available space.
-vec2 get_scale_ratio(void) {
- vec2 native_size = vec2(1280, 720);
- vec2 ratio = vec2(
- (window_size.y * native_size.x) / (native_size.y * window_size.x),
- (window_size.x * native_size.y) / (native_size.x * window_size.y)
- );
- return min(ratio, 1);
-}
-
-void main(void) {
- tex_coord = in_tex_coord;
- vec2 t_pos = (transform * in_position) + offset;
- gl_Position = vec4(t_pos * get_scale_ratio(), 0, 1);
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
index cd52762c..30a3de64 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
@@ -32,48 +32,45 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public int RbHandle { get; private set; }
public int TexHandle { get; private set; }
- public FrameBuffer(int Width, int Height)
+ public FrameBuffer(int Width, int Height, bool HasRenderBuffer)
{
this.Width = Width;
this.Height = Height;
Handle = GL.GenFramebuffer();
- RbHandle = GL.GenRenderbuffer();
TexHandle = GL.GenTexture();
+
+ if (HasRenderBuffer)
+ {
+ RbHandle = GL.GenRenderbuffer();
+ }
}
}
- private struct ShaderProgram
- {
- public int Handle;
- public int VpHandle;
- public int FpHandle;
- }
+ private const int NativeWidth = 1280;
+ private const int NativeHeight = 720;
private Dictionary<long, FrameBuffer> Fbs;
- private ShaderProgram Shader;
-
private Rect Viewport;
private Rect Window;
- private bool IsInitialized;
+ private FrameBuffer CurrFb;
+ private FrameBuffer CurrReadFb;
- private int RawFbTexWidth;
- private int RawFbTexHeight;
- private int RawFbTexHandle;
+ private FrameBuffer RawFb;
- private int CurrFbHandle;
- private int CurrTexHandle;
+ private bool FlipX;
+ private bool FlipY;
- private int VaoHandle;
- private int VboHandle;
+ private int CropTop;
+ private int CropLeft;
+ private int CropRight;
+ private int CropBottom;
public OGLFrameBuffer()
{
Fbs = new Dictionary<long, FrameBuffer>();
-
- Shader = new ShaderProgram();
}
public void Create(long Key, int Width, int Height)
@@ -92,7 +89,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return;
}
- Fb = new FrameBuffer(Width, Height);
+ Fb = new FrameBuffer(Width, Height, true);
SetupTexture(Fb.TexHandle, Width, Height);
@@ -129,7 +126,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
- CurrFbHandle = Fb.Handle;
+ CurrFb = Fb;
}
}
@@ -147,75 +144,50 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
{
- CurrTexHandle = Fb.TexHandle;
+ CurrReadFb = Fb;
}
}
public void Set(byte[] Data, int Width, int Height)
{
- if (RawFbTexHandle == 0)
+ if (RawFb == null)
{
- RawFbTexHandle = GL.GenTexture();
+ CreateRawFb(Width, Height);
}
- if (RawFbTexWidth != Width ||
- RawFbTexHeight != Height)
+ if (RawFb.Width != Width ||
+ RawFb.Height != Height)
{
- SetupTexture(RawFbTexHandle, Width, Height);
+ SetupTexture(RawFb.TexHandle, Width, Height);
- RawFbTexWidth = Width;
- RawFbTexHeight = Height;
+ RawFb.Width = Width;
+ RawFb.Height = Height;
}
GL.ActiveTexture(TextureUnit.Texture0);
- GL.BindTexture(TextureTarget.Texture2D, RawFbTexHandle);
+ GL.BindTexture(TextureTarget.Texture2D, RawFb.TexHandle);
(PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, Format, Type, Data);
- CurrTexHandle = RawFbTexHandle;
+ CurrReadFb = RawFb;
}
- public void SetTransform(float SX, float SY, float Rotate, float TX, float TY)
+ public void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom)
{
- EnsureInitialized();
-
- Matrix2 Transform;
-
- Transform = Matrix2.CreateScale(SX, SY);
- Transform *= Matrix2.CreateRotation(Rotate);
-
- Vector2 Offs = new Vector2(TX, TY);
+ this.FlipX = FlipX;
+ this.FlipY = FlipY;
- int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
-
- GL.UseProgram(Shader.Handle);
-
- int TransformUniformLocation = GL.GetUniformLocation(Shader.Handle, "transform");
-
- GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);
-
- int OffsetUniformLocation = GL.GetUniformLocation(Shader.Handle, "offset");
-
- GL.Uniform2(OffsetUniformLocation, ref Offs);
-
- GL.UseProgram(CurrentProgram);
+ CropTop = Top;
+ CropLeft = Left;
+ CropRight = Right;
+ CropBottom = Bottom;
}
public void SetWindowSize(int Width, int Height)
{
- int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
-
- GL.UseProgram(Shader.Handle);
-
- int WindowSizeUniformLocation = GL.GetUniformLocation(Shader.Handle, "window_size");
-
- GL.Uniform2(WindowSizeUniformLocation, new Vector2(Width, Height));
-
- GL.UseProgram(CurrentProgram);
-
Window = new Rect(0, 0, Width, Height);
}
@@ -237,72 +209,59 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Render()
{
- if (CurrTexHandle != 0)
+ if (CurrReadFb != null)
{
- EnsureInitialized();
-
- //bool CullFaceEnable = GL.IsEnabled(EnableCap.CullFace);
-
- bool DepthTestEnable = GL.IsEnabled(EnableCap.DepthTest);
-
- bool StencilTestEnable = GL.IsEnabled(EnableCap.StencilTest);
-
- bool AlphaBlendEnable = GL.IsEnabled(EnableCap.Blend);
+ int SrcX0, SrcX1, SrcY0, SrcY1;
- //GL.Disable(EnableCap.CullFace);
+ if (CropLeft == 0 && CropRight == 0)
+ {
+ SrcX0 = 0;
+ SrcX1 = CurrReadFb.Width;
+ }
+ else
+ {
+ SrcX0 = CropLeft;
+ SrcX1 = CropRight;
+ }
- GL.Disable(EnableCap.DepthTest);
+ if (CropTop == 0 && CropBottom == 0)
+ {
+ SrcY0 = 0;
+ SrcY1 = CurrReadFb.Height;
+ }
+ else
+ {
+ SrcY0 = CropTop;
+ SrcY1 = CropBottom;
+ }
- GL.Disable(EnableCap.StencilTest);
+ float RatioX = MathF.Min(1f, (Window.Height * (float)NativeWidth) / ((float)NativeHeight * Window.Width));
+ float RatioY = MathF.Min(1f, (Window.Width * (float)NativeHeight) / ((float)NativeWidth * Window.Height));
- GL.Disable(EnableCap.Blend);
+ int DstWidth = (int)(Window.Width * RatioX);
+ int DstHeight = (int)(Window.Height * RatioY);
- GL.ActiveTexture(TextureUnit.Texture0);
+ int DstPaddingX = (Window.Width - DstWidth) / 2;
+ int DstPaddingY = (Window.Height - DstHeight) / 2;
- GL.BindTexture(TextureTarget.Texture2D, CurrTexHandle);
+ int DstX0 = FlipX ? Window.Width - DstPaddingX : DstPaddingX;
+ int DstX1 = FlipX ? DstPaddingX : Window.Width - DstPaddingX;
- int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
+ int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
+ int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
- SetViewport(Window);
-
- GL.Clear(
- ClearBufferMask.ColorBufferBit |
- ClearBufferMask.DepthBufferBit);
-
- GL.BindVertexArray(VaoHandle);
+ GL.Viewport(0, 0, Window.Width, Window.Height);
- GL.UseProgram(Shader.Handle);
+ GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, CurrReadFb.Handle);
- GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
- //Restore the original state.
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, CurrFbHandle);
-
- GL.UseProgram(CurrentProgram);
-
- //if (CullFaceEnable)
- //{
- // GL.Enable(EnableCap.CullFace);
- //}
-
- if (DepthTestEnable)
- {
- GL.Enable(EnableCap.DepthTest);
- }
-
- if (StencilTestEnable)
- {
- GL.Enable(EnableCap.StencilTest);
- }
-
- if (AlphaBlendEnable)
- {
- GL.Enable(EnableCap.Blend);
- }
-
- SetViewport(Viewport);
+ GL.BlitFramebuffer(
+ SrcX0, SrcY0, SrcX1, SrcY1,
+ DstX0, DstY0, DstX1, DstY1,
+ ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
}
}
@@ -354,8 +313,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Data);
Callback(Data);
-
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, CurrFbHandle);
}
}
@@ -390,84 +347,27 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
- private void EnsureInitialized()
- {
- if (!IsInitialized)
- {
- IsInitialized = true;
-
- SetupShader();
- SetupVertex();
- }
- }
-
- private void SetupShader()
- {
- Shader.VpHandle = GL.CreateShader(ShaderType.VertexShader);
- Shader.FpHandle = GL.CreateShader(ShaderType.FragmentShader);
-
- string VpSource = EmbeddedResource.GetString("GlFbVtxShader");
- string FpSource = EmbeddedResource.GetString("GlFbFragShader");
-
- GL.ShaderSource(Shader.VpHandle, VpSource);
- GL.ShaderSource(Shader.FpHandle, FpSource);
- GL.CompileShader(Shader.VpHandle);
- GL.CompileShader(Shader.FpHandle);
-
- Shader.Handle = GL.CreateProgram();
-
- GL.AttachShader(Shader.Handle, Shader.VpHandle);
- GL.AttachShader(Shader.Handle, Shader.FpHandle);
- GL.LinkProgram(Shader.Handle);
- GL.UseProgram(Shader.Handle);
-
- Matrix2 Transform = Matrix2.Identity;
-
- int TexUniformLocation = GL.GetUniformLocation(Shader.Handle, "tex");
-
- GL.Uniform1(TexUniformLocation, 0);
-
- int WindowSizeUniformLocation = GL.GetUniformLocation(Shader.Handle, "window_size");
-
- GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f));
-
- int TransformUniformLocation = GL.GetUniformLocation(Shader.Handle, "transform");
-
- GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);
- }
-
- private void SetupVertex()
+ private void CreateRawFb(int Width, int Height)
{
- VaoHandle = GL.GenVertexArray();
- VboHandle = GL.GenBuffer();
-
- float[] Buffer = new float[]
+ if (RawFb == null)
{
- -1, 1, 0, 0,
- 1, 1, 1, 0,
- -1, -1, 0, 1,
- 1, -1, 1, 1
- };
-
- IntPtr Length = new IntPtr(Buffer.Length * 4);
+ RawFb = new FrameBuffer(Width, Height, false);
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
- GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
- GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
+ SetupTexture(RawFb.TexHandle, Width, Height);
- GL.BindVertexArray(VaoHandle);
+ RawFb.Width = Width;
+ RawFb.Height = Height;
- GL.EnableVertexAttribArray(0);
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, RawFb.Handle);
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
+ GL.FramebufferTexture(
+ FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ RawFb.TexHandle,
+ 0);
- GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 16, 0);
-
- GL.EnableVertexAttribArray(1);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
-
- GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8);
+ GL.Viewport(0, 0, Width, Height);
+ }
}
private void SetupTexture(int Handle, int Width, int Height)
diff --git a/Ryujinx.Graphics/Ryujinx.Graphics.csproj b/Ryujinx.Graphics/Ryujinx.Graphics.csproj
index d0fad107..7d86cbe1 100644
--- a/Ryujinx.Graphics/Ryujinx.Graphics.csproj
+++ b/Ryujinx.Graphics/Ryujinx.Graphics.csproj
@@ -21,13 +21,4 @@
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
</ItemGroup>
- <ItemGroup>
- <EmbeddedResource Include="Gal\OpenGL\FbVtxShader.glsl">
- <LogicalName>GlFbVtxShader</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="Gal\OpenGL\FbFragShader.glsl">
- <LogicalName>GlFbFragShader</LogicalName>
- </EmbeddedResource>
- </ItemGroup>
-
</Project>
diff --git a/Ryujinx.HLE/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/OsHle/Services/Vi/NvFlinger.cs
index 5307127b..41f2916f 100644
--- a/Ryujinx.HLE/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.HLE/OsHle/Services/Vi/NvFlinger.cs
@@ -293,54 +293,17 @@ namespace Ryujinx.HLE.OsHle.Services.Android
Rect Crop = BufferQueue[Slot].Crop;
- int RealWidth = FbWidth;
- int RealHeight = FbHeight;
+ bool FlipX = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX);
+ bool FlipY = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY);
- float XSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX) ? -1 : 1;
- float YSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY) ? -1 : 1;
+ //Rotation is being ignored
- float ScaleX = 1;
- float ScaleY = 1;
+ int Top = Crop.Top;
+ int Left = Crop.Left;
+ int Right = Crop.Right;
+ int Bottom = Crop.Bottom;
- float OffsX = 0;
- float OffsY = 0;
-
- if (Crop.Right != 0 &&
- Crop.Bottom != 0)
- {
- //Who knows if this is right, I was never good with math...
- RealWidth = Crop.Right - Crop.Left;
- RealHeight = Crop.Bottom - Crop.Top;
-
- if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90))
- {
- ScaleY = (float)FbHeight / RealHeight;
- ScaleX = (float)FbWidth / RealWidth;
-
- OffsY = ((-(float)Crop.Left / Crop.Right) + ScaleX - 1) * -XSign;
- OffsX = ((-(float)Crop.Top / Crop.Bottom) + ScaleY - 1) * -YSign;
- }
- else
- {
- ScaleX = (float)FbWidth / RealWidth;
- ScaleY = (float)FbHeight / RealHeight;
-
- OffsX = ((-(float)Crop.Left / Crop.Right) + ScaleX - 1) * XSign;
- OffsY = ((-(float)Crop.Top / Crop.Bottom) + ScaleY - 1) * -YSign;
- }
- }
-
- ScaleX *= XSign;
- ScaleY *= YSign;
-
- float Rotate = 0;
-
- if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90))
- {
- Rotate = -MathF.PI * 0.5f;
- }
-
- Renderer.QueueAction(() => Renderer.FrameBuffer.SetTransform(ScaleX, ScaleY, Rotate, OffsX, OffsY));
+ Renderer.QueueAction(() => Renderer.FrameBuffer.SetTransform(FlipX, FlipY, Top, Left, Right, Bottom));
//TODO: Support double buffering here aswell, it is broken for GPU
//frame buffers because it seems to be completely out of sync.