carb/PluginCoreUtils.h
File members: carb/PluginCoreUtils.h
// Copyright (c) 2018-2024, 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 "Defines.h"
#include "../omni/core/Api.h" // OMNI_API
#include "../omni/core/Omni.h"
#include <cstddef>
#include <cstdint>
const char* const kCarbGetFrameworkVersionFnName = "carbGetFrameworkVersion";
const char* const kCarbOnPluginRegisterFnName = "carbOnPluginRegister";
const char* const kCarbOnPluginRegisterExFnName = "carbOnPluginRegisterEx";
const char* const kCarbOnPluginRegisterEx2FnName = "carbOnPluginRegisterEx2";
const char* const kCarbOnPluginPreStartupFnName = "carbOnPluginPreStartup";
const char* const kCarbOnPluginStartupFnName = "carbOnPluginStartup";
const char* const kCarbOnPluginStartupExFnName = "carbOnPluginStartupEx";
const char* const kCarbOnPluginShutdownFnName = "carbOnPluginShutdown";
const char* const kCarbOnPluginQuickShutdownFnName = "carbOnPluginQuickShutdown";
const char* const kCarbOnPluginPostShutdownFnName = "carbOnPluginPostShutdown";
const char* const kCarbGetPluginDepsFnName = "carbGetPluginDeps";
const char* const kCarbOnReloadDependencyFnName = "carbOnReloadDependency";
namespace omni
{
namespace core
{
OMNI_DECLARE_INTERFACE(ITypeFactory) // forward declaration
}
namespace log
{
class ILog; // forward declaration
}
} // namespace omni
#define OMNI_MODULE_GLOBALS_FOR_PLUGIN() \
namespace \
{ \
::omni::core::ITypeFactory* s_omniTypeFactory = nullptr; \
::omni::log::ILog* s_omniLog = nullptr; \
::omni::structuredlog::IStructuredLog* s_omniStructuredLog = nullptr; \
} \
OMNI_MODULE_DEFINE_LOCATION_FUNCTIONS() \
OMNI_MODULE_GLOBALS_BUILD_CONFIG_SYMBOLS(); \
OMNI_API void* omniGetBuiltInWithoutAcquire(::OmniBuiltIn type) \
{ \
switch (type) \
{ \
case ::OmniBuiltIn::eITypeFactory: \
return s_omniTypeFactory; \
case ::OmniBuiltIn::eILog: \
return s_omniLog; \
case ::OmniBuiltIn::eIStructuredLog: \
return s_omniStructuredLog; \
default: \
return nullptr; \
} \
}
#define OMNI_MODULE_SET_GLOBALS_FOR_PLUGIN(in_) \
s_omniTypeFactory = (in_)->omniTypeFactory; \
s_omniLog = (in_)->omniLog; \
s_omniStructuredLog = (in_)->omniStructuredLog;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// FOR_EACH macro implementation, use as FOR_EACH(OTHER_MACRO, p0, p1, p2,)
# define EXPAND(x) x
# define FE_1(WHAT, X) EXPAND(WHAT(X))
# define FE_2(WHAT, X, ...) EXPAND(WHAT(X) FE_1(WHAT, __VA_ARGS__))
# define FE_3(WHAT, X, ...) EXPAND(WHAT(X) FE_2(WHAT, __VA_ARGS__))
# define FE_4(WHAT, X, ...) EXPAND(WHAT(X) FE_3(WHAT, __VA_ARGS__))
# define FE_5(WHAT, X, ...) EXPAND(WHAT(X) FE_4(WHAT, __VA_ARGS__))
# define FE_6(WHAT, X, ...) EXPAND(WHAT(X) FE_5(WHAT, __VA_ARGS__))
# define FE_7(WHAT, X, ...) EXPAND(WHAT(X) FE_6(WHAT, __VA_ARGS__))
# define FE_8(WHAT, X, ...) EXPAND(WHAT(X) FE_7(WHAT, __VA_ARGS__))
# define FE_9(WHAT, X, ...) EXPAND(WHAT(X) FE_8(WHAT, __VA_ARGS__))
# define FE_10(WHAT, X, ...) EXPAND(WHAT(X) FE_9(WHAT, __VA_ARGS__))
# define FE_11(WHAT, X, ...) EXPAND(WHAT(X) FE_10(WHAT, __VA_ARGS__))
# define FE_12(WHAT, X, ...) EXPAND(WHAT(X) FE_11(WHAT, __VA_ARGS__))
# define FE_13(WHAT, X, ...) EXPAND(WHAT(X) FE_12(WHAT, __VA_ARGS__))
# define FE_14(WHAT, X, ...) EXPAND(WHAT(X) FE_13(WHAT, __VA_ARGS__))
# define FE_15(WHAT, X, ...) EXPAND(WHAT(X) FE_14(WHAT, __VA_ARGS__))
# define FE_16(WHAT, X, ...) EXPAND(WHAT(X) FE_15(WHAT, __VA_ARGS__))
# define FE_17(WHAT, X, ...) EXPAND(WHAT(X) FE_16(WHAT, __VA_ARGS__))
# define FE_18(WHAT, X, ...) EXPAND(WHAT(X) FE_17(WHAT, __VA_ARGS__))
# define FE_19(WHAT, X, ...) EXPAND(WHAT(X) FE_18(WHAT, __VA_ARGS__))
# define FE_20(WHAT, X, ...) EXPAND(WHAT(X) FE_19(WHAT, __VA_ARGS__))
# define FE_21(WHAT, X, ...) EXPAND(WHAT(X) FE_20(WHAT, __VA_ARGS__))
# define FE_22(WHAT, X, ...) EXPAND(WHAT(X) FE_21(WHAT, __VA_ARGS__))
# define FE_23(WHAT, X, ...) EXPAND(WHAT(X) FE_22(WHAT, __VA_ARGS__))
# define FE_24(WHAT, X, ...) EXPAND(WHAT(X) FE_23(WHAT, __VA_ARGS__))
# define FE_25(WHAT, X, ...) EXPAND(WHAT(X) FE_24(WHAT, __VA_ARGS__))
# define FE_26(WHAT, X, ...) EXPAND(WHAT(X) FE_25(WHAT, __VA_ARGS__))
# define FE_27(WHAT, X, ...) EXPAND(WHAT(X) FE_26(WHAT, __VA_ARGS__))
# define FE_28(WHAT, X, ...) EXPAND(WHAT(X) FE_27(WHAT, __VA_ARGS__))
# define FE_29(WHAT, X, ...) EXPAND(WHAT(X) FE_28(WHAT, __VA_ARGS__))
# define FE_30(WHAT, X, ...) EXPAND(WHAT(X) FE_29(WHAT, __VA_ARGS__))
# define FE_31(WHAT, X, ...) EXPAND(WHAT(X) FE_30(WHAT, __VA_ARGS__))
# define FE_32(WHAT, X, ...) EXPAND(WHAT(X) FE_31(WHAT, __VA_ARGS__))
//... repeat as needed
# define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, \
_22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, NAME, ...) \
NAME
# define FOR_EACH(action, ...) \
EXPAND(GET_MACRO(__VA_ARGS__, FE_32, FE_31, FE_30, FE_29, FE_28, FE_27, FE_26, FE_25, FE_24, FE_23, FE_22, \
FE_21, FE_20, FE_19, FE_18, FE_17, FE_16, FE_15, FE_14, FE_13, FE_12, FE_11, FE_10, FE_9, \
FE_8, FE_7, FE_6, FE_5, FE_4, FE_3, FE_2, FE_1)(action, __VA_ARGS__))
# define DECLARE_FILL_FUNCTION(X) void fillInterface(X& iface);
// carbOnPluginRegisterEx2() was added with carbonite version 0.5 without changing the carbonite version number.
// Therefore, this exists only to support older carbonite version 0.5 instances that are not aware of
// carbOnPluginRegisterEx2. This macro can be safely removed when Framework version 0.5 is no longer supported.
static_assert(carb::kFrameworkVersion.major == 0, "Remove CARB_PLUGIN_IMPL_WITH_INIT_0_5");
# define CARB_PLUGIN_IMPL_WITH_INIT_0_5(impl, ...) \
FOR_EACH(DECLARE_FILL_FUNCTION, __VA_ARGS__) \
template <typename T1> \
void fillInterface0_5(carb::PluginRegistryEntry::Interface* interfaces) \
{ \
interfaces[0].desc = T1::getLatestInterfaceDesc(); \
static T1 s_pluginInterface{}; \
fillInterface(s_pluginInterface); \
interfaces[0].ptr = &s_pluginInterface; \
interfaces[0].size = sizeof(T1); \
} \
template <typename T1, typename T2, typename... Types> \
void fillInterface0_5(carb::PluginRegistryEntry::Interface* interfaces) \
{ \
fillInterface0_5<T1>(interfaces); \
fillInterface0_5<T2, Types...>(interfaces + 1); \
} \
template <typename... Types> \
static void onPluginRegister0_5(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry* outEntry) \
{ \
static carb::PluginRegistryEntry::Interface s_interfaces[sizeof...(Types)] = {}; \
fillInterface0_5<Types...>(s_interfaces); \
outEntry->interfaces = s_interfaces; \
outEntry->interfaceCount = sizeof(s_interfaces) / sizeof(s_interfaces[0]); \
outEntry->implDesc = impl; \
\
g_carbFramework = frameworkDesc->framework; \
g_carbClientName = impl.name; \
OMNI_MODULE_SET_GLOBALS_FOR_PLUGIN(frameworkDesc) \
} \
CARB_EXPORT void carbOnPluginRegisterEx( \
carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry* outEntry) \
{ \
onPluginRegister0_5<__VA_ARGS__>(frameworkDesc, outEntry); \
}
# define CARB_PLUGIN_IMPL_WITH_INIT_0_5_EX(impl, ...) \
template <typename T1> \
void fillInterface0_5(carb::PluginRegistryEntry::Interface* interfaces) \
{ \
interfaces->desc = T1::getLatestInterfaceDesc(); \
static void* s_pluginInterface[(sizeof(T1) / sizeof(void*)) + 1] = {}; \
carb::Version ver = interfaces->desc.version; \
bool b = fillInterface<T1>(&ver, s_pluginInterface); \
CARB_FATAL_UNLESS(b, "Failed to construct interface for type %s", interfaces->desc.name); \
CARB_FATAL_UNLESS( \
ver == interfaces->desc.version, \
"Interface %s constructor requested version %u.%u but got %u.%u (must match exactly as the interface declared itself to be this version)", \
interfaces[0].desc.name, interfaces->desc.version.major, interfaces->desc.version.minor, ver.major, \
ver.minor); \
interfaces->ptr = &s_pluginInterface; \
interfaces->size = sizeof(T1); \
} \
template <typename T1, typename T2, typename... Types> \
void fillInterface0_5(carb::PluginRegistryEntry::Interface* interfaces) \
{ \
fillInterface0_5<T1>(interfaces); \
fillInterface0_5<T2, Types...>(interfaces + 1); \
} \
template <typename... Types> \
static void onPluginRegister0_5(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry* outEntry) \
{ \
static carb::PluginRegistryEntry::Interface s_interfaces[sizeof...(Types)]; \
fillInterface0_5<Types...>(s_interfaces); \
outEntry->interfaces = s_interfaces; \
outEntry->interfaceCount = sizeof(s_interfaces) / sizeof(s_interfaces[0]); \
outEntry->implDesc = impl; \
\
g_carbFramework = frameworkDesc->framework; \
g_carbClientName = impl.name; \
OMNI_MODULE_SET_GLOBALS_FOR_PLUGIN(frameworkDesc) \
} \
CARB_EXPORT void carbOnPluginRegisterEx( \
carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry* outEntry) \
{ \
onPluginRegister0_5<__VA_ARGS__>(frameworkDesc, outEntry); \
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
#define CARB_PLUGIN_IMPL_WITH_INIT(impl, ...) \
\
/* Forward declare fill functions for every interface */ \
FOR_EACH(DECLARE_FILL_FUNCTION, __VA_ARGS__) \
\
template <typename T1> \
void populate(carb::PluginRegistryEntry2::Interface2* iface) \
{ \
iface->sizeofThisStruct = sizeof(carb::PluginRegistryEntry2::Interface2); \
iface->desc = T1::getLatestInterfaceDesc(); \
iface->size = sizeof(T1); \
iface->align = alignof(T1); \
iface->Constructor = [](void* p) { fillInterface(*new (p) T1); }; \
iface->Destructor = [](void* p) { static_cast<T1*>(p)->~T1(); }; \
} \
\
template <typename T1, typename T2, typename... Types> \
void populate(carb::PluginRegistryEntry2::Interface2* interfaces) \
{ \
populate<T1>(interfaces); \
populate<T2, Types...>(interfaces + 1); \
} \
\
template <typename... Types> \
static void registerPlugin(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry2* outEntry) \
{ \
outEntry->sizeofThisStruct = sizeof(carb::PluginRegistryEntry2); \
static carb::PluginRegistryEntry2::Interface2 s_interfaces[sizeof...(Types)] = {}; \
populate<Types...>(s_interfaces); \
outEntry->interfaces = s_interfaces; \
outEntry->interfaceCount = CARB_COUNTOF(s_interfaces); \
outEntry->implDesc = impl; \
\
g_carbFramework = frameworkDesc->framework; \
g_carbClientName = impl.name; \
OMNI_MODULE_SET_GLOBALS_FOR_PLUGIN(frameworkDesc) \
} \
\
CARB_EXPORT void carbOnPluginRegisterEx2( \
carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry2* outEntry) \
{ \
registerPlugin<__VA_ARGS__>(frameworkDesc, outEntry); \
} \
\
CARB_EXPORT carb::Version carbGetFrameworkVersion() \
{ \
return carb::kFrameworkVersion; \
}
#define CARB_PLUGIN_IMPL_WITH_INIT_EX(impl, ...) \
/* forward declare fillInterface function */ \
template <class T1> \
bool fillInterface(carb::Version*, void*); \
template <class T1> \
void destroyInterface(carb::Version, void*) \
{ \
} \
\
template <typename T1> \
void populate(carb::PluginRegistryEntry2::Interface2* iface) \
{ \
iface->sizeofThisStruct = sizeof(carb::PluginRegistryEntry2::Interface2); \
iface->desc = T1::getLatestInterfaceDesc(); \
iface->size = sizeof(T1); \
iface->align = alignof(T1); \
iface->Constructor = nullptr; \
iface->Destructor = nullptr; \
iface->VersionedConstructor = &fillInterface<T1>; \
iface->VersionedDestructor = &destroyInterface<T1>; \
} \
\
template <typename T1, typename T2, typename... Types> \
void populate(carb::PluginRegistryEntry2::Interface2* interfaces) \
{ \
populate<T1>(interfaces); \
populate<T2, Types...>(interfaces + 1); \
} \
\
template <typename... Types> \
static void registerPlugin(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry2* outEntry) \
{ \
outEntry->sizeofThisStruct = sizeof(carb::PluginRegistryEntry2); \
static carb::PluginRegistryEntry2::Interface2 s_interfaces[sizeof...(Types)] = {}; \
populate<Types...>(s_interfaces); \
outEntry->interfaces = s_interfaces; \
outEntry->interfaceCount = CARB_COUNTOF(s_interfaces); \
outEntry->implDesc = impl; \
\
g_carbFramework = frameworkDesc->framework; \
g_carbClientName = impl.name; \
OMNI_MODULE_SET_GLOBALS_FOR_PLUGIN(frameworkDesc) \
} \
\
CARB_EXPORT void carbOnPluginRegisterEx2( \
carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry2* outEntry) \
{ \
registerPlugin<__VA_ARGS__>(frameworkDesc, outEntry); \
} \
\
CARB_EXPORT carb::Version carbGetFrameworkVersion() \
{ \
return carb::kFrameworkVersion; \
}
#if CARB_COMPILER_MSC
# pragma section(".state", read, write)
#endif
#define CARB_STATE \
CARB_DEPRECATED("hot reload has been removed") CARB_DECLSPEC(allocate(".state")) CARB_ATTRIBUTE(section(".state"))
// The below is for documentation only
#ifdef DOXYGEN_BUILD
CARB_EXPORT carb::Version carbGetFrameworkVersion();
CARB_EXPORT void carbOnPluginRegister(carb::Framework* framework, carb::PluginRegistryEntry* outEntry);
CARB_EXPORT void carbOnPluginRegisterEx(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry* outEntry);
CARB_EXPORT void carbOnPluginRegisterEx2(carb::PluginFrameworkDesc* frameworkDesc, carb::PluginRegistryEntry2* outEntry);
CARB_EXPORT void carbOnPluginPreStartup();
CARB_EXPORT void carbOnPluginStartup();
CARB_EXPORT bool carbOnPluginStartupEx();
CARB_EXPORT void carbOnPluginShutdown();
CARB_EXPORT void carbOnPluginQuickShutdown();
CARB_EXPORT void carbOnPluginPostShutdown();
CARB_EXPORT void carbGetPluginDeps(struct carb::InterfaceDesc** deps, size_t* count);
CARB_EXPORT void carbOnReloadDependency(carb::PluginReloadState reloadState,
void* pluginInterface,
carb::PluginImplDesc desc);
struct InterfaceType
{
CARB_PLUGIN_INTERFACE("carb::InterfaceType", 1, 0);
};
void fillInterface(InterfaceType& iface);
template <class T>
bool fillInterface(carb::Version* v, void* buf);
template <class T>
void destroyInterface(Version v, void* buf);
#endif