diff --git a/nx/include/switch/nvidia/buffer.h b/nx/include/switch/nvidia/buffer.h index e7c7e5a9..1386785c 100644 --- a/nx/include/switch/nvidia/buffer.h +++ b/nx/include/switch/nvidia/buffer.h @@ -258,5 +258,8 @@ void nvBufferExit(void); Result nvBufferCreate(NvBuffer* m, size_t size, u32 align, NvBufferKind kind); Result nvBufferCreateRw(NvBuffer* m, size_t size, u32 align, NvBufferKind kind); void nvBufferFree(NvBuffer* m); - void* nvBufferGetAddr(NvBuffer* m); + +Result nvBufferMakeCpuUncached(NvBuffer* m); +Result nvBufferMakeCpuCached(NvBuffer* m); + diff --git a/nx/include/switch/nvidia/gpu/cmd_list.h b/nx/include/switch/nvidia/gpu/cmd_list.h index 24301f2e..b2bbb252 100644 --- a/nx/include/switch/nvidia/gpu/cmd_list.h +++ b/nx/include/switch/nvidia/gpu/cmd_list.h @@ -1,14 +1,19 @@ #pragma once +typedef struct NvGpu NvGpu; + typedef struct { NvBuffer buffer; + size_t num_cmds; + size_t max_cmds; + NvGpu* parent; + iova_t gpu_addr; } NvCmdList; -static inline iova_t nvcmdsGetGpuAddr() { - return 0; // TODO -} +Result nvCmdListCreate(NvCmdList* c, NvGpu* parent, size_t max_cmds); +void nvCmdListClose(NvCmdList* c); -static inline u64 nvcmdsGetListSize() { - return 0; // TODO -} +iova_t nvCmdListGetGpuAddr(NvCmdList* c); +u64 nvCmdListGetListSize(NvCmdList* c); +u32* nvCmdListInsert(NvCmdList* c, size_t num_cmds); diff --git a/nx/source/nvidia/buffer.c b/nx/source/nvidia/buffer.c index fda0e744..6d0e6434 100644 --- a/nx/source/nvidia/buffer.c +++ b/nx/source/nvidia/buffer.c @@ -2,6 +2,7 @@ #include "types.h" #include "result.h" #include "arm/atomics.h" +#include "kernel/svc.h" #include "services/nv.h" #include "nvidia/ioctl.h" #include "nvidia/buffer.h" @@ -60,7 +61,8 @@ static Result _nvBufferCreate(NvBuffer* m, size_t size, u32 flags, u32 align, Nv m->fd = -1; if (R_SUCCEEDED(rc)) - rc = nvioctlNvmap_Alloc(g_nvmap_fd, m->fd, 0, flags | NvBufferFlags_Nintendo, align, kind, m->ptr); + rc = nvioctlNvmap_Alloc( + g_nvmap_fd, m->fd, 0, flags | NvBufferFlags_Nintendo, align, kind, m->ptr); if (R_FAILED(rc)) nvBufferFree(m); @@ -76,6 +78,14 @@ Result nvBufferCreateRw(NvBuffer* m, size_t size, u32 align, NvBufferKind kind) return _nvBufferCreate(m, size, NvBufferFlags_Writable, align, kind); } +Result nvBufferMakeCpuUncached(NvBuffer* m) { + return svcSetMemoryAttribute(m->ptr, m->size, 8, 8); +} + +Result nvBufferMakeCpuCached(NvBuffer* m) { + return svcSetMemoryAttribute(m->ptr, m->size, 8, 0); +} + void nvBufferFree(NvBuffer* m) { if (!m->has_init) diff --git a/nx/source/nvidia/gpu/cmd_list.c b/nx/source/nvidia/gpu/cmd_list.c new file mode 100644 index 00000000..33d84537 --- /dev/null +++ b/nx/source/nvidia/gpu/cmd_list.c @@ -0,0 +1,49 @@ +#include + +Result nvCmdListCreate(NvCmdList* c, NvGpu* parent, size_t max_cmds) +{ + Result rc; + + rc = nvBufferCreate(&c->buffer, max_cmds * 4, 0x1000, NvBufferKind_Pitch); + + if (R_SUCCEEDED(rc)) { + nvBufferMakeCpuUncached(&c->buffer); + + rc = nvAddressSpaceMapBuffer( + &parent->addr_space, &c->buffer, NvBufferKind_Pitch, &c->gpu_addr); + + c->num_cmds = 0; + c->max_cmds = max_cmds; + c->parent = parent; + } + + return rc; +} + +void nvCmdListClose(NvCmdList* c) +{ + // TODO: nvAddressSpaceUnmapBuffer? + nvBufferMakeCpuCached(&c->buffer); + nvBufferFree(&c->buffer); +} + +iova_t nvCmdListGetGpuAddr(NvCmdList* c) { + return c->gpu_addr; +} + +u64 nvCmdListGetListSize(NvCmdList* c) { + return c->num_cmds * 4; +} + +u32* nvCmdListInsert(NvCmdList* c, size_t num_cmds) +{ + // Has enough space? + if ((c->num_cmds + num_cmds) > c->max_cmds) + return NULL; + + u32* ptr = (u32*) nvBufferGetAddr(&c->buffer); + ptr += c->num_cmds; + + c->num_cmds += num_cmds; + return ptr; +} diff --git a/nx/source/nvidia/gpu/gpfifo.c b/nx/source/nvidia/gpu/gpfifo.c index 007d9ce8..d27cae47 100644 --- a/nx/source/nvidia/gpu/gpfifo.c +++ b/nx/source/nvidia/gpu/gpfifo.c @@ -20,7 +20,7 @@ Result nvGpfifoSubmit(NvGpfifo* f, NvCmdList* cmd_list, NvFence* fence_out) nvioctl_gpfifo_entry ent; nvioctl_fence fence; - ent.desc = nvcmdsGetGpuAddr(cmd_list) | (nvcmdsGetListSize(cmd_list) << 42); + ent.desc = nvCmdListGetGpuAddr(cmd_list) | (nvCmdListGetListSize(cmd_list) << 42); rc = nvioctlChannel_SubmitGpfifo( f->parent->fd, &ent, 1, 0/*flags*/, &fence);