diff options
| author | Halldor Fannar <[email protected]> | 2017-02-09 15:26:47 +0000 |
|---|---|---|
| committer | Halldor Fannar <[email protected]> | 2017-02-09 15:26:47 +0000 |
| commit | b814d180089b1e5415f89554e46de2edd978a592 (patch) | |
| tree | b6a61b518e2b567c7d485913a7fca54f6719bc5c /samples/AnselSDKDelayLoader/source/DelayLoader.cpp | |
| parent | Initial commit (diff) | |
| download | anselsdk-b814d180089b1e5415f89554e46de2edd978a592.tar.xz anselsdk-b814d180089b1e5415f89554e46de2edd978a592.zip | |
First publish of the SDK.
Diffstat (limited to 'samples/AnselSDKDelayLoader/source/DelayLoader.cpp')
| -rw-r--r-- | samples/AnselSDKDelayLoader/source/DelayLoader.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/samples/AnselSDKDelayLoader/source/DelayLoader.cpp b/samples/AnselSDKDelayLoader/source/DelayLoader.cpp new file mode 100644 index 0000000..6b837fb --- /dev/null +++ b/samples/AnselSDKDelayLoader/source/DelayLoader.cpp @@ -0,0 +1,281 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2016 NVIDIA Corporation. All rights reserved. + + +#define ANSEL_SDK_DELAYLOAD +#include "DelayLoader.h" +#include <ansel/Camera.h> +#include <ansel/Hints.h> +#include <ansel/Configuration.h> +#include <cmath> +#include <Windows.h> +#include <stdio.h> +#include <codecvt> + + +namespace +{ + HMODULE anselSDK = NULL; +} + +namespace ansel +{ + namespace + { + typedef SetConfigurationStatus(__cdecl *PFNSETCONFIGURATION)(const Configuration& cfg); + typedef void(__cdecl *PFNUPDATECAMERA)(Camera& camera); + typedef void(__cdecl *PFNSESSIONFUNC)(); + typedef bool(__cdecl *PFNISANSELAVAILABLE)(); + typedef void(__cdecl *PFNMARKHDRBUFFERBIND)(HintType, uint64_t); + typedef void(__cdecl *PFNMARKHDRBUFFERFINISHED)(uint64_t); + PFNMARKHDRBUFFERFINISHED markHdrBufferFinishedFunc = nullptr; + PFNMARKHDRBUFFERBIND markHdrBufferBindFunc = nullptr; + PFNSESSIONFUNC stopSessionFunc = nullptr; + PFNSESSIONFUNC startSessionFunc = nullptr; + PFNUPDATECAMERA updateCameraFunc = nullptr; + PFNSETCONFIGURATION setConfigurationFunc = nullptr; + + DelayLoadStatus resolveFunctionPointers() + { + if (anselSDK == NULL) + return kDelayLoadDllNotFound; + + setConfigurationFunc = reinterpret_cast<PFNSETCONFIGURATION>(GetProcAddress(anselSDK, "setConfiguration")); + stopSessionFunc = reinterpret_cast<PFNSESSIONFUNC>(GetProcAddress(anselSDK, "stopSession")); + startSessionFunc = reinterpret_cast<PFNSESSIONFUNC>(GetProcAddress(anselSDK, "startSession")); + updateCameraFunc = reinterpret_cast<PFNUPDATECAMERA>(GetProcAddress(anselSDK, "updateCamera")); + markHdrBufferBindFunc = reinterpret_cast<PFNMARKHDRBUFFERBIND>(GetProcAddress(anselSDK, "markHdrBufferBind")); + markHdrBufferFinishedFunc = reinterpret_cast<PFNMARKHDRBUFFERFINISHED>(GetProcAddress(anselSDK, "markHdrBufferFinished")); + + if (setConfigurationFunc == nullptr || + stopSessionFunc == nullptr || + startSessionFunc == nullptr || + updateCameraFunc == nullptr || + markHdrBufferBindFunc == nullptr || + markHdrBufferFinishedFunc == nullptr) + return kDelayLoadIncompatibleVersion; + + return kDelayLoadOk; + } + + void makeQuaternionFromRotationMatrix(nv::Quat& q, const float r[3][3]) + { + float trace = r[0][0] + r[1][1] + r[2][2]; + + if (trace > 0.0f) { + // |w| > 1/2, may as well choose w > 1/2 + float s = sqrtf(trace + 1.0f); // 2w + + q.w = s * 0.5f; + s = 0.5f / s; // 1/(4w) + + q.x = (r[2][1] - r[1][2]) * s; + q.y = (r[0][2] - r[2][0]) * s; + q.z = (r[1][0] - r[0][1]) * s; + } + else { + // |w| <= 1/2 + int i = 0; + if (r[1][1] > r[0][0]) i = 1; + if (r[2][2] > r[i][i]) i = 2; + + int j = (1 << i) & 3; // i + 1 modulo 3. + int k = (1 << j) & 3; + + float s = sqrtf(r[i][i] - r[j][j] - r[k][k] + 1.0f); + + float* component = &q.x; + component[i] = s * 0.5f; + s = 0.5f / s; + component[j] = (r[i][j] + r[j][i]) * s; + component[k] = (r[k][i] + r[i][k]) * s; + q.w = (r[k][j] - r[j][k]) * s; + } + } + + void makeRotationMatrixFromQuaternion(float rot[3][3], const nv::Quat& q) + { + float s = 2.0f; + + float xs = q.x * s; + float ys = q.y * s; + float zs = q.z * s; + + float wx = q.w * xs; + float wy = q.w * ys; + float wz = q.w * zs; + + float xx = q.x * xs; + float xy = q.x * ys; + float xz = q.x * zs; + + float yy = q.y * ys; + float yz = q.y * zs; + float zz = q.z * zs; + + rot[0][0] = 1.0f - (yy + zz); + rot[0][1] = xy - wz; + rot[0][2] = xz + wy; + + rot[1][0] = xy + wz; + rot[1][1] = 1.0f - (xx + zz); + rot[1][2] = yz - wx; + + rot[2][0] = xz - wy; + rot[2][1] = yz + wx; + rot[2][2] = 1.0f - (xx + yy); + } + + // This may seem like a funky construct so allow me to explain. This code serves only + // one purpose: to create a signaling object that Ansel (when loaded from driver shim) + // can use to detect that a game has integrated the SDK. Note that this same object + // will also be created by the SDK DLL when loaded but this is safe since creating + // the same mutex again just provides a handle to the already existing mutex. + class SdkMutex + { + public: + SdkMutex() + { + DWORD id = GetCurrentProcessId(); + char name[MAX_PATH]; + sprintf_s(name, "NVIDIA/Ansel/%d", id); + CreateMutexA(NULL, false, name); + } + }; + + SdkMutex s_mySdkMutex; + } + + + SetConfigurationStatus setConfiguration(const Configuration& config) + { + if (setConfigurationFunc) + return setConfigurationFunc(config); + else + return kSetConfigurationSdkNotLoaded; + } + + void updateCamera(ansel::Camera& cam) + { + if (updateCameraFunc) + updateCameraFunc(cam); + } + + void stopSession() + { + if (stopSessionFunc) + stopSessionFunc(); + } + + void startSession() + { + if (startSessionFunc) + startSessionFunc(); + } + + bool isAnselAvailable() + { + // search for NvCamera32/64 DLL in the process + const char* moduleName = +#if _M_AMD64 + "NvCamera64.dll"; +#else + "NvCamera32.dll"; +#endif + + return GetModuleHandleA(moduleName) != nullptr; + } + + void markHdrBufferBind(HintType hintType, uint64_t threadId) + { + if (markHdrBufferBindFunc) + markHdrBufferBindFunc(hintType, threadId); + } + + void markHdrBufferFinished(uint64_t threadId) + { + if (markHdrBufferFinishedFunc) + markHdrBufferFinishedFunc(threadId); + } + + void quaternionToRotationMatrixVectors(const nv::Quat& q, nv::Vec3& right, nv::Vec3& up, nv::Vec3& forward) + { + float rot[3][3]; + makeRotationMatrixFromQuaternion(rot, q); + right = { rot[0][0], rot[1][0], rot[2][0] }; + up = { rot[0][1], rot[1][1], rot[2][1] }; + forward = { rot[0][2], rot[1][2], rot[2][2] }; + } + + void rotationMatrixVectorsToQuaternion(const nv::Vec3& right, const nv::Vec3& up, const nv::Vec3& forward, nv::Quat& q) + { + const float rot[3][3] = { + { right.x, up.x, forward.x }, + { right.y, up.y, forward.y }, + { right.z, up.z, forward.z } + }; + makeQuaternionFromRotationMatrix(q, rot); + } +} + +DelayLoadStatus loadAnselSDKLibrary(const char* pathToLibraryUtf8) +{ + if (anselSDK == NULL) + { + if (pathToLibraryUtf8) + { + // convert from utf8 to wchar_t: + std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; + std::wstring pathWstring = converter.from_bytes(pathToLibraryUtf8); + anselSDK = LoadLibraryW(pathWstring.c_str()); + } + else + { + #if defined(_M_IX86) + #define ANSEL_BITNESS "32" + #elif defined(_M_AMD64) + #define ANSEL_BITNESS "64" + #endif + + #if defined(_DEBUG) + #define ANSEL_RUNTIME_FLAVOR "d" + #else + #define ANSEL_RUNTIME_FLAVOR "" + #endif + + const char* libName = "AnselSDK" ANSEL_BITNESS ANSEL_RUNTIME_FLAVOR ".dll"; + anselSDK = LoadLibraryA(libName); + } + + if (anselSDK == NULL) + return kDelayLoadDllNotFound; + else + return ansel::resolveFunctionPointers(); + } + + return kDelayLoadOk; +} |