vulakn教程--Drawing a Triangle--Set up--Instance

发表于2016-12-14
评论0 1.9k浏览

原文地址: Vulakn-tutorial


Instance

Creating an instance

在 initVulkan 里添加函数createInstance :

1
2
3
void initVulkan() {
    createInstance();
}

声明变量:

1
2
private:
VDeleter instance {vkDestroyInstance};

然后需要填充两个结构体: VkApplicationInfo和 VkInstanceCreateInfo 
VkApplicationInfo 是一个可选项,它提供的一些有用的信息可以使驱动对我们的应用进行优化。

(1)VkApplicationInfo 结构如下 :

1
2
3
4
5
6
7
8
9
typedef struct VkApplicationInfo {
VkStructureType sType;
const void* pNext;
const char* pApplicationName;
uint32_t applicationVersion;
const char* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
} VkApplicationInfo ;

填充 :

1
2
3
4
5
6
7
VkApplicationInfo   appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";    // 自定义
appInfo.applicationVersion = 1  //自定义
appInfo.pEngineName = "No Engine"//自定义
appInfo.engineVersion =1;   //自定义
appInfo.apiVersion = VK_API_VERSION_1_0;

说明: 几乎所有VkXXXInfo结构都有sType字段,同样它们的值有一个固定模式:VK_STRUCTURE_TYPE XXX_INFOapiVersion 是Vulkan的版本号,在vulkan.h中有如下定义 :

1
2
// Vulkan 1.0 version number
#define VK_API_VERSION_1_0      VK_MAKE_VERSION(1, 0, 0)

所以此处apiVersion值 为VK_API_VERSION_1_0.

(2) VkInstanceCreateInfo结构如下:

1
2
3
4
5
VkInstanceCreateInfo createinfo = {};
createinfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createinfo.pNext = NULL;
createinfo.flags = 0;
createinfo.pApplicationInfo = &appinfo;     //我们在(1) 中创建的

说明: 在Vulkan中,几乎所有需要创建的 XXX对象,都要填充类似VkXXXCreateInfo结构体。VkInstanceCreateInfo 告诉Vulkan驱动我们将使用的全局扩展(global extensions )和验证层(global validation layers )。 
flag 保留,未来可能使用(for future use),保持默认或者赋值为0. 
后面还有两个字段enabledExtensionCount ,enabledLayerCount ,表示使全局扩展(extension)和验证层(Validation layers)的数量,以及它们的名字(后面还将详细介绍具体的extension 和 layers)

因为Vulkan是跨平台的,所以它需要类似于“插件”一样的扩展来和窗体系统(window system)进行联系。 
glfw 内置拥有获取扩展的方法:

1
2
3
4
5
6
7
unsigned int glfwExtensionCount = 0;
const char** glfwExtensions;
 
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
 
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;

先将Validation layers置0,后面我们再讨论这个问题。 
createInfo.enabledLayerCount = 0;

在创建Instance之前先来看一下Vulkan的函数返回值VkResult:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef enum VkResult {
    VK_SUCCESS = 0,
    VK_NOT_READY = 1,
    VK_TIMEOUT = 2,
    VK_EVENT_SET = 3,
    VK_EVENT_RESET = 4,
    VK_INCOMPLETE = 5,
    VK_ERROR_OUT_OF_HOST_MEMORY = -1,
    VK_ERROR_FEATURE_NOT_PRESENT = -8,
    VK_SUBOPTIMAL_KHR = 1000001003,
    VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
    … 
    
 
    } VkResult;

成功值: 
VK_SUCCESS: 成功执行。 
VK_NOT_READY: 尚未准备好。 
VK_TIMEOUT: 超时。 
VK_INCOMPLETE: 对于真正需要的结果A来说,返回的结果B小于A的数量。 
VK_SUBOPTIMAL_KHR: Swap Chain 不能和Surface 完全匹配,但任然能用。 
其他…


