mirror of
https://github.com/KhronosGroup/Vulkan-Hpp.git
synced 2025-09-11 21:08:26 -04:00
Add support for a full volk replacement by supporting a global DispatchLoaderDynamic. The global dynamic dispatcher will be available if either the define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC is set to 1 or if VK_NO_PROTOTYPES is defined. In those cases it is required to add VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE; to any compilation unit of the project to allocate storage for the dispatcher. (#390)
This commit is contained in:
parent
9df0fac638
commit
e26cb8113a
@ -1100,13 +1100,13 @@ void VulkanHppGenerator::appendDispatchLoaderDynamic(std::string & str)
|
|||||||
|
|
||||||
#if !defined(VK_NO_PROTOTYPES)
|
#if !defined(VK_NO_PROTOTYPES)
|
||||||
// This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
|
// This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
|
||||||
DispatchLoaderDynamic(vk::Instance const& instance, vk::Device const& device = {})
|
DispatchLoaderDynamic(vk::Instance const& instance, vk::Device const& device)
|
||||||
{
|
{
|
||||||
init(instance, device);
|
init(instance, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
|
// This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
|
||||||
void init(vk::Instance const& instance, vk::Device const& device = {})
|
void init(vk::Instance const& instance, vk::Device const& device)
|
||||||
{
|
{
|
||||||
init(static_cast<VkInstance>(instance), ::vkGetInstanceProcAddr, static_cast<VkDevice>(device), device ? ::vkGetDeviceProcAddr : nullptr);
|
init(static_cast<VkInstance>(instance), ::vkGetInstanceProcAddr, static_cast<VkDevice>(device), device ? ::vkGetDeviceProcAddr : nullptr);
|
||||||
}
|
}
|
||||||
@ -1134,47 +1134,75 @@ void VulkanHppGenerator::appendDispatchLoaderDynamic(std::string & str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This interface does not require a linked vulkan library.
|
// This interface does not require a linked vulkan library.
|
||||||
void init( VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr, VkDevice device = VK_NULL_HANDLE, PFN_vkGetDeviceProcAddr getDeviceProcAddr = nullptr )
|
void init( VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr, VkDevice device = VK_NULL_HANDLE, PFN_vkGetDeviceProcAddr /*getDeviceProcAddr*/ = nullptr )
|
||||||
{
|
{
|
||||||
VULKAN_HPP_ASSERT(instance && getInstanceProcAddr);
|
VULKAN_HPP_ASSERT(instance && getInstanceProcAddr);
|
||||||
vkGetInstanceProcAddr = getInstanceProcAddr;
|
vkGetInstanceProcAddr = getInstanceProcAddr;
|
||||||
vkGetDeviceProcAddr = getDeviceProcAddr ? getDeviceProcAddr : PFN_vkGetDeviceProcAddr( vkGetInstanceProcAddr( instance, "vkGetDeviceProcAddr") );
|
init( vk::Instance(instance) );
|
||||||
|
if (device) {
|
||||||
|
init( vk::Device(device) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init( vk::Instance instance )
|
||||||
|
{
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
std::string strDeviceFunctions;
|
||||||
|
std::string strDeviceFunctionsInstance;
|
||||||
|
std::string strInstanceFunctions;
|
||||||
for (auto const& handle : m_handles)
|
for (auto const& handle : m_handles)
|
||||||
{
|
{
|
||||||
for (auto const& command : handle.second.commands)
|
for (auto const& command : handle.second.commands)
|
||||||
{
|
{
|
||||||
if ((command.first != "vkGetDeviceProcAddr") && (command.first != "vkGetInstanceProcAddr"))
|
if ((command.first != "vkGetInstanceProcAddr"))
|
||||||
{
|
{
|
||||||
std::string enter, leave;
|
std::string enter, leave;
|
||||||
appendPlatformEnter(enter, command.second.platform);
|
appendPlatformEnter(enter, command.second.platform);
|
||||||
appendPlatformLeave(leave, command.second.platform);
|
appendPlatformLeave(leave, command.second.platform);
|
||||||
|
|
||||||
str += enter;
|
|
||||||
if (!command.second.params.empty()
|
if (!command.second.params.empty()
|
||||||
&& m_handles.find(command.second.params[0].type.type) != m_handles.end()
|
&& m_handles.find(command.second.params[0].type.type) != m_handles.end()
|
||||||
&& command.second.params[0].type.type != "VkInstance"
|
&& command.second.params[0].type.type != "VkInstance"
|
||||||
&& command.second.params[0].type.type != "VkPhysicalDevice")
|
&& command.second.params[0].type.type != "VkPhysicalDevice")
|
||||||
{
|
{
|
||||||
str += " " + command.first + " = PFN_" + command.first
|
strDeviceFunctions += enter;
|
||||||
+ "( device ? vkGetDeviceProcAddr( device, \"" + command.first + "\" ) : vkGetInstanceProcAddr( instance, \"" + command.first + "\" ) );\n";
|
strDeviceFunctions += " " + command.first + " = PFN_" + command.first
|
||||||
|
+ "( vkGetDeviceProcAddr( device, \"" + command.first + "\" ) );\n";
|
||||||
|
strDeviceFunctions += leave;
|
||||||
|
|
||||||
|
strDeviceFunctionsInstance += enter;
|
||||||
|
strDeviceFunctionsInstance += " " + command.first + " = PFN_" + command.first
|
||||||
|
+ "( vkGetInstanceProcAddr( instance, \"" + command.first + "\" ) );\n";
|
||||||
|
strDeviceFunctionsInstance += leave;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str += " " + command.first + " = PFN_" + command.first + "( vkGetInstanceProcAddr( instance, \"" + command.first + "\" ) );\n";
|
strInstanceFunctions += enter;
|
||||||
|
strInstanceFunctions += " " + command.first + " = PFN_" + command.first + "( vkGetInstanceProcAddr( instance, \"" + command.first + "\" ) );\n";
|
||||||
|
strInstanceFunctions += leave;
|
||||||
}
|
}
|
||||||
str += leave;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str += " }\n"
|
|
||||||
" };\n";
|
str += strInstanceFunctions;
|
||||||
|
str += strDeviceFunctionsInstance;
|
||||||
|
str += " }\n\n";
|
||||||
|
str += " void init( vk::Device device )\n {\n";
|
||||||
|
str += strDeviceFunctions;
|
||||||
|
str += R"( }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE namespace vk { DispatchLoaderDynamic defaultDispatchLoaderDynamic; }
|
||||||
|
|
||||||
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanHppGenerator::appendDispatchLoaderStatic(std::string & str)
|
void VulkanHppGenerator::appendDispatchLoaderStatic(std::string & str)
|
||||||
{
|
{
|
||||||
str += R"(
|
str += R"(
|
||||||
|
#if !defined(VK_NO_PROTOTYPES)
|
||||||
class DispatchLoaderStatic
|
class DispatchLoaderStatic
|
||||||
{
|
{
|
||||||
public:)";
|
public:)";
|
||||||
@ -1211,19 +1239,35 @@ void VulkanHppGenerator::appendDispatchLoaderStatic(std::string & str)
|
|||||||
appendPlatformLeave(str, command.second.platform);
|
appendPlatformLeave(str, command.second.platform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str += " };\n";
|
str += " };\n#endif\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanHppGenerator::appendDispatchLoaderDefault(std::string & str)
|
void VulkanHppGenerator::appendDispatchLoaderDefault(std::string & str)
|
||||||
{
|
{
|
||||||
str += "\n"
|
str += "\n"
|
||||||
"#if !defined(VK_NO_PROTOTYPES)";
|
R"( class DispatchLoaderDynamic;
|
||||||
appendDispatchLoaderStatic(str);
|
#if !defined(VULKAN_HPP_DISPATCH_LOADER_DYNAMIC)
|
||||||
str += R"(
|
# if defined(VK_NO_PROTOTYPES)
|
||||||
typedef DispatchLoaderStatic DispatchLoaderDefault;
|
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||||
#else // !defined(VK_NO_PROTOTYPES)
|
# else
|
||||||
class NeedExplicitDispatchLoader;
|
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0
|
||||||
typedef NeedExplicitDispatchLoader DispatchLoaderDefault;
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(VULKAN_HPP_DEFAULT_DISPATCHER)
|
||||||
|
# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
|
||||||
|
#define VULKAN_HPP_DEFAULT_DISPATCHER ::vk::defaultDispatchLoaderDynamic
|
||||||
|
# else
|
||||||
|
# define VULKAN_HPP_DEFAULT_DISPATCHER ::vk::DispatchLoaderStatic()
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(VULKAN_HPP_DEFAULT_DISPATCHER_TYPE)
|
||||||
|
# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
|
||||||
|
#define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::vk::DispatchLoaderDynamic
|
||||||
|
# else
|
||||||
|
# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::vk::DispatchLoaderStatic
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
@ -1950,7 +1994,7 @@ void VulkanHppGenerator::appendFunctionHeaderArgumentsEnhanced(std::string & str
|
|||||||
str += "Dispatch const &d";
|
str += "Dispatch const &d";
|
||||||
if (withDefaults && !withAllocator)
|
if (withDefaults && !withAllocator)
|
||||||
{
|
{
|
||||||
str += " = Dispatch()";
|
str += " = VULKAN_HPP_DEFAULT_DISPATCHER";
|
||||||
}
|
}
|
||||||
str += " ";
|
str += " ";
|
||||||
}
|
}
|
||||||
@ -1977,7 +2021,7 @@ void VulkanHppGenerator::appendFunctionHeaderArgumentsStandard(std::string & str
|
|||||||
str += "Dispatch const &d";
|
str += "Dispatch const &d";
|
||||||
if (withDefaults)
|
if (withDefaults)
|
||||||
{
|
{
|
||||||
str += " = Dispatch() ";
|
str += " = VULKAN_HPP_DEFAULT_DISPATCHER ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2087,7 +2131,7 @@ void VulkanHppGenerator::appendFunctionHeaderTemplate(std::string & str, std::st
|
|||||||
str += ", ";
|
str += ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str += std::string("typename Dispatch") + (withDefault ? " = DispatchLoaderDefault" : "") + ">\n";
|
str += std::string("typename Dispatch") + (withDefault ? " = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE" : "") + ">\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanHppGenerator::appendHandle(std::string & str, std::pair<std::string, HandleData> const& handleData, std::set<std::string> & listedHandles) const
|
void VulkanHppGenerator::appendHandle(std::string & str, std::pair<std::string, HandleData> const& handleData, std::set<std::string> & listedHandles) const
|
||||||
@ -2908,7 +2952,7 @@ void VulkanHppGenerator::appendUniqueTypes(std::string & str, std::string const&
|
|||||||
std::string deleterPool = handleIt->second.deletePool.empty() ? "" : ", " + stripPrefix(handleIt->second.deletePool, "Vk");
|
std::string deleterPool = handleIt->second.deletePool.empty() ? "" : ", " + stripPrefix(handleIt->second.deletePool, "Vk");
|
||||||
str += "\n"
|
str += "\n"
|
||||||
" template <typename Dispatch> class UniqueHandleTraits<" + type + ", Dispatch> { public: using deleter = " + deleterType + deleterAction + "<" + deleterParent + deleterPool + ", Dispatch>; };\n"
|
" template <typename Dispatch> class UniqueHandleTraits<" + type + ", Dispatch> { public: using deleter = " + deleterType + deleterAction + "<" + deleterParent + deleterPool + ", Dispatch>; };\n"
|
||||||
" using Unique" + type + " = UniqueHandle<" + type + ", DispatchLoaderDefault>;";
|
" using Unique" + type + " = UniqueHandle<" + type + ", VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;";
|
||||||
}
|
}
|
||||||
str += "\n"
|
str += "\n"
|
||||||
"#endif /*VULKAN_HPP_NO_SMART_HANDLE*/\n";
|
"#endif /*VULKAN_HPP_NO_SMART_HANDLE*/\n";
|
||||||
@ -4501,7 +4545,7 @@ int main( int argc, char **argv )
|
|||||||
class ObjectDestroy
|
class ObjectDestroy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectDestroy( OwnerType owner = OwnerType(), Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = Dispatch() )
|
ObjectDestroy( OwnerType owner = OwnerType(), Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER )
|
||||||
: m_owner( owner )
|
: m_owner( owner )
|
||||||
, m_allocationCallbacks( allocationCallbacks )
|
, m_allocationCallbacks( allocationCallbacks )
|
||||||
, m_dispatch( &dispatch )
|
, m_dispatch( &dispatch )
|
||||||
@ -4529,7 +4573,7 @@ int main( int argc, char **argv )
|
|||||||
class ObjectDestroy<NoParent,Dispatch>
|
class ObjectDestroy<NoParent,Dispatch>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectDestroy( Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = Dispatch() )
|
ObjectDestroy( Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER )
|
||||||
: m_allocationCallbacks( allocationCallbacks )
|
: m_allocationCallbacks( allocationCallbacks )
|
||||||
, m_dispatch( &dispatch )
|
, m_dispatch( &dispatch )
|
||||||
{}
|
{}
|
||||||
@ -4554,7 +4598,7 @@ int main( int argc, char **argv )
|
|||||||
class ObjectFree
|
class ObjectFree
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectFree( OwnerType owner = OwnerType(), Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = Dispatch() )
|
ObjectFree( OwnerType owner = OwnerType(), Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER )
|
||||||
: m_owner( owner )
|
: m_owner( owner )
|
||||||
, m_allocationCallbacks( allocationCallbacks )
|
, m_allocationCallbacks( allocationCallbacks )
|
||||||
, m_dispatch( &dispatch )
|
, m_dispatch( &dispatch )
|
||||||
@ -4600,7 +4644,7 @@ int main( int argc, char **argv )
|
|||||||
class PoolFree
|
class PoolFree
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PoolFree( OwnerType owner = OwnerType(), PoolType pool = PoolType(), Dispatch const &dispatch = Dispatch() )
|
PoolFree( OwnerType owner = OwnerType(), PoolType pool = PoolType(), Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER )
|
||||||
: m_owner( owner )
|
: m_owner( owner )
|
||||||
, m_pool( pool )
|
, m_pool( pool )
|
||||||
, m_dispatch( &dispatch )
|
, m_dispatch( &dispatch )
|
||||||
@ -5290,6 +5334,7 @@ namespace std
|
|||||||
+ classOptional
|
+ classOptional
|
||||||
+ classStructureChain
|
+ classStructureChain
|
||||||
+ classUniqueHandle;
|
+ classUniqueHandle;
|
||||||
|
generator.appendDispatchLoaderStatic(str);
|
||||||
generator.appendDispatchLoaderDefault(str);
|
generator.appendDispatchLoaderDefault(str);
|
||||||
str += classObjectDestroy
|
str += classObjectDestroy
|
||||||
+ classObjectFree
|
+ classObjectFree
|
||||||
|
@ -15,47 +15,41 @@
|
|||||||
// VulkanHpp Samples : DispatchLoaderDynamic
|
// VulkanHpp Samples : DispatchLoaderDynamic
|
||||||
// Compile test on DispatchLoaderDynamic functions
|
// Compile test on DispatchLoaderDynamic functions
|
||||||
|
|
||||||
|
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkan/vulkan.hpp"
|
#include "vulkan/vulkan.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
static char const* AppName = "DispatchLoaderDynamic";
|
static char const* AppName = "DispatchLoaderDynamic";
|
||||||
static char const* EngineName = "Vulkan.hpp";
|
static char const* EngineName = "Vulkan.hpp";
|
||||||
|
|
||||||
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE;
|
||||||
|
|
||||||
int main(int /*argc*/, char ** /*argv*/)
|
int main(int /*argc*/, char ** /*argv*/)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vk::DispatchLoaderDynamic dld0;
|
|
||||||
vk::DynamicLoader dl;
|
vk::DynamicLoader dl;
|
||||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
// empty DispatchLoaderDynamic, used for init calls later on
|
vk::Instance instance = vk::createInstance({}, nullptr);
|
||||||
vk::DispatchLoaderDynamic dld_boot(vkGetInstanceProcAddr);
|
|
||||||
vk::Instance instance = vk::createInstance({}, nullptr, dld_boot);
|
|
||||||
|
|
||||||
vk::DispatchLoaderDynamic dld1(instance, vkGetInstanceProcAddr);
|
// initialize function pointers for instance
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
|
||||||
// compare to the empty dispatcher, and init the empty dispatcher the same way
|
|
||||||
assert(memcmp(&dld0, &dld1, sizeof(vk::DispatchLoaderDynamic)) != 0);
|
|
||||||
dld0.init(instance, vkGetInstanceProcAddr);
|
|
||||||
assert(memcmp(&dld0, &dld1, sizeof(vk::DispatchLoaderDynamic)) == 0);
|
|
||||||
|
|
||||||
// create a dispatcher, based on additional vkDevice/vkGetDeviceProcAddr
|
// create a dispatcher, based on additional vkDevice/vkGetDeviceProcAddr
|
||||||
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(dld1);
|
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
|
||||||
|
|
||||||
assert(!physicalDevices.empty());
|
assert(!physicalDevices.empty());
|
||||||
|
|
||||||
vk::Device device = physicalDevices[0].createDevice({}, nullptr, dld1);
|
vk::Device device = physicalDevices[0].createDevice({}, nullptr);
|
||||||
|
|
||||||
// device specialization functions
|
// function pointer specialization for device
|
||||||
vk::DispatchLoaderDynamic dld2(instance, vkGetInstanceProcAddr, device);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(device);
|
||||||
|
|
||||||
|
|
||||||
// compare to "simpler" dispatcher and make them equal
|
|
||||||
assert(memcmp(&dld0, &dld2, sizeof(vk::DispatchLoaderDynamic)) != 0);
|
|
||||||
dld0.init(instance, vkGetInstanceProcAddr, device);
|
|
||||||
assert(memcmp(&dld0, &dld2, sizeof(vk::DispatchLoaderDynamic)) == 0);
|
|
||||||
}
|
}
|
||||||
catch (vk::SystemError err)
|
catch (vk::SystemError err)
|
||||||
{
|
{
|
||||||
|
4387
vulkan/vulkan.hpp
4387
vulkan/vulkan.hpp
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user