vulakn教程--Drawing a Triangle--Set up--Base code

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

原文地址:vulkan-tutorial

Base code

General structure

上一章通过构建一个窗体来完成VS对Vulkan的配置,并将配置好的工程设置为模板以备后续的使用。在上一章的最后我们用这个模板创建了一个名为:Hello Triangle 的新工程,现在让我们为这个工程搭建一个框架。

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
#include
#include
#include
 
class HelloTriangleApplication {
public:
    void run() {
        initVulkan();
        mainLoop();
    }
 
private:
    void initVulkan() {
 
    }
 
    void mainLoop() {
 
    }
};
 
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;
}

stdexception 引入异常,functional 引入lambda功能。

Resource management

每一个Vulkan对象不再使用后,都需要用一个清理函数来销毁,就像malloc 分配的内存要用free 销毁一样。手动来销毁每一个对象是一个非常繁杂且容易出错的任务。我们利用C++的RAII原理来创建一个包裹类,当对象离开有效作用域后自动为我们销毁对象。如下,在创建VkInstance前,用类似方法声明VkInstance对象,并告诉我们的包裹类,销毁Instance对象的方法是vkDestroyInstance:

1
VDeleter instance{vkDestroyInstance};   //VDeleter是我们的包裹类。

然后创建这个Instance:

1
vkCreateInstance(&instanceCreateInfo, nullptr, &instance);

当Instance离开有效作用域,比如,关闭了应用,VDeleter将自动使用vkDestroyInstance将Instance销毁。 
以下是VDeleter的定义:

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
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;
    }
};

后续的所有教程都将使用VDeleter来管理我们的对象。

Integrating GLFW

如果你只想离屏渲染(off-screen rendering),不需要创建窗口vulkan一样可以很好的工作。但是,难道你不觉得在屏幕上显示一些东西会更酷吗?首先用如如下语句取代#include :

1
2
#define GLFW_INCLUDE_VULKAN
#include

#define GLFW_INCLUDE_VULKAN告诉glfw 在引入自己的头文件时也要引入vulkan.h

run里添加initWindow来创建窗体:

1
2
3
4
5
6
7
8
9
10
void run() {
    initWindow();
    initVulkan();
    mainLoop();
}
 
private:
    void initWindow() {
 
    }

初始化:

1
glfwInit()   ;

GLFW最初是为创建OPENGL 的 context设计的,为了避免它创建OPENGL context,需要设置 :

1
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

允许窗口改变大小会引起其他的问题,后续我们再讨论,为了操作简单,这里禁止改变窗口大小:

1
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

创建窗体:

1
2
3
const int WIDTH = 800;
const int HEIGHT = 600;
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);

第三个参数为窗口(window)创建一个监视器,最后一个参数和OPENGL 相关。

显示 ,直到遇到错误或关闭窗口:

1
2
3
while (!glfwWindowShouldClose(window)) {
 glfwPollEvents();
}

为了方便你对照和理解,这里所有代码:

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
#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;
 
    void initWindow() {
        glfwInit();
 
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
 
        window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
    }
 
    void initVulkan() {
 
    }
 
    void mainLoop() {
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
        }
    }
};
 
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;
}

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