您的位置:首页 > 其它

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

2016-09-03 11:57 302 查看
原文地址: Vulakn-tutorial

Instance

Creating an instance

initVulkan
里添加函数
createInstance


void initVulkan() {
createInstance();
}


声明变量:

private:
VDeleter<VkInstance> instance {vkDestroyInstance};


然后需要填充两个结构体: VkApplicationInfo和 VkInstanceCreateInfo

VkApplicationInfo 是一个可选项,它提供的一些有用的信息可以使驱动对我们的应用进行优化。

(1)
VkApplicationInfo
结构如下 :

typedef struct VkApplicationInfo {
VkStructureType sType;
const void* pNext;
const char* pApplicationName;
uint32_t applicationVersion;
const char* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
} VkApplicationInfo ;


填充 :

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
中有如下定义 :

// 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
结构如下:

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 内置拥有获取扩展的方法:

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:

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:

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:

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的数量:

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


用这个数量创建容器:

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


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

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


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

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

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


完整代码:

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <iostream>
#include <stdexcept>
#include <functional>

const int WIDTH = 800;
const int HEIGHT = 600;

template <typename T>
class VDeleter {
public:
VDeleter() : VDeleter([](T, VkAllocationCallbacks*) {}) {}

VDeleter(std::function<void(T, VkAllocationCallbacks*)> deletef) {
this->deleter = [=](T obj) { deletef(obj, nullptr); };
}

VDeleter(const VDeleter<VkInstance>& instance, std::function<void(VkInstance, T, VkAllocationCallbacks*)> deletef) {
this->deleter = [&instance, deletef](T obj) { deletef(instance, obj, nullptr); };
}

VDeleter(const VDeleter<VkDevice>& 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<VkInstance> 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Vulkan实例