Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created October 3, 2020 19:25
Show Gist options
  • Save untodesu/ca793ad8500e2ae49493786f1b2eeae8 to your computer and use it in GitHub Desktop.
Save untodesu/ca793ad8500e2ae49493786f1b2eeae8 to your computer and use it in GitHub Desktop.
//
// vulkan.cpp -- internal vulkan wrapper.
// Copyright (C) 2020, Voxelius team.
//
#include <voxelius/engine.h>
#include "debug.h"
#include "vulkan.h"
const bool VkQueueIndices::IsValid(void) const
{
if(m_graphics == -1)
return false;
return true;
}
VkPhysicalDeviceInfo::VkPhysicalDeviceInfo(void) : m_rating(0)
{
}
VkPhysicalDeviceInfo::VkPhysicalDeviceInfo(VkPhysicalDevice dev) : m_rating(0)
{
vkGetPhysicalDeviceFeatures(dev, &m_features);
vkGetPhysicalDeviceProperties(dev, &m_properties);
uint32_t numQueueProps;
vkGetPhysicalDeviceQueueFamilyProperties(dev, &numQueueProps, nullptr);
m_queueProps.resize(numQueueProps);
vkGetPhysicalDeviceQueueFamilyProperties(dev, &numQueueProps, m_queueProps.data());
int qpi = 0;
for(VkQueueFamilyProperties &prop : m_queueProps) {
if(prop.queueFlags & VK_QUEUE_GRAPHICS_BIT)
m_queueIndices.m_graphics = qpi;
qpi++;
}
if(m_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
m_rating += 1000;
m_rating += m_properties.limits.maxImageDimension2D;
}
const int VkPhysicalDeviceInfo::GetRating(void) const
{
return m_rating;
}
VxVulkan::VxVulkan(IVxEngine *pEngine) : m_pEngine(pEngine)
{
}
void VxVulkan::CreateInstance(SDL_Window *pWindow)
{
VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.apiVersion = VK_API_VERSION_1_0;
appInfo.pEngineName = "Voxelius";
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
uint32_t numExtensions;
SDL_Vulkan_GetInstanceExtensions(pWindow, &numExtensions, nullptr);
std::vector<const char *> extensions(numExtensions);
SDL_Vulkan_GetInstanceExtensions(pWindow, &numExtensions, extensions.data());
extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.enabledLayerCount = 0;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledExtensionCount = (uint32_t)extensions.size();
createInfo.ppEnabledExtensionNames = extensions.data();
VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
VX_AssertMsg(result == VK_SUCCESS, "Failed to create VkInstance.");
}
void VxVulkan::DestroyInstance(void)
{
vkDestroyInstance(m_instance, nullptr);
}
void VxVulkan::CreateSurface(SDL_Window *pWindow)
{
SDL_bool result = SDL_Vulkan_CreateSurface(pWindow, m_instance, &m_surface);
VX_AssertMsg(result == SDL_TRUE, "Failed to crate VkSurfaceKHR");
}
void VxVulkan::DestroySurface(void)
{
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
}
void VxVulkan::PickPhysicalDevice(void)
{
uint32_t numDevices;
vkEnumeratePhysicalDevices(m_instance, &numDevices, nullptr);
VX_AssertMsg(numDevices > 0, "No Vulkan-compatible GPU found.");
std::vector<VkPhysicalDevice> devices(numDevices);
vkEnumeratePhysicalDevices(m_instance, &numDevices, devices.data());
std::vector<VkPhysicalDeviceInfo> infos(numDevices);
for(uint32_t i = 0; i < numDevices; i++)
infos[i] = VkPhysicalDeviceInfo(devices[i]);
uint32_t di = 0;
int maxrate = -1;
for(uint32_t i = 0; i < numDevices; i++) {
if(infos[i].m_queueIndices.IsValid()) {
int rating = infos[i].GetRating();
if(rating > maxrate) {
maxrate = rating;
di = i;
}
}
}
VX_AssertMsg(maxrate != -1, "No suitable GPU found.");
m_pEngine->Log(VX_LOG_INFO, "Using %s (rating=%d)", infos[di].m_properties.deviceName, maxrate);
m_physDeviceInfo = infos[di];
m_physDevice = devices[di];
}
void VxVulkan::CreateDevice(void)
{
float queuePriority = 1.0;
VkDeviceQueueCreateInfo queueInfo;
queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo.queueFamilyIndex = (uint32_t)m_physDeviceInfo.m_queueIndices.m_graphics;
queueInfo.queueCount = 1;
queueInfo.pQueuePriorities = &queuePriority;
VkDeviceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.enabledExtensionCount = 0;
createInfo.pEnabledFeatures = &m_physDeviceInfo.m_features;
createInfo.pQueueCreateInfos = &queueInfo;
createInfo.queueCreateInfoCount = 1;
VkResult result = vkCreateDevice(m_physDevice, &createInfo, nullptr, &m_device);
VX_AssertMsg(result == VK_SUCCESS, "Failed to create VkDevice.");
vkGetDeviceQueue(m_device, (uint32_t)m_physDeviceInfo.m_queueIndices.m_graphics, 0, &m_qGraphics);
}
void VxVulkan::DestroyDevice(void)
{
vkDestroyDevice(m_device, nullptr);
}
//
// vulkan.h -- internal vulkan wrapper.
// Copyright (C) 2020, Voxelius team.
//
#ifndef VX_VULKAN_H_
#define VX_VULKAN_H_
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/volk.h>
#include <vector>
class IVxEngine;
class VkQueueIndices {
public:
const bool IsValid(void) const;
public:
int m_graphics = -1;
};
class VkPhysicalDeviceInfo {
public:
VkPhysicalDeviceInfo(void);
VkPhysicalDeviceInfo(VkPhysicalDevice dev);
const int GetRating(void) const;
public:
VkPhysicalDeviceFeatures m_features;
VkPhysicalDeviceProperties m_properties;
std::vector<VkQueueFamilyProperties> m_queueProps;
VkQueueIndices m_queueIndices;
private:
int m_rating;
};
class VxVulkan {
public:
VxVulkan(IVxEngine *pEngine);
void CreateInstance(SDL_Window *pWindow);
void DestroyInstance(void);
void CreateSurface(SDL_Window *pWindow);
void DestroySurface(void);
void PickPhysicalDevice(void);
void CreateDevice(void);
void DestroyDevice(void);
private:
IVxEngine *m_pEngine;
VkInstance m_instance;
VkPhysicalDevice m_physDevice;
VkPhysicalDeviceInfo m_physDeviceInfo;
VkDevice m_device;
VkQueue m_qGraphics;
VkSurfaceKHR m_surface;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment