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)
This commit is contained in:
Ac_K 2019-09-02 01:55:38 +02:00 committed by gdkchan
parent a1c7415565
commit c00c638ecc
3 changed files with 65 additions and 2 deletions

View file

@ -3,5 +3,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
class NvChannel class NvChannel
{ {
public int Timeout; public int Timeout;
public int SubmitTimeout;
public int Timeslice;
} }
} }

View file

@ -0,0 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
{
enum NvChannelPriority
{
Low = 50,
Medium = 100,
High = 150
}
}

View file

@ -25,6 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
case 0x0001: return Submit (context); case 0x0001: return Submit (context);
case 0x0002: return GetSyncpoint (context); case 0x0002: return GetSyncpoint (context);
case 0x0003: return GetWaitBase (context); case 0x0003: return GetWaitBase (context);
case 0x0007: return SetSubmitTimeout (context);
case 0x0009: return MapBuffer (context); case 0x0009: return MapBuffer (context);
case 0x000a: return UnmapBuffer (context); case 0x000a: return UnmapBuffer (context);
case 0x4714: return SetUserData (context); case 0x4714: return SetUserData (context);
@ -37,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
case 0x480d: return SetPriority (context); case 0x480d: return SetPriority (context);
case 0x481a: return AllocGpfifoEx2 (context); case 0x481a: return AllocGpfifoEx2 (context);
case 0x481b: return KickoffPbWithAttr(context); case 0x481b: return KickoffPbWithAttr(context);
case 0x481d: return SetTimeslice (context);
} }
throw new NotImplementedException(cmd.ToString("x8")); throw new NotImplementedException(cmd.ToString("x8"));
@ -103,6 +105,19 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
return NvResult.Success; 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) private static int MapBuffer(ServiceCtx context)
{ {
long inputPosition = context.Request.GetBufferType0x21().Position; long inputPosition = context.Request.GetBufferType0x21().Position;
@ -200,6 +215,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
GetChannel(context).Timeout = context.Memory.ReadInt32(inputPosition); GetChannel(context).Timeout = context.Memory.ReadInt32(inputPosition);
Logger.PrintStub(LogClass.ServiceNv);
return NvResult.Success; return NvResult.Success;
} }
@ -259,11 +276,27 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
private static int SetPriority(ServiceCtx context) private static int SetPriority(ServiceCtx context)
{ {
long inputPosition = context.Request.GetBufferType0x21().Position; long inputPosition = context.Request.GetBufferType0x21().Position;
long outputPosition = context.Request.GetBufferType0x22().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); Logger.PrintStub(LogClass.ServiceNv);
// TODO: disable and preempt channel when GPU scheduler will be implemented.
return NvResult.Success; return NvResult.Success;
} }
@ -301,6 +334,25 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
return NvResult.Success; 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) private static void PushGpfifo(ServiceCtx context, NvGpuVmm vmm, long gpfifo)
{ {
context.Device.Gpu.Pusher.Push(vmm, gpfifo); context.Device.Gpu.Pusher.Push(vmm, gpfifo);