diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 7c81068ed8..630ca3c038 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -75,6 +75,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span inpu return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output); case 0xd: return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output); + case 0x18: + return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx, input, output, fd); case 0x1a: return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output, fd); case 0x1b: @@ -167,12 +169,36 @@ NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { return NvResult::Success; } -NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params, DeviceFD fd) { - LOG_WARNING(Service_NVDRV, - "called, num_entries={:X}, flags={:X}, unk0={:X}, " - "unk1={:X}, unk2={:X}, unk3={:X}", - params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, - params.unk3); +NvResult nvhost_gpu::AllocGPFIFOEx(IoctlAllocGpfifoEx& params, DeviceFD fd) { + LOG_DEBUG(Service_NVDRV, + "called, num_entries={:X}, flags={:X}, reserved1={:X}, " + "reserved2={:X}, reserved3={:X}", + params.num_entries, params.flags, params.reserved[0], params.reserved[1], + params.reserved[2]); + + if (channel_state->initialized) { + LOG_CRITICAL(Service_NVDRV, "Already allocated!"); + return NvResult::AlreadyAllocated; + } + + u64 program_id{}; + if (auto* const session = core.GetSession(sessions[fd]); session != nullptr) { + program_id = session->process->GetProgramId(); + } + + system.GPU().InitChannel(*channel_state, program_id); + + params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); + + return NvResult::Success; +} + +NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd) { + LOG_DEBUG(Service_NVDRV, + "called, num_entries={:X}, flags={:X}, reserved1={:X}, " + "reserved2={:X}, reserved3={:X}", + params.num_entries, params.flags, params.reserved[0], params.reserved[1], + params.reserved[2]); if (channel_state->initialized) { LOG_CRITICAL(Service_NVDRV, "Already allocated!"); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index e0aeef9536..b4ea1e5f60 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -128,27 +128,13 @@ private: static_assert(sizeof(NvFence) == 8, "Fence is incorrect size"); struct IoctlAllocGpfifoEx { - u32_le num_entries{}; - u32_le flags{}; - u32_le unk0{}; - u32_le unk1{}; - u32_le unk2{}; - u32_le unk3{}; - u32_le unk4{}; - u32_le unk5{}; - }; - static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); - - struct IoctlAllocGpfifoEx2 { u32_le num_entries{}; // in + u32_le num_jobs{}; // in u32_le flags{}; // in - u32_le unk0{}; // in (1 works) NvFence fence_out{}; // out - u32_le unk1{}; // in - u32_le unk2{}; // in - u32_le unk3{}; // in + std::array reserved{}; // in and ingored (for now) according to switch brew }; - static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); + static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); struct IoctlAllocObjCtx { u32_le class_num{}; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, @@ -192,7 +178,8 @@ private: NvResult ZCullBind(IoctlZCullBind& params); NvResult SetErrorNotifier(IoctlSetErrorNotifier& params); NvResult SetChannelPriority(IoctlChannelSetPriority& params); - NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params, DeviceFD fd); + NvResult AllocGPFIFOEx(IoctlAllocGpfifoEx& params, DeviceFD fd); + NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd); NvResult AllocateObjectContext(IoctlAllocObjCtx& params); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries);