mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-06-01 02:18:46 +02:00
130 lines
4.6 KiB
C++
130 lines
4.6 KiB
C++
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
|
|
#include <os.h>
|
|
#include <gpu/gpfifo.h>
|
|
#include <kernel/types/KProcess.h>
|
|
#include <services/nvdrv/driver.h>
|
|
#include "nvhost_channel.h"
|
|
|
|
namespace skyline::service::nvdrv::device {
|
|
NvHostChannel::NvHostChannel(const DeviceState &state, NvDeviceType type) : smExceptionBreakpointIntReportEvent(std::make_shared<type::KEvent>(state)), smExceptionBreakpointPauseReportEvent(std::make_shared<type::KEvent>(state)), errorNotifierEvent(std::make_shared<type::KEvent>(state)), NvDevice(state, type, {
|
|
{0x4801, NFUNC(NvHostChannel::SetNvmapFd)},
|
|
{0x4803, NFUNC(NvHostChannel::SetSubmitTimeout)},
|
|
{0x4808, NFUNC(NvHostChannel::SubmitGpfifo)},
|
|
{0x4809, NFUNC(NvHostChannel::AllocObjCtx)},
|
|
{0x480B, NFUNC(NvHostChannel::ZcullBind)},
|
|
{0x480C, NFUNC(NvHostChannel::SetErrorNotifier)},
|
|
{0x480D, NFUNC(NvHostChannel::SetPriority)},
|
|
{0x481A, NFUNC(NvHostChannel::AllocGpfifoEx2)},
|
|
{0x4714, NFUNC(NvHostChannel::SetUserData)},
|
|
}) {
|
|
auto driver = nvdrv::driver.lock();
|
|
auto &hostSyncpoint = driver->hostSyncpoint;
|
|
|
|
channelFence.id = hostSyncpoint.AllocateSyncpoint(false);
|
|
channelFence.UpdateValue(hostSyncpoint);
|
|
}
|
|
|
|
void NvHostChannel::SetNvmapFd(IoctlData &buffer) {}
|
|
|
|
void NvHostChannel::SetSubmitTimeout(IoctlData &buffer) {}
|
|
|
|
void NvHostChannel::SubmitGpfifo(IoctlData &buffer) {
|
|
struct Data {
|
|
u64 address;
|
|
u32 numEntries;
|
|
union {
|
|
struct __attribute__((__packed__)) {
|
|
bool fenceWait : 1;
|
|
bool fenceIncrement : 1;
|
|
bool hwFormat : 1;
|
|
u8 _pad0_ : 1;
|
|
bool suppressWfi : 1;
|
|
u8 _pad1_ : 3;
|
|
bool incrementWithValue : 1;
|
|
};
|
|
u32 raw;
|
|
} flags;
|
|
Fence fence;
|
|
} &args = state.process->GetReference<Data>(buffer.output.at(0).address);
|
|
|
|
auto driver = nvdrv::driver.lock();
|
|
auto &hostSyncpoint = driver->hostSyncpoint;
|
|
|
|
if (args.flags.fenceWait) {
|
|
if (args.flags.incrementWithValue) {
|
|
buffer.status = NvStatus::BadValue;
|
|
return;
|
|
}
|
|
|
|
if (hostSyncpoint.HasSyncpointExpired(args.fence.id, args.fence.value))
|
|
throw exception("Waiting on a fence through SubmitGpfifo is unimplemented");
|
|
}
|
|
|
|
state.gpu->gpfifo.Push(std::span(state.process->GetPointer<gpu::gpfifo::GpEntry>(args.address), args.numEntries));
|
|
|
|
args.fence.id = channelFence.id;
|
|
|
|
u32 increment = (args.flags.fenceIncrement ? 2 : 0) + (args.flags.incrementWithValue ? args.fence.value : 0);
|
|
args.fence.value = hostSyncpoint.IncrementSyncpointMaxExt(args.fence.id, increment);
|
|
|
|
if (args.flags.fenceIncrement)
|
|
throw exception("Incrementing a fence through SubmitGpfifo is unimplemented");
|
|
|
|
args.flags.raw = 0;
|
|
}
|
|
|
|
void NvHostChannel::AllocObjCtx(IoctlData &buffer) {}
|
|
|
|
void NvHostChannel::ZcullBind(IoctlData &buffer) {}
|
|
|
|
void NvHostChannel::SetErrorNotifier(IoctlData &buffer) {}
|
|
|
|
void NvHostChannel::SetPriority(IoctlData &buffer) {
|
|
auto priority = state.process->GetObject<NvChannelPriority>(buffer.input.at(0).address);
|
|
|
|
switch (priority) {
|
|
case NvChannelPriority::Low:
|
|
timeslice = 1300;
|
|
break;
|
|
case NvChannelPriority::Medium:
|
|
timeslice = 2600;
|
|
break;
|
|
case NvChannelPriority::High:
|
|
timeslice = 5200;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NvHostChannel::AllocGpfifoEx2(IoctlData &buffer) {
|
|
struct Data {
|
|
u32 numEntries;
|
|
u32 numJobs;
|
|
u32 flags;
|
|
Fence fence;
|
|
u32 reserved[3];
|
|
} &args = state.process->GetReference<Data>(buffer.input.at(0).address);
|
|
|
|
auto driver = nvdrv::driver.lock();
|
|
channelFence.UpdateValue(driver->hostSyncpoint);
|
|
args.fence = channelFence;
|
|
}
|
|
|
|
void NvHostChannel::SetUserData(IoctlData &buffer) {}
|
|
|
|
std::shared_ptr<type::KEvent> NvHostChannel::QueryEvent(u32 eventId) {
|
|
switch (eventId) {
|
|
case 1:
|
|
return smExceptionBreakpointIntReportEvent;
|
|
case 2:
|
|
return smExceptionBreakpointPauseReportEvent;
|
|
case 3:
|
|
return errorNotifierEvent;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
}
|