From 1908b29708a6b67bd80d0cdcf71bacf90e08c009 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 14 Nov 2017 20:20:08 -0500 Subject: [PATCH] Added nvioctlChannel_SubmitGPFIFO(). --- nx/include/switch/gfx/nvioctl.h | 6 ++++++ nx/source/gfx/nvgfx.c | 9 ++++++++- nx/source/gfx/nvioctl.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/nx/include/switch/gfx/nvioctl.h b/nx/include/switch/gfx/nvioctl.h index 375f976b..f6f54041 100644 --- a/nx/include/switch/gfx/nvioctl.h +++ b/nx/include/switch/gfx/nvioctl.h @@ -53,6 +53,11 @@ typedef struct { u32 value; } nvioctl_fence; +typedef struct { + u32 entry0; + u32 entry1; +} nvioctl_gpfifo_entry; + //Used with nvioctlChannel_AllocObjCtx(). enum nvioctl_channel_obj_classnum { NVIOCTL_CHANNEL_OBJ_CLASSNUM_2d = 0x902D, @@ -86,6 +91,7 @@ Result nvioctlNvmap_Create(u32 fd, u32 size, u32 *nvmap_handle); Result nvioctlNvmap_Alloc(u32 fd, u32 nvmap_handle, u32 heapmask, u32 flags, u32 align, u8 kind, void* addr); Result nvioctlChannel_SetNvmapFd(u32 fd, u32 nvmap_fd); +Result nvioctlChannel_SubmitGPFIFO(u32 fd, nvioctl_gpfifo_entry *entries, u32 num_entries, u32 flags, nvioctl_fence *fence_out); Result nvioctlChannel_AllocObjCtx(u32 fd, u32 class_num, u32 flags); Result nvioctlChannel_ZCullBind(u32 fd, u32 in[4]); Result nvioctlChannel_SetErrorNotifier(u32 fd, u64 offset, u64 size, u32 nvmap_handle); diff --git a/nx/source/gfx/nvgfx.c b/nx/source/gfx/nvgfx.c index b868403f..843f8c82 100644 --- a/nx/source/gfx/nvgfx.c +++ b/nx/source/gfx/nvgfx.c @@ -23,6 +23,7 @@ static u32 g_nvgfx_zcullinfo[40>>2]; static nvioctl_va_region g_nvgfx_nvhostasgpu_varegions[2]; static nvioctl_l2_state g_nvgfx_l2state; static nvioctl_fence g_nvgfx_nvhost_fence; +static nvioctl_fence g_nvgfx_nvhostgpu_gpfifo_fence; static u8 *g_nvgfx_nvhost_userdata; static size_t g_nvgfx_nvhost_userdata_size; @@ -78,6 +79,8 @@ Result nvgfxInitialize(void) { u32 zcullbind_data[4] = {0x58000, 0x5, 0x2, 0x0}; + nvioctl_gpfifo_entry gpfifo_entries[2] = {{0x00030000, 0x00177a05}, {0x00031778, 0x80002e05}}; + g_nvgfx_fd_nvhostctrlgpu = 0; g_nvgfx_fd_nvhostasgpu = 0; g_nvgfx_fd_nvmap = 0; @@ -91,6 +94,7 @@ Result nvgfxInitialize(void) { memset(g_nvgfx_nvhostasgpu_varegions, 0, sizeof(g_nvgfx_nvhostasgpu_varegions)); memset(&g_nvgfx_l2state, 0, sizeof(nvioctl_l2_state)); memset(&g_nvgfx_nvhost_fence, 0, sizeof(g_nvgfx_nvhost_fence)); + memset(&g_nvgfx_nvhostgpu_gpfifo_fence, 0, sizeof(g_nvgfx_nvhostgpu_gpfifo_fence)); g_nvgfx_nvhostasgpu_allocspace_offset = 0; g_nvgfx_zcullctxsize = 0; @@ -171,7 +175,10 @@ Result nvgfxInitialize(void) { if (R_SUCCEEDED(rc)) rc = nvioctlChannel_ZCullBind(g_nvgfx_fd_nvhostgpu, zcullbind_data); - //Officially, ipcQueryPointerBufferSize and NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO are used here with the duplicate session setup during nv serv init. + //Officially, ipcQueryPointerBufferSize and NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(nvioctlChannel_SubmitGPFIFO) are used here with the duplicate service session setup during nv serv init. + //TODO: This is probably used for GPU rendering? Is this really needed when not doing actual GPU rendering? + //Skip this since this causes a white-screen hang. + //if (R_SUCCEEDED(rc)) rc = nvioctlChannel_SubmitGPFIFO(g_nvgfx_fd_nvhostgpu, gpfifo_entries, 2, 0x104, &g_nvgfx_nvhostgpu_gpfifo_fence); //if (R_SUCCEEDED(rc)) rc = -1; diff --git a/nx/source/gfx/nvioctl.c b/nx/source/gfx/nvioctl.c index 6deab847..93e1e40b 100644 --- a/nx/source/gfx/nvioctl.c +++ b/nx/source/gfx/nvioctl.c @@ -251,6 +251,34 @@ Result nvioctlChannel_SetNvmapFd(u32 fd, u32 nvmap_fd) { return nvIoctl(fd, _IOW(0x48, 0x01, data), &data); } +Result nvioctlChannel_SubmitGPFIFO(u32 fd, nvioctl_gpfifo_entry *entries, u32 num_entries, u32 flags, nvioctl_fence *fence_out) { + Result rc=0; + + if(num_entries > 0x200) return MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);//Make sure stack data doesn't get very large. + + struct { + u64 gpfifo; // in (ignored) pointer to gpfifo fence structs + u32 num_entries; // in number of fence objects being submitted + u32 flags; // in + nvioctl_fence fence_out; // out returned new fence object for others to wait on + nvioctl_gpfifo_entry entries[num_entries]; // in depends on num_entries + } data; + + + memset(&data, 0, sizeof(data)); + data.gpfifo = 1; + data.num_entries = num_entries; + data.flags = flags; + memcpy(data.entries, entries, sizeof(data.entries)); + + rc = nvIoctl(fd, _IOWR(0x48, 0x08, data), &data); + if (R_FAILED(rc)) return rc; + + if(fence_out) memcpy(fence_out, &data.fence_out, sizeof(data.fence_out)); + + return rc; +} + Result nvioctlChannel_AllocObjCtx(u32 fd, u32 class_num, u32 flags) { struct { u32 class_num; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, 0xB06F=channel_gpfifo