diff options
Diffstat (limited to 'Ryujinx.Core')
| -rw-r--r-- | Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Core/OsHle/Services/Nv/NvMap.cs | 1 | ||||
| -rw-r--r-- | Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 119 |
3 files changed, 45 insertions, 77 deletions
diff --git a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs index e41f03a4..abda5b86 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs @@ -244,6 +244,8 @@ namespace Ryujinx.Core.OsHle.Services.Nv Context.Memory.WriteInt64(Position + 0x20, Offset); + Map.GpuAddress = Offset; + return 0; } diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs index 9ef70319..f3dd1f47 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs @@ -8,5 +8,6 @@ namespace Ryujinx.Core.OsHle.Services.Nv public int Align; public int Kind; public long CpuAddress; + public long GpuAddress; } }
\ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 45b99ead..4ab64e2a 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -2,6 +2,7 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Services.Nv; using Ryujinx.Graphics.Gal; +using Ryujinx.Graphics.Gpu; using System; using System.Collections.Generic; using System.IO; @@ -63,13 +64,7 @@ namespace Ryujinx.Core.OsHle.Services.Android private ManualResetEvent WaitBufferFree; - private object RenderQueueLock; - - private int RenderQueueCount; - - private bool NvFlingerDisposed; - - private bool KeepRunning; + private bool Disposed; public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent) { @@ -92,10 +87,6 @@ namespace Ryujinx.Core.OsHle.Services.Android BufferQueue = new BufferEntry[0x40]; WaitBufferFree = new ManualResetEvent(false); - - RenderQueueLock = new object(); - - KeepRunning = true; } public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code) @@ -285,35 +276,24 @@ namespace Ryujinx.Core.OsHle.Services.Android return 0; } - private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot) + private void SendFrameBuffer(ServiceCtx Context, int Slot) { - int FbWidth = BufferQueue[Slot].Data.Width; - int FbHeight = BufferQueue[Slot].Data.Height; - - long FbSize = (uint)FbWidth * FbHeight * 4; + int FbWidth = 1280; + int FbHeight = 720; NvMap Map = GetNvMap(Context, Slot); NvMapFb MapFb = (NvMapFb)INvDrvServices.NvMapsFb.GetData(Context.Process, 0); - long Address = Map.CpuAddress; + long CpuAddr = Map.CpuAddress; + long GpuAddr = Map.GpuAddress; if (MapFb.HasBufferOffset(Slot)) { - Address += MapFb.GetBufferOffset(Slot); - } - - if ((ulong)(Address + FbSize) > AMemoryMgr.AddrSize) - { - Logging.Error($"Frame buffer address {Address:x16} is invalid!"); - - BufferQueue[Slot].State = BufferState.Free; + CpuAddr += MapFb.GetBufferOffset(Slot); - ReleaseEvent.Handle.Set(); - - WaitBufferFree.Set(); - - return; + //TODO: Enable once the frame buffers problems are fixed. + //GpuAddr += MapFb.GetBufferOffset(Slot); } BufferQueue[Slot].State = BufferState.Acquired; @@ -367,41 +347,28 @@ namespace Ryujinx.Core.OsHle.Services.Android Rotate = -MathF.PI * 0.5f; } - lock (RenderQueueLock) - { - if (NvFlingerDisposed) - { - return; - } + Renderer.SetFrameBufferTransform(ScaleX, ScaleY, Rotate, OffsX, OffsY); - Interlocked.Increment(ref RenderQueueCount); + //TODO: Support double buffering here aswell, it is broken for GPU + //frame buffers because it seems to be completely out of sync. + if (Context.Ns.Gpu.Engine3d.IsFrameBufferPosition(GpuAddr)) + { + //Frame buffer is rendered to by the GPU, we can just + //bind the frame buffer texture, it's not necessary to read anything. + Renderer.SetFrameBuffer(GpuAddr); } - - byte* Fb = (byte*)Context.Memory.Ram + Address; - - Context.Ns.Gpu.Renderer.QueueAction(delegate() + else { - Context.Ns.Gpu.Renderer.SetFrameBuffer( - Fb, - FbWidth, - FbHeight, - ScaleX, - ScaleY, - OffsX, - OffsY, - Rotate); - - BufferQueue[Slot].State = BufferState.Free; + //Frame buffer is not set on the GPU registers, in this case + //assume that the app is manually writing to it. + Texture Texture = new Texture(CpuAddr, FbWidth, FbHeight); - Interlocked.Decrement(ref RenderQueueCount); + byte[] Data = TextureReader.Read(Context.Memory, Texture); - ReleaseEvent.Handle.Set(); + Renderer.SetFrameBuffer(Data, FbWidth, FbHeight); + } - lock (WaitBufferFree) - { - WaitBufferFree.Set(); - } - }); + Context.Ns.Gpu.Renderer.QueueAction(() => ReleaseBuffer(Slot)); } private NvMap GetNvMap(ServiceCtx Context, int Slot) @@ -420,6 +387,18 @@ namespace Ryujinx.Core.OsHle.Services.Android return INvDrvServices.NvMaps.GetData<NvMap>(Context.Process, NvMapHandle); } + private void ReleaseBuffer(int Slot) + { + BufferQueue[Slot].State = BufferState.Free; + + ReleaseEvent.Handle.Set(); + + lock (WaitBufferFree) + { + WaitBufferFree.Set(); + } + } + private int GetFreeSlotBlocking(int Width, int Height) { int Slot; @@ -435,7 +414,7 @@ namespace Ryujinx.Core.OsHle.Services.Android Logging.Debug("Waiting for a free BufferQueue slot..."); - if (!KeepRunning) + if (Disposed) { break; } @@ -445,7 +424,7 @@ namespace Ryujinx.Core.OsHle.Services.Android WaitBufferFree.WaitOne(); } - while (KeepRunning); + while (!Disposed); Logging.Debug($"Found free BufferQueue slot {Slot}!"); @@ -485,26 +464,12 @@ namespace Ryujinx.Core.OsHle.Services.Android protected virtual void Dispose(bool Disposing) { - if (Disposing && !NvFlingerDisposed) + if (Disposing && !Disposed) { - lock (RenderQueueLock) - { - NvFlingerDisposed = true; - } - - //Ensure that all pending actions was sent before - //we can safely assume that the class was disposed. - while (RenderQueueCount > 0) - { - Thread.Yield(); - } - - Renderer.ResetFrameBuffer(); + Disposed = true; lock (WaitBufferFree) { - KeepRunning = false; - WaitBufferFree.Set(); } |