错误值: 
VK_ERROR_FORMAT_NOT_SUPPORTED 设备不支持的格式。. 
VK_ERROR_FRAGMENTED_POOL 由于碎片的原因 Pool分配失败。 
VK_ERROR_SURFACE_LOST_KHR Surface 不再可用。 
其他….

创建Instance:

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

这样Instance就创建好了,运行一下你的程序,看看Instacne是否创建成功。


Checking for extension support

本节代码中并未使用这种方法,但你可以分别打印出它和glfw获取的extension有什么区别。

虽然glfw提供了获取extension的内置方法,我们同样可以使用vulkan核心API中的方法来检测当前平台所支持的extension:

1
2
3
4
VkResult vkEnumerateInstanceExtensionProperties(
    const char* pLayerName,
    uint32_t* pPropertyCount,
    VkExtensionProperties* pProperties);

它接收三个参数:

  • pLayerName: 是一个Validation layer,用来过滤extension ,这里先置为nullptr。
  • pPropertyCount: 返回extension 的数量。
  • pProperties : extension的具体细节,如果这个值为nullptr,则,函数只返回extension的数量,即pPropertyCount,否则返回pPropertyCount个VkExtensionProperties。

首先获取extension的数量:

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

用这个数量创建容器:

1
std::vector extensions(extensionCount);

最后获取平台上支持的extension:

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

打印出来看看每个extension具体是什么 :

1
2
3
4
std::cout << "available extensions:" << std::endl;
 
for (const auto& extension : extensions) {
    std::cout << "t" << extension.extensionName << std::endl;

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define GLFW_INCLUDE_VULKAN
#include
 
#include
#include
#include
 
const int WIDTH = 800;
const int HEIGHT = 600;
 
template "">
class VDeleter {
public:
    VDeleter() : VDeleter([](T, VkAllocationCallbacks*) {}) {}
 
    VDeleter(std::function<void(t, vkallocationcallbacks*)=""> deletef) {
        this->deleter = [=](T obj) { deletef(obj, nullptr); };
    }
 
    VDeleter(const VDeleter& instance, std::function<void(vkinstance, t,="" vkallocationcallbacks*)=""> deletef) {
        this->deleter = [&instance, deletef](T obj) { deletef(instance, obj, nullptr); };
    }
 
    VDeleter(const VDeleter& device, std::function<void(vkdevice, t,="" vkallocationcallbacks*)=""> deletef) {
        this->deleter = [&device, deletef](T obj) { deletef(device, obj, nullptr); };
    }
 
    ~VDeleter() {
        cleanup();
    }
 
    T* operator &() {
        cleanup();
        return &object;
    }
 
    operator T() const {
        return object;
    }
 
private:
    T object{VK_NULL_HANDLE};
    std::function<void(t)> deleter;
 
    void cleanup() {
        if (object != VK_NULL_HANDLE) {
            deleter(object);
        }
        object = VK_NULL_HANDLE;
    }
};
 
class HelloTriangleApplication {
public:
    void run() {
        initWindow();
        initVulkan();
        mainLoop();
    }
 
private:
    GLFWwindow* window;
 
    VDeleter instance{vkDestroyInstance};
 
    void initWindow() {
        glfwInit();
 
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
 
        window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
    }
 
    void initVulkan() {
        createInstance();
    }
 
    void mainLoop() {
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
        }
    }
 
    void createInstance() {
        VkApplicationInfo appInfo = {};
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        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;
 
        VkInstanceCreateInfo createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        createInfo.pApplicationInfo = &appInfo;
 
        unsigned int glfwExtensionCount = 0;
        const char** glfwExtensions;
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
 
        createInfo.enabledExtensionCount = glfwExtensionCount;
        createInfo.ppEnabledExtensionNames = glfwExtensions;
 
        createInfo.enabledLayerCount = 0;
 
        if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
            throw std::runtime_error("failed to create instance!");
        }
    }
};
 
int main() {
    HelloTriangleApplication app;
 
    try {
        app.run();
    } catch (const std::runtime_error& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
 
    return EXIT_SUCCESS;
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引