diff --git a/nx/Makefile b/nx/Makefile index 03da511a..05438ed2 100644 --- a/nx/Makefile +++ b/nx/Makefile @@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH) #--------------------------------------------------------------------------------- TARGET := nx #BUILD := build -SOURCES := source/arm source/kernel source/services source/nvidia source/nvidia/ioctl source/nvidia/gpu source/display source/audio source/runtime source/runtime/devices source/runtime/util/utf +SOURCES := source/arm source/kernel source/services source/nvidia source/nvidia/ioctl source/display source/audio source/runtime source/runtime/devices source/runtime/util/utf DATA := data INCLUDES := include external/bsd/include diff --git a/nx/include/switch.h b/nx/include/switch.h index eed6c5c5..7ebd44e5 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -89,17 +89,12 @@ extern "C" { #include "switch/display/nvgfx.h" #include "switch/nvidia/ioctl.h" -#include "switch/nvidia/buffer.h" +#include "switch/nvidia/map.h" #include "switch/nvidia/address_space.h" #include "switch/nvidia/channel.h" #include "switch/nvidia/info.h" #include "switch/nvidia/fence.h" -#include "switch/nvidia/gpu/cmd_list.h" -#include "switch/nvidia/gpu/gpfifo.h" -#include "switch/nvidia/gpu/zcull_ctx.h" -#include "switch/nvidia/gpu/3d_ctx.h" -#include "switch/nvidia/gpu/error_notifier.h" -#include "switch/nvidia/gpu/gpu.h" +#include "switch/nvidia/gpu_channel.h" #include "switch/audio/driver.h" diff --git a/nx/include/switch/nvidia/address_space.h b/nx/include/switch/nvidia/address_space.h index dc51ef30..02fa0f39 100644 --- a/nx/include/switch/nvidia/address_space.h +++ b/nx/include/switch/nvidia/address_space.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include "ioctl.h" typedef struct NvAddressSpace { u32 fd; @@ -18,6 +19,3 @@ Result nvAddressSpaceMap(NvAddressSpace* a, u32 nvmap_handle, bool is_gpu_cachea Result nvAddressSpaceMapFixed(NvAddressSpace* a, u32 nvmap_handle, bool is_gpu_cacheable, NvKind kind, iova_t iova); Result nvAddressSpaceModify(NvAddressSpace* a, iova_t iova, u64 offset, u64 size, NvKind kind); Result nvAddressSpaceUnmap(NvAddressSpace* a, iova_t iova); - -struct NvChannel; -Result nvAddressSpaceBindToChannel(NvAddressSpace* a, struct NvChannel* channel); diff --git a/nx/include/switch/nvidia/buffer.h b/nx/include/switch/nvidia/buffer.h deleted file mode 100644 index 5557dd54..00000000 --- a/nx/include/switch/nvidia/buffer.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "types.h" -#include "address_space.h" - -typedef struct NvAddressSpace NvAddressSpace; - -typedef struct NvBuffer { - u32 fd; - u32 size; - void* cpu_addr; - iova_t gpu_addr; - iova_t gpu_addr_texture; - NvAddressSpace* addr_space; - NvKind kind; - bool has_init; - bool is_cpu_cacheable; - bool is_gpu_cacheable; -} NvBuffer; - -Result nvBufferInit(void); -u32 nvBufferGetNvmapFd(void); -void nvBufferExit(void); - -Result nvBufferCreate(NvBuffer* m, size_t size, u32 align, bool is_cpu_cacheable, bool is_gpu_cacheable, NvKind kind, NvAddressSpace* as); -void nvBufferFree(NvBuffer* m); - -void* nvBufferGetCpuAddr(NvBuffer* m); -iova_t nvBufferGetGpuAddr(NvBuffer* m); - -Result nvBufferMapAsTexture(NvBuffer* m, NvKind kind); -iova_t nvBufferGetGpuAddrTexture(NvBuffer* m); diff --git a/nx/include/switch/nvidia/channel.h b/nx/include/switch/nvidia/channel.h index 9bfe1bb8..09572463 100644 --- a/nx/include/switch/nvidia/channel.h +++ b/nx/include/switch/nvidia/channel.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include "ioctl.h" typedef struct NvChannel { u32 fd; @@ -11,4 +12,3 @@ void nvChannelClose(NvChannel* c); Result nvChannelSetPriority(NvChannel* c, NvChannelPriority prio); Result nvChannelSetTimeout(NvChannel* c, u32 timeout); -Result nvChannelSetNvmapFd(NvChannel* c); diff --git a/nx/include/switch/nvidia/gpu/3d_ctx.h b/nx/include/switch/nvidia/gpu/3d_ctx.h deleted file mode 100644 index 124044a5..00000000 --- a/nx/include/switch/nvidia/gpu/3d_ctx.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -typedef struct NvGpu NvGpu; - -typedef struct { - NvGpu* parent; - u64 obj_id; -} Nv3DContext; - -Result nv3DContextCreate(Nv3DContext* t, NvGpu* parent); -void nv3DContextClose(Nv3DContext* t); diff --git a/nx/include/switch/nvidia/gpu/cmd_list.h b/nx/include/switch/nvidia/gpu/cmd_list.h deleted file mode 100644 index 8418d316..00000000 --- a/nx/include/switch/nvidia/gpu/cmd_list.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -typedef struct NvGpu NvGpu; - -typedef struct { - NvBuffer buffer; - size_t offset; - size_t num_cmds; - size_t max_cmds; - NvGpu* parent; -} NvCmdList; - -Result nvCmdListCreate(NvCmdList* c, NvGpu* parent, size_t max_cmds); -void nvCmdListClose(NvCmdList* c); - -iova_t nvCmdListGetGpuAddr(NvCmdList* c); -u64 nvCmdListGetListSize(NvCmdList* c); - -void nvCmdListReset(NvCmdList* c); -u32* nvCmdListInsert(NvCmdList* c, size_t num_cmds); diff --git a/nx/include/switch/nvidia/gpu/error_notifier.h b/nx/include/switch/nvidia/gpu/error_notifier.h deleted file mode 100644 index 1221e5d4..00000000 --- a/nx/include/switch/nvidia/gpu/error_notifier.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef struct NvGpu NvGpu; - -typedef struct { - NvGpu* parent; - Event event; - bool has_init; -} NvErrorNotifier; - -Result nvErrorNotifierCreate(NvErrorNotifier* t, NvGpu* parent); -void nvErrorNotifierClose(NvErrorNotifier* t); -Result nvErrorNotifierWait(NvErrorNotifier* t, u64 timeout); -Result nvErrorNotifierGetError(NvErrorNotifier* t, NvError* out); diff --git a/nx/include/switch/nvidia/gpu/gpfifo.h b/nx/include/switch/nvidia/gpu/gpfifo.h deleted file mode 100644 index 1869737a..00000000 --- a/nx/include/switch/nvidia/gpu/gpfifo.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#define GPFIFO_QUEUE_SIZE 0x800 -#define GPFIFO_ENTRY_NOT_MAIN BIT(9) -#define GPFIFO_ENTRY_NO_PREFETCH BIT(31) - -typedef struct { - NvChannel* parent; - u32 syncpt_id; - u32 num_entries; - nvioctl_gpfifo_entry entries[GPFIFO_QUEUE_SIZE]; -} NvGpfifo; - -Result nvGpfifoCreate(NvGpfifo* f, NvChannel* parent); -void nvGpfifoClose(NvGpfifo* f); - -Result nvGpfifoAppendEntry(NvGpfifo* f, iova_t start, size_t num_cmds, u32 flags); -Result nvGpfifoAppendCmdList(NvGpfifo* f, NvCmdList* cmd_list, u32 flags); -Result nvGpfifoFlush(NvGpfifo* f, u32 fence_incr, NvFence* fence_out); diff --git a/nx/include/switch/nvidia/gpu/gpu.h b/nx/include/switch/nvidia/gpu/gpu.h deleted file mode 100644 index 9827895e..00000000 --- a/nx/include/switch/nvidia/gpu/gpu.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -typedef struct NvGpu { - NvAddressSpace addr_space; - NvChannel gpu_channel; - NvGpfifo gpfifo; - NvZcullContext zcull_ctx; - Nv3DContext _3d_ctx; - NvErrorNotifier error_notifier; -} NvGpu; - -Result nvGpuCreate(NvGpu* g); -void nvGpuClose(NvGpu* g); diff --git a/nx/include/switch/nvidia/gpu/zcull_ctx.h b/nx/include/switch/nvidia/gpu/zcull_ctx.h deleted file mode 100644 index 48176d4f..00000000 --- a/nx/include/switch/nvidia/gpu/zcull_ctx.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -typedef struct NvGpu NvGpu; - -typedef struct { - NvGpu* parent; - NvBuffer ctx_buf; -} NvZcullContext; - -Result nvZcullContextCreate(NvZcullContext* z, NvGpu* parent); -void nvZcullContextClose(NvZcullContext* z); diff --git a/nx/include/switch/nvidia/gpu_channel.h b/nx/include/switch/nvidia/gpu_channel.h new file mode 100644 index 00000000..c89b052b --- /dev/null +++ b/nx/include/switch/nvidia/gpu_channel.h @@ -0,0 +1,43 @@ +#pragma once +#include "../kernel/event.h" +#include "channel.h" +#include "fence.h" + +#define GPFIFO_QUEUE_SIZE 0x800 +#define GPFIFO_ENTRY_NOT_MAIN BIT(9) +#define GPFIFO_ENTRY_NO_PREFETCH BIT(31) + +typedef struct NvGpuChannel +{ + NvChannel base; + Event error_event; + u64 object_id; + NvFence fence; + u32 fence_incr; + nvioctl_gpfifo_entry entries[GPFIFO_QUEUE_SIZE]; + u32 num_entries; +} NvGpuChannel; + +Result nvGpuChannelCreate(NvGpuChannel* c, struct NvAddressSpace* as); +void nvGpuChannelClose(NvGpuChannel* c); + +Result nvGpuChannelZcullBind(NvGpuChannel* c, iova_t iova); +Result nvGpuChannelAppendEntry(NvGpuChannel* c, iova_t start, size_t num_cmds, u32 flags, u32 flush_threshold); +Result nvGpuChannelKickoff(NvGpuChannel* c); +Result nvGpuChannelGetErrorNotification(NvGpuChannel* c, NvError* error); + +static inline u32 nvGpuChannelGetSyncpointId(NvGpuChannel* c) +{ + return c->fence.id; +} + +static inline void nvGpuChannelGetFence(NvGpuChannel* c, NvFence* fence_out) +{ + fence_out->id = c->fence.id; + fence_out->value = c->fence.value + c->fence_incr; +} + +static inline void nvGpuChannelIncrFence(NvGpuChannel* c) +{ + ++c->fence_incr; +} diff --git a/nx/include/switch/nvidia/map.h b/nx/include/switch/nvidia/map.h new file mode 100644 index 00000000..cf3c3cfc --- /dev/null +++ b/nx/include/switch/nvidia/map.h @@ -0,0 +1,34 @@ +#pragma once +#include "types.h" + +typedef struct NvMap { + u32 handle; + u32 id; + u32 size; + void* cpu_addr; + NvKind kind; + bool has_init; + bool is_cpu_cacheable; +} NvMap; + +Result nvMapInit(void); +u32 nvMapGetFd(void); +void nvMapExit(void); + +Result nvMapCreate(NvMap* m, void* cpu_addr, u32 size, u32 align, NvKind kind, bool is_cpu_cacheable); +void nvMapFree(NvMap* m); + +static inline u32 nvMapGetHandle(NvMap* m) +{ + return m->handle; +} + +static inline u32 nvMapGetId(NvMap* m) +{ + return m->id; +} + +static inline void* nvMapGetCpuAddr(NvMap* m) +{ + return m->cpu_addr; +} diff --git a/nx/source/nvidia/address_space.c b/nx/source/nvidia/address_space.c index 9badc09e..8dbf065d 100644 --- a/nx/source/nvidia/address_space.c +++ b/nx/source/nvidia/address_space.c @@ -5,8 +5,6 @@ #include "kernel/svc.h" #include "services/nv.h" #include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/channel.h" #include "nvidia/address_space.h" Result nvAddressSpaceCreate(NvAddressSpace* a, u32 page_size) @@ -96,8 +94,3 @@ Result nvAddressSpaceUnmap(NvAddressSpace* a, iova_t iova) { return nvioctlNvhostAsGpu_UnmapBuffer(a->fd, iova); } - -Result nvAddressSpaceBindToChannel(NvAddressSpace* a, NvChannel* channel) -{ - return nvioctlNvhostAsGpu_BindChannel(a->fd, channel->fd); -} diff --git a/nx/source/nvidia/buffer.c b/nx/source/nvidia/buffer.c deleted file mode 100644 index 4f836039..00000000 --- a/nx/source/nvidia/buffer.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "arm/cache.h" -#include "kernel/svc.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" - -static u32 g_nvmap_fd = -1; -static u64 g_refCnt; - -Result nvBufferInit(void) -{ - Result rc; - - if (atomicIncrement64(&g_refCnt) > 0) - return 0; - - rc = nvOpen(&g_nvmap_fd, "/dev/nvmap"); - - if (R_FAILED(rc)) - atomicDecrement64(&g_refCnt); - - return rc; -} - -void nvBufferExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) - { - if (g_nvmap_fd != -1) - nvClose(g_nvmap_fd); - - g_nvmap_fd = -1; - } -} - -u32 nvBufferGetNvmapFd(void) { - return g_nvmap_fd; -} - -Result nvBufferCreate( - NvBuffer* m, size_t size, u32 align, bool is_cpu_cacheable, bool is_gpu_cacheable, NvKind kind, - NvAddressSpace* as) -{ - Result rc; - - size = (size + align - 1) & ~(align - 1); - - m->has_init = true; - m->is_cpu_cacheable = is_cpu_cacheable; - m->is_gpu_cacheable = is_gpu_cacheable; - m->size = size; - m->fd = -1; - m->cpu_addr = memalign(align, size); - m->gpu_addr = 0; - m->gpu_addr_texture = 0; - m->addr_space = as; - m->kind = kind; - - if (m->cpu_addr == NULL) - return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); - - rc = nvioctlNvmap_Create(g_nvmap_fd, size, &m->fd); - - if (R_SUCCEEDED(rc)) - rc = nvioctlNvmap_Alloc(g_nvmap_fd, m->fd, - 0, is_cpu_cacheable ? 1 : 0, align, kind, m->cpu_addr); - - if (R_SUCCEEDED(rc) && !is_cpu_cacheable) { - armDCacheFlush(m->cpu_addr, m->size); - svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 8); - } - - if (R_SUCCEEDED(rc)) - rc = nvAddressSpaceMap(as, m->fd, is_gpu_cacheable, NvKind_Pitch, &m->gpu_addr); - - if (R_FAILED(rc)) - nvBufferFree(m); - - return rc; -} - -void nvBufferFree(NvBuffer* m) -{ - if (!m->has_init) - return; - - if (m->gpu_addr_texture) { - nvAddressSpaceUnmap(m->addr_space, m->gpu_addr_texture); - m->gpu_addr_texture = 0; - } - - if (m->gpu_addr) { - nvAddressSpaceUnmap(m->addr_space, m->gpu_addr); - m->gpu_addr = 0; - } - - if (m->fd != -1) { - nvioctlNvmap_Free(g_nvmap_fd, m->fd); - m->fd = -1; - } - - if (m->cpu_addr) { - if (!m->is_cpu_cacheable) - svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 0); - - free(m->cpu_addr); - m->cpu_addr = NULL; - } - - m->has_init = false; -} - -void* nvBufferGetCpuAddr(NvBuffer* m) { - return m->cpu_addr; -} - -iova_t nvBufferGetGpuAddr(NvBuffer* m) { - return m->gpu_addr; -} - -Result nvBufferMapAsTexture(NvBuffer* m, NvKind kind) { - return nvAddressSpaceMap(m->addr_space, m->fd, m->is_gpu_cacheable, kind, &m->gpu_addr_texture); -} - -iova_t nvBufferGetGpuAddrTexture(NvBuffer* m) { - return m->gpu_addr_texture; -} diff --git a/nx/source/nvidia/channel.c b/nx/source/nvidia/channel.c index 58270df3..c8099c41 100644 --- a/nx/source/nvidia/channel.c +++ b/nx/source/nvidia/channel.c @@ -5,7 +5,7 @@ #include "kernel/svc.h" #include "services/nv.h" #include "nvidia/ioctl.h" -#include "nvidia/buffer.h" +#include "nvidia/map.h" #include "nvidia/channel.h" Result nvChannelCreate(NvChannel* c, const char* dev) @@ -19,6 +19,9 @@ Result nvChannelCreate(NvChannel* c, const char* dev) if (R_FAILED(rc)) c->fd = -1; + if (R_SUCCEEDED(rc)) + rc = nvioctlChannel_SetNvmapFd(c->fd, nvMapGetFd()); + if (R_FAILED(rc)) nvChannelClose(c); @@ -43,7 +46,3 @@ Result nvChannelSetPriority(NvChannel* c, NvChannelPriority prio) { Result nvChannelSetTimeout(NvChannel* c, u32 timeout) { return nvioctlChannel_SetTimeout(c->fd, timeout); } - -Result nvChannelSetNvmapFd(NvChannel* c) { - return nvioctlChannel_SetNvmapFd(c->fd, nvBufferGetNvmapFd()); -} diff --git a/nx/source/nvidia/gpu/3d_ctx.c b/nx/source/nvidia/gpu/3d_ctx.c deleted file mode 100644 index e01da2f1..00000000 --- a/nx/source/nvidia/gpu/3d_ctx.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - -Result nv3DContextCreate(Nv3DContext* t, NvGpu* parent) -{ - t->parent = parent; - - return nvioctlChannel_AllocObjCtx( - parent->gpu_channel.fd, NvClassNumber_3D, 0, &t->obj_id); -} - -void nv3DContextClose(Nv3DContext* t) { - // Empty -} diff --git a/nx/source/nvidia/gpu/cmd_list.c b/nx/source/nvidia/gpu/cmd_list.c deleted file mode 100644 index 06cf3099..00000000 --- a/nx/source/nvidia/gpu/cmd_list.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - -Result nvCmdListCreate(NvCmdList* c, NvGpu* parent, size_t max_cmds) -{ - Result rc; - - rc = nvBufferCreate( - &c->buffer, max_cmds * 4, 0x1000, NvKind_Pitch, false, false, - &parent->addr_space); - - if (R_SUCCEEDED(rc)) { - c->offset = 0; - c->num_cmds = 0; - c->max_cmds = max_cmds; - c->parent = parent; - } - - return rc; -} - -void nvCmdListClose(NvCmdList* c) { - nvBufferFree(&c->buffer); -} - -iova_t nvCmdListGetGpuAddr(NvCmdList* c) { - return nvBufferGetGpuAddr(&c->buffer); -} - -u64 nvCmdListGetListSize(NvCmdList* c) { - return c->num_cmds; -} - -void nvCmdListReset(NvCmdList* c) { - c->offset = 0; - c->num_cmds = 0; -} - -u32* nvCmdListInsert(NvCmdList* c, size_t num_cmds) -{ - // Has enough space? - if ((c->offset + c->num_cmds + num_cmds) > c->max_cmds) - return NULL; - - c->num_cmds += num_cmds; - - u32* list = (u32*) nvBufferGetCpuAddr(&c->buffer); - return &list[c->offset + c->num_cmds - num_cmds]; -} diff --git a/nx/source/nvidia/gpu/error_notifier.c b/nx/source/nvidia/gpu/error_notifier.c deleted file mode 100644 index ad236eb8..00000000 --- a/nx/source/nvidia/gpu/error_notifier.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - -Result nvErrorNotifierCreate(NvErrorNotifier* t, NvGpu* parent) -{ - Result rc; - - rc = nvQueryEvent(parent->gpu_channel.fd, NvEventId_Gpu_ErrorNotifier, &t->event); - - if (R_SUCCEEDED(rc)) - rc = nvioctlChannel_SetErrorNotifier(parent->gpu_channel.fd, 1); - - if (R_SUCCEEDED(rc)) { - t->parent = parent; - t->has_init = true; - } - - return rc; -} - -void nvErrorNotifierClose(NvErrorNotifier* t) -{ - if (!t->has_init) - return; - - nvioctlChannel_SetErrorNotifier(t->parent->gpu_channel.fd, 0); - eventClose(&t->event); -} - -Result nvErrorNotifierWait(NvErrorNotifier* t, u64 timeout) { - return eventWait(&t->event, timeout); -} - -Result nvErrorNotifierGetError(NvErrorNotifier* t, NvError* out) { - return nvioctlChannel_GetErrorNotification(t->parent->gpu_channel.fd, out); -} diff --git a/nx/source/nvidia/gpu/gpfifo.c b/nx/source/nvidia/gpu/gpfifo.c deleted file mode 100644 index 86324449..00000000 --- a/nx/source/nvidia/gpu/gpfifo.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "kernel/detect.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/info.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - - -Result nvGpfifoCreate(NvGpfifo* f, NvChannel* parent) -{ - f->parent = parent; - - NvFence fence; - Result res = nvioctlChannel_AllocGpfifoEx2(parent->fd, GPFIFO_QUEUE_SIZE, 1, 0, 0, 0, 0, &fence); - f->syncpt_id = fence.id; - return res; -} - -void nvGpfifoClose(NvGpfifo* f) { - /**/ -} - -Result nvGpfifoAppendEntry(NvGpfifo* f, iova_t start, size_t num_cmds, u32 flags) -{ - if (f->num_entries >= GPFIFO_QUEUE_SIZE) - return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); - - nvioctl_gpfifo_entry* entry = &f->entries[f->num_entries++]; - entry->desc = start; - entry->desc32[1] |= flags | (num_cmds << 10); - return 0; -} - -Result nvGpfifoAppendCmdList(NvGpfifo* f, NvCmdList* cmd_list, u32 flags) -{ - Result rc = nvGpfifoAppendEntry(f, - nvCmdListGetGpuAddr(cmd_list) + 4*cmd_list->offset, - cmd_list->num_cmds, - flags); - - if (R_SUCCEEDED(rc)) { - cmd_list->offset += cmd_list->num_cmds; - cmd_list->num_cmds = 0; - } - - return rc; -} - -Result nvGpfifoFlush(NvGpfifo* f, u32 fence_incr, NvFence* fence_out) -{ - Result rc; - NvFence fence; - - if (!f->num_entries) - return MAKERESULT(Module_Libnx, LibnxError_NotFound); - - fence.id = 0; - fence.value = fence_incr; - - u32 flags = BIT(2); - if (fence_incr) - flags |= BIT(8); - - if (kernelAbove400()) - rc = nvioctlChannel_KickoffPb(f->parent->fd, f->entries, f->num_entries, flags, &fence); - else - rc = nvioctlChannel_SubmitGpfifo(f->parent->fd, f->entries, f->num_entries, flags, &fence); - - if (R_SUCCEEDED(rc)) { - f->num_entries = 0; - if (fence_out) - *fence_out = fence; - } - - return rc; -} diff --git a/nx/source/nvidia/gpu/gpu.c b/nx/source/nvidia/gpu/gpu.c deleted file mode 100644 index 34faade1..00000000 --- a/nx/source/nvidia/gpu/gpu.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/info.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - -Result nvGpuCreate(NvGpu* g) -{ - Result rc; - - if (R_FAILED(nvInfoInit())) - return MAKERESULT(Module_Libnx, LibnxError_NvinfoFailedToInitialize); - - if (R_FAILED(nvBufferInit())) { - nvInfoExit(); - return MAKERESULT(Module_Libnx, LibnxError_NvbufFailedToInitialize); - } - - rc = nvChannelCreate(&g->gpu_channel, "/dev/nvhost-gpu"); - - if (R_SUCCEEDED(rc)) - rc = nvAddressSpaceCreate(&g->addr_space, nvInfoGetGpuCharacteristics()->big_page_size); - - if (R_SUCCEEDED(rc)) - rc = nvAddressSpaceBindToChannel(&g->addr_space, &g->gpu_channel); - - if (R_SUCCEEDED(rc)) - rc = nvChannelSetNvmapFd(&g->gpu_channel); - - if (R_SUCCEEDED(rc)) - rc = nvGpfifoCreate(&g->gpfifo, &g->gpu_channel); - - if (R_SUCCEEDED(rc)) - rc = nv3DContextCreate(&g->_3d_ctx, g); - - if (R_SUCCEEDED(rc)) - rc = nvErrorNotifierCreate(&g->error_notifier, g); - - if (R_SUCCEEDED(rc)) - rc = nvChannelSetPriority(&g->gpu_channel, NvChannelPriority_Medium); - - if (R_SUCCEEDED(rc)) - rc = nvZcullContextCreate(&g->zcull_ctx, g); - - if (R_FAILED(rc)) - nvGpuClose(g); - - return rc; -} - -void nvGpuClose(NvGpu* g) -{ - nvErrorNotifierClose(&g->error_notifier); - nvChannelClose(&g->gpu_channel); - nvZcullContextClose(&g->zcull_ctx); - nv3DContextClose(&g->_3d_ctx); - nvGpfifoClose(&g->gpfifo); - nvAddressSpaceClose(&g->addr_space); - - nvBufferExit(); - nvInfoExit(); -} diff --git a/nx/source/nvidia/gpu/zcull_ctx.c b/nx/source/nvidia/gpu/zcull_ctx.c deleted file mode 100644 index ae080bd8..00000000 --- a/nx/source/nvidia/gpu/zcull_ctx.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/svc.h" -#include "kernel/event.h" -#include "services/nv.h" -#include "nvidia/ioctl.h" -#include "nvidia/buffer.h" -#include "nvidia/address_space.h" -#include "nvidia/channel.h" -#include "nvidia/fence.h" -#include "nvidia/info.h" -#include "nvidia/gpu/cmd_list.h" -#include "nvidia/gpu/gpfifo.h" -#include "nvidia/gpu/zcull_ctx.h" -#include "nvidia/gpu/3d_ctx.h" -#include "nvidia/gpu/error_notifier.h" -#include "nvidia/gpu/gpu.h" - -Result nvZcullContextCreate(NvZcullContext* z, NvGpu* parent) -{ - Result rc; - - z->parent = parent; - - rc = nvBufferCreate( - &z->ctx_buf, nvInfoGetZcullCtxSize(), 0x20000, NvKind_Pitch, false, true, - &parent->addr_space); - - if (R_SUCCEEDED(rc)) - rc = nvioctlChannel_ZCullBind( - parent->gpu_channel.fd, nvBufferGetGpuAddr(&z->ctx_buf), - NvZcullConfig_SeparateBuffer); - - return rc; -} - -void nvZcullContextClose(NvZcullContext* z) { - nvBufferFree(&z->ctx_buf); -} diff --git a/nx/source/nvidia/gpu_channel.c b/nx/source/nvidia/gpu_channel.c new file mode 100644 index 00000000..1ecf8cbd --- /dev/null +++ b/nx/source/nvidia/gpu_channel.c @@ -0,0 +1,130 @@ +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/svc.h" +#include "kernel/detect.h" +#include "services/nv.h" +#include "nvidia/ioctl.h" +#include "nvidia/map.h" +#include "nvidia/address_space.h" +#include "nvidia/fence.h" +#include "nvidia/gpu_channel.h" + +Result nvGpuChannelCreate(NvGpuChannel* c, struct NvAddressSpace* as) +{ + Result res; + + res = nvChannelCreate(&c->base, "/dev/nvhost-gpu"); + if (R_FAILED(res)) + return res; + + c->fence_incr = 0; + c->num_entries = 0; + + res = nvioctlNvhostAsGpu_BindChannel(as->fd, c->base.fd); + + if (R_SUCCEEDED(res)) + res = nvioctlChannel_AllocGpfifoEx2(c->base.fd, GPFIFO_QUEUE_SIZE, 1, 0, 0, 0, 0, &c->fence); + + if (R_SUCCEEDED(res)) + res = nvioctlChannel_AllocObjCtx(c->base.fd, NvClassNumber_3D, 0, &c->object_id); + + if (R_SUCCEEDED(res)) + res = nvQueryEvent(c->base.fd, NvEventId_Gpu_ErrorNotifier, &c->error_event); + + if (R_SUCCEEDED(res)) + res = nvioctlChannel_SetErrorNotifier(c->base.fd, 1); + + if (R_SUCCEEDED(res)) + res = nvChannelSetPriority(&c->base, NvChannelPriority_Medium); + + if (R_FAILED(res)) + nvGpuChannelClose(c); + + return res; +} + +void nvGpuChannelClose(NvGpuChannel* c) +{ + if (!c->base.has_init) + return; + + if (c->error_event.revent != INVALID_HANDLE) { + nvioctlChannel_SetErrorNotifier(c->base.fd, 0); + eventClose(&c->error_event); + } + + nvChannelClose(&c->base); +} + +Result nvGpuChannelZcullBind(NvGpuChannel* c, iova_t iova) +{ + return nvioctlChannel_ZCullBind(c->base.fd, iova, NvZcullConfig_SeparateBuffer); +} + +Result nvGpuChannelAppendEntry(NvGpuChannel* c, iova_t start, size_t num_cmds, u32 flags, u32 flush_threshold) +{ + Result res; + if (flush_threshold >= GPFIFO_QUEUE_SIZE) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + if (c->num_entries >= (GPFIFO_QUEUE_SIZE-flush_threshold)) { + res = nvGpuChannelKickoff(c); + if (R_FAILED(res)) + return res; + } + if (c->num_entries >= GPFIFO_QUEUE_SIZE) + return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); + + nvioctl_gpfifo_entry* entry = &c->entries[c->num_entries++]; + entry->desc = start; + entry->desc32[1] |= flags | (num_cmds << 10); + return 0; +} + +static Result _nvGpuChannelKickoffRaw(NvGpuChannel* c, u32 flags) +{ + NvFence fence; + fence.id = 0; + fence.value = c->fence_incr; + + if (kernelAbove400()) + return nvioctlChannel_KickoffPb(c->base.fd, c->entries, c->num_entries, flags, &fence); + else + return nvioctlChannel_SubmitGpfifo(c->base.fd, c->entries, c->num_entries, flags, &fence); +} + +Result nvGpuChannelKickoff(NvGpuChannel* c) +{ + if (!c->num_entries) + return 0; + + u32 flags = BIT(2); + if (c->fence_incr) + flags |= BIT(8); + + Result res; + for (;;) + { + res = _nvGpuChannelKickoffRaw(c, flags); + if (res != MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Busy)) + break; + svcSleepThread(100000000); + } + + if (R_SUCCEEDED(res)) { + c->fence.value += c->fence_incr; + c->fence_incr = 0; + c->num_entries = 0; + } + + return res; +} + +Result nvGpuChannelGetErrorNotification(NvGpuChannel* c, NvError* error) +{ + Result res = eventWait(&c->error_event, 0); + if (R_SUCCEEDED(res)) + res = nvioctlChannel_GetErrorNotification(c->base.fd, error); + return res; +} diff --git a/nx/source/nvidia/info.c b/nx/source/nvidia/info.c index 7feac426..cc77ae3b 100644 --- a/nx/source/nvidia/info.c +++ b/nx/source/nvidia/info.c @@ -5,7 +5,6 @@ #include "kernel/svc.h" #include "services/nv.h" #include "nvidia/ioctl.h" -#include "nvidia/buffer.h" #include "nvidia/info.h" static u32 g_ctrlgpu_fd = -1; diff --git a/nx/source/nvidia/map.c b/nx/source/nvidia/map.c new file mode 100644 index 00000000..b371ed78 --- /dev/null +++ b/nx/source/nvidia/map.c @@ -0,0 +1,102 @@ +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "arm/cache.h" +#include "kernel/svc.h" +#include "services/nv.h" +#include "nvidia/ioctl.h" +#include "nvidia/map.h" + +static u32 g_nvmap_fd = -1; +static u64 g_refCnt; + +Result nvMapInit(void) +{ + Result rc; + + if (atomicIncrement64(&g_refCnt) > 0) + return 0; + + rc = nvOpen(&g_nvmap_fd, "/dev/nvmap"); + + if (R_FAILED(rc)) + atomicDecrement64(&g_refCnt); + + return rc; +} + +void nvMapExit(void) +{ + if (atomicDecrement64(&g_refCnt) == 0) + { + if (g_nvmap_fd != -1) + nvClose(g_nvmap_fd); + + g_nvmap_fd = -1; + } +} + +u32 nvMapGetFd(void) +{ + return g_nvmap_fd; +} + +Result nvMapCreate(NvMap* m, void* cpu_addr, u32 size, u32 align, NvKind kind, bool is_cpu_cacheable) +{ + Result rc; + + if (align < 0x1000) + align = 0x1000; + if (align & (align-1)) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + if (!size || (size & 0xFFF)) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + if (!cpu_addr || ((uintptr_t)cpu_addr & 0xFFF)) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + m->has_init = true; + m->is_cpu_cacheable = is_cpu_cacheable; + m->size = size; + m->handle = -1; + m->cpu_addr = cpu_addr; + m->kind = kind; + + rc = nvioctlNvmap_Create(g_nvmap_fd, size, &m->handle); + + if (R_SUCCEEDED(rc)) + rc = nvioctlNvmap_Alloc(g_nvmap_fd, m->handle, + 0, is_cpu_cacheable ? 1 : 0, align, kind, m->cpu_addr); + + if (R_SUCCEEDED(rc) && !is_cpu_cacheable) { + armDCacheFlush(m->cpu_addr, m->size); + svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 8); + } + + if (R_SUCCEEDED(rc)) + rc = nvioctlNvmap_GetId(g_nvmap_fd, m->handle, &m->id); + + if (R_FAILED(rc)) + nvMapFree(m); + + return rc; +} + +void nvMapFree(NvMap* m) +{ + if (!m->has_init) + return; + + if (m->handle != -1) { + nvioctlNvmap_Free(g_nvmap_fd, m->handle); + m->handle = -1; + } + + if (m->cpu_addr) { + if (!m->is_cpu_cacheable) + svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 0); + m->cpu_addr = NULL; + } + + m->has_init = false; +}