github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/gpu/buffer.go (about) 1 package gpu 2 3 import ( 4 "fmt" 5 "github.com/racerxdl/gonx/nx/nxerrors" 6 "github.com/racerxdl/gonx/nx/nxtypes" 7 "github.com/racerxdl/gonx/services/nv" 8 "github.com/racerxdl/gonx/svc" 9 "unsafe" 10 ) 11 12 type Buffer struct { 13 NvMapHandle uint32 14 Size uintptr 15 Alignment uint32 16 Kind uint8 17 } 18 19 func InitializeFromId(id uint32) (*Buffer, error) { 20 if gpuInitializations <= 0 { 21 return nil, nxerrors.GPUNotInitialized 22 } 23 24 buff := &Buffer{} 25 26 nvIocFromIdArgs := nvmapIocGetIdArgs{ 27 id: id, 28 } 29 30 handle, err := nv.Ioctl(nvmapFd, NVMAP_IOC_FROM_ID, unsafe.Pointer(&nvIocFromIdArgs), unsafe.Sizeof(nvIocFromIdArgs)) 31 if err != nil { 32 return nil, err 33 } 34 35 if handle != 0 { 36 return nil, nxerrors.IPCError{ 37 Message: "error calling NVMAP_IOC_FROM_ID", 38 Result: uint64(handle), 39 } 40 } 41 42 buff.NvMapHandle = nvIocFromIdArgs.handle 43 44 nvParam := nvmapIocParamArgs{ 45 handle: buff.NvMapHandle, 46 param: 1, // SIZE 47 } 48 49 handle, err = nv.Ioctl(nvmapFd, NVMAP_IOC_PARAM, unsafe.Pointer(&nvParam), unsafe.Sizeof(nvParam)) 50 if err != nil { 51 return nil, err 52 } 53 54 if handle != 0 { 55 return nil, nxerrors.IPCError{ 56 Message: "error calling NVMAP_IOC_PARAM", 57 Result: uint64(handle), 58 } 59 } 60 61 buff.Size = uintptr(nvParam.value) 62 63 nvParam.param = 2 // ALIGNMENT 64 handle, err = nv.Ioctl(nvmapFd, NVMAP_IOC_PARAM, unsafe.Pointer(&nvParam), unsafe.Sizeof(nvParam)) 65 if err != nil { 66 return nil, err 67 } 68 69 if handle != 0 { 70 return nil, nxerrors.IPCError{ 71 Message: "error calling NVMAP_IOC_PARAM", 72 Result: uint64(handle), 73 } 74 } 75 76 buff.Alignment = nvParam.value 77 78 nvParam.param = 5 // KIND 79 handle, err = nv.Ioctl(nvmapFd, NVMAP_IOC_PARAM, unsafe.Pointer(&nvParam), unsafe.Sizeof(nvParam)) 80 if err != nil { 81 return nil, err 82 } 83 84 if handle != 0 { 85 return nil, nxerrors.IPCError{ 86 Message: "error calling NVMAP_IOC_PARAM", 87 Result: uint64(handle), 88 } 89 } 90 91 buff.Kind = uint8(nvParam.value) 92 93 return buff, nil 94 } 95 96 func (b *Buffer) GetID() (id uint32, err error) { 97 if gpuInitializations <= 0 { 98 return 0, nxerrors.GPUNotInitialized 99 } 100 101 nvIdArgs := nvmapIocGetIdArgs{ 102 handle: b.NvMapHandle, 103 } 104 105 handle, err := nv.Ioctl(nvmapFd, NVMAP_IOC_GET_ID, unsafe.Pointer(&nvIdArgs), unsafe.Sizeof(nvIdArgs)) 106 107 if err != nil { 108 return 0, err 109 } 110 111 if handle != 0 { 112 return 0, nxerrors.IPCError{ 113 Message: "error calling NVMAP_IOC_GET_ID", 114 Result: uint64(handle), 115 } 116 } 117 return nvIdArgs.id, nil 118 } 119 120 func (b *Buffer) Destroy() (refCount uint32, flags uint32, err error) { 121 if gpuInitializations <= 0 { 122 return 0, 0, nxerrors.GPUNotInitialized 123 } 124 125 nvmFree := nvmapIocFreeArgs{ 126 handle: b.NvMapHandle, 127 } 128 129 handle, err := nv.Ioctl(nvmapFd, NVMAP_IOC_FREE, unsafe.Pointer(&nvmFree), unsafe.Sizeof(nvmFree)) 130 131 if err != nil { 132 return 0, 0, err 133 } 134 135 if handle != 0 { 136 return 0, 0, nxerrors.IPCError{ 137 Message: "error calling NVMAP_IOC_FREE", 138 Result: uint64(handle), 139 } 140 } 141 142 return uint32(nvmFree.refcount), nvmFree.flags, nil 143 } 144 145 // CreateBuffer creates a buffer in GPU 146 // equivalent to nvMapCreate on libnx 147 func CreateBuffer(addr unsafe.Pointer, size uintptr, heapMask, alignment uint32, kind nv.Kind) (*Buffer, error) { 148 if gpuInitializations <= 0 { 149 return nil, nxerrors.GPUNotInitialized 150 } 151 152 if alignment < 0x1000 { 153 alignment = 0x1000 154 } 155 156 uaddr := uintptr(addr) 157 158 if uint64(uaddr)&(uint64(alignment)-1) != 0 { 159 // GPU Driver crashes if this is not checked 160 fmt.Println("A") 161 return nil, nxerrors.GPUBufferUnaligned 162 } 163 164 if size == 0 || (size&0xFFF > 0) { 165 // GPU Driver crashes if this is not checked 166 fmt.Println("B") 167 return nil, nxerrors.GPUBufferUnaligned 168 } 169 170 if addr == nil || (uintptr(addr)&0xFFF > 0) { 171 // GPU Driver crashes if this is not checked 172 fmt.Println("C") 173 return nil, nxerrors.GPUBufferUnaligned 174 } 175 176 gpuB := &Buffer{ 177 Size: size, 178 Kind: uint8(kind), 179 Alignment: alignment, 180 } 181 182 nvmCreate := nvmapIocCreateArgs{ 183 size: uint32(size), 184 } 185 186 handle, err := nv.Ioctl(nvmapFd, NVMAP_IOC_CREATE, unsafe.Pointer(&nvmCreate), unsafe.Sizeof(nvmCreate)) 187 if err != nil { 188 return nil, err 189 } 190 if handle != 0 { 191 return nil, nxerrors.IPCError{ 192 Message: "error calling NVMAP_IOC_CREATE", 193 Result: uint64(handle), 194 } 195 } 196 197 gpuB.NvMapHandle = nvmCreate.handle 198 199 err = nvmapAlloc(nvmCreate.handle, heapMask, 0, alignment, uint32(kind), uintptr(addr)) 200 if err != nil { 201 return nil, err 202 } 203 204 r := svc.SetMemoryAttribute(uintptr(addr), uintptr(size), 0x8, 0x8) 205 if r != nxtypes.ResultOK { 206 return nil, nxerrors.CannotSetMemoryAttributes 207 } 208 209 return gpuB, nil 210 } 211 212 func nvmapAlloc(nvmapHandle, heapMask, flags, align, kind uint32, addr uintptr) error { 213 nvmAlloc := nvmapIocAllocArgs{ 214 handle: nvmapHandle, 215 heapmask: heapMask, 216 flags: flags, 217 align: align, 218 kind: uint8(kind), 219 addr: uint64(addr), 220 } 221 222 handle, err := nv.Ioctl(nvmapFd, NVMAP_IOC_ALLOC, unsafe.Pointer(&nvmAlloc), unsafe.Sizeof(nvmAlloc)) 223 if err != nil { 224 return err 225 } 226 if handle != 0 { 227 return nxerrors.IPCError{ 228 Message: "error calling NVMAP_IOC_ALLOC", 229 Result: uint64(handle), 230 } 231 } 232 233 return nil 234 }