aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Graphics.GAL/IWindow.cs6
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/GpuContext.cs38
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureManager.cs26
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/ConcurrentRangeList.cs208
-rw-r--r--Ryujinx.Graphics.Gpu/Window.cs94
-rw-r--r--Ryujinx.Graphics.OpenGL/Window.cs196
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/NvFlinger.cs43
-rw-r--r--Ryujinx.HLE/Switch.cs5
-rw-r--r--Ryujinx/Ui/GLScreen.cs4
11 files changed, 137 insertions, 497 deletions
diff --git a/Ryujinx.Graphics.GAL/IWindow.cs b/Ryujinx.Graphics.GAL/IWindow.cs
index 3d5130c2..369f7b9a 100644
--- a/Ryujinx.Graphics.GAL/IWindow.cs
+++ b/Ryujinx.Graphics.GAL/IWindow.cs
@@ -2,11 +2,7 @@ namespace Ryujinx.Graphics.GAL
{
public interface IWindow
{
- void Present();
-
- void QueueTexture(ITexture texture, ImageCrop crop, object context);
-
- void RegisterTextureReleaseCallback(TextureReleaseCallback callback);
+ void Present(ITexture texture, ImageCrop crop);
void SetSize(int width, int height);
}
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 1832a5e3..19e67993 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -76,8 +76,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
}
- public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
-
private void UpdateState(GpuState state)
{
// Shaders must be the first one to be updated if modified, because
diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs
index b52e4e49..51961522 100644
--- a/Ryujinx.Graphics.Gpu/GpuContext.cs
+++ b/Ryujinx.Graphics.Gpu/GpuContext.cs
@@ -1,9 +1,6 @@
using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.GAL.Texture;
using Ryujinx.Graphics.Gpu.Engine;
-using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.Memory;
-using Ryujinx.Graphics.Gpu.State;
using System;
namespace Ryujinx.Graphics.Gpu
@@ -24,6 +21,8 @@ namespace Ryujinx.Graphics.Gpu
public DmaPusher DmaPusher { get; }
+ public Window Window { get; }
+
internal int SequenceNumber { get; private set; }
private Lazy<Capabilities> _caps;
@@ -44,6 +43,8 @@ namespace Ryujinx.Graphics.Gpu
DmaPusher = new DmaPusher(this);
+ Window = new Window(this);
+
_caps = new Lazy<Capabilities>(GetCapabilities);
}
@@ -52,37 +53,6 @@ namespace Ryujinx.Graphics.Gpu
SequenceNumber++;
}
- public ITexture GetTexture(
- ulong address,
- int width,
- int height,
- int stride,
- bool isLinear,
- int gobBlocksInY,
- Format format,
- int bytesPerPixel)
- {
- FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
-
- TextureInfo info = new TextureInfo(
- address,
- width,
- height,
- 1,
- 1,
- 1,
- 1,
- stride,
- isLinear,
- gobBlocksInY,
- 1,
- 1,
- Target.Texture2D,
- formatInfo);
-
- return Methods.GetTexture(address)?.HostTexture;
- }
-
private Capabilities GetCapabilities()
{
return Renderer.GetCapabilities();
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 28ad3f77..120abe3f 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -335,18 +335,6 @@ namespace Ryujinx.Graphics.Gpu.Image
return true;
}
- if (_info.FormatInfo.Format == Format.R8G8B8A8Srgb &&
- info.FormatInfo.Format == Format.R8G8B8A8Unorm && !strict)
- {
- return true;
- }
-
- if (_info.FormatInfo.Format == Format.R8G8B8A8Unorm &&
- info.FormatInfo.Format == Format.R8G8B8A8Srgb && !strict)
- {
- return true;
- }
-
return _info.FormatInfo.Format == info.FormatInfo.Format;
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 045c2ed9..413ba327 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Image
private ITexture[] _rtHostColors;
private ITexture _rtHostDs;
- private ConcurrentRangeList<Texture> _textures;
+ private RangeList<Texture> _textures;
private AutoDeleteCache _cache;
@@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_rtHostColors = new ITexture[Constants.TotalRenderTargets];
- _textures = new ConcurrentRangeList<Texture>();
+ _textures = new RangeList<Texture>();
_cache = new AutoDeleteCache();
}
@@ -561,28 +561,6 @@ namespace Ryujinx.Graphics.Gpu.Image
info.SwizzleA);
}
- public Texture Find2(ulong address)
- {
- Texture[] ts = _textures.FindOverlaps(address, 1);
-
- if (ts.Length == 2)
- {
- return ts[1];
- }
-
- if (ts.Length == 0)
- {
- ts = _textures.FindOverlaps(address - 1, 2);
- }
-
- if (ts.Length == 0)
- {
- return null;
- }
-
- return ts[0];
- }
-
public void Flush()
{
foreach (Texture texture in _cache)
diff --git a/Ryujinx.Graphics.Gpu/Memory/ConcurrentRangeList.cs b/Ryujinx.Graphics.Gpu/Memory/ConcurrentRangeList.cs
deleted file mode 100644
index 6d7d1ce2..00000000
--- a/Ryujinx.Graphics.Gpu/Memory/ConcurrentRangeList.cs
+++ /dev/null
@@ -1,208 +0,0 @@
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Gpu.Memory
-{
- class ConcurrentRangeList<T> where T : IRange<T>
- {
- private List<T> _items;
-
- public ConcurrentRangeList()
- {
- _items = new List<T>();
- }
-
- public void Add(T item)
- {
- lock (_items)
- {
- int index = BinarySearch(item.Address);
-
- if (index < 0)
- {
- index = ~index;
- }
-
- _items.Insert(index, item);
- }
- }
-
- public bool Remove(T item)
- {
- lock (_items)
- {
- int index = BinarySearch(item.Address);
-
- if (index >= 0)
- {
- while (index > 0 && _items[index - 1].Address == item.Address)
- {
- index--;
- }
-
- while (index < _items.Count)
- {
- if (_items[index].Equals(item))
- {
- _items.RemoveAt(index);
-
- return true;
- }
-
- if (_items[index].Address > item.Address)
- {
- break;
- }
-
- index++;
- }
- }
- }
-
- return false;
- }
-
- public T FindFirstOverlap(T item)
- {
- return FindFirstOverlap(item.Address, item.Size);
- }
-
- public T FindFirstOverlap(ulong address, ulong size)
- {
- lock (_items)
- {
- int index = BinarySearch(address, size);
-
- if (index < 0)
- {
- return default(T);
- }
-
- return _items[index];
- }
- }
-
- public T[] FindOverlaps(T item)
- {
- return FindOverlaps(item.Address, item.Size);
- }
-
- public T[] FindOverlaps(ulong address, ulong size)
- {
- List<T> overlapsList = new List<T>();
-
- ulong endAddress = address + size;
-
- lock (_items)
- {
- foreach (T item in _items)
- {
- if (item.Address >= endAddress)
- {
- break;
- }
-
- if (item.OverlapsWith(address, size))
- {
- overlapsList.Add(item);
- }
- }
- }
-
- return overlapsList.ToArray();
- }
-
- public T[] FindOverlaps(ulong address)
- {
- List<T> overlapsList = new List<T>();
-
- lock (_items)
- {
- int index = BinarySearch(address);
-
- if (index >= 0)
- {
- while (index > 0 && _items[index - 1].Address == address)
- {
- index--;
- }
-
- while (index < _items.Count)
- {
- T overlap = _items[index++];
-
- if (overlap.Address != address)
- {
- break;
- }
-
- overlapsList.Add(overlap);
- }
- }
- }
-
- return overlapsList.ToArray();
- }
-
- private int BinarySearch(ulong address)
- {
- int left = 0;
- int right = _items.Count - 1;
-
- while (left <= right)
- {
- int range = right - left;
-
- int middle = left + (range >> 1);
-
- T item = _items[middle];
-
- if (item.Address == address)
- {
- return middle;
- }
-
- if (address < item.Address)
- {
- right = middle - 1;
- }
- else
- {
- left = middle + 1;
- }
- }
-
- return ~left;
- }
-
- private int BinarySearch(ulong address, ulong size)
- {
- int left = 0;
- int right = _items.Count - 1;
-
- while (left <= right)
- {
- int range = right - left;
-
- int middle = left + (range >> 1);
-
- T item = _items[middle];
-
- if (item.OverlapsWith(address, size))
- {
- return middle;
- }
-
- if (address < item.Address)
- {
- right = middle - 1;
- }
- else
- {
- left = middle + 1;
- }
- }
-
- return ~left;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Window.cs b/Ryujinx.Graphics.Gpu/Window.cs
new file mode 100644
index 00000000..a3dc3b26
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Window.cs
@@ -0,0 +1,94 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.GAL.Texture;
+using Ryujinx.Graphics.Gpu.Image;
+using System;
+using System.Collections.Concurrent;
+
+namespace Ryujinx.Graphics.Gpu
+{
+ public class Window
+ {
+ private GpuContext _context;
+
+ private struct PresentationTexture
+ {
+ public TextureInfo Info { get; }
+ public ImageCrop Crop { get; }
+ public Action<object> Callback { get; }
+ public object UserObj { get; }
+
+ public PresentationTexture(
+ TextureInfo info,
+ ImageCrop crop,
+ Action<object> callback,
+ object userObj)
+ {
+ Info = info;
+ Crop = crop;
+ Callback = callback;
+ UserObj = userObj;
+ }
+ }
+
+ private ConcurrentQueue<PresentationTexture> _frameQueue;
+
+ public Window(GpuContext context)
+ {
+ _context = context;
+
+ _frameQueue = new ConcurrentQueue<PresentationTexture>();
+ }
+
+ public void EnqueueFrameThreadSafe(
+ ulong address,
+ int width,
+ int height,
+ int stride,
+ bool isLinear,
+ int gobBlocksInY,
+ Format format,
+ int bytesPerPixel,
+ ImageCrop crop,
+ Action<object> callback,
+ object userObj)
+ {
+ FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
+
+ TextureInfo info = new TextureInfo(
+ address,
+ width,
+ height,
+ 1,
+ 1,
+ 1,
+ 1,
+ stride,
+ isLinear,
+ gobBlocksInY,
+ 1,
+ 1,
+ Target.Texture2D,
+ formatInfo);
+
+ _frameQueue.Enqueue(new PresentationTexture(info, crop, callback, userObj));
+ }
+
+ public void Present(Action swapBuffersCallback)
+ {
+ _context.AdvanceSequence();
+
+ if (_frameQueue.TryDequeue(out PresentationTexture pt))
+ {
+ Image.Texture texture = _context.Methods.TextureManager.FindOrCreateTexture(pt.Info);
+
+ texture.SynchronizeMemory();
+
+ _context.Renderer.Window.Present(texture.HostTexture, pt.Crop);
+
+ swapBuffersCallback();
+
+ pt.Callback(pt.UserObj);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs
index 3fe83dd1..cf520ed4 100644
--- a/Ryujinx.Graphics.OpenGL/Window.cs
+++ b/Ryujinx.Graphics.OpenGL/Window.cs
@@ -1,7 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using System;
-using System.Collections.Generic;
namespace Ryujinx.Graphics.OpenGL
{
@@ -13,53 +12,19 @@ namespace Ryujinx.Graphics.OpenGL
private int _width;
private int _height;
- private int _resizeWidth;
- private int _resizeHeight;
-
- private bool _sizeChanged;
-
- private object _resizeLocker;
-
- private int _blitFramebufferHandle;
private int _copyFramebufferHandle;
- private int _screenTextureHandle;
-
- private TextureReleaseCallback _release;
-
- private struct PresentationTexture
- {
- public TextureView Texture { get; }
-
- public ImageCrop Crop { get; }
-
- public object Context { get; }
-
- public PresentationTexture(TextureView texture, ImageCrop crop, object context)
- {
- Texture = texture;
- Crop = crop;
- Context = context;
- }
- }
-
- private Queue<PresentationTexture> _textures;
-
public Window()
{
_width = NativeWidth;
_height = NativeHeight;
-
- _resizeLocker = new object();
-
- _textures = new Queue<PresentationTexture>();
}
- public void Present()
+ public void Present(ITexture texture, ImageCrop crop)
{
- GL.Disable(EnableCap.FramebufferSrgb);
+ TextureView view = (TextureView)texture;
- CopyTextureFromQueue();
+ GL.Disable(EnableCap.FramebufferSrgb);
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
@@ -67,52 +32,10 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetCopyFramebufferHandleLazy());
- GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
-
- GL.Clear(ClearBufferMask.ColorBufferBit);
-
- int windowWidth = _width;
- int windowHeight = _height;
-
- GL.BlitFramebuffer(
- 0,
- 0,
- windowWidth,
- windowHeight,
- 0,
- 0,
- windowWidth,
- windowHeight,
- ClearBufferMask.ColorBufferBit,
- BlitFramebufferFilter.Linear);
-
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
-
- GL.Enable(EnableCap.FramebufferSrgb);
- }
-
- private void CopyTextureFromQueue()
- {
- if (!_textures.TryDequeue(out PresentationTexture presentationTexture))
- {
- return;
- }
-
- TextureView texture = presentationTexture.Texture;
- ImageCrop crop = presentationTexture.Crop;
- object context = presentationTexture.Context;
-
- int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
- int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
-
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetCopyFramebufferHandleLazy());
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetBlitFramebufferHandleLazy());
-
GL.FramebufferTexture(
FramebufferTarget.ReadFramebuffer,
FramebufferAttachment.ColorAttachment0,
- texture.Handle,
+ view.Handle,
0);
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
@@ -124,7 +47,7 @@ namespace Ryujinx.Graphics.OpenGL
if (crop.Left == 0 && crop.Right == 0)
{
srcX0 = 0;
- srcX1 = texture.Width;
+ srcX1 = view.Width;
}
else
{
@@ -135,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL
if (crop.Top == 0 && crop.Bottom == 0)
{
srcY0 = 0;
- srcY1 = texture.Height;
+ srcY1 = view.Height;
}
else
{
@@ -173,126 +96,25 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
- texture.Release();
-
- Release(context);
- }
-
- public void QueueTexture(ITexture texture, ImageCrop crop, object context)
- {
- if (texture == null)
- {
- Release(context);
-
- return;
- }
-
- TextureView textureView = (TextureView)texture;
-
- textureView.Acquire();
-
- _textures.Enqueue(new PresentationTexture(textureView, crop, context));
- }
-
- public void RegisterTextureReleaseCallback(TextureReleaseCallback callback)
- {
- _release = callback;
+ GL.Enable(EnableCap.FramebufferSrgb);
}
public void SetSize(int width, int height)
{
- lock (_resizeLocker)
- {
- _resizeWidth = width;
- _resizeHeight = height;
-
- _sizeChanged = true;
- }
- }
-
- private void Release(object context)
- {
- if (_release != null)
- {
- _release(context);
- }
- }
-
- private int GetBlitFramebufferHandleLazy()
- {
- int handle = _blitFramebufferHandle;
-
- if (handle == 0)
- {
- handle = GL.GenFramebuffer();
-
- _blitFramebufferHandle = handle;
- }
-
- return handle;
+ _width = width;
+ _height = height;
}
private int GetCopyFramebufferHandleLazy()
{
int handle = _copyFramebufferHandle;
- void GenerateAndBindTexture()
- {
- int textureHandle = GenerateWindowTexture();
-
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, handle);
-
- GL.FramebufferTexture(
- FramebufferTarget.Framebuffer,
- FramebufferAttachment.ColorAttachment0,
- textureHandle,
- 0);
-
- _screenTextureHandle = textureHandle;
- }
-
if (handle == 0)
{
handle = GL.GenFramebuffer();
_copyFramebufferHandle = handle;
-
- GenerateAndBindTexture();
}
- else if (_sizeChanged)
- {
- GL.DeleteTexture(_screenTextureHandle);
-
- lock (_resizeLocker)
- {
- _width = _resizeWidth;
- _height = _resizeHeight;
-
- _sizeChanged = false;
- }
-
- GenerateAndBindTexture();
- }
-
- return handle;
- }
-
- private int GenerateWindowTexture()
- {
- int handle = GL.GenTexture();
-
- GL.BindTexture(TextureTarget.Texture2D, handle);
-
- GL.TexImage2D(
- TextureTarget.Texture2D,
- 0,
- PixelInternalFormat.Rgba8,
- _width,
- _height,
- 0,
- PixelFormat.Rgba,
- PixelType.UnsignedByte,
- IntPtr.Zero);
return handle;
}
diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/NvFlinger.cs
index 50b55ee0..fa798177 100644
--- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/NvFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/NvFlinger.cs
@@ -1,7 +1,7 @@
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.Kernel.Threading;
-using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
using System;
using System.Collections.Generic;
@@ -295,11 +295,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_bufferQueue[slot].State = BufferState.Acquired;
- Rect crop = _bufferQueue[slot].Crop;
-
- bool flipX = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipX);
- bool flipY = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipY);
-
Format format = ConvertColorFormat(_bufferQueue[slot].Data.Buffer.Surfaces[0].ColorFormat);
int bytesPerPixel =
@@ -310,7 +305,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
// Note: Rotation is being ignored.
- ITexture texture = context.Device.Gpu.GetTexture(
+ Rect cropRect = _bufferQueue[slot].Crop;
+
+ bool flipX = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipX);
+ bool flipY = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipY);
+
+ ImageCrop crop = new ImageCrop(
+ cropRect.Left,
+ cropRect.Right,
+ cropRect.Top,
+ cropRect.Bottom,
+ flipX,
+ flipY);
+
+ context.Device.Gpu.Window.EnqueueFrameThreadSafe(
fbAddr,
fbWidth,
fbHeight,
@@ -318,24 +326,15 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
false,
gobBlocksInY,
format,
- bytesPerPixel);
-
- _renderer.Window.RegisterTextureReleaseCallback(ReleaseBuffer);
-
- ImageCrop imageCrop = new ImageCrop(
- crop.Left,
- crop.Right,
- crop.Top,
- crop.Bottom,
- flipX,
- flipY);
-
- _renderer.Window.QueueTexture(texture, imageCrop, slot);
+ bytesPerPixel,
+ crop,
+ ReleaseBuffer,
+ slot);
}
- private void ReleaseBuffer(object context)
+ private void ReleaseBuffer(object slot)
{
- ReleaseBuffer((int)context);
+ ReleaseBuffer((int)slot);
}
private void ReleaseBuffer(int slot)
diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs
index e5a5f273..9df1d757 100644
--- a/Ryujinx.HLE/Switch.cs
+++ b/Ryujinx.HLE/Switch.cs
@@ -122,6 +122,11 @@ namespace Ryujinx.HLE
Gpu.DmaPusher.DispatchCalls();
}
+ public void PresentFrame(Action swapBuffersCallback)
+ {
+ Gpu.Window.Present(swapBuffersCallback);
+ }
+
internal void Unload()
{
FileSystem.Dispose();
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 6d1060ee..1cce6a1f 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -294,7 +294,7 @@ namespace Ryujinx.Ui
private new void RenderFrame()
{
- _renderer.Window.Present();
+ _device.PresentFrame(SwapBuffers);
_device.Statistics.RecordSystemFrameTime();
@@ -312,8 +312,6 @@ namespace Ryujinx.Ui
_titleEvent = true;
- SwapBuffers();
-
_device.System.SignalVsync();
_device.VsyncEvent.Set();