Vulkan Cookbook 第一章 4 准备加载Vulkan API函数

准备加载Vulkan API函数

译者注:示例代码点击此处

当我们想在我们的应用程序中使用Vulkan API时,我们需要获取Vulkan文档中指定的过程。为了做到这一点,我们可以向Vulkan Loader库添加一个依赖项,在我们的项目中静态链接它,并使用vulkan.h头文件中定义的函数原型。第二种方法是禁用vulkan.h头文件中定义的函数原型,并在我们的应用程序中动态加载函数指针。
第一种方法稍微容易一点,但它使用Vulkan Loader库中直接定义的函数。当我们在给定设备上执行操作时,Vulkan Loader需要根据我们提供的设备句柄将函数调用重定向到正确的实现。此重定向需要一些时间,因此会影响性能。
第二个选项需要在应用程序端进行更多工作,但允许我们跳过前面的重定向(跳转)并保留一些性能。它是通过直接从我们想要使用的设备加载功能来执行的。这样,如果我们不需要它们,我们也可以只选择Vulkan函数的子集。
在本书中,介绍了第二种方法,因为这使开发人员可以更好地控制应用程序中的内容。要从Vulkan Loader库动态加载函数,可以方便地将所有Vulkan API函数的名称包装到一组简单的宏中,并将声明定义和函数加载分成多个文件。

怎么做...

1.在项目中定义VK_NO_PROTOTYPES预处理器定义:在项目属性中执行此操作(使用Microsoft Visual Studio或Qt Creator等开发环境时),或者在包含vulkan.h文件之前使用#define VK_NO_PROTOTYPES预处理器指令 在我们的应用程序的源代码中。
2.创建一个名为ListOfVulkanFunctions.inl的新文件。
3.在文件中键入以下内容:

#ifndef EXPORTED_VULKAN_FUNCTION
#define EXPORTED_VULKAN_FUNCTION( function ) 
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef EXPORTED_VULKAN_FUNCTION

#ifndef GLOBAL_LEVEL_VULKAN_FUNCTION
#define GLOBAL_LEVEL_VULKAN_FUNCTION( function ) 
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef GLOBAL_LEVEL_VULKAN_FUNCTION

#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION
#define INSTANCE_LEVEL_VULKAN_FUNCTION( function ) 
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef INSTANCE_LEVEL_VULKAN_FUNCTION

#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION
#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( function, extension )
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION 

#ifndef DEVICE_LEVEL_VULKAN_FUNCTION
#define DEVICE_LEVEL_VULKAN_FUNCTION( function ) 
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef DEVICE_LEVEL_VULKAN_FUNCTION

#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION
#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( function, extension )
#endif
//译者注:稍后会在这里用宏插入函数名称
#undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION

4.创建一个新文件名为VulkanFunctions.h
5.将以下内容插入到文件中:

#include "vulkan.h" 

namespace VulkanCookbook {

#define EXPORTED_VULKAN_FUNCTION( name ) extern PFN_##name name; 
#define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name name;
#define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name name;
#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) extern PFN_##name name;
#define DEVICE_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name name;
#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) extern PFN_##name name;

 #include "ListOfVulkanFunctions.inl"

 } // namespace VulkanCookbook

6.创建一个名为VulkanFunctions.cpp.源代码文件。
7.在文件中插入以下内容:

#include "VulkanFunctions.h" 

namespace VulkanCookbook {

#define EXPORTED_VULKAN_FUNCTION( name ) PFN_##name name; 
#define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
#define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) PFN_##name name;
#define DEVICE_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) PFN_##name name;

#include "ListOfVulkanFunctions.inl" 

} // namespace VulkanCookbook

这个怎么运作...

VulkanFunctions.h和VulkanFunctions.cpp的宏定义似乎是不必要的,也的确不是不必要的。这两个文件应该用于声明和定义变量,但为了减少拼写错误,函数名称会在ListOfVulkanFunctions.inl中使用宏定义添加,不需要在多个地方多次重复函数的名称,我们将在其中存储指向Vulkan API函数的指针。

我们如何知道用于存储指向Vulkan API函数的指针的变量类型? 这很简单。 每个函数原型的类型直接来自函数的名称。 当函数名为<name>时,其类型为PFN_<name>。 例如,创建图像的函数称为vkCreateImage(),因此该函数的类型为PFN_vkCreateImage。 这就是为什么在VulkanFunctions.h和VulkanFunctions.cpp中定义的宏只有一个函做为作为参数,这可以很容易的拼出类型。

最后也很重要的是,请记住,我们应该将存储Vulkan函数地址的变量的声明和定义放在命名空间,类或结构中。 这是因为,如果它们是全局的,这可能会导致某些操作系统出现问题。 最好记住命名空间并增加代码的可移植性。

提示:将包含Vulkan API函数指针的变量的声明和定义放在结构,类或命名空间中。

现在已经准备好了,我们可以开始加载Vulkan函数了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值