Implement SubmitGpfifoEx and fix nvdec

This commit is contained in:
Thog 2019-10-28 23:42:36 +01:00
commit 72db77fbe6
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
6 changed files with 116 additions and 27 deletions

View file

@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
{ "/dev/nvhost-ctrl", typeof(NvHostCtrlFileDevice) }, { "/dev/nvhost-ctrl", typeof(NvHostCtrlFileDevice) },
{ "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuFileDevice) }, { "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuFileDevice) },
{ "/dev/nvhost-as-gpu", typeof(NvHostAsGpuFileDevice) }, { "/dev/nvhost-as-gpu", typeof(NvHostAsGpuFileDevice) },
{ "/dev/nvhost-gpu", typeof(NvHostChannelFileDevice) }, { "/dev/nvhost-gpu", typeof(NvHostGpuFileDevice) },
//{ "/dev/nvhost-msenc", typeof(NvHostChannelFileDevice) }, //{ "/dev/nvhost-msenc", typeof(NvHostChannelFileDevice) },
{ "/dev/nvhost-nvdec", typeof(NvHostChannelFileDevice) }, { "/dev/nvhost-nvdec", typeof(NvHostChannelFileDevice) },
//{ "/dev/nvhost-nvjpg", typeof(NvHostChannelFileDevice) }, //{ "/dev/nvhost-nvjpg", typeof(NvHostChannelFileDevice) },
@ -67,13 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv
} }
else else
{ {
Logger.PrintWarning(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!");
} }
} }
Logger.PrintWarning(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!");
return -1; return -1;
} }
@ -85,8 +82,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv
NvIoctl.Direction ioctlDirection = ioctlCommand.GetDirectionValue(); NvIoctl.Direction ioctlDirection = ioctlCommand.GetDirectionValue();
uint ioctlSize = ioctlCommand.GetSizeValue(); uint ioctlSize = ioctlCommand.GetSizeValue();
bool isRead = (ioctlDirection & NvIoctl.Direction.Read) == NvIoctl.Direction.Read; bool isRead = (ioctlDirection & NvIoctl.Direction.Read) != 0;
bool isWrite = (ioctlDirection & NvIoctl.Direction.Write) == NvIoctl.Direction.Write; bool isWrite = (ioctlDirection & NvIoctl.Direction.Write) != 0;
if ((isWrite && ioctlSize > outputDataSize) || (isRead && ioctlSize > inputDataSize)) if ((isWrite && ioctlSize > outputDataSize) || (isRead && ioctlSize > inputDataSize))
{ {
@ -403,7 +400,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv
// DumpGraphicsMemoryInfo() // DumpGraphicsMemoryInfo()
public ResultCode DumpGraphicsMemoryInfo(ServiceCtx context) public ResultCode DumpGraphicsMemoryInfo(ServiceCtx context)
{ {
throw new ServiceNotImplementedException(context); Logger.PrintStub(LogClass.ServiceNv);
return ResultCode.Success;
} }
[Command(10)] // 3.0.0+ [Command(10)] // 3.0.0+
@ -414,10 +413,48 @@ namespace Ryujinx.HLE.HOS.Services.Nv
} }
[Command(11)] // 3.0.0+ [Command(11)] // 3.0.0+
// Ioctl2(s32 fd, u32 ioctl_cmd, buffer<bytes, 0x21> in_args, buffer<bytes, 0x21> in_additional_buffer) -> (u32 error_code, buffer<bytes, 0x22> out_args) // Ioctl2(s32 fd, u32 ioctl_cmd, buffer<bytes, 0x21> in_args, buffer<bytes, 0x21> inline_in_buffer) -> (u32 error_code, buffer<bytes, 0x22> out_args)
public ResultCode Ioctl2(ServiceCtx context) public ResultCode Ioctl2(ServiceCtx context)
{ {
throw new ServiceNotImplementedException(context); NvResult errorCode = EnsureInitialized();
if (errorCode == NvResult.Success)
{
int fd = context.RequestData.ReadInt32();
NvIoctl ioctlCommand = context.RequestData.ReadStruct<NvIoctl>();
(long inlineInBufferPosition, long inlineInBufferSize) = context.Request.GetBufferType0x21(1);
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
Span<byte> inlineInBuffer = new Span<byte>(context.Memory.ReadBytes(inlineInBufferPosition, inlineInBufferSize));
if (errorCode == NvResult.Success)
{
errorCode = GetFileDeviceFromFd(fd, out NvFileDevice fileDevice);
if (errorCode == NvResult.Success)
{
NvInternalResult internalResult = fileDevice.Ioctl2(ioctlCommand, arguments, inlineInBuffer);
if (internalResult == NvInternalResult.NotImplemented)
{
throw new NvIoctlNotImplementedException(context, fileDevice, ioctlCommand);
}
errorCode = ConvertInternalErrorCode(internalResult);
if (errorCode == NvResult.Success && (ioctlCommand.GetDirectionValue() & NvIoctl.Direction.Write) != 0)
{
context.Memory.WriteBytes(context.Request.GetBufferType0x22(0).Position, arguments.ToArray());
}
}
}
}
context.ResponseData.Write((uint)errorCode);
return ResultCode.Success;
} }
[Command(12)] // 3.0.0+ [Command(12)] // 3.0.0+
@ -431,7 +468,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv
// FinishInitialize(unknown<8>) // FinishInitialize(unknown<8>)
public ResultCode FinishInitialize(ServiceCtx context) public ResultCode FinishInitialize(ServiceCtx context)
{ {
throw new ServiceNotImplementedException(context); Logger.PrintStub(LogClass.ServiceNv);
return ResultCode.Success;
} }
} }
} }

View file

@ -2,6 +2,7 @@
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
@ -37,25 +38,32 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
return NvInternalResult.NotImplemented; return NvInternalResult.NotImplemented;
} }
public virtual NvInternalResult Ioctl2(NvIoctl command, Span<byte> arguments, Span<byte> inBuffer) public virtual NvInternalResult Ioctl2(NvIoctl command, Span<byte> arguments, Span<byte> inlineInBuffer)
{ {
return NvInternalResult.NotImplemented; return NvInternalResult.NotImplemented;
} }
public virtual NvInternalResult Ioctl3(NvIoctl command, Span<byte> arguments, Span<byte> outBuffer) public virtual NvInternalResult Ioctl3(NvIoctl command, Span<byte> arguments, Span<byte> inlineOutBuffer)
{ {
return NvInternalResult.NotImplemented; return NvInternalResult.NotImplemented;
} }
protected delegate NvInternalResult IoctlProcessor<T>(ref T arguments); protected delegate NvInternalResult IoctlProcessor<T>(ref T arguments);
protected delegate NvInternalResult IoctlProcessorSpan<T>(Span<T> arguments); protected delegate NvInternalResult IoctlProcessorSpan<T>(Span<T> arguments);
protected delegate NvInternalResult IoctlProcessorInline<T, Y>(ref T arguments, Span<Y> inlineData);
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessor<T> callback, Span<byte> arguments) where T : struct protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessor<T> callback, Span<byte> arguments) where T : struct
{ {
Debug.Assert(arguments.Length == Marshal.SizeOf<T>()); Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0]); return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0]);
} }
protected static NvInternalResult CallIoctlMethod<T, Y>(IoctlProcessorInline<T, Y> callback, Span<byte> arguments, Span<byte> inlineInBuffer) where T : struct where Y : struct
{
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0], MemoryMarshal.Cast<byte, Y>(inlineInBuffer));
}
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessorSpan<T> callback, Span<byte> arguments) where T : struct protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessorSpan<T> callback, Span<byte> arguments) where T : struct
{ {
return callback(MemoryMarshal.Cast<byte, T>(arguments)); return callback(MemoryMarshal.Cast<byte, T>(arguments));

View file

@ -243,17 +243,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
SubmitGpfifoArguments gpfifoSubmissionHeader = MemoryMarshal.Cast<byte, SubmitGpfifoArguments>(arguments)[0]; SubmitGpfifoArguments gpfifoSubmissionHeader = MemoryMarshal.Cast<byte, SubmitGpfifoArguments>(arguments)[0];
Span<long> gpfifoEntries = MemoryMarshal.Cast<byte, long>(arguments.Slice(headerSize)).Slice(0, gpfifoSubmissionHeader.NumEntries); Span<long> gpfifoEntries = MemoryMarshal.Cast<byte, long>(arguments.Slice(headerSize)).Slice(0, gpfifoSubmissionHeader.NumEntries);
NvGpuVmm vmm = NvHostAsGpuFileDevice.GetAddressSpaceContext(_owner).Vmm; return SubmitGpfifo(ref gpfifoSubmissionHeader, gpfifoEntries);
foreach (long entry in gpfifoEntries)
{
_gpu.Pusher.Push(vmm, entry);
}
gpfifoSubmissionHeader.Fence.Id = 0;
gpfifoSubmissionHeader.Fence.Value = 0;
return NvInternalResult.Success;
} }
private NvInternalResult AllocObjCtx(ref AllocObjCtxArguments arguments) private NvInternalResult AllocObjCtx(ref AllocObjCtxArguments arguments)
@ -338,6 +328,21 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
return NvInternalResult.Success; return NvInternalResult.Success;
} }
protected NvInternalResult SubmitGpfifo(ref SubmitGpfifoArguments header, Span<long> entries)
{
NvGpuVmm vmm = NvHostAsGpuFileDevice.GetAddressSpaceContext(_owner).Vmm;
foreach (long entry in entries)
{
_gpu.Pusher.Push(vmm, entry);
}
header.Fence.Id = 0;
header.Fence.Value = 0;
return NvInternalResult.Success;
}
public override void Close() public override void Close()
{ {
// TODO // TODO

View file

@ -0,0 +1,33 @@
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
using System;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
{
internal class NvHostGpuFileDevice : NvHostChannelFileDevice
{
public NvHostGpuFileDevice(ServiceCtx context) : base(context)
{
}
public override NvInternalResult Ioctl2(NvIoctl command, Span<byte> arguments, Span<byte> inlineInBuffer)
{
NvInternalResult result = NvInternalResult.NotImplemented;
if (command.GetTypeValue() == NvIoctl.NvHostMagic)
{
switch (command.GetNumberValue())
{
case 0x1b:
result = CallIoctlMethod<SubmitGpfifoArguments, long>(SubmitGpfifoEx, arguments, inlineInBuffer);
break;
}
}
return result;
}
private NvInternalResult SubmitGpfifoEx(ref SubmitGpfifoArguments arguments, Span<long> inlineData)
{
return SubmitGpfifo(ref arguments, inlineData);
}
}
}

View file

@ -9,12 +9,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types
public int MapAddress; public int MapAddress;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MapCommandBufferArguments struct MapCommandBufferArguments
{ {
public int NumEntries; public int NumEntries;
public int DataAddress; // Ignored by the driver. public int DataAddress; // Ignored by the driver.
public bool AttachHostChDas; [MarshalAs(UnmanagedType.I1)]
public bool AttachHostChDas;
public byte Padding1; public byte Padding1;
public short Padding2; public short Padding2;
} }

View file

@ -37,6 +37,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.Types
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.AppendLine($"Device File: {FileDevice.GetType().Name}");
sb.AppendLine();
sb.AppendLine($"Ioctl (0x{Command.RawValue:x8})"); sb.AppendLine($"Ioctl (0x{Command.RawValue:x8})");
sb.AppendLine($"\tNumber: 0x{Command.GetNumberValue():x8}"); sb.AppendLine($"\tNumber: 0x{Command.GetNumberValue():x8}");
sb.AppendLine($"\tType: 0x{Command.GetTypeValue():x8}"); sb.AppendLine($"\tType: 0x{Command.GetTypeValue():x8}");