例項(Instance)
Vulkan 例項 是 Vulkan API中的一個基本概念,它是連線 Vulkan 庫和應用程式之間的橋梁,用於初始化Vulkan 庫。 建立 Vulkan 例項涉及到向驅動程式提供應用程式的一些細節,如應用程式資訊和引擎資訊等。
在Vulkan中,例項(VkInstance)是儲存所有每個套用狀態的物件,應用程式必須在執行任何其他 Vulkan 操作之前建立一個 Vulkan 例項。
這個 類似於 OpenGL 的上下文概念 ,一個例項代表一整 Vulkan 環境(或上下文)。不同的 Vulkan環境能夠獲取到不同的 Vulkan 功能特性。
建立 VkInstance
Vulkan 編程中 ,建立一個 Vulkan 元件有一個固定的規則,首先需要設定一個建立元件資訊的結構體 VkxxxCreateInfo,然後呼叫建立元件的 API VkCreatexxx 。
VkInstanceCreateInfo
typedefstructVkInstanceCreateInfo {
VkStructureType sType;
constvoid* pNext;
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
constchar* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
constchar* const* ppEnabledExtensionNames;
} VkInstanceCreateInfo;
sType 是該結構體的型別列舉值, 必須 是 VkStructureType::VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO 。
pNext 要麽是 nullptr 要麽指向其他結構體來擴充套件該結構體。
flags 是 VkInstanceCreateFlagBits 所表示的位域值,用於設定 VkInstance 的行為。
pApplicationInfo 要麽是 nullptr, 要麽指向套用資訊結構體,用於套用細節設定。
enabledLayerCount 啟用的 layer 數量。
ppEnabledLayerNames 指向數量為 enabledLayerCount 的 layer 字串陣列,用於設定要啟用的 layer。
enabledExtensionCount 啟用 instance 擴充套件的數量。
ppEnabledExtensionNames 指向數量為 enabledExtensionCount 的擴充套件字串陣列,用於設定要啟用的 instance 擴充套件。
重點講下 VkApplicationInfo、Layer 和 Extension 。
VkApplicationInfo
VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = "my_vulkan_app",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "vulkan_tutorial",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_MAKE_VERSION(1, 0, 0),
};
sType 是該結構體的型別列舉值, 必須 是 VkStructureType::VK_STRUCTURE_TYPE_APPLICATION_INFO 。
pNext 要麽是 NULL 要麽指向其他結構體來擴充套件該結構體。
pApplicationName 要麽是 NULL 要麽指向一個以空字元為結尾的 UTF-8 字串,用於表示使用者自訂套用名稱。
applicationVersion 一個無符號整型,用於使用者自訂套用版本。
pEngineName 要麽是 nullptr 要麽指向一個以空字元為結尾的 UTF-8 字串,用於表示使用者自訂引擎名稱。
engineVersion 一個無符號整型,用於使用者自訂引擎版本。
apiVersion 是 套用打算使用的 Vulkan 的最高 核心 版本,並且忽略 apiVersion 的 patch 版本 。
其中 pApplicationName 、 applicationVersion 、 pEngineName 和 engineVersion 這幾個值隨便設定,甚至可以不設定,賦為空都可以,這些參數不影響例項的建立。
而 apiVersion 參數是最為重要的核心參數 ,當建立例項時,該參數用於指定此例項環境中 Vulkan 的 核心 版本 。
如果你 Vulkan 版本設定錯了,可能沒法使用一些特性。
Vulkan API 的最新版本是 1.3,目前 Vulkan 有 4 個版本:
Vulkan 1.0 主要提供光柵化圖形和平行計算的功能。對應 VK_API_VERSION_1_0 。
Vulkan 1.1 主要為 Vulkan 1.0 不完善的地方進行補全。對應 VK_API_VERSION_1_1 。
Vulkan 1.2 主要提供硬體光追的功能。對應 VK_API_VERSION_1_2 。
Vulkan 1.3 主要提供動態光柵化圖形的功能。對應 VK_API_VERSION_1_3 。
每個 Vulkan 新版本的釋出不單單提供基本功能,還會提供一系列擴充套件功能,並且會將之前版本中的一些擴充套件功能提升囊括至核心版本中 。
Layer
Vulkan 的 Layer(層)是一種重要的機制,允許開發者在 Vulkan API 的核心功能上插入額外的功能和工具
。
常用作正確性驗證檢查。
比如你添加了驗證層 VK_LAYER_KHRONOS_validation ,如果在執行階段發生了使用錯誤, Layer 會輸出錯誤資訊,幫助開發者定位錯誤
。
目前 Vulkan 支持的 層 如下:
VK_LAYER_KHRON OS_validation Vulkan API 驗證和錯誤檢查。
VK_LAYER_LUNARG_gfxreconstruct 使用 GFXReconstruct 捕獲套用的 Vulkan 指令。
VK_LAYER_LUNARG_api_dump 輸出呼叫的 API 和傳入的參數。
VK_LAYER_KHRONOS_profiles 幫助測試硬體的效能,而不需要物理接觸每個裝置。該 層 將會覆蓋從 GPU 查詢到的數據。
VK_LAYER_LUNARG_monitor 在套用界面的標題處顯示幀率。
VK_LAYER_LUNARG_screenshot 將顯示的畫面幀輸出到一個圖片檔中。
VK_LAYER_KHRONOS_synchronization2 使用系統實作的 VK_KHR_synchronization2 擴充套件,而不是驅動實作的。
VK_LAYER_KHRONOS_shader_object 使用系統實作的 VK_EXT_shader_object 擴充套件,而不是驅動實作的。
可以透過 vkEnumerateInstanceLayerProperties函式獲取系統中 Vulkan 支持的 Layer :
uint32_t layer_property_count = 0;
vkEnumerateInstanceLayerProperties(&layer_property_count, nullptr);
std::vector<VkLayerProperties> layer_properties(layer_property_count);
vkEnumerateInstanceLayerProperties(&layer_property_count, layer_properties.data());
思考:vkEnumerateInstanceLayerProperties 這個函式為什麽呼叫了 2 次?
其中 VkLayerProperties 定義如下
:
// 由 VK_VERSION_1_0 提供
typedefstructVkLayerProperties {
char layerName[VK_MAX_EXTENSION_NAME_SIZE];
uint32_t specVersion;
uint32_t implementationVersion;
char description[VK_MAX_DESCRIPTION_SIZE];
} VkLayerProperties;
Extension
Vulkan Extensions(擴充套件)是對 Vulkan API 的功能擴充套件,它們允許硬體制造商、平台開發者和第三方提供額外的功能和特性,這些功能和特性不包含在核心 Vulkan 規範中。
在 Vulkan 中有兩類擴充套件:
Instance 擴充套件 與使用哪一個 GPU 裝置無關,與 Vulkan 環境有關。 VkInstanceCreateInfo 中的 enabledExtensionCount 和 ppEnabledExtensionNames 就是用於配置此類 Instance 擴充套件 。
Device 擴充套件 與使用哪一個 GPU 裝置有關。不同廠家的 GPU 裝置會支持不同的裝置擴充套件。這將會在之後的章節展開。
VkInstance 支持的例項擴充套件可以透過 vkEnumerateInstanceExtensionProperties 函式獲取 :
// 由 VK_VERSION_1_0 提供
VkResult vkEnumerateInstanceExtensionProperties(
constchar* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties);
要想獲取全部的擴充套件,該函式的呼叫與 vkEnumerateInstanceLayerProperties(...) 類似,呼叫兩遍,第一遍 pProperties 為 nullptr ,第二遍為有效值即可:
uint32_t extension_property_count = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extension_property_count, nullptr);
std::vector<VkExtensionProperties> extension_properties(extension_property_count);
vkEnumerateInstanceExtensionProperties(nullptr, &extension_property_count, extension_properties.data());
其中 VkExtensionProperties 定義如下 :
// 由 VK_VERSION_1_0 提供
typedefstructVkExtensionProperties {
char extensionName[VK_MAX_EXTENSION_NAME_SIZE];//副檔名稱
uint32_t specVersion;//版本
} VkExtensionProperties;
有一些例項擴充套件我們需要重點關註一下
VK_KHR_surface 代表視窗通用平面擴充套件。
VK_{vender}_{platform}_surface 代表各個平台各自的視窗平面(各自平台適配到通用平面)。
比如
VK_KHR_win32_surface 為 Windows 平台,供應商為 Khronos 。
VK_OHOS_surface 為 OpenHarmony 平台,供應商為 華為 。
VK_KHR_android_surface 為 Android 平台,供應商為 Khronos 。
VK_KHR_[wayland/xcb/xlib]_surface 為 Linux 平台(其中 [wayland/xcb/xlib] 表示三者其一),供應商為 Khronos 。
建立 Instance 範例 :
VkInstance instance = nullptr;
std::vector<constchar*> instance_extensions;
instance_extensions.push_back("VK_KHR_surface");
instance_extensions.push_back("VK_KHR_android_surface");//Android
//如果是 WIndow 平台使用 VK_KHR_win32_surface
std::vector<constchar *> instance_layers;
instance_layers.push_back("VK_LAYER_KHRONOS_validation");//添加驗證層
VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = "my_vulkan_app",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "example",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_MAKE_VERSION(1, 0, 0),
};
VkInstanceCreateInfo instanceCreateInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.pApplicationInfo = appInfo,
.enabledLayerCount =
static_cast<uint32_t>(instance_layers.size()),
.ppEnabledLayerNames = instance_layers.data(),
.enabledExtensionCount =
static_cast<uint32_t>(instance_extensions.size()),
.ppEnabledExtensionNames = instance_extensions.data(),
};
VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
if (result != VK_SUCCESS)
{
//VkInstance 建立失敗
}
// 開啟 Vulkan 編程 ...
vkDestroyInstance(instance, nullptr);//透過 vkDestroyInstance 函式銷毀 instance
-- END --
進技術交流群, 掃碼添加我的微信:Byte-Flow
獲取相關資料和源碼
學習音視訊、OpenGL ES、Vulkan 、Metal、影像濾鏡、視訊特效及相關渲染技術的付費社群,面試指導,1v1 簡歷服務,職業規劃。
我的付費社群