vulakn教程--Drawing a Triangle--Set up--Base code
原文地址:vulkan-tutorial
Base code
General structure
上一章通过构建一个窗体来完成VS对Vulkan的配置,并将配置好的工程设置为模板以备后续的使用。在上一章的最后我们用这个模板创建了一个名为:Hello Triangle 的新工程,现在让我们为这个工程搭建一个框架。
123456789101112131415161718192021222324252627282930313233 #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的定义:
1234567891011121314151617181920212223242526272829303132333435363738394041 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
:
12 #define GLFW_INCLUDE_VULKAN
#include
#define GLFW_INCLUDE_VULKAN
告诉glfw 在引入自己的头文件时也要引入vulkan.h
。
在run
里添加initWindow
来创建窗体:
12345678910 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);
创建窗体:
123 const
int
WIDTH = 800;
const
int
HEIGHT = 600;
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT,
"Vulkan"
, nullptr, nullptr);
第三个参数为窗口(window)创建一个监视器,最后一个参数和OPENGL 相关。
显示 ,直到遇到错误或关闭窗口:
123 while
(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
为了方便你对照和理解,这里所有代码:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 #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;
}