using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine; using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Synchronization; using System; using System.Collections.Generic; using System.Threading; namespace Ryujinx.Graphics.Gpu { /// /// GPU emulation context. /// public sealed class GpuContext : IDisposable { /// /// Event signaled when the host emulation context is ready to be used by the gpu context. /// public ManualResetEvent HostInitalized { get; } /// /// Host renderer. /// public IRenderer Renderer { get; } /// /// Physical memory access (it actually accesses the process memory, not actual physical memory). /// internal PhysicalMemory PhysicalMemory { get; private set; } /// /// GPU memory manager. /// public MemoryManager MemoryManager { get; } /// /// GPU engine methods processing. /// internal Methods Methods { get; } /// /// GPU General Purpose FIFO queue. /// public GPFifoDevice GPFifo { get; } /// /// GPU synchronization manager. /// public SynchronizationManager Synchronization { get; } /// /// Presentation window. /// public Window Window { get; } /// /// Internal sequence number, used to avoid needless resource data updates /// in the middle of a command buffer before synchronizations. /// internal int SequenceNumber { get; private set; } /// /// Internal sync number, used to denote points at which host synchronization can be requested. /// internal ulong SyncNumber { get; private set; } /// /// Actions to be performed when a CPU waiting sync point is triggered. /// If there are more than 0 items when this happens, a host sync object will be generated for the given , /// and the SyncNumber will be incremented. /// internal List SyncActions { get; } private readonly Lazy _caps; /// /// Host hardware capabilities. /// internal Capabilities Capabilities => _caps.Value; /// /// Event for signalling shader cache loading progress. /// public event Action ShaderCacheStateChanged { add => Methods.ShaderCache.ShaderCacheStateChanged += value; remove => Methods.ShaderCache.ShaderCacheStateChanged -= value; } /// /// Creates a new instance of the GPU emulation context. /// /// Host renderer public GpuContext(IRenderer renderer) { Renderer = renderer; MemoryManager = new MemoryManager(this); Methods = new Methods(this); GPFifo = new GPFifoDevice(this); Synchronization = new SynchronizationManager(); Window = new Window(this); _caps = new Lazy(Renderer.GetCapabilities); HostInitalized = new ManualResetEvent(false); SyncActions = new List(); } /// /// Initialize the GPU shader cache. /// public void InitializeShaderCache() { HostInitalized.WaitOne(); Methods.ShaderCache.Initialize(); } /// /// Advances internal sequence number. /// This forces the update of any modified GPU resource. /// internal void AdvanceSequence() { SequenceNumber++; } /// /// Sets the process memory manager, after the application process is initialized. /// This is required for any GPU memory access. /// /// CPU memory manager public void SetVmm(Cpu.IVirtualMemoryManagerTracked cpuMemory) { PhysicalMemory = new PhysicalMemory(cpuMemory); } /// /// Registers an action to be performed the next time a syncpoint is incremented. /// This will also ensure a host sync object is created, and is incremented. /// /// The action to be performed on sync object creation public void RegisterSyncAction(Action action) { SyncActions.Add(action); } /// /// Creates a host sync object if there are any pending sync actions. The actions will then be called. /// If no actions are present, a host sync object is not created. /// public void CreateHostSyncIfNeeded() { if (SyncActions.Count > 0) { Renderer.CreateSync(SyncNumber); SyncNumber++; foreach (Action action in SyncActions) { action(); } SyncActions.Clear(); } } /// /// Disposes all GPU resources currently cached. /// It's an error to push any GPU commands after disposal. /// Additionally, the GPU commands FIFO must be empty for disposal, /// and processing of all commands must have finished. /// public void Dispose() { Methods.ShaderCache.Dispose(); Methods.BufferManager.Dispose(); Methods.TextureManager.Dispose(); Renderer.Dispose(); GPFifo.Dispose(); HostInitalized.Dispose(); PhysicalMemory.Dispose(); } } }