02Vulkan——应用程序架构与创建实例

流过昼夜 提交于 2020-08-07 21:33:49

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应用程序需要的函数、结构体、和枚举。stdexceptiostream头文件用于抛出异常信息,而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;
}

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!