vulakn教程--Drawing a Triangle--Set up--Instance
原文地址: Vulakn-tutorial
Instance
Creating an instance
在 initVulkan
里添加函数createInstance
:
123 void
initVulkan() {
createInstance();
}
声明变量:
12 private
:
VDeleter instance {vkDestroyInstance};
然后需要填充两个结构体: VkApplicationInfo和 VkInstanceCreateInfo
VkApplicationInfo 是一个可选项,它提供的一些有用的信息可以使驱动对我们的应用进行优化。
(1)VkApplicationInfo
结构如下 :
123456789 typedef
struct
VkApplicationInfo {
VkStructureType sType;
const
void
* pNext;
const
char
* pApplicationName;
uint32_t applicationVersion;
const
char
* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
} VkApplicationInfo ;
填充 :
1234567 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_INFO
. apiVersion
是Vulkan的版本号,在vulkan.h
中有如下定义 :
12 // 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
结构如下:
12345 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 内置拥有获取扩展的方法:
1234567 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:
123456789101112131415 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:
123 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:
1234 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的数量:
12 uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
用这个数量创建容器:
1 std::vector extensions(extensionCount);
最后获取平台上支持的extension:
1 vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
打印出来看看每个extension具体是什么 :
1234 std::cout <<
"available extensions:"
<< std::endl;
for
(
const
auto& extension : extensions) {
std::cout <<
"t"
<< extension.extensionName << std::endl;
完整代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 #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;
}