#pragma once
#include <windows.h>

#define CUDACALL __stdcall
typedef struct PCUDE_CONTEXT* CUDA_CONTEXT;

typedef INT(CUDACALL* CUDAMEMORYALLOCATE)(ULONG_PTR, SIZE_T);
typedef INT(CUDACALL* CUDAINIT)(INT);
typedef INT(CUDACALL* CUDAGETDEVICECOUNT)(PINT);
typedef INT(CUDACALL* CUDAGETDEVICE)(PINT, INT);
typedef INT(CUDACALL* CUDACREATECONTEXT)(CUDA_CONTEXT*, DWORD, INT);
typedef INT(CUDACALL* CUDADESTROYCONTEXT)(CUDA_CONTEXT*);
typedef INT(CUDACALL* CUDAMEMORYCOPYTODEVICE)(ULONG_PTR, PVOID, SIZE_T);
typedef INT(CUDACALL* CUDAMEMORYCOPYTOHOST)(PVOID, ULONG_PTR, SIZE_T);
typedef INT(CUDACALL* CUDAMEMORYFREE)(ULONG_PTR);

#define CUDA_SUCCESS 0

typedef struct _NVIDIA_API_TABLE {
	HMODULE NvidiaLibary;
	CUDAMEMORYALLOCATE CudaMemoryAllocate;
	CUDAINIT CudaInit;
	CUDAGETDEVICECOUNT CudaGetDeviceCount;
	CUDAGETDEVICE CudaGetDevice;
	CUDACREATECONTEXT CudaCreateContext;
	CUDAMEMORYCOPYTODEVICE CudaMemoryCopyToDevice;
	CUDAMEMORYCOPYTOHOST CudaMemoryCopyToHost;
	CUDAMEMORYFREE CudaMemoryFree;
	CUDADESTROYCONTEXT CudaDestroyContext;
} NVIDIA_API_TABLE, * PNVIDIA_API_TABLE;

BOOL InitNvidiaCudaAPITable(PNVIDIA_API_TABLE Api);
ULONG_PTR RtlAllocateGpuMemory(PNVIDIA_API_TABLE Api, DWORD ByteSize);
CUDA_CONTEXT initCuda(NVIDIA_API_TABLE* Api, CUDA_CONTEXT* ctx);