vulkan init

This commit is contained in:
Mahdi Dibaiee 2023-01-20 12:04:55 +00:00
parent 56fb7bf113
commit f33e781370
2 changed files with 175 additions and 6 deletions

View File

@ -6,7 +6,7 @@ VK_LAYER_PATH=${VULKAN_SDK}/macOS/share/vulkan/explicit_layer.d
.PHONY: main .PHONY: main
main: main.cpp main: main.cpp
# compile # compile
clang++ -I${_BREW_PREFIX}/include -I${VULKAN_SDK}/macOS/include -c main.cpp -o main.o clang++ -I${_BREW_PREFIX}/include -I${VULKAN_SDK}/macOS/include --std=c++17 -c main.cpp -o main.o
# link # link
clang++ -L${_BREW_PREFIX}/lib -lglfw.3.3 -L${VULKAN_SDK}/macOS/lib -lvulkan.1.3.236 -l vulkan.1 main.o -o main clang++ -L${_BREW_PREFIX}/lib -lglfw.3.3 -L${VULKAN_SDK}/macOS/lib -lvulkan.1.3.236 -l vulkan.1 main.o -o main

179
main.cpp
View File

@ -1,4 +1,5 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <vulkan/vulkan_beta.h>
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -6,6 +7,17 @@
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include <cstdlib> #include <cstdlib>
#include <optional>
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
class HelloTriangleApplication { class HelloTriangleApplication {
public: public:
@ -20,6 +32,11 @@ private:
GLFWwindow* window; GLFWwindow* window;
VkInstance instance; VkInstance instance;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device;
VkQueue graphicsQueue;
const uint32_t WIDTH = 800; const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600; const uint32_t HEIGHT = 600;
@ -32,6 +49,149 @@ private:
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
} }
void initVulkan() {
createInstance();
pickPhysicalDevice();
createLogicalDevice();
}
void createLogicalDevice() {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
queueCreateInfo.queueCount = 1;
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 = 1;
std::vector<const char*> extensions(1);
extensions.emplace_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
createInfo.ppEnabledExtensionNames = extensions.data();*/
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
createInfo.enabledLayerCount = 0;
}
VkResult result = vkCreateDevice(physicalDevice, &createInfo, nullptr, &device);
if (result != VK_SUCCESS) {
std::cout << "error: " << result << std::endl;
throw std::runtime_error("failed to create logical device");
}
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
}
void pickPhysicalDevice() {
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
if (deviceCount == 0) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
for (const auto& device : devices) {
if (isDeviceSuitable(device)) {
physicalDevice = device;
break;
}
}
if (physicalDevice == VK_NULL_HANDLE) {
throw std::runtime_error("could not find a suitable GPU");
}
}
bool isDeviceSuitable(VkPhysicalDevice device) {
/*VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(device, &props);
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(device, &features);
return props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && features.geometryShader;*/
QueueFamilyIndices indices = findQueueFamilies(device);
return indices.isComplete();
}
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
bool isComplete() {
return graphicsFamily.has_value();
}
};
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i;
}
if (indices.isComplete()) {
break;
}
i++;
}
return indices;
}
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const char* layerName : validationLayers) {
bool layerFound = false;
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}
void createInstance() { void createInstance() {
VkApplicationInfo appInfo{}; VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@ -64,7 +224,19 @@ private:
createInfo.enabledExtensionCount = (uint32_t) requiredExtensions.size(); createInfo.enabledExtensionCount = (uint32_t) requiredExtensions.size();
createInfo.ppEnabledExtensionNames = requiredExtensions.data(); createInfo.ppEnabledExtensionNames = requiredExtensions.data();
createInfo.enabledLayerCount = 0;
// Check validation layers
if (enableValidationLayers) {
if (!checkValidationLayerSupport()) {
throw std::runtime_error("validation layers requested, but not available!");
}
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
createInfo.enabledLayerCount = 0;
}
std::cout << "Validation layers: OK" << std::endl;
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
@ -94,10 +266,6 @@ private:
} }
} }
void initVulkan() {
createInstance();
}
void mainLoop() { void mainLoop() {
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
glfwPollEvents(); glfwPollEvents();
@ -105,6 +273,7 @@ private:
} }
void cleanup() { void cleanup() {
vkDestroyDevice(device, nullptr);
vkDestroyInstance(instance, nullptr); vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window); glfwDestroyWindow(window);