Vulkan Tutorial 03 理解Instance

操作系统:Windows8.1

显卡:Nivida GTX965M

开发工具:Visual Studio 2017


Creating an instance

与Vulkan打交道,通常的步骤是创建一个intance去初始化Vulkan library。这个instance是您的应用程序与Vulkan库之间的连接桥梁,通常创建过程中,需要向驱动程序提供一些应用层的信息。

首先添加一个createInstance函数,并在initVulkan函数中调用。

void initVulkan() {
    createInstance();
}

另外添加一个类成员来保存instance句柄:

private:
VkInstance instance;

现在我们创建一个instance,并且为该数据结构赋予自定义应用程序的信息。这些数据从技术角度是可选择的,但是它可以为驱动程序提供一些有用的信息来优化程序特殊的使用情景,比如驱动程序使用一些图形引擎的特殊行为。这个数据结构称为VkApplicationInfo:

VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;appInfo.pNext = nullptr;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;

如前所述,Vulkan中的许多数据结构要求在sType成员中明确的指定类型。pNext成员可用于指向特定的扩展结构。我们在这里使用默认初始化,将其设置为nullptr。

Vulkan中的大量信息通过结构体而不是函数参数传递,我们将填充一个结构体以提供足够的信息创建instance。下一个结构体不是可选的,它需要告知Vulkan驱动程序我们需要使用哪些全局的 extensions 和 validation layers。这里的全局意味着它适用于整个程序,而不是特定的设备,这些内容将在接下来的小节中说明。

VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;createInfo.pApplicationInfo = &appInfo;

前几个参数比较简单。接下来的两个指定需要的全局扩展,Vulakn对于平台特性是零API支持的(至少暂时这样),这意味着需要一个扩展才能与不同平台的窗体系统进行交互。GLFW有一个方便的内置函数,返回它有关的扩展信息,我们可以传递给struct:

unsigned int glfwExtensionCount = 0;
const char** glfwExtensions;

glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;

结构体的最后两个成员确定需要开启的全局的validation layers。我们将会在下一节中深入探讨这部分内容,在这一节设置为空。

createInfo.enabledLayerCount = 0;

我们现在已经指定了Vulkan创建一个实例需要的一切信息,调用vkCreateInstance创建属于我们的第一个instance:

VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);

如你所见,Vulkan中创建、实例化相关的函数参数一般遵循如下原则定义:

  1. 使用有关creation info 的结构体指针
  2. 使用自定义分配器回调的指针
  3. 使用保存新对象句柄的指针

如果一切顺利,此刻instance的句柄应该存储在VkInstance类成员中了。几乎所有的Vulkan函数都返回一个值为VK_SUCCESS或错误代码的VkResult类型的值。要检查instance是否已经成功创建只需要检查success值:

if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
    throw std::runtime_error("failed to create instance!");
}

现在运行程序,确认我们的instance创建成功。

Checking for extension support



如果你查看vkCreateInstance的文档,你会看到一个可能出现的错误代码是VK_ERROR_EXTENSION_NOT_PRESENT。我们可以简单地指定我们需要的扩展,如果该错误代码返回,则终止它们。这对于窗体系统或者诸如此类的扩展是有意义的,那么如何检查可选功能呢?

在创建instance之前检索支持的扩展列表,通过vkEnumerateInstanceExtensionProperties函数。它指向一个变量,该变量存储扩展数量和一个VkExtensionProperties数组来存储扩展的详细信息。它也接受一个可选择的参数,允许我们通过特定的validation layers过滤扩展,现在我们暂时忽略这些。

要分配一个数组来保存扩展的详细信息,我们首先需要知道有多少个扩展存在。可以通过将后一个参数置空来获取扩展数量:

uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

现在我们分配一个集合去持有扩展的详细信息(include <vector>)

std::vector<VkExtensionProperties> extensions(extensionCount);

最后我们可以遍历扩展的详细信息:

vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());

每个VkExtensionProperties结构体包含扩展的名称和版本。我们可以用简单的for循环打印他们(\t是缩进)

std::cout << "available extensions:" << std::endl;

for (const auto& extension : extensions) {
    std::cout << "\t" << extension.extensionName << std::endl;
}

如果需要获取有关Vulkan支持的一些详细信息,可以将此代码添加到createInstance函数。作为一个尝试,创建一个函数,检查glfwGetRequiredInstanceExtensions返回的所有扩展是否都包含在受支持的扩展列表中。

Cleaning up



在程序退出前,请正确销毁VkInstance。这部分可以定义在cleanup函数中,调用vkDestroyInstance函数完成。

void cleanup() {
    vkDestroyInstance(instance, nullptr);

    glfwDestroyWindow(window);

    glfwTerminate();
}

vkDestroyInstance函数的参数很简单。像之前小节提到的,Vulkan中的分配和释放功能有一个可选的分配器回调,我们通过将nullptr设置忽略。后续小节中创建的所有Vulkan相关资源,集中在cleanup函数中进行清理,且确保在销毁instance之前销毁。

在进行更复杂的内容之前,是时候了解validation layers了。

获取工程代码 Githubcheckout

时间: 2024-10-12 00:29:35

Vulkan Tutorial 03 理解Instance的相关文章

Vulkan Tutorial 04 理解Validation layers

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 What are validation layers? Vulkan API的设计核心是尽量最小化驱动程序的额外开销,所谓额外开销更多的是指向渲染以外的运算.其中一个具体的表现就是默认条件下,Vulkan API的错误检查的支持非常有限.即使遍历不正确的值或者将需要的参数传递为空指针,也不会有明确的处理逻辑,并且直接导致崩溃或者未定义的异常行为.之所以这样,是因为Vulkan要求每

[译]Vulkan教程(03)开发环境

这是我翻译(https://vulkan-tutorial.com)上的Vulkan教程的第3篇. In this chapter we'll set up your environment for developing Vulkan applications and install some useful libraries. All of the tools we'll use, with the exception of the compiler, are compatible with

Vulkan Tutorial 05 物理设备与队列簇

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Selecting a physical device 通过VkInstance初始化Vulkan后,我们需要在系统中查找并选择一个支持我们所需功能的显卡.实际上,我们可以选择任意数量的显卡并同时使用他们,但在本小节中,我们简单的设定选择规则,即将查找到的第一个图形卡作为我们适合的物理设备. 我们添加函数pickPhysicalDevice并在initVulkan函数中调用. vo

Vulkan Tutorial 06 逻辑设备与队列

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在选择要使用的物理设备之后,我们需要设置一个逻辑设备用于交互.逻辑设备创建过程与instance创建过程类似,也需要描述我们需要使用的功能.因为我们已经查询过哪些队列簇可用,在这里需要进一步为逻辑设备创建具体类型的命令队列.如果有不同的需求,也可以基于同一个物理设备创建多个逻辑设备. 首先添加一个新的类成员来存储逻辑设备句柄. VkDevice devic

Vulkan Tutorial 18 重构交换链

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 现在我们已经成功的在屏幕上绘制出三角形,但是在某些情况下,它会出现异常情况.窗体surface会发生改变,使得交换链不在于其兼容.可能导致这种情况发生的原因之一是窗体的大小变化.我们必须在这个时机重新创建交换链. Recreating the swap chain 添加新的函数recreateSwapChain并调用createSwapChain及依赖于交

Vulkan Tutorial 09 图像与视图

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 使用任何的VkImage,包括在交换链或者渲染管线中的,我们都需要创建VkImageView对象.从字面上理解它就是一个针对图像的视图或容器,通过它具体的渲染管线才能够读写渲染数据,换句话说VkImage不能与渲染管线进行交互.除此之外,图像视图可以进一步定义具体Image的格式,比如定义为2D贴图,那么本质上就不需要任何级别的mipmapping. 在本章节我们会新增一个crea

Vulkan Tutorial 22 Index buffer

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在实际产品的运行环境中3D模型的数据往往共享多个三角形之间的顶点数据.即使绘制一些简单的图形也是如此,比如矩形: 绘制矩形需要两个三角形,通常意味着我们需要6个顶点数据.问题是其中的两个顶点会重复,导致数据会有50%的冗余.如果更复杂的模型,该问题会更加严重,平均每三个三角形就会发生重复顶点使用的情况.解决问题的方法是使用index buffer,即索引缓

Vulkan Tutorial 19 Vertex input description

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在接下来几个章节中,我们将会使用内存顶点缓冲区来替换之前硬编码到vertex shader中的顶点数据.我们将从最简单的方法开始创建一个CPU可见的缓冲区,并使用memcpy直接将顶点数据直接复制到缓冲区,之后将会使用分段缓冲区将顶点数据赋值到高性能的内存. Vertex shader 首先要修改的是顶点着色器,不再包含顶点数据.顶点着色器接受顶点缓冲区的

Vulkan Tutorial 12 Fixed functions

操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 早起的图形API在图形渲染管线的许多阶段提供了默认的状态.在Vulkan中,从viewport的大小到混色函数,需要凡事做到亲历亲为.在本章节中我们会填充有关固有功能操作的所有结构体. Vertex input VkPipelineVertexInputStateCreateInfo结构体描述了顶点数据的格式,该结构体数据传递到vertex shader中.它以两种方式进行描述: