与物理设备和队列族相对应的,是逻辑设备和队列。
创建逻辑设备时,假设只用带有图形能力的队列族的队列,该队列暂时使用一个,也不考虑校验层
1,设置队列
//暂时只使用带有图形能力的队列族
QueueFaminliyIndices indices = findQueueFamilies(physicalDevice);
//针对一个队列族需要的队列数量(一般1个即可)
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily;
queueCreateInfo.queueCount = 1;
//多个线程创建指令缓冲,都需要这个队列提交,所以需要对各个指令缓冲赋予优先级,控制指令缓冲的执行顺序(0.0-1.0)
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;
2,创建逻辑设备也要考虑到应用程序使用到的设备特性,暂时为空
VkPhysicalDeviceFeatures deviceFeatures = {};
3,创建逻辑设备结构体,暂时不用校验层
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = 0;
//
createInfo.enabledLayerCount = 0;
4,根据物理设备和逻辑设备信息创建逻辑设备
vkCreateDevice(physicalDevice, &createInfo, nullptr, &device);
5,获取队列族的队列句柄
//存储逻辑设备的队列句柄
VkQueue graphicsQueue;
vkGetDeviceQueue(device, indices.graphicsFamily, 0, &graphicsQueue);
5,清除逻辑设备
vkDestroyDevice ( device , nullp tr ) ;
运行结果依然为空窗口

代码如下:
MyApplication.h
#pragma once
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <vulkan/vulkan.h>
#include
#include “D:/install/filament-v1.18.0/third_party/imgui/examples/libs/glfw/include/GLFW/glfw3.h”
#include
#include
#include
#include
//队列族索引
struct QueueFaminliyIndices
{
//-1表示没找到满足需求的队列族
int graphicsFamily = -1;
bool isCompleted()
{
return graphicsFamily >= 0;
}
};
class MyApplication
{
public:
void run();
private:
//初始化窗口
void initWindow();
//初始化Vulkan对象
void initVulkan();
//主循环进行渲染操作
void mainLoop();
//资源清理
void cleanUp();
//创建一个实例初始化Vulkan库,指定驱动程序需要使用的应用程序信息
void createInstance();
//查询显卡设备
void pickPhysicalDevice();
//返回查找的队列族索引
QueueFaminliyIndices findQueueFamilies(VkPhysicalDevice device);
//确保选择的设备能执行需要的指令
bool isDeviceSuitable(VkPhysicalDevice device);
//创建逻辑设备
void createLogicalDevice();
private:
//窗口
GLFWwindow* window = nullptr;
//实例句柄
VkInstance instance;
//存储显卡信息
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
//逻辑设备
VkDevice device;
//存储逻辑设备的队列句柄
VkQueue graphicsQueue;
};
MyApplication.cpp
#include “MyApplication.h”
void MyApplication::run()
{
initWindow();
initVulkan();
mainLoop();
cleanUp();
}
void MyApplication::initWindow()
{
//初始化GLFW库,
glfwInit();
//阻止创建OpenGL上下文
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
//禁止窗口大小改变
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
//存储窗口句柄
const int WIDTH = 800;
const int HEIGHT = 600;
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan window", nullptr, nullptr);
}
void MyApplication::initVulkan()
{
createInstance();
pickPhysicalDevice();
createLogicalDevice();
}
void MyApplication::mainLoop()
{
//在没有错误和窗口没有被关闭下一直运行,事件循环
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
}
}
void MyApplication::cleanUp()
{
vkDestroyDevice(device, nullptr);
//在应用程序结束前清除vulkan实例
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
glfwTerminate();
}
void MyApplication::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;
//创建Vulkan驱动程序需要的信息
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
//返回需要的窗口交互扩展
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
//全局扩展层(对整个应用程序都有效,而不仅仅对一个设备有效)
//暂时设置为0,不使用全局扩展层
createInfo.enabledLayerCount = 0;
//创建Vulkan实例
VkResult result = vkCreateInstance(
&createInfo, //包含创建信息的结构体指针
nullptr, //自定义的分配器回调函数,暂时设置为nullptr,不使用
&instance); //指向新对象句柄存储位置的指针。
//检测扩展支持
//获取扩展数量
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
//存储信息数组
std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
}
void MyApplication::pickPhysicalDevice()
{
//获取显卡设备数量
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
//获取显卡数组
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
//选择合适的
for (const auto& device : devices)
{
if (isDeviceSuitable(device))
{
physicalDevice = device;
break;
}
}
}
QueueFaminliyIndices MyApplication::findQueueFamilies(VkPhysicalDevice device)
{
//获取设备的队列族个数
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
//获取队列族数组
std::vector queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
QueueFaminliyIndices indices;
//暂时只需要支持图形指令
int i = 0;
for (const auto& queueFamily : queueFamilies )
{
if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
indices.graphicsFamily = i;
}
if (indices.isCompleted())
{
break;
}
i++;
}
return indices;
}
bool MyApplication::isDeviceSuitable(VkPhysicalDevice device)
{
QueueFaminliyIndices indices = findQueueFamilies(device);
return indices.isCompleted();
}
void MyApplication::createLogicalDevice()
{
//暂时只使用带有图形能力的队列族
QueueFaminliyIndices indices = findQueueFamilies(physicalDevice);
//针对一个队列族需要的队列数量(一般1个即可)
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily;
queueCreateInfo.queueCount = 1;
//多个线程创建指令缓冲,都需要这个队列提交,所以需要对各个指令缓冲赋予优先级,控制指令缓冲的执行顺序(0.0-1.0)
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;
//应用的设备特性
VkPhysicalDeviceFeatures deviceFeatures = {};
//创建逻辑设备
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = 0;
//暂时不用校验层
createInfo.enabledLayerCount = 0;
vkCreateDevice(physicalDevice, &createInfo, nullptr, &device);
//获取队列族的队列句柄
vkGetDeviceQueue(device, indices.graphicsFamily, 0, &graphicsQueue);
}
调用
#define GLFW_INCLUDE_VULKAN
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include “MyApplication.h”
int main()
{
MyApplication app;
app.run();
return 0;
}
1359

被折叠的 条评论
为什么被折叠?



