mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Major refactor and redesign of nvidia wrapper objects, see details:
- NvBuffer replaced with NvMap, which only manages the creation of raw nvmap objects. Users must map these objects manually to address spaces. - nvAddressSpaceBindToChannel removed. - nvChannelSetNvmapFd is now automatic and has been removed. - Nv3DContext, NvCmdList, NvErrorNotifier, NvGpfifo, NvGpu and NvZcullContext have all been removed. - Introduced NvGpuChannel, which provides all functionality that was part of said removed objects. - Other miscellaneous changes and fixes.
This commit is contained in:
parent
85a20f43dc
commit
5fe01c065a
@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
TARGET := nx
|
TARGET := nx
|
||||||
#BUILD := build
|
#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
|
DATA := data
|
||||||
INCLUDES := include external/bsd/include
|
INCLUDES := include external/bsd/include
|
||||||
|
|
||||||
|
@ -89,17 +89,12 @@ extern "C" {
|
|||||||
#include "switch/display/nvgfx.h"
|
#include "switch/display/nvgfx.h"
|
||||||
|
|
||||||
#include "switch/nvidia/ioctl.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/address_space.h"
|
||||||
#include "switch/nvidia/channel.h"
|
#include "switch/nvidia/channel.h"
|
||||||
#include "switch/nvidia/info.h"
|
#include "switch/nvidia/info.h"
|
||||||
#include "switch/nvidia/fence.h"
|
#include "switch/nvidia/fence.h"
|
||||||
#include "switch/nvidia/gpu/cmd_list.h"
|
#include "switch/nvidia/gpu_channel.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/audio/driver.h"
|
#include "switch/audio/driver.h"
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "ioctl.h"
|
||||||
|
|
||||||
typedef struct NvAddressSpace {
|
typedef struct NvAddressSpace {
|
||||||
u32 fd;
|
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 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 nvAddressSpaceModify(NvAddressSpace* a, iova_t iova, u64 offset, u64 size, NvKind kind);
|
||||||
Result nvAddressSpaceUnmap(NvAddressSpace* a, iova_t iova);
|
Result nvAddressSpaceUnmap(NvAddressSpace* a, iova_t iova);
|
||||||
|
|
||||||
struct NvChannel;
|
|
||||||
Result nvAddressSpaceBindToChannel(NvAddressSpace* a, struct NvChannel* channel);
|
|
||||||
|
@ -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);
|
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "ioctl.h"
|
||||||
|
|
||||||
typedef struct NvChannel {
|
typedef struct NvChannel {
|
||||||
u32 fd;
|
u32 fd;
|
||||||
@ -11,4 +12,3 @@ void nvChannelClose(NvChannel* c);
|
|||||||
|
|
||||||
Result nvChannelSetPriority(NvChannel* c, NvChannelPriority prio);
|
Result nvChannelSetPriority(NvChannel* c, NvChannelPriority prio);
|
||||||
Result nvChannelSetTimeout(NvChannel* c, u32 timeout);
|
Result nvChannelSetTimeout(NvChannel* c, u32 timeout);
|
||||||
Result nvChannelSetNvmapFd(NvChannel* c);
|
|
||||||
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
43
nx/include/switch/nvidia/gpu_channel.h
Normal file
43
nx/include/switch/nvidia/gpu_channel.h
Normal file
@ -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;
|
||||||
|
}
|
34
nx/include/switch/nvidia/map.h
Normal file
34
nx/include/switch/nvidia/map.h
Normal file
@ -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;
|
||||||
|
}
|
@ -5,8 +5,6 @@
|
|||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
#include "nvidia/buffer.h"
|
|
||||||
#include "nvidia/channel.h"
|
|
||||||
#include "nvidia/address_space.h"
|
#include "nvidia/address_space.h"
|
||||||
|
|
||||||
Result nvAddressSpaceCreate(NvAddressSpace* a, u32 page_size)
|
Result nvAddressSpaceCreate(NvAddressSpace* a, u32 page_size)
|
||||||
@ -96,8 +94,3 @@ Result nvAddressSpaceUnmap(NvAddressSpace* a, iova_t iova)
|
|||||||
{
|
{
|
||||||
return nvioctlNvhostAsGpu_UnmapBuffer(a->fd, iova);
|
return nvioctlNvhostAsGpu_UnmapBuffer(a->fd, iova);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nvAddressSpaceBindToChannel(NvAddressSpace* a, NvChannel* channel)
|
|
||||||
{
|
|
||||||
return nvioctlNvhostAsGpu_BindChannel(a->fd, channel->fd);
|
|
||||||
}
|
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
#include "nvidia/buffer.h"
|
#include "nvidia/map.h"
|
||||||
#include "nvidia/channel.h"
|
#include "nvidia/channel.h"
|
||||||
|
|
||||||
Result nvChannelCreate(NvChannel* c, const char* dev)
|
Result nvChannelCreate(NvChannel* c, const char* dev)
|
||||||
@ -19,6 +19,9 @@ Result nvChannelCreate(NvChannel* c, const char* dev)
|
|||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
c->fd = -1;
|
c->fd = -1;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
rc = nvioctlChannel_SetNvmapFd(c->fd, nvMapGetFd());
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
nvChannelClose(c);
|
nvChannelClose(c);
|
||||||
|
|
||||||
@ -43,7 +46,3 @@ Result nvChannelSetPriority(NvChannel* c, NvChannelPriority prio) {
|
|||||||
Result nvChannelSetTimeout(NvChannel* c, u32 timeout) {
|
Result nvChannelSetTimeout(NvChannel* c, u32 timeout) {
|
||||||
return nvioctlChannel_SetTimeout(c->fd, timeout);
|
return nvioctlChannel_SetTimeout(c->fd, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nvChannelSetNvmapFd(NvChannel* c) {
|
|
||||||
return nvioctlChannel_SetNvmapFd(c->fd, nvBufferGetNvmapFd());
|
|
||||||
}
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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];
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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);
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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();
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#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);
|
|
||||||
}
|
|
130
nx/source/nvidia/gpu_channel.c
Normal file
130
nx/source/nvidia/gpu_channel.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include <malloc.h>
|
||||||
|
#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;
|
||||||
|
}
|
@ -5,7 +5,6 @@
|
|||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
#include "nvidia/buffer.h"
|
|
||||||
#include "nvidia/info.h"
|
#include "nvidia/info.h"
|
||||||
|
|
||||||
static u32 g_ctrlgpu_fd = -1;
|
static u32 g_ctrlgpu_fd = -1;
|
||||||
|
102
nx/source/nvidia/map.c
Normal file
102
nx/source/nvidia/map.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include <malloc.h>
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user