Implement SubmitGpfifoEx and fix nvdec
This commit is contained in:
parent
9b6bafb742
commit
72db77fbe6
6 changed files with 116 additions and 27 deletions
|
@ -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,12 +67,9 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,12 @@ 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.
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
public bool AttachHostChDas;
|
public bool AttachHostChDas;
|
||||||
public byte Padding1;
|
public byte Padding1;
|
||||||
public short Padding2;
|
public short Padding2;
|
||||||
|
|
|
@ -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}");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue