Compare commits

...

13 Commits

Author SHA1 Message Date
Nguyen Dac Nam
e916a991a8 nvdec: add ChannelUnmapCmdBuffer 2020-02-19 14:39:37 +07:00
Nguyen Dac Nam
16cfb8335b nvdec: add ChannelUnmapCmdBuffer stub and implement sync point. 2020-02-19 14:38:42 +07:00
namkazy
4050a1f5bf fix follow change request @lioncash 2020-02-19 08:52:12 +07:00
Nguyen Dac Nam
474425c89d Apply suggestions from code review
Co-Authored-By: Mat M. <mathew1800@gmail.com>
2020-02-19 01:21:18 +07:00
Nguyen Dac Nam
9b9c13caf2 clang-format 2020-02-19 01:08:38 +07:00
Nguyen Dac Nam
c6cf839ef9 clang-format 2020-02-19 01:08:07 +07:00
Nguyen Dac Nam
e44ab5f004 nvhost_nvdec: implement IocChannelGetSyncPoint and ChannelSubmit 2020-02-19 01:03:51 +07:00
Nguyen Dac Nam
5479b9b50d nvhost_nvdec: add IocChannelGetSyncPoint and ChannelSubmit 2020-02-19 01:03:22 +07:00
Nguyen Dac Nam
a039b29eb3 nvhost_nvdec: implement ChannelGetWaitBase 2020-02-19 01:02:08 +07:00
Nguyen Dac Nam
5381beb694 nvhost_nvdec: IocChannelGetWaitBase header 2020-02-19 01:01:28 +07:00
Nguyen Dac Nam
a1342a0042 nvhost_nvdec: stubbed ChannelMapCmdBuffer 2020-02-19 00:58:20 +07:00
Nguyen Dac Nam
633474b561 nvhost_nvdec: add function ChannelMapCmdBuffer 2020-02-19 00:56:49 +07:00
Nguyen Dac Nam
1ec70c2355 nvhost_nvdec: define IoctlMapCmdBuffer and IoctlHandleMapBuffer 2020-02-19 00:55:18 +07:00
2 changed files with 246 additions and 0 deletions

View File

@@ -6,10 +6,18 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
#include "video_core/gpu.h"
namespace Service::Nvidia::Devices {
constexpr u32 NVHOST_IOCTL_MAGIC(0x0);
constexpr u32 NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER(0x9);
constexpr u32 NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER_EX(0x25);
constexpr u32 NVHOST_IOCTL_CHANNEL_UNMAP_CMD_BUFFER(0x0A);
constexpr u32 NVHOST_IOCTL_CHANNEL_SUBMIT(0x1);
nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {}
nvhost_nvdec::~nvhost_nvdec() = default;
@@ -22,6 +30,20 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::IocSetNVMAPfdCommand:
return SetNVMAPfd(input, output);
case IoctlCommand::IocChannelGetWaitBase:
return ChannelGetWaitBase(input, output);
case IoctlCommand::IocChannelGetSyncPoint:
return ChannelGetSyncPoint(input, output);
}
if (command.group == NVHOST_IOCTL_MAGIC) {
if (command.cmd == NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER) {
return ChannelMapCmdBuffer(input, output);
} else if (command.cmd == NVHOST_IOCTL_CHANNEL_UNMAP_CMD_BUFFER) {
return ChannelUnmapCmdBuffer(input, output);
} else if (command.cmd == NVHOST_IOCTL_CHANNEL_SUBMIT) {
return ChannelSubmit(input, output);
}
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -37,4 +59,119 @@ u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& outp
return 0;
}
u32 nvhost_nvdec::ChannelSubmit(const std::vector<u8>& input, std::vector<u8>& output) {
u32 start_point = 16;
auto& gpu = system.GPU();
IoctlSubmit params{};
std::memcpy(&params, input.data(), start_point);
std::vector<IoctlCmdBuf> cmd_bufs(params.num_cmdbufs);
std::memcpy(cmd_bufs.data(), input.data() + start_point,
sizeof(IoctlCmdBuf) * params.num_cmdbufs);
start_point += sizeof(IoctlCmdBuf) * params.num_cmdbufs;
// TODO(namkazt): what to do with this?
std::vector<IoctlReloc> relocs(params.num_relocs);
std::memcpy(relocs.data(), input.data() + start_point, sizeof(IoctlReloc) * params.num_relocs);
start_point += sizeof(IoctlReloc) * params.num_relocs;
// TODO(namkazt): what to do with this?
std::vector<IoctlRelocShift> reloc_shifts(params.num_relocs);
std::memcpy(reloc_shifts.data(), input.data() + start_point,
sizeof(IoctlRelocShift) * params.num_relocs);
start_point += sizeof(IoctlRelocShift) * params.num_relocs;
// TODO(namkazt): what to do with this?
std::vector<IoctlSyncPtIncr> sync_point_incrs(params.num_syncpt_incrs);
std::memcpy(sync_point_incrs.data(), input.data() + start_point,
sizeof(IoctlSyncPtIncr) * params.num_syncpt_incrs);
start_point += sizeof(IoctlSyncPtIncr) * params.num_syncpt_incrs;
// apply increment to sync points
for (const auto& sync_incr : sync_point_incrs) {
if (sync_incr.syncpt_id >= MaxSyncPoints) {
continue;
}
gpu.IncrementSyncPoint(sync_incr.syncpt_id);
}
// TODO(namkazt): check on fence
LOG_WARNING(
Service_NVDRV,
"(STUBBED) called, num_cmdbufs: {}, num_relocs: {}, num_syncpt_incrs: {}, num_fences: {}",
params.num_cmdbufs, params.num_relocs, params.num_syncpt_incrs, params.num_fences);
std::memcpy(output.data(), &params, sizeof(params));
// TODO(namkazt): write result back to output
return NvResult::Success;
}
u32 nvhost_nvdec::ChannelGetSyncPoint(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlChannelSyncPoint params{};
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "called, module_id: {}", params.syncpt_id);
if (params.syncpt_id >= MaxSyncPoints) {
return NvResult::BadParameter;
}
auto& gpu = system.GPU();
params.syncpt_value = gpu.GetSyncpointValue(params.syncpt_id);
std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
u32 nvhost_nvdec::ChannelGetWaitBase(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlChannelWaitBase params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, module_id: {}", params.module_id);
params.waitbase_value = 0;
std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
u32 nvhost_nvdec::ChannelMapCmdBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlMapCmdBuffer params{};
std::memcpy(&params, input.data(), sizeof(params));
std::vector<IoctlHandleMapBuffer> handles(params.num_handles);
std::memcpy(handles.data(), input.data() + sizeof(params),
sizeof(IoctlHandleMapBuffer) * params.num_handles);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, num_handles: {}, is_compressed: {}",
params.num_handles, params.is_compressed);
// TODO(namkazt): Uses nvmap_pin internally to pin a given number of nvmap handles to an
// appropriate device physical address.
std::memcpy(output.data(), &params, sizeof(params));
std::memcpy(output.data() + sizeof(params), handles.data(),
sizeof(IoctlHandleMapBuffer) * params.num_handles);
return NvResult::Success;
}
u32 nvhost_nvdec::ChannelUnmapCmdBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlUnmapCmdBuffer params{};
std::memcpy(&params, input.data(), sizeof(params));
std::vector<IoctlHandleUnmapBuffer> handles(params.num_handles);
std::memcpy(handles.data(), input.data() + sizeof(params),
sizeof(IoctlHandleUnmapBuffer) * params.num_handles);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, num_handles: {}, is_compressed: {}",
params.num_handles, params.is_compressed);
// TODO(namkazt): Uses nvmap_unpin internally to unpin a given number of nvmap handles from
// their device physical address.
std::memcpy(output.data(), &params, sizeof(params));
std::memcpy(output.data() + sizeof(params), handles.data(),
sizeof(IoctlHandleMapBuffer) * params.num_handles);
return NvResult::Success;
}
} // namespace Service::Nvidia::Devices

View File

@@ -8,6 +8,7 @@
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
#include "core/hle/service/nvdrv/nvdrv.h"
namespace Service::Nvidia::Devices {
@@ -23,6 +24,8 @@ public:
private:
enum class IoctlCommand : u32_le {
IocSetNVMAPfdCommand = 0x40044801,
IocChannelGetSyncPoint = 0xC0080002,
IocChannelGetWaitBase = 0xC0080003,
};
struct IoctlSetNvmapFD {
@@ -30,9 +33,115 @@ private:
};
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
struct IoctlCmdBuf {
u32_le mem;
u32_le offset;
u32_le words;
};
static_assert(sizeof(IoctlCmdBuf) == 12, "IoctlCmdBuf is incorrect size");
struct IoctlReloc {
u32_le cmdbuf_mem;
u32_le cmdbuf_offset;
u32_le target;
u32_le target_offset;
};
static_assert(sizeof(IoctlReloc) == 16, "IoctlReloc is incorrect size");
struct IoctlRelocShift {
u32_le shift;
};
static_assert(sizeof(IoctlRelocShift) == 4, "IoctlRelocShift is incorrect size");
struct IoctlSyncPtIncr {
u32_le syncpt_id;
u32_le syncpt_incrs;
};
static_assert(sizeof(IoctlSyncPtIncr) == 8, "IoctlSyncPtIncr is incorrect size");
struct IoctlFence {
u32_le id;
u32_le thresh;
};
static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size");
struct IoctlSubmit {
// [in]
u32_le num_cmdbufs;
// [in]
u32_le num_relocs;
// [in]
u32_le num_syncpt_incrs;
// [in]
u32_le num_fences;
// __in struct cmdbuf cmdbufs[];
// __in struct reloc relocs[];
// __in struct reloc_shift reloc_shifts[];
// __in struct syncpt_incr syncpt_incrs[];
// __out struct fence fences[];
};
static_assert(sizeof(IoctlSubmit) == 16, "IoctlSubmit is incorrect size");
struct IoctlHandleMapBuffer {
u32_le handle_id_in; // nvmap handle to map
u32_le phys_addr_out; // returned device physical address mapped to the handle
};
static_assert(sizeof(IoctlHandleMapBuffer) == 8, "IoctlHandleMapBuffer is incorrect size");
struct IoctlMapCmdBuffer {
// [in] number of nvmap handles to map
u32_le num_handles;
// [in] ignored
INSERT_PADDING_BYTES(0x4);
// [in] memory to map is compressed
u8 is_compressed;
// [in] padding[3] u8 ignored
INSERT_PADDING_BYTES(0x3);
};
static_assert(sizeof(IoctlMapCmdBuffer) == 12, "IoctlMapCmdBuffer is incorrect size");
struct IoctlHandleUnmapBuffer {
u32_le handle_id_in; // nvmap handle to map
INSERT_PADDING_BYTES(0x4); // reserved - ignored
};
static_assert(sizeof(IoctlHandleUnmapBuffer) == 8, "IoctlHandleUnmapBuffer is incorrect size");
struct IoctlUnmapCmdBuffer {
// [in] number of nvmap handles to map
u32_le num_handles;
// [in] ignored
INSERT_PADDING_BYTES(0x4);
// [in] memory to map is compressed
u8 is_compressed;
// [in] padding[3] u8 ignored
INSERT_PADDING_BYTES(0x3);
};
static_assert(sizeof(IoctlUnmapCmdBuffer) == 12, "IoctlUnmapCmdBuffer is incorrect size");
struct IoctlChannelWaitBase {
// [in]
u32_le module_id;
// [out] Returns the current waitbase value for a given module. Always returns 0
u32_le waitbase_value;
};
static_assert(sizeof(IoctlChannelWaitBase) == 8, "IoctChannelWaitBase is incorrect size");
struct IoctlChannelSyncPoint {
// [in]
u32_le syncpt_id;
// [out] Returns the current syncpoint value for a given module. Identical to Linux driver.
u32_le syncpt_value;
};
static_assert(sizeof(IoctlChannelSyncPoint) == 8, "IoctChannelSyncPoint is incorrect size");
u32_le nvmap_fd{};
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelSubmit(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelGetSyncPoint(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelGetWaitBase(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelMapCmdBuffer(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelUnmapCmdBuffer(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices