From fc17383815ce94bd81659d2cb91e05ea10ca1cb5 Mon Sep 17 00:00:00 2001 From: BtbN Date: Sun, 5 Jan 2014 23:05:24 +0100 Subject: [PATCH] Get rid of dependency on CUDA SDK by dynamicaly loading the required functions --- ObsNvenc/ObsNvenc.vcxproj | 26 ++++++----- ObsNvenc/ObsNvenc.vcxproj.filters | 6 +++ ObsNvenc/inc/cudaDynload.h | 50 +++++++++++++++++++++ ObsNvenc/inc/nvmain.h | 2 +- ObsNvenc/src/cudaDynload.cpp | 75 +++++++++++++++++++++++++++++++ ObsNvenc/src/nvEncodeAPI.cpp | 3 ++ 6 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 ObsNvenc/inc/cudaDynload.h create mode 100644 ObsNvenc/src/cudaDynload.cpp diff --git a/ObsNvenc/ObsNvenc.vcxproj b/ObsNvenc/ObsNvenc.vcxproj index f55853b9..16da949e 100644 --- a/ObsNvenc/ObsNvenc.vcxproj +++ b/ObsNvenc/ObsNvenc.vcxproj @@ -86,13 +86,13 @@ Level3 Disabled true - $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(CUDA_PATH)\include;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true - $(CUDA_PATH)\lib\$(Platform);$(SolutionDir)\OBSApi\$(Configuration)\;%(AdditionalLibraryDirectories) - cuda.lib;OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) + $(SolutionDir)\OBSApi\$(Configuration)\;%(AdditionalLibraryDirectories) + OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) $(SolutionDir)\rundir\pdb32\$(TargetName).pdb $(SolutionDir)\rundir\pdb32\stripped\$(TargetName).pdb @@ -105,13 +105,13 @@ Level3 Disabled true - $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(CUDA_PATH)\include;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true - $(CUDA_PATH)\lib\$(Platform);$(SolutionDir)\OBSApi\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - cuda.lib;OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) + $(SolutionDir)\OBSApi\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) $(SolutionDir)\rundir\pdb64\$(TargetName).pdb $(SolutionDir)\rundir\pdb64\stripped\$(TargetName).pdb @@ -126,15 +126,15 @@ true true true - $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(CUDA_PATH)\include;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true true true - $(CUDA_PATH)\lib\$(Platform);$(SolutionDir)\OBSApi\$(Configuration)\;%(AdditionalLibraryDirectories) - cuda.lib;OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) + $(SolutionDir)\OBSApi\$(Configuration)\;%(AdditionalLibraryDirectories) + OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) $(SolutionDir)\rundir\pdb32\$(TargetName).pdb $(SolutionDir)\rundir\pdb32\stripped\$(TargetName).pdb @@ -149,15 +149,15 @@ true true true - $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(CUDA_PATH)\include;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + $(ProjectDir)\license;$(ProjectDir)\inc;$(SolutionDir)\OBSApi;$(SolutionDir)\Source;$(SolutionDir)\extras;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true true true - $(CUDA_PATH)\lib\$(Platform);$(SolutionDir)\OBSApi\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - cuda.lib;OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) + $(SolutionDir)\OBSApi\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + OBSApi.lib;ws2_32.lib;%(AdditionalDependencies) $(SolutionDir)\rundir\pdb64\$(TargetName).pdb $(SolutionDir)\rundir\pdb64\stripped\$(TargetName).pdb @@ -166,11 +166,13 @@ + + diff --git a/ObsNvenc/ObsNvenc.vcxproj.filters b/ObsNvenc/ObsNvenc.vcxproj.filters index 7f115b39..2618bb56 100644 --- a/ObsNvenc/ObsNvenc.vcxproj.filters +++ b/ObsNvenc/ObsNvenc.vcxproj.filters @@ -20,6 +20,9 @@ Quelldateien + + Quelldateien + @@ -34,5 +37,8 @@ Headerdateien + + Headerdateien + \ No newline at end of file diff --git a/ObsNvenc/inc/cudaDynload.h b/ObsNvenc/inc/cudaDynload.h new file mode 100644 index 00000000..08797938 --- /dev/null +++ b/ObsNvenc/inc/cudaDynload.h @@ -0,0 +1,50 @@ +/******************************************************************************** +Copyright (C) 2014 Timo Rothenpieler + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +********************************************************************************/ + +#ifndef H_OBSNVENC_CUDADYNLOAD__H +#define H_OBSNVENC_CUDADYNLOAD__H + +typedef enum cudaError_enum { + CUDA_SUCCESS = 0 +} CUresult; +typedef int CUdevice; +typedef void* CUcontext; + +#define CUDAAPI __stdcall + +typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags); +typedef CUresult(CUDAAPI *PCUDEVICEGETCOUNT)(int *count); +typedef CUresult(CUDAAPI *PCUDEVICEGET)(CUdevice *device, int ordinal); +typedef CUresult(CUDAAPI *PCUDEVICEGETNAME)(char *name, int len, CUdevice dev); +typedef CUresult(CUDAAPI *PCUDEVICECOMPUTECAPABILITY)(int *major, int *minor, CUdevice dev); +typedef CUresult(CUDAAPI *PCUCTXCREATE)(CUcontext *pctx, unsigned int flags, CUdevice dev); +typedef CUresult(CUDAAPI *PCUCTXPOPCURRENT)(CUcontext *pctx); +typedef CUresult(CUDAAPI *PCUCTXDESTROY)(CUcontext ctx); + +extern PCUINIT cuInit; +extern PCUDEVICEGETCOUNT cuDeviceGetCount; +extern PCUDEVICEGET cuDeviceGet; +extern PCUDEVICEGETNAME cuDeviceGetName; +extern PCUDEVICECOMPUTECAPABILITY cuDeviceComputeCapability; +extern PCUCTXCREATE cuCtxCreate; +extern PCUCTXPOPCURRENT cuCtxPopCurrent; +extern PCUCTXDESTROY cuCtxDestroy; + +bool dyLoadCuda(); + +#endif diff --git a/ObsNvenc/inc/nvmain.h b/ObsNvenc/inc/nvmain.h index bfde48a2..75026ec0 100644 --- a/ObsNvenc/inc/nvmain.h +++ b/ObsNvenc/inc/nvmain.h @@ -22,7 +22,7 @@ #pragma warning(disable: 4005) #include -#include +#include "cudaDynload.h" #include "nvEncodeAPI.h" extern ConfigFile **NvAppConfig; diff --git a/ObsNvenc/src/cudaDynload.cpp b/ObsNvenc/src/cudaDynload.cpp new file mode 100644 index 00000000..689549a0 --- /dev/null +++ b/ObsNvenc/src/cudaDynload.cpp @@ -0,0 +1,75 @@ +/******************************************************************************** +Copyright (C) 2014 Timo Rothenpieler + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +********************************************************************************/ + +#include "nvmain.h" +#include "cudaDynload.h" + +PCUINIT cuInit = NULL; +PCUDEVICEGETCOUNT cuDeviceGetCount = NULL; +PCUDEVICEGET cuDeviceGet = NULL; +PCUDEVICEGETNAME cuDeviceGetName = NULL; +PCUDEVICECOMPUTECAPABILITY cuDeviceComputeCapability = NULL; +PCUCTXCREATE cuCtxCreate = NULL; +PCUCTXPOPCURRENT cuCtxPopCurrent = NULL; +PCUCTXDESTROY cuCtxDestroy = NULL; + +static HMODULE cudaLib = NULL; + +#define CHECK_LOAD_FUNC(f, s) \ +{ \ + f = (decltype(f))GetProcAddress(cudaLib, s); \ + if (f == NULL) \ + { \ + NvLog(TEXT("Failed loading %S from CUDA library"), s); \ + goto error; \ + } \ +} + +bool dyLoadCuda() +{ + if (cudaLib != NULL) + return true; + + cudaLib = LoadLibrary(TEXT("nvcuda.dll")); + if (cudaLib == NULL) + { + NvLog(TEXT("Failed loading CUDA dll")); + goto error; + } + + CHECK_LOAD_FUNC(cuInit, "cuInit"); + CHECK_LOAD_FUNC(cuDeviceGetCount, "cuDeviceGetCount"); + CHECK_LOAD_FUNC(cuDeviceGet, "cuDeviceGet"); + CHECK_LOAD_FUNC(cuDeviceGetName, "cuDeviceGetName"); + CHECK_LOAD_FUNC(cuDeviceComputeCapability, "cuDeviceComputeCapability"); + CHECK_LOAD_FUNC(cuCtxCreate, "cuCtxCreate_v2"); + CHECK_LOAD_FUNC(cuCtxPopCurrent, "cuCtxPopCurrent_v2"); + CHECK_LOAD_FUNC(cuCtxDestroy, "cuCtxDestroy"); + + NvLog(TEXT("CUDA loaded successfully")); + + return true; + +error: + + if (cudaLib != NULL) + FreeLibrary(cudaLib); + cudaLib = NULL; + + return false; +} diff --git a/ObsNvenc/src/nvEncodeAPI.cpp b/ObsNvenc/src/nvEncodeAPI.cpp index 991f1869..abbb535a 100644 --- a/ObsNvenc/src/nvEncodeAPI.cpp +++ b/ObsNvenc/src/nvEncodeAPI.cpp @@ -55,6 +55,9 @@ bool checkNvEnc() if (iNvencDeviceCount != 0) return true; + if (!dyLoadCuda()) + return false; + checkCudaErrors(cuInit(0)); checkCudaErrors(cuDeviceGetCount(&deviceCount));