1.总体结构
#include <vulkan/vulkan.h>
#include <iostream>
#include <stdexcept>
#include <functional>
class CApplicationTest {
public:
void run() {
initVulkan();
mainLoop();
cleanup();
}
private:
void initVulkan() {
}
void mainLoop() {
}
void cleanup() {
}
};
int main() {
CApplicationTest ApplicationTest;
try {
app.run();
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
头文件作用:
首先从
LunarG SDK
中添加Vulkan
头文件,它提供了Vulkan
应用程序需要的函数、结构体、和枚举。stdexcept和iostream头文件用于抛出异常信息,而functional头文件用于资源管理部分支持lambda
表达式。
程序思路:
程序被封装到一个类中,该类结构将会存储Vulkan私有成员对象,并添加基本的函数来初始化他们。首先会从initVulkan函数开始调用。当一切准备好,进入主循环开始渲染帧。将会加入mainLoop函数包含loop循环调用,该循环调用直到GLFW窗体管理才会停止。当窗体关闭并且mainLoop返回时,我们需要释放我们已经申请过的任何资源,该清理逻辑在cleanup函数中去定义。
整合GLFW:
当创建可视化的内容,需要用GLFW,, 并将#include <vulkan/vulkan.h> 进行相应的替换。
#define GLFW_INCLUDE_VULKAN #include <GLFW/glfw3.h>
最终代码:
#define GLFW_INCLUDE_VULKAN #include <GLFW/glfw3.h> #include <iostream> #include <stdexcept> #include <cstdlib> #include <vector> const int WIDTH = 800; const int HEIGHT = 600; struct EQueueFamilyIndices { int GraphicsFamily = -1; bool isComplete() { return GraphicsFamily >= 0; } }; class CApplicationTest { public: void run() { initWindow(); initVulkan(); mainLoop(); cleanUp(); } private: GLFWwindow * window; VkInstance m_Instance; //创建窗口 void initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, "VulKanTest", nullptr, nullptr); } //创建vulkan实例 void initVulkan() { createInstance(); //创建实例之后,需要在系统中找到一个支持功能的显卡,查找第一个图像卡作为适合物理设备 pickPhysicalDevice(); } //循环渲染 void mainLoop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } } //退出 void cleanUp() { vkDestroyInstance(m_Instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); } void createInstance() { VkApplicationInfo appInfo = { }; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pNext = nullptr; appInfo.pApplicationName = "Hello World!"; 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; //需要一个扩展才能与不同平台的窗体系统进行交互 //GLFW有一个方便的内置函数,返回它有关的扩展信息 //我们可以传递给struct: unsigned int glfwExtendsionCount = 0; const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtendsionCount); createInfo.enabledExtensionCount = glfwExtendsionCount; createInfo.ppEnabledExtensionNames = glfwExtensions; createInfo.enabledExtensionCount = 0; //创建Instance VkResult result = vkCreateInstance(&createInfo, nullptr, &m_Instance); //检查是否创建成功 if (result != VK_SUCCESS) { throw std::runtime_error("faild to createInstance!"); } } //检查物理设备 void pickPhysicalDevice() { VkPhysicalDevice PhysicakDevice = VK_NULL_HANDLE; //获取图像卡列表 uint32_t DeviceCount = 0; vkEnumeratePhysicalDevices(m_Instance, &DeviceCount, nullptr); if (DeviceCount == 0) { throw std::runtime_error("failed to find GPUS with Vulkan support!"); } //分配数组存储所有的句柄 std::vector<VkPhysicalDevice> Devices(DeviceCount); vkEnumeratePhysicalDevices(m_Instance, &DeviceCount, Devices.data()); //检查它们是否适合我们要执行的操作 for (const auto& device : Devices) { if (isDeviceSuitable(device)) { PhysicakDevice = device; break; } } if (PhysicakDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } } //判断是否支持gPU函数 bool isDeviceSuitable(VkPhysicalDevice vDevice) { EQueueFamilyIndices Indices = findQueueFamilies(vDevice); return Indices.isComplete(); } //检测设备中支持的队列蔟 EQueueFamilyIndices findQueueFamilies(VkPhysicalDevice vDevice) { EQueueFamilyIndices Indices; uint32_t QueueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(vDevice, &QueueFamilyCount, nullptr); std::vector<VkQueueFamilyProperties> QueueFamilies(QueueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(vDevice, &QueueFamilyCount, QueueFamilies.data()); //找到一个支持VK_QUEUE_GRAPHICS_BIT的队列簇 int i = 0; for (const auto& QueueFamily : QueueFamilies) { if (QueueFamily.queueCount > 0 && QueueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { Indices.GraphicsFamily = i; } if (Indices.isComplete()) { break; } i++; } return Indices; } }; int main() { CApplicationTest ApplicationTest; try { ApplicationTest.run(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_FAILURE; }
来源:oschina
链接:https://my.oschina.net/1024and1314/blog/4306250