1. 程式人生 > >Vulkan Cookbook 第一章 4 準備載入Vulkan API函式

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, #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 API函式指標的變數的宣告和定義放在結構,類或名稱空間中。

現在我們已經準備好了,我們可以開始載入Vulkan函數了。