diff options
Diffstat (limited to 'Ryujinx.HLE/HOS')
13 files changed, 175 insertions, 111 deletions
diff --git a/Ryujinx.HLE/HOS/ArmProcessContext.cs b/Ryujinx.HLE/HOS/ArmProcessContext.cs index 457d1218..89ce0eb3 100644 --- a/Ryujinx.HLE/HOS/ArmProcessContext.cs +++ b/Ryujinx.HLE/HOS/ArmProcessContext.cs @@ -1,27 +1,34 @@ using ARMeilleure.Memory; using ARMeilleure.State; using Ryujinx.Cpu; +using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.Memory; namespace Ryujinx.HLE.HOS { - class ArmProcessContext<T> : IProcessContext where T : class, IVirtualMemoryManager, IMemoryManager + class ArmProcessContext<T> : IProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager { + private readonly long _pid; + private readonly GpuContext _gpuContext; private readonly CpuContext _cpuContext; private T _memoryManager; public IVirtualMemoryManager AddressSpace => _memoryManager; - public ArmProcessContext(T memoryManager, bool for64Bit) + public ArmProcessContext(long pid, GpuContext gpuContext, T memoryManager, bool for64Bit) { if (memoryManager is IRefCounted rc) { rc.IncrementReferenceCount(); } - _memoryManager = memoryManager; + gpuContext.RegisterProcess(pid, memoryManager); + + _pid = pid; + _gpuContext = gpuContext; _cpuContext = new CpuContext(memoryManager, for64Bit); + _memoryManager = memoryManager; } public void Execute(ExecutionContext context, ulong codeAddress) @@ -36,6 +43,7 @@ namespace Ryujinx.HLE.HOS rc.DecrementReferenceCount(); _memoryManager = null; + _gpuContext.UnregisterProcess(_pid); } } } diff --git a/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index 04d06e1f..50dbd843 100644 --- a/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Configuration; using Ryujinx.Cpu; +using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.Memory; @@ -9,19 +10,26 @@ namespace Ryujinx.HLE.HOS { class ArmProcessContextFactory : IProcessContextFactory { - public IProcessContext Create(KernelContext context, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) + private readonly GpuContext _gpu; + + public ArmProcessContextFactory(GpuContext gpu) + { + _gpu = gpu; + } + + public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) { MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode; switch (mode) { case MemoryManagerMode.SoftwarePageTable: - return new ArmProcessContext<MemoryManager>(new MemoryManager(addressSpaceSize, invalidAccessHandler), for64Bit); + return new ArmProcessContext<MemoryManager>(pid, _gpu, new MemoryManager(addressSpaceSize, invalidAccessHandler), for64Bit); case MemoryManagerMode.HostMapped: case MemoryManagerMode.HostMappedUnsafe: bool unsafeMode = mode == MemoryManagerMode.HostMappedUnsafe; - return new ArmProcessContext<MemoryManagerHostMapped>(new MemoryManagerHostMapped(addressSpaceSize, unsafeMode, invalidAccessHandler), for64Bit); + return new ArmProcessContext<MemoryManagerHostMapped>(pid, _gpu, new MemoryManagerHostMapped(addressSpaceSize, unsafeMode, invalidAccessHandler), for64Bit); default: throw new ArgumentOutOfRangeException(); diff --git a/Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs b/Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs index fbd6c139..10df43a8 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs @@ -4,6 +4,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { interface IProcessContextFactory { - IProcessContext Create(KernelContext context, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit); + IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit); } } diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 90cd01f0..fbdd812e 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -126,6 +126,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift); + Pid = KernelContext.NewKipId(); + + if (Pid == 0 || (ulong)Pid >= KernelConstants.InitialProcessId) + { + throw new InvalidOperationException($"Invalid KIP Id {Pid}."); + } + InitializeMemoryManager(creationInfo.Flags); bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr); @@ -171,13 +178,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - Pid = KernelContext.NewKipId(); - - if (Pid == 0 || (ulong)Pid >= KernelConstants.InitialProcessId) - { - throw new InvalidOperationException($"Invalid KIP Id {Pid}."); - } - return ParseProcessInfo(creationInfo); } @@ -233,6 +233,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift); + Pid = KernelContext.NewProcessId(); + + if (Pid == -1 || (ulong)Pid < KernelConstants.InitialProcessId) + { + throw new InvalidOperationException($"Invalid Process Id {Pid}."); + } + InitializeMemoryManager(creationInfo.Flags); bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr); @@ -286,13 +293,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - Pid = KernelContext.NewProcessId(); - - if (Pid == -1 || (ulong)Pid < KernelConstants.InitialProcessId) - { - throw new InvalidOperationException($"Invalid Process Id {Pid}."); - } - result = ParseProcessInfo(creationInfo); if (result != KernelResult.Success) @@ -1051,14 +1051,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process bool for64Bit = flags.HasFlag(ProcessCreationFlags.Is64Bit); - Context = _contextFactory.Create(KernelContext, 1UL << addrSpaceBits, InvalidAccessHandler, for64Bit); - - // TODO: This should eventually be removed. - // The GPU shouldn't depend on the CPU memory manager at all. - if (flags.HasFlag(ProcessCreationFlags.IsApplication)) - { - KernelContext.Device.Gpu.SetVmm((IVirtualMemoryManagerTracked)CpuMemory); - } + Context = _contextFactory.Create(KernelContext, Pid, 1UL << addrSpaceBits, InvalidAccessHandler, for64Bit); if (Context.AddressSpace is MemoryManagerHostMapped) { diff --git a/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs b/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs index 5920fe44..ff250e88 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs @@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { class ProcessContextFactory : IProcessContextFactory { - public IProcessContext Create(KernelContext context, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) + public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit) { return new ProcessContext(new AddressSpaceManager(addressSpaceSize)); } diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs index cc1c76c2..93ddd7ee 100644 --- a/Ryujinx.HLE/HOS/ProgramLoader.cs +++ b/Ryujinx.HLE/HOS/ProgramLoader.cs @@ -83,7 +83,7 @@ namespace Ryujinx.HLE.HOS KProcess process = new KProcess(context); - var processContextFactory = new ArmProcessContextFactory(); + var processContextFactory = new ArmProcessContextFactory(context.Device.Gpu); result = process.InitializeKip( creationInfo, @@ -228,7 +228,7 @@ namespace Ryujinx.HLE.HOS return false; } - var processContextFactory = new ArmProcessContextFactory(); + var processContextFactory = new ArmProcessContextFactory(context.Device.Gpu); result = process.Initialize( creationInfo, diff --git a/Ryujinx.HLE/HOS/Services/Nv/Host1xContext.cs b/Ryujinx.HLE/HOS/Services/Nv/Host1xContext.cs new file mode 100644 index 00000000..1fcc12b5 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Nv/Host1xContext.cs @@ -0,0 +1,47 @@ +using Ryujinx.Graphics.Gpu; +using Ryujinx.Graphics.Gpu.Memory; +using Ryujinx.Graphics.Host1x; +using Ryujinx.Graphics.Nvdec; +using Ryujinx.Graphics.Vic; +using System; + +namespace Ryujinx.HLE.HOS.Services.Nv +{ + class Host1xContext : IDisposable + { + public MemoryManager Smmu { get; } + public NvMemoryAllocator MemoryAllocator { get; } + public Host1xDevice Host1x { get;} + + public Host1xContext(GpuContext gpu, long pid) + { + MemoryAllocator = new NvMemoryAllocator(); + Host1x = new Host1xDevice(gpu.Synchronization); + Smmu = gpu.CreateMemoryManager(pid); + var nvdec = new NvdecDevice(Smmu); + var vic = new VicDevice(Smmu); + Host1x.RegisterDevice(ClassId.Nvdec, nvdec); + Host1x.RegisterDevice(ClassId.Vic, vic); + + nvdec.FrameDecoded += (FrameDecodedEventArgs e) => + { + // FIXME: + // Figure out what is causing frame ordering issues on H264. + // For now this is needed as workaround. + if (e.CodecId == CodecId.H264) + { + vic.SetSurfaceOverride(e.LumaOffset, e.ChromaOffset, 0); + } + else + { + vic.DisableSurfaceOverride(); + } + }; + } + + public void Dispose() + { + Host1x.Dispose(); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index 25279af3..24c784c3 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -3,7 +3,6 @@ using Ryujinx.Common.Logging; using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel; @@ -24,8 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv [Service("nvdrv:t")] class INvDrvServices : IpcService { - private static Dictionary<string, Type> _deviceFileRegistry = - new Dictionary<string, Type>() + private static Dictionary<string, Type> _deviceFileRegistry = new Dictionary<string, Type>() { { "/dev/nvmap", typeof(NvMapDeviceFile) }, { "/dev/nvhost-ctrl", typeof(NvHostCtrlDeviceFile) }, @@ -39,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv //{ "/dev/nvhost-display", typeof(NvHostChannelDeviceFile) }, }; - private static IdDictionary _deviceFileIdRegistry = new IdDictionary(); + public static IdDictionary DeviceFileIdRegistry = new IdDictionary(); private IVirtualMemoryManager _clientMemory; private long _owner; @@ -61,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv deviceFile.Path = path; - return _deviceFileIdRegistry.Add(deviceFile); + return DeviceFileIdRegistry.Add(deviceFile); } else { @@ -139,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv return NvResult.InvalidParameter; } - deviceFile = _deviceFileIdRegistry.GetData<NvDeviceFile>(fd); + deviceFile = DeviceFileIdRegistry.GetData<NvDeviceFile>(fd); if (deviceFile == null) { @@ -302,7 +300,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv { deviceFile.Close(); - _deviceFileIdRegistry.Delete(fd); + DeviceFileIdRegistry.Delete(fd); } } @@ -569,14 +567,16 @@ namespace Ryujinx.HLE.HOS.Services.Nv public static void Destroy() { - foreach (object entry in _deviceFileIdRegistry.Values) + NvHostChannelDeviceFile.Destroy(); + + foreach (object entry in DeviceFileIdRegistry.Values) { NvDeviceFile deviceFile = (NvDeviceFile)entry; deviceFile.Close(); } - _deviceFileIdRegistry.Clear(); + DeviceFileIdRegistry.Clear(); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs index ac0c4ab1..b3be6fba 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs @@ -1,22 +1,22 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types; +using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.Memory; using System; -using System.Collections.Concurrent; namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu { class NvHostAsGpuDeviceFile : NvDeviceFile { - private static ConcurrentDictionary<KProcess, AddressSpaceContext> _addressSpaceContextRegistry = new ConcurrentDictionary<KProcess, AddressSpaceContext>(); - private NvMemoryAllocator _memoryAllocator; + private readonly AddressSpaceContext _asContext; + private readonly NvMemoryAllocator _memoryAllocator; public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { - _memoryAllocator = context.Device.MemoryAllocator; + _asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner)); + _memoryAllocator = new NvMemoryAllocator(); } public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments) @@ -77,20 +77,24 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult BindChannel(ref BindChannelArguments arguments) { - Logger.Stub?.PrintStub(LogClass.ServiceNv); + var channelDeviceFile = INvDrvServices.DeviceFileIdRegistry.GetData<NvHostChannelDeviceFile>(arguments.Fd); + if (channelDeviceFile == null) + { + // TODO: Return invalid Fd error. + } + + channelDeviceFile.Channel.BindMemory(_asContext.Gmm); return NvInternalResult.Success; } private NvInternalResult AllocSpace(ref AllocSpaceArguments arguments) { - AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); - ulong size = (ulong)arguments.Pages * (ulong)arguments.PageSize; NvInternalResult result = NvInternalResult.Success; - lock (addressSpaceContext) + lock (_asContext) { // Note: When the fixed offset flag is not set, // the Offset field holds the alignment size instead. @@ -132,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu } else { - addressSpaceContext.AddReservation(arguments.Offset, size); + _asContext.AddReservation(arguments.Offset, size); } } @@ -141,18 +145,16 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult FreeSpace(ref FreeSpaceArguments arguments) { - AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); + ulong size = (ulong)arguments.Pages * (ulong)arguments.PageSize; NvInternalResult result = NvInternalResult.Success; - lock (addressSpaceContext) + lock (_asContext) { - ulong size = (ulong)arguments.Pages * (ulong)arguments.PageSize; - - if (addressSpaceContext.RemoveReservation(arguments.Offset)) + if (_asContext.RemoveReservation(arguments.Offset)) { _memoryAllocator.DeallocateRange(arguments.Offset, size); - addressSpaceContext.Gmm.Unmap(arguments.Offset, size); + _asContext.Gmm.Unmap(arguments.Offset, size); } else { @@ -168,16 +170,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult UnmapBuffer(ref UnmapBufferArguments arguments) { - AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); - - lock (addressSpaceContext) + lock (_asContext) { - if (addressSpaceContext.RemoveMap(arguments.Offset, out ulong size)) + if (_asContext.RemoveMap(arguments.Offset, out ulong size)) { if (size != 0) { _memoryAllocator.DeallocateRange(arguments.Offset, size); - addressSpaceContext.Gmm.Unmap(arguments.Offset, size); + _asContext.Gmm.Unmap(arguments.Offset, size); } } else @@ -191,22 +191,20 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments) { - const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16}, size 0x{1:x16} and alignment 0x{2:x16}!"; - - AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); + const string MapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16}, size 0x{1:x16} and alignment 0x{2:x16}!"; ulong physicalAddress; if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0) { - lock (addressSpaceContext) + lock (_asContext) { - if (addressSpaceContext.TryGetMapPhysicalAddress(arguments.Offset, out physicalAddress)) + if (_asContext.TryGetMapPhysicalAddress(arguments.Offset, out physicalAddress)) { ulong virtualAddress = arguments.Offset + arguments.BufferOffset; physicalAddress += arguments.BufferOffset; - addressSpaceContext.Gmm.Map(physicalAddress, virtualAddress, arguments.MappingSize); + _asContext.Gmm.Map(physicalAddress, virtualAddress, arguments.MappingSize); return NvInternalResult.Success; } @@ -246,7 +244,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu NvInternalResult result = NvInternalResult.Success; - lock (addressSpaceContext) + lock (_asContext) { // Note: When the fixed offset flag is not set, // the Offset field holds the alignment size instead. @@ -254,13 +252,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu if (!virtualAddressAllocated) { - if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size, pageSize)) + if (_asContext.ValidateFixedBuffer(arguments.Offset, size, pageSize)) { - addressSpaceContext.Gmm.Map(physicalAddress, arguments.Offset, size); + _asContext.Gmm.Map(physicalAddress, arguments.Offset, size); } else { - string message = string.Format(mapErrorMsg, arguments.Offset, size, pageSize); + string message = string.Format(MapErrorMsg, arguments.Offset, size, pageSize); Logger.Warning?.Print(LogClass.ServiceNv, message); @@ -275,7 +273,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu _memoryAllocator.AllocateRange(va, size, freeAddressStartPosition); } - addressSpaceContext.Gmm.Map(physicalAddress, va, size); + _asContext.Gmm.Map(physicalAddress, va, size); arguments.Offset = va; } @@ -289,7 +287,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu } else { - addressSpaceContext.AddMap(arguments.Offset, size, physicalAddress, virtualAddressAllocated); + _asContext.AddMap(arguments.Offset, size, physicalAddress, virtualAddressAllocated); } } @@ -312,12 +310,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu private NvInternalResult Remap(Span<RemapArguments> arguments) { - AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); + MemoryManager gmm = _asContext.Gmm; for (int index = 0; index < arguments.Length; index++) { - MemoryManager gmm = GetAddressSpaceContext(Context).Gmm; - ulong mapOffs = (ulong)arguments[index].MapOffset << 16; ulong gpuVa = (ulong)arguments[index].GpuOffset << 16; ulong size = (ulong)arguments[index].Pages << 16; @@ -345,10 +341,5 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu } public override void Close() { } - - public static AddressSpaceContext GetAddressSpaceContext(ServiceCtx context) - { - return _addressSpaceContextRegistry.GetOrAdd(context.Process, (key) => new AddressSpaceContext(context)); - } } } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs index 4e7f82ef..ab9d798e 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/Types/AddressSpaceContext.cs @@ -34,9 +34,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types private readonly SortedList<ulong, Range> _maps; private readonly SortedList<ulong, Range> _reservations; - public AddressSpaceContext(ServiceCtx context) + public AddressSpaceContext(MemoryManager gmm) { - Gmm = context.Device.Gpu.MemoryManager; + Gmm = gmm; _maps = new SortedList<ulong, Range>(); _reservations = new SortedList<ulong, Range>(); @@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types return _reservations.Remove(gpuVa); } - private Range BinarySearch(SortedList<ulong, Range> list, ulong address) + private static Range BinarySearch(SortedList<ulong, Range> list, ulong address) { int left = 0; int right = list.Count - 1; @@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types return null; } - private Range BinarySearchLt(SortedList<ulong, Range> list, ulong address) + private static Range BinarySearchLt(SortedList<ulong, Range> list, ulong address) { Range ltRg = null; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs index 644fc835..ebaab0c9 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs @@ -1,13 +1,13 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu.Memory; -using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; using Ryujinx.Memory; using System; +using System.Collections.Concurrent; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -15,6 +15,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel { class NvHostChannelDeviceFile : NvDeviceFile { + private static readonly ConcurrentDictionary<long, Host1xContext> _host1xContextRegistry = new(); + private const uint MaxModuleSyncpoint = 16; private uint _timeout; @@ -24,8 +26,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private readonly Switch _device; private readonly IVirtualMemoryManager _memory; - private readonly NvMemoryAllocator _memoryAllocator; - private readonly GpuChannel _channel; + private readonly Host1xContext _host1xContext; + + public GpuChannel Channel { get; } public enum ResourcePolicy { @@ -43,13 +46,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { - _device = context.Device; - _memory = memory; - _timeout = 3000; - _submitTimeout = 0; - _timeslice = 0; - _memoryAllocator = _device.MemoryAllocator; - _channel = _device.Gpu.CreateChannel(); + _device = context.Device; + _memory = memory; + _timeout = 3000; + _submitTimeout = 0; + _timeslice = 0; + _host1xContext = GetHost1XContext(context.Device.Gpu, owner); + Channel = _device.Gpu.CreateChannel(); ChannelSyncpoints = new uint[MaxModuleSyncpoint]; @@ -162,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel var data = _memory.GetSpan(map.Address + commandBuffer.Offset, commandBuffer.WordsCount * 4); - _device.Host1x.Submit(MemoryMarshal.Cast<byte, int>(data)); + _host1xContext.Host1x.Submit(MemoryMarshal.Cast<byte, int>(data)); } } @@ -172,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel tmpCmdBuff[0] = (4 << 28) | (int)fences[0].Id; - _device.Host1x.Submit(tmpCmdBuff); + _host1xContext.Host1x.Submit(tmpCmdBuff); return NvInternalResult.Success; } @@ -233,7 +236,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel int headerSize = Unsafe.SizeOf<MapCommandBufferArguments>(); MapCommandBufferArguments commandBufferHeader = MemoryMarshal.Cast<byte, MapCommandBufferArguments>(arguments)[0]; Span<CommandBufferHandle> commandBufferEntries = MemoryMarshal.Cast<byte, CommandBufferHandle>(arguments.Slice(headerSize)).Slice(0, commandBufferHeader.NumEntries); - MemoryManager gmm = NvHostAsGpuDeviceFile.GetAddressSpaceContext(Context).Gmm; foreach (ref CommandBufferHandle commandBufferEntry in commandBufferEntries) { @@ -250,12 +252,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel { if (map.DmaMapAddress == 0) { - ulong va = _memoryAllocator.GetFreeAddress((ulong) map.Size, out ulong freeAddressStartPosition, 1, MemoryManager.PageSize); + ulong va = _host1xContext.MemoryAllocator.GetFreeAddress((ulong)map.Size, out ulong freeAddressStartPosition, 1, MemoryManager.PageSize); if (va != NvMemoryAllocator.PteUnmapped && va <= uint.MaxValue && (va + (uint)map.Size) <= uint.MaxValue) { - _memoryAllocator.AllocateRange(va, (uint)map.Size, freeAddressStartPosition); - gmm.Map(map.Address, va, (uint)map.Size); + _host1xContext.MemoryAllocator.AllocateRange(va, (uint)map.Size, freeAddressStartPosition); + _host1xContext.Smmu.Map(map.Address, va, (uint)map.Size); map.DmaMapAddress = va; } else @@ -276,7 +278,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel int headerSize = Unsafe.SizeOf<MapCommandBufferArguments>(); MapCommandBufferArguments commandBufferHeader = MemoryMarshal.Cast<byte, MapCommandBufferArguments>(arguments)[0]; Span<CommandBufferHandle> commandBufferEntries = MemoryMarshal.Cast<byte, CommandBufferHandle>(arguments.Slice(headerSize)).Slice(0, commandBufferHeader.NumEntries); - MemoryManager gmm = NvHostAsGpuDeviceFile.GetAddressSpaceContext(Context).Gmm; foreach (ref CommandBufferHandle commandBufferEntry in commandBufferEntries) { @@ -297,7 +298,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel // To make unmapping work, we need separate address space per channel. // Right now NVDEC and VIC share the GPU address space which is not correct at all. - // gmm.Free((ulong)map.DmaMapAddress, (uint)map.Size); + // _host1xContext.MemoryAllocator.Free((ulong)map.DmaMapAddress, (uint)map.Size); // map.DmaMapAddress = 0; } @@ -431,10 +432,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel if (header.Flags.HasFlag(SubmitGpfifoFlags.FenceWait) && !_device.System.HostSyncpoint.IsSyncpointExpired(header.Fence.Id, header.Fence.Value)) { - _channel.PushHostCommandBuffer(CreateWaitCommandBuffer(header.Fence)); + Channel.PushHostCommandBuffer(CreateWaitCommandBuffer(header.Fence)); } - _channel.PushEntries(entries); + Channel.PushEntries(entries); header.Fence.Id = _channelSyncpoint.Id; @@ -456,7 +457,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel if (header.Flags.HasFlag(SubmitGpfifoFlags.FenceIncrement)) { - _channel.PushHostCommandBuffer(CreateIncrementCommandBuffer(ref header.Fence, header.Flags)); + Channel.PushHostCommandBuffer(CreateIncrementCommandBuffer(ref header.Fence, header.Flags)); } header.Flags = SubmitGpfifoFlags.None; @@ -545,7 +546,22 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel public override void Close() { - _channel.Dispose(); + Channel.Dispose(); + } + + private static Host1xContext GetHost1XContext(GpuContext gpu, long pid) + { + return _host1xContextRegistry.GetOrAdd(pid, (long key) => new Host1xContext(gpu, key)); + } + + public static void Destroy() + { + foreach (Host1xContext host1xContext in _host1xContextRegistry.Values) + { + host1xContext.Dispose(); + } + + _host1xContextRegistry.Clear(); } } } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs b/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs index 44746db6..7369bee5 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs @@ -4,7 +4,7 @@ using System; using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Common.Logging; -namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices +namespace Ryujinx.HLE.HOS.Services.Nv { class NvMemoryAllocator { diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 9d8e526f..6e56aefa 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -49,8 +49,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger private class TextureCallbackInformation { - public Layer Layer; - public BufferItem Item; + public Layer Layer; + public BufferItem Item; } public SurfaceFlinger(Switch device) @@ -385,6 +385,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } _device.Gpu.Window.EnqueueFrameThreadSafe( + layer.Owner, frameBufferAddress, frameBufferWidth, frameBufferHeight, |
