From c00c638ecc2c7266a19e49fe4427ce840a333f55 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Mon, 2 Sep 2019 01:55:38 +0200 Subject: [PATCH] NvHostChannelIoctl: Implement setter for SetSubmitTimeout, SetPriority and SetTimeslice (#747) - Implement accurate setter for SetPriority. - Implement accurate setter for SetTimeslice (close #666). - Implement basic setter for SetSubmitTimeout (close #678). (plus some comments and a missing `PrintStub` call) --- .../Services/Nv/NvHostChannel/NvChannel.cs | 2 + .../Nv/NvHostChannel/NvChannelPriority.cs | 9 +++ .../Nv/NvHostChannel/NvHostChannelIoctl.cs | 56 ++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannelPriority.cs diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannel.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannel.cs index 54e709f9..74d27a75 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannel.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannel.cs @@ -3,5 +3,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel class NvChannel { public int Timeout; + public int SubmitTimeout; + public int Timeslice; } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannelPriority.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannelPriority.cs new file mode 100644 index 00000000..d41e7609 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvChannelPriority.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel +{ + enum NvChannelPriority + { + Low = 50, + Medium = 100, + High = 150 + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs index e7879f4a..fdfb3fa5 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs @@ -25,6 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel case 0x0001: return Submit (context); case 0x0002: return GetSyncpoint (context); case 0x0003: return GetWaitBase (context); + case 0x0007: return SetSubmitTimeout (context); case 0x0009: return MapBuffer (context); case 0x000a: return UnmapBuffer (context); case 0x4714: return SetUserData (context); @@ -37,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel case 0x480d: return SetPriority (context); case 0x481a: return AllocGpfifoEx2 (context); case 0x481b: return KickoffPbWithAttr(context); + case 0x481d: return SetTimeslice (context); } throw new NotImplementedException(cmd.ToString("x8")); @@ -103,6 +105,19 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel return NvResult.Success; } + private static int SetSubmitTimeout(ServiceCtx context) + { + long inputPosition = context.Request.GetBufferType0x21().Position; + + GetChannel(context).SubmitTimeout = context.Memory.ReadInt32(inputPosition); + + // TODO: Handle the timeout in the submit method. + + Logger.PrintStub(LogClass.ServiceNv); + + return NvResult.Success; + } + private static int MapBuffer(ServiceCtx context) { long inputPosition = context.Request.GetBufferType0x21().Position; @@ -200,6 +215,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel GetChannel(context).Timeout = context.Memory.ReadInt32(inputPosition); + Logger.PrintStub(LogClass.ServiceNv); + return NvResult.Success; } @@ -259,11 +276,27 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel private static int SetPriority(ServiceCtx context) { - long inputPosition = context.Request.GetBufferType0x21().Position; - long outputPosition = context.Request.GetBufferType0x22().Position; + long inputPosition = context.Request.GetBufferType0x21().Position; + + switch ((NvChannelPriority)context.Memory.ReadInt32(inputPosition)) + { + case NvChannelPriority.Low: + GetChannel(context).Timeslice = 1300; // Timeslice low priority in micro-seconds + break; + case NvChannelPriority.Medium: + GetChannel(context).Timeslice = 2600; // Timeslice medium priority in micro-seconds + break; + case NvChannelPriority.High: + GetChannel(context).Timeslice = 5200; // Timeslice high priority in micro-seconds + break; + default: + return NvResult.InvalidInput; + } Logger.PrintStub(LogClass.ServiceNv); + // TODO: disable and preempt channel when GPU scheduler will be implemented. + return NvResult.Success; } @@ -301,6 +334,25 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel return NvResult.Success; } + private static int SetTimeslice(ServiceCtx context) + { + long inputPosition = context.Request.GetBufferType0x21().Position; + int timeslice = context.Memory.ReadInt32(inputPosition); + + if (timeslice < 1000 || timeslice > 50000) + { + return NvResult.InvalidInput; + } + + GetChannel(context).Timeslice = timeslice; // in micro-seconds + + Logger.PrintStub(LogClass.ServiceNv); + + // TODO: disable and preempt channel when GPU scheduler will be implemented. + + return NvResult.Success; + } + private static void PushGpfifo(ServiceCtx context, NvGpuVmm vmm, long gpfifo) { context.Device.Gpu.Pusher.Push(vmm, gpfifo);