From 1a22b484f80fe7d7d2dc4e21eb1a71de421ad87b Mon Sep 17 00:00:00 2001 From: plutooo Date: Sat, 10 Mar 2018 16:27:28 +0100 Subject: [PATCH] Implemented zcull_ctx, 3d_ctx, random fixes --- nx/include/switch/nvidia/address_space.h | 2 +- nx/include/switch/nvidia/buffer.h | 19 ++++++------ nx/include/switch/nvidia/channel.h | 5 +++- nx/include/switch/nvidia/gpu/zcull_ctx.h | 3 +- nx/include/switch/nvidia/ioctl.h | 38 ++++++++++++++---------- nx/source/nvidia/address_space.c | 4 +-- nx/source/nvidia/buffer.c | 1 + nx/source/nvidia/channel.c | 4 +++ nx/source/nvidia/gpu/3d_ctx.c | 4 +-- nx/source/nvidia/gpu/zcull_ctx.c | 17 +++++++++-- nx/source/nvidia/ioctl/nvchannel.c | 14 +++++++-- 11 files changed, 74 insertions(+), 37 deletions(-) diff --git a/nx/include/switch/nvidia/address_space.h b/nx/include/switch/nvidia/address_space.h index 63059974..6ed435fc 100644 --- a/nx/include/switch/nvidia/address_space.h +++ b/nx/include/switch/nvidia/address_space.h @@ -20,7 +20,7 @@ Result nvasReserveAlign(NvAddressSpace* a, NvPageSize align, u32 pages, NvPageSi Result nvasReserveAtFixedAddr(NvAddressSpace* a, iova_t addr, u32 pages, NvPageSize page_sz); Result nvasReserveFull(NvAddressSpace* a); -Result nvasMapBuffer(NvAddressSpace* a, NvBuffer* buffer, NvBufferKind kind, iova_t* iova_out); +Result nvasMapBuffer(NvAddressSpace* a, NvBuffer* buffer, iova_t* iova_out); struct NvChannel; Result nvasBindToChannel(NvAddressSpace* a, struct NvChannel* channel); diff --git a/nx/include/switch/nvidia/buffer.h b/nx/include/switch/nvidia/buffer.h index cfdf5967..4f06259c 100644 --- a/nx/include/switch/nvidia/buffer.h +++ b/nx/include/switch/nvidia/buffer.h @@ -2,19 +2,12 @@ #include "../types.h" -typedef struct { - u32 fd; - u32 size; - void* ptr; - bool has_init; -} NvBuffer; - typedef enum { NvBufferFlags_Writable=1 } NvBufferFlags; typedef enum { - NvBufferKind_PitCh=0x0, + NvBufferKind_Pitch=0x0, NvBufferKind_Z16=0x1, NvBufferKind_Z16_2C=0x2, NvBufferKind_Z16_MS2_2C=0x3, @@ -249,8 +242,16 @@ typedef enum { NvBufferKind_Invalid=0xff, } NvBufferKind; +typedef struct { + u32 fd; + u32 size; + void* ptr; + NvBufferKind kind; + bool has_init; +} NvBuffer; + Result nvbufInit(void); -void nvbufExit(void); +void nvbufExit(void); Result nvbufCreate(NvBuffer* m, size_t size, u32 align, NvBufferKind kind); Result nvbufCreateRw(NvBuffer* m, size_t size, u32 align, NvBufferKind kind); diff --git a/nx/include/switch/nvidia/channel.h b/nx/include/switch/nvidia/channel.h index f5758007..427afded 100644 --- a/nx/include/switch/nvidia/channel.h +++ b/nx/include/switch/nvidia/channel.h @@ -1,4 +1,5 @@ #pragma once +#include "ioctl.h" typedef struct NvChannel { u32 fd; @@ -6,4 +7,6 @@ typedef struct NvChannel { } NvChannel; Result nvchannelCreate(NvChannel* c, const char* dev); -void nvchannelClose(NvChannel* c); +void nvchannelClose(NvChannel* c); + +Result nvchannelSetPriority(NvChannel* c, NvChannelPriority prio); diff --git a/nx/include/switch/nvidia/gpu/zcull_ctx.h b/nx/include/switch/nvidia/gpu/zcull_ctx.h index 197b70db..cf423c04 100644 --- a/nx/include/switch/nvidia/gpu/zcull_ctx.h +++ b/nx/include/switch/nvidia/gpu/zcull_ctx.h @@ -3,7 +3,8 @@ typedef struct NvGpu NvGpu; typedef struct { - NvGpu* parent; + NvGpu* parent; + NvBuffer ctx_buf; } NvZcullContext; Result nvzcullCreate(NvZcullContext* z, NvGpu* parent); diff --git a/nx/include/switch/nvidia/ioctl.h b/nx/include/switch/nvidia/ioctl.h index f1839032..cf521107 100644 --- a/nx/include/switch/nvidia/ioctl.h +++ b/nx/include/switch/nvidia/ioctl.h @@ -104,22 +104,30 @@ typedef struct { u32 entry1; } nvioctl_gpfifo_entry; -//Used with nvioctlChannel_AllocObjCtx(). -enum nvioctl_channel_obj_classnum { - NvChannelObjClassNum_2D = 0x902D, - NvChannelObjClassNum_3D = 0xB197, - NvChannelObjClassNum_Compute = 0xB1C0, - NvChannelObjClassNum_Kepler = 0xA140, - NvChannelObjClassNum_DMA = 0xB0B5, - NvChannelObjClassNum_ChannelGpfifo = 0xB06F -}; +// Used with nvioctlChannel_AllocObjCtx(). +typedef enum nvioctl_channel_obj_classnum { + NvClassNumber_2D = 0x902D, + NvClassNumber_3D = 0xB197, + NvClassNumber_Compute = 0xB1C0, + NvClassNumber_Kepler = 0xA140, + NvClassNumber_DMA = 0xB0B5, + NvClassNumber_ChannelGpfifo = 0xB06F +} NvClassNumber; -//Used with nvioctlChannel_SetPriority(). -enum nvioctl_channel_priority { - NvChannelPriority_Low = 0x32, - NvChannelPriority_Medium = 0x64, - NvChannelPriority_High = 0x96 -}; +// Used with nvioctlChannel_SetPriority(). +typedef enum nvioctl_channel_priority { + NvChannelPriority_Low = 50, + NvChannelPriority_Medium = 100, + NvChannelPriority_High = 150 +} NvChannelPriority; + +// Used with nvioctlChannel_ZCullBind(). +typedef enum { + NvZcullConfig_Global = 0, + NvZcullConfig_NoCtxSwitch = 1, + NvZcullConfig_SeparateBuffer = 2, + NvZcullConfig_PartOfRegularBuffer = 3 +} NvZcullConfig; Result nvioctlNvhostCtrl_EventSignal(u32 fd, u32 event_id); Result nvioctlNvhostCtrl_EventWait(u32 fd, u32 syncpt_id, u32 threshold, s32 timeout, u32 event_id, u32 *out); diff --git a/nx/source/nvidia/address_space.c b/nx/source/nvidia/address_space.c index ee0211ec..224849c4 100644 --- a/nx/source/nvidia/address_space.c +++ b/nx/source/nvidia/address_space.c @@ -43,8 +43,8 @@ Result nvasReserveFull(NvAddressSpace* a) { return nvasReserveAlign(a, NvPageSize_64K, 0x10000, NvPageSize_64K, NULL); } -Result nvasMapBuffer(NvAddressSpace* a, NvBuffer* buffer, NvBufferKind kind, iova_t* iova_out) { - return nvioctlNvhostAsGpu_MapBufferEx(a->fd, 0, kind, buffer->fd, 0, 0, buffer->size, 0, iova_out); +Result nvasMapBuffer(NvAddressSpace* a, NvBuffer* buffer, iova_t* iova_out) { + return nvioctlNvhostAsGpu_MapBufferEx(a->fd, 0, buffer->kind, buffer->fd, 0, 0, buffer->size, 0, iova_out); } Result nvasBindToChannel(NvAddressSpace* a, NvChannel* channel) diff --git a/nx/source/nvidia/buffer.c b/nx/source/nvidia/buffer.c index ac74d1e2..1ce3a80c 100644 --- a/nx/source/nvidia/buffer.c +++ b/nx/source/nvidia/buffer.c @@ -43,6 +43,7 @@ static Result _nvbufCreate(NvBuffer* m, size_t size, u32 flags, u32 align, NvBuf m->size = size; m->fd = -1; m->ptr = memalign(size, align); + m->kind = kind; if (m->ptr == NULL) return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); diff --git a/nx/source/nvidia/channel.c b/nx/source/nvidia/channel.c index e2dc1cdf..f069da03 100644 --- a/nx/source/nvidia/channel.c +++ b/nx/source/nvidia/channel.c @@ -27,3 +27,7 @@ void nvchannelClose(NvChannel* c) c->fd = -1; } + +Result nvchannelSetPriority(NvChannel* c, NvChannelPriority prio) { + return nvioctlChannel_SetPriority(c->fd, prio); +} diff --git a/nx/source/nvidia/gpu/3d_ctx.c b/nx/source/nvidia/gpu/3d_ctx.c index bac68fdb..966dcb2b 100644 --- a/nx/source/nvidia/gpu/3d_ctx.c +++ b/nx/source/nvidia/gpu/3d_ctx.c @@ -3,9 +3,7 @@ Result nv3dCreate(Nv3dContext* t, NvGpu* parent) { t->parent = parent; - - // TODO: Get class number from nvinfo*(). - return nvioctlChannel_AllocObjCtx(parent->gpu_channel.fd, 0xB197, 0, &t->obj_id); + return nvioctlChannel_AllocObjCtx(parent->gpu_channel.fd, NvClassNumber_3D, 0, &t->obj_id); } void nv3dClose(Nv3dContext* t) { diff --git a/nx/source/nvidia/gpu/zcull_ctx.c b/nx/source/nvidia/gpu/zcull_ctx.c index e8f0e46d..8986c71a 100644 --- a/nx/source/nvidia/gpu/zcull_ctx.c +++ b/nx/source/nvidia/gpu/zcull_ctx.c @@ -2,10 +2,23 @@ Result nvzcullCreate(NvZcullContext* z, NvGpu* parent) { + Result rc; + z->parent = parent; - return 0; + rc = nvbufCreateRw(&z->ctx_buf, nvinfoGetZcullCtxSize(), 0x1000, NvBufferKind_Pitch); + + iova_t iova_out; + + if (R_SUCCEEDED(rc)) + rc = nvasMapBuffer(&parent->addr_space, &z->ctx_buf, &iova_out); + + if (R_SUCCEEDED(rc)) + rc = nvioctlChannel_ZCullBind(parent->gpu_channel.fd, iova_out, NvZcullConfig_SeparateBuffer); + + return rc; } void nvzcullClose(NvZcullContext* z) { - /**/ + // TODO: Unmap z->ctx_buf from parent->addr_space? + nvbufFree(&z->ctx_buf); } diff --git a/nx/source/nvidia/ioctl/nvchannel.c b/nx/source/nvidia/ioctl/nvchannel.c index 80665580..9dcfe56a 100644 --- a/nx/source/nvidia/ioctl/nvchannel.c +++ b/nx/source/nvidia/ioctl/nvchannel.c @@ -56,10 +56,18 @@ Result nvioctlChannel_AllocObjCtx(u32 fd, u32 class_num, u32 flags, u64* id_out) memset(&data, 0, sizeof(data)); data.class_num = class_num; data.flags = flags; - if (id_out != NULL) - *id_out = data.obj_id; + data.obj_id = 0xDEADBEEF; + + Result rc = nvIoctl(fd, _NV_IOWR(0x48, 0x09, data), &data); + + if (R_SUCCEEDED(rc)) { + if (id_out != NULL) { + *id_out = data.obj_id; + } + } + + return rc; - return nvIoctl(fd, _NV_IOWR(0x48, 0x09, data), &data); } Result nvioctlChannel_ZCullBind(u32 fd, u64 gpu_va, u32 mode) {