carb/ClientUtils.h
File members: carb/ClientUtils.h
// Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, 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.
//
#pragma once
#include "Framework.h"
#include "assert/AssertUtils.h"
#include "crashreporter/CrashReporterUtils.h"
#include "l10n/L10nUtils.h"
#include "logging/Log.h"
#include "logging/StandardLogger.h"
#include "profiler/Profile.h"
#include "../omni/core/Omni.h"
#include <vector>
namespace carb
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace detail
{
inline void registerBuiltinFileSystem(Framework* f)
{
f->registerPlugin(g_carbClientName, f->getBuiltinFileSystemDesc());
}
inline void registerBuiltinLogging(Framework* f)
{
f->registerPlugin(g_carbClientName, f->getBuiltinLoggingDesc());
}
inline void registerBuiltinAssert(Framework* f)
{
f->registerPlugin(g_carbClientName, f->getBuiltinAssertDesc());
}
inline void registerBuiltinThreadUtil(Framework* f)
{
f->registerPlugin(g_carbClientName, f->getBuiltinThreadUtilDesc());
}
inline void registerAtexitHandler()
{
# if CARB_PLATFORM_WINDOWS && !defined _DLL
// Since we're not using the dynamic runtime, we need to notify carb.dll if the executable's atexit() functions run.
// We only do this if this is compiled into the executable here, so check that
auto exeHandle = GetModuleHandleW(NULL);
HMODULE myHandle;
if (GetModuleHandleExW(
CARBWIN_GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | CARBWIN_GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCWSTR)®isterAtexitHandler, &myHandle) &&
myHandle == exeHandle)
{
// Verified that this function is compiled into the executable and without dynamic runtime.
auto carbHandle = GetModuleHandleW(L"carb.dll");
auto proc = (void (*)(void*))(carbHandle ? GetProcAddress(carbHandle, "carbControlAtexit") : nullptr);
if (proc)
{
// Call our undocumented function and pass our atexit() function so that carb.dll can register a callback
// to know when the first-chance (executable) atexit happens.
proc((void*)&atexit);
}
}
# endif
}
} // namespace detail
#endif
inline Framework* acquireFrameworkAndRegisterBuiltins(const OmniCoreStartArgs* args = nullptr)
{
// Acquire framework and set into global variable
Framework* framework = acquireFramework(g_carbClientName);
if (framework)
{
g_carbFramework = framework;
static_assert(
kFrameworkVersion.major == 0,
"The framework automatically registers builtins now; the registerXXX functions can be removed once the framework version changes.");
detail::registerAtexitHandler();
// Starting up logging
detail::registerBuiltinLogging(framework);
logging::registerLoggingForClient();
// Starting up filesystem
detail::registerBuiltinFileSystem(framework);
detail::registerBuiltinAssert(framework);
detail::registerBuiltinThreadUtil(framework);
// grab the assertion helper interface.
assert::registerAssertForClient();
// grab the l10n interface.
l10n::registerLocalizationForClient();
// start up ONI
OMNI_CORE_START(args);
}
return framework;
}
inline void releaseFrameworkAndDeregisterBuiltins()
{
if (isFrameworkValid())
{
logging::deregisterLoggingForClient();
assert::deregisterAssertForClient();
l10n::deregisterLocalizationForClient();
// Release structured log before unloading plugins
omniReleaseStructuredLog();
g_carbFramework->unloadAllPlugins();
OMNI_CORE_STOP();
releaseFramework();
}
g_carbFramework = nullptr;
}
} // namespace carb
#define CARB_GLOBALS(clientName) CARB_GLOBALS_EX(clientName, nullptr)
#define CARB_GLOBALS_EX(clientName, clientDescription) \
CARB_FRAMEWORK_GLOBALS(clientName) \
CARB_LOG_GLOBALS() \
CARB_PROFILER_GLOBALS() \
CARB_ASSERT_GLOBALS() \
CARB_LOCALIZATION_GLOBALS() \
CARB_CRASH_REPORTER_GLOBALS() \
OMNI_GLOBALS_ADD_DEFAULT_CHANNEL(clientName, clientDescription)