[译]Vulkan教程(05)Instance
[译]Vulkan教程(05)Instance
Creating an instance 创建一个instance
The very first thing you need to do is initialize the Vulkan library by creating an instance. The instance is the connection between your application and the Vulkan library and creating it involves specifying some details about your application to the driver.
第一件要做的事,是初始化Vulkan库,这需要通过创建一个instance来实现。Instance是你的app和Vulkan库联系的桥梁,创建它时需要向driver提供你的app的一些信息。
Start by adding a createInstance
function and add a call to it in the initVulkan
function.
首先,添加createInstance
函数,在initVulkan
函数中调用它。
void initVulkan() {
createInstance();
}
Additionally add a class member to hold the handle to the instance:
另外添加一个成员来记录这个instance:
private:
VkInstance instance;
Now, to create an instance we'll first have to fill in a struct with some information about our application. This data is technically optional, but it may provide some useful information to the driver to optimize for our specific application, for example because it uses a well-known graphics engine with certain special behavior. This struct is called VkApplicationInfo
:
现在,为了创建intance,我们必须将app的一些信息填入一个struct。这个数据实际上是可选的,但是它可能为driver提供一些有用的信息,以优化我们的app。例如,因为它用了一个著名的图形引擎,其有特殊的行为。(译者注:这句似乎是个病句)这个struct是VkApplicationInfo
:
void createInstance() {
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(, , );
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(, , );
appInfo.apiVersion = VK_API_VERSION_1_0;
}
As mentioned before, many structs in Vulkan require you to explicitly specify the type in the sType
member. This is also one of the many structs with a pNext
member that can point to extension information in the future. We're using default initialization here to leave it as nullptr
.
如前所述,Vulkan中的许多struct要求你显式地在成员sType
中标明其类型。VkApplicationInfo
也是其中之一,其成员pNext
未来可能指向扩展信息。我们这里就用默认的初始化方式,保持其为nullptr
即可。
A lot of information in Vulkan is passed through structs instead of function parameters and we'll have to fill in one more struct to provide sufficient information for creating an instance. This next struct is not optional and tells the Vulkan driver which global extensions and validation layers we want to use. Global here means that they apply to the entire program and not a specific device, which will become clear in the next few chapters.
Vulkan中的许多信息都是通过struct传递,而不是一般的函数参数,我们不得不填充若干struct来为创建instance提供足够的信息。下一个struct是必选的,它告诉Vulkan的driver,我们想要使用哪些全局扩展和验证层。这里的全局是指它们在整个程序中可用,不是仅对某个device可用。在后续章节中你会理解得更清楚。
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
The first two parameters are straightforward. The next two layers specify the desired global extensions. As mentioned in the overview chapter, Vulkan is a platform agnostic API, which means that you need an extension to interface with the window system. GLFW has a handy built-in function that returns the extension(s) it needs to do that which we can pass to the struct:
前2个参数很直观。接下来的2个标明想要的全局扩展。如前所述,Vulkan是平台不可知论的API,这意味着你需要一个与窗口系统交互的扩展。GLFW有一个方便易用的内建函数,其返回一个与窗口系统交互的扩展。我们可以将struct传递给这个内建函数:
uint32_t glfwExtensionCount = ;
const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
The last two members of the struct determine the global validation layers to enable. We'll talk about these more in-depth in the next chapter, so just leave these empty for now.
这个struct的最后2个成员决定了要启用的全局验证层。我们将在后续章节深入讨论之,现在就让它们为空好了。
createInfo.enabledLayerCount = ;
We've now specified everything Vulkan needs to create an instance and we can finally issue the vkCreateInstance
call:
我们已经标明了Vulkan需要的一切,现在可以创建instance了。我们调用vkCreateInstance
函数:
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
As you'll see, the general pattern that object creation function parameters in Vulkan follow is:
- Pointer to struct with creation info
- Pointer to custom allocator callbacks, always
nullptr
in this tutorial - Pointer to the variable that stores the handle to the new object
如你所见,在Vulkan中创建对象的函数的参数的一般模式如下:
- 指向创建信息struct的指针
- 指向自定义申请内存的回调函数的指针,本教程中始终为
nullptr
- 指向保存新对象句柄的变量的指针
If everything went well then the handle to the instance was stored in the VkInstance
class member. Nearly all Vulkan functions return a value of type VkResult
that is either VK_SUCCESS
or an error code. To check if the instance was created successfully, we don't need to store the result and can just use a check for the success value instead:
如果一切顺利,instance的句柄就保存到了VkInstance
类型的成员中。几乎所有Vulkan函数都返回一个VkResult
类型,它要么是VK_SUCCESS
,要么是一个错误码。要检查instance是否被成功创建,我们不需要保存这个结果,只需判断一下这个值即可:
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("failed to create instance!");
}
Now run the program to make sure that the instance is created successfully.
现在运行程序,确保instance被成功创建了。
Checking for extension support 检查扩展支持
If you look at the vkCreateInstance
documentation then you'll see that one of the possible error codes is VK_ERROR_EXTENSION_NOT_PRESENT
. We could simply specify the extensions we require and terminate if that error code comes back. That makes sense for essential extensions like the window system interface, but what if we want to check for optional functionality?
如果你看一下vkCreateInstance
的文档,你会看到错误码之一是VK_ERROR_EXTENSION_NOT_PRESENT
。我们可以简单地标明我们想要的扩展,如果得到了错误码,就关闭程序。这对关键扩展(例如窗口系统接口)是合理的,但是如果我们想检查一下可选功能呢?
To retrieve a list of supported extensions before creating an instance, there's the vkEnumerateInstanceExtensionProperties
function. It takes a pointer to a variable that stores the number of extensions and an array of VkExtensionProperties
to store details of the extensions. It also takes an optional first parameter that allows us to filter extensions by a specific validation layer, which we'll ignore for now.
为了在创建instance前检索支持的扩展,可以使用vkEnumerateInstanceExtensionProperties
函数。它接收一个记录扩展数量的变量的指针,和一个记录扩展细节的VkExtensionProperties
数组。它还接收一个可选参数,允许我们用一个特定的验证层过滤扩展,目前我们忽略它即可。
To allocate an array to hold the extension details we first need to know how many there are. You can request just the number of extensions by leaving the latter parameter empty:
为了申请一个用于记录扩展细节的数组,我们首先需要知道数组长度。你可以让后一个参数为空,从而只请求扩展的数量:
uint32_t extensionCount = ;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
Now allocate an array to hold the extension details (include <vector>
):
现在申请一个用于记录扩展细节的数组(include <vector>
):
std::vector<VkExtensionProperties> extensions(extensionCount);
Finally we can query the extension details:
最后我们可以查询扩展细节了:
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
Each VkExtensionProperties
struct contains the name and version of an extension. We can list them with a simple for loop (\t
is a tab for indentation):
每个VkExtensionProperties
结构体,包含扩展的名字和版本。我们可以用一个循环来列出它们(\t
是tab缩进):
std::cout << "available extensions:" << std::endl; for (const auto& extension : extensions) {
std::cout << "\t" << extension.extensionName << std::endl;
}
You can add this code to the createInstance
function if you'd like to provide some details about the Vulkan support. As a challenge, try to create a function that checks if all of the extensions returned byglfwGetRequiredInstanceExtensions
are included in the supported extensions list.
如果你想提供一些Vulkan支持的细节,你可以将这段代码添加到createInstance
函数。作为一项挑战,尝试创建一个函数,其检查是否glfwGetRequiredInstanceExtensions
函数返回的所有的扩展都包含在支持的扩展列表中。
Cleaning up 打扫干净
The VkInstance
should be only destroyed right before the program exits. It can be destroyed in cleanup
with the vkDestroyInstance
function:
程序即将退出前,应该销毁VkInstance
。它可以在cleanup
函数中被vkDestroyInstance
函数销毁:
void cleanup() {
vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate();
}
The parameters for the vkDestroyInstance
function are straightforward. As mentioned in the previous chapter, the allocation and deallocation functions in Vulkan have an optional allocator callback that we'll ignore by passing nullptr
to it. All of the other Vulkan resources that we'll create in the following chapters should be cleaned up before the instance is destroyed.
函数vkDestroyInstance
的参数很直观。如前所述,Vulkan中的申请和销毁函数有一个可选的回调函数,我们将忽略它,只传递nullptr
给它。在销毁instance前,我们在后续章节创建的所有Vulkan资源都应当被销毁。
Before continuing with the more complex steps after instance creation, it's time to evaluate our debugging options by checking out validation layers.
创建instance之后,在继续更复杂的步骤之前,是时候评估一下我们的调试选项了,方式是,鼓捣一下验证层。
- Previous上一章
- Next下一章
[译]Vulkan教程(05)Instance的更多相关文章
- [译]Vulkan教程(24)索引buffer
[译]Vulkan教程(24)索引buffer Index buffer 索引buffer Introduction 入门 The 3D meshes you'll be rendering in a ...
- [译]Vulkan教程(21)顶点input描述
[译]Vulkan教程(21)顶点input描述 Vertex input description 顶点input描述 Introduction 入门 In the next few chapters ...
- [译]Vulkan教程(20)重建交换链
[译]Vulkan教程(20)重建交换链 Swap chain recreation 重建交换链 Introduction 入门 The application we have now success ...
- [译]Vulkan教程(16)图形管道基础之总结
[译]Vulkan教程(16)图形管道基础之总结 Conclusion 总结 We can now combine all of the structures and objects from the ...
- [译]Vulkan教程(14)图形管道基础之固定功能
[译]Vulkan教程(14)图形管道基础之固定功能 Fixed functions 固定功能 The older graphics APIs provided default state for m ...
- [译]Vulkan教程(10)交换链
[译]Vulkan教程(10)交换链 Vulkan does not have the concept of a "default framebuffer", hence it r ...
- [译]Vulkan教程(09)窗口表面
[译]Vulkan教程(09)窗口表面 Since Vulkan is a platform agnostic API, it can not interface directly with the ...
- [译]Vulkan教程(08)逻辑设备和队列
[译]Vulkan教程(08)逻辑设备和队列 Introduction 入门 After selecting a physical device to use we need to set up a ...
- [译]Vulkan教程(07)物理设备和队列家族
[译]Vulkan教程(07)物理设备和队列家族 Selecting a physical device 选择一个物理设备 After initializing the Vulkan library ...
随机推荐
- LeetCode 1290. 二进制链表转整数
地址 https://www.acwing.com/solution/LeetCode/content/7132/ 题目描述给你一个单链表的引用结点 head.链表中每个结点的值不是 0 就是 1.已 ...
- fineuploader php服务端
新版本的fineuploader项目中已经没有现成的php server端,需要额外使用composer进行安装,折腾好久才下下来,在此分享出来给大家. 下载地址: http://files.cnbl ...
- 骚年,如果你还不懂一些java常识?中了奖也无法兑换
今天下午约着几个朋友一起去看叶问4,结果碰到了一个有趣的事情,正好和java有关所以写一篇文章来记录一下. 事件:我和朋友小李.小王一起去看电影 时间:2019/12/21 地点:H市某家电影院 起因 ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]
我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...
- div拖拽效果 JQuery
<!DOCTYPE html> <html> <head> <meta name="description" content=" ...
- RabbitMQ 离线安装(带视频)
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 疯狂创客圈 高并 ...
- 自学Java编程,如何混到一个7k薪资实习生的岗位
现在Java软件开发的专业一直都是热门,有很多专业的学生,比如电子.机械.会计.土木等等专业由于专业本身没有更高的提升空间,所以现在的年轻人更加喜欢做一些科技前沿的工作,毕竟现在接触的都是电子产品.而 ...
- 基于Redis消息的订阅发布应用场景
目录 基于Redis消息的订阅发布应用场景 1.应用背景 2.困境 2.1 锁表风险 2.2 实时性差 2.3 增加编程复杂性 2.4 实时效果 3.解决方案 3.1 前端传值给服务端 3.2 服务端 ...
- CAD图纸怎么看?这两种方法值得看
在CAD日常的工作中,每天都是需要接触到CAD图纸文件,有一些房屋设计.建筑施工图.室内家具设计图纸等,这些CAD图纸的格式均为dwg格式的.是不能够直接进行打开查看的,需要借助CAD看图软件来使用. ...
- Docker Compose部署GitLab服务,搭建自己的代码托管平台(图文教程)
场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...