vulkan device

This commit is contained in:
ouczbs 2024-03-02 09:53:28 +08:00
parent d6cb37383b
commit d8163fd614
14 changed files with 115 additions and 289 deletions

View File

@ -1,3 +1,4 @@
#pragma once
#include <Windows.h>
namespace renderapi {
class Window {

View File

@ -6,17 +6,15 @@ namespace vulkanapi {
{
auto instanceCreator = InstanceCreator();
mInstance = new Instance(instanceCreator);
std::vector<VkPhysicalDevice> available_devices;
mInstance->EnumerateAvailablePhysicalDevices(available_devices);
int device_count = available_devices.size();
if (device_count <= deviceIndex) {
zlog::error("Could not get the number of available physical devices. out of boundry. {} > {}", deviceIndex, device_count);
if (device_count == 0) {
return;
}
deviceIndex = 0;
}
mDevice = new Device(mInstance->Ptr(), available_devices[deviceIndex]);
auto deviceCreator = DeviceCreator(*mInstance);
deviceCreator.desiredPhysicalDeviceFeatures.geometryShader = VK_TRUE;
deviceCreator.AddQueue("TransferQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
deviceCreator.AddQueue("RenderQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
deviceCreator.AddQueue("ComputeQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
deviceCreator.AddQueue("PresentQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
mDevice = new Device(deviceCreator);
}
Backend::~Backend()
{

View File

@ -4,6 +4,7 @@
#include "wrapper/instance.h"
#include "wrapper/instance_creator.h"
#include "wrapper/device.h"
#include "wrapper/device_creator.h"
namespace vulkanapi {
class Backend{
protected:

View File

@ -1,4 +1,4 @@
//#pragma once
#pragma once
#include <Windows.h>
#include <functional>
#include <vulkan/vulkan.h>

View File

@ -1,40 +1,14 @@
#include "device.h"
#include "device_help.h"
#include "device_creator.h"
namespace vulkanapi {
Device::Device(VkInstance instance, VkPhysicalDevice physDevice):mPhysical(physDevice)
{
std::vector<VkQueueFamilyProperties> queue_families;
CheckAvailableQueueFamiliesAndTheirProperties(physDevice, queue_families);
Device::Device(DeviceCreator& Creator)
{
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
_QueueCreateInfos(queue_create_infos, queue_families);
std::vector<char const*> desired_extensions = {
"VK_KHR_swapchain",
};
VkPhysicalDeviceFeatures device_features{};
_EnabledFeatures(device_features);
VkDeviceCreateInfo device_create_info = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType
nullptr, // const void * pNext
0, // VkDeviceCreateFlags flags
static_cast<uint32_t>(queue_create_infos.size()), // uint32_t queueCreateInfoCount
queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos
0, // uint32_t enabledLayerCount
nullptr, // const char * const * ppEnabledLayerNames
static_cast<uint32_t>(desired_extensions.size()), // uint32_t enabledExtensionCount
desired_extensions.data(), // const char * const * ppEnabledExtensionNames
&device_features // const VkPhysicalDeviceFeatures * pEnabledFeatures
};
VkResult result = vkCreateDevice(physDevice, &device_create_info, nullptr, &mPtr);
if((result != VK_SUCCESS) || (mPtr == VK_NULL_HANDLE)) {
zlog::error("Could not create logical device.");
}
}
}
uint32_t Device::GetQueueFamilyIndex(VkQueueFlags flag)
{
std::vector<VkQueueFamilyProperties> queue_families;
CheckAvailableQueueFamiliesAndTheirProperties(mPhysical, queue_families);
// CheckAvailableQueueFamiliesAndTheirProperties(mPhysical, queue_families);
for (uint32_t i = 0, l = queue_families.size(); i < l; i++) {
if ((queue_families[i].queueFlags & flag) == flag) {
return i;

View File

@ -3,7 +3,9 @@
#include "../vulkan.h"
namespace vulkanapi {
class DeviceCreator;
class Device{
friend class DeviceCreator;
protected:
VkDevice mPtr{ NULL };
VkPhysicalDevice mPhysical{NULL};
@ -15,8 +17,7 @@ namespace vulkanapi {
return mPhysical;
}
public:
Device(){};
Device(VkInstance ptr, VkPhysicalDevice physDevice);
Device(DeviceCreator& Creator);
uint32_t GetQueueFamilyIndex(VkQueueFlags flag);
VkCommandPool CreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator);

View File

@ -0,0 +1,41 @@
#pragma once
#include "device.h"
#include "device_creator.h"
#include "zlog.h"
namespace vulkanapi {
DeviceCreator::DeviceCreator(Instance& instance)
:instance(instance)
, desiredPhysicalDeviceType(VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
, desiredPhysicalDeviceFeatures()
{
}
void DeviceCreator::AddQueue(std::string name, VkQueueFlags flag, float prioritie)
{
desiredQueues.emplace_back(name, flag, prioritie);
}
void DeviceCreator::AddWindowExtension()
{
AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
AddQueue("PresentQueue", VK_QUEUE_FLAG_BITS_MAX_ENUM, 1.0f);
#ifdef _USE_GRAPHIC_DEBUG
AddLayer("VK_LAYER_KHRONOS_validation");
AddLayer("VK_LAYER_RENDERDOC_Capture");
#endif
}
void DeviceCreator::QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<VkQueueFamilyProperties>& queue_families)
{
std::vector<VkLayerProperties> availableLayers();
}
void DeviceCreator::AddExtension(std::string extensionName)
{
desiredExtensions.push_back(extensionName);
}
#ifdef _USE_GRAPHIC_DEBUG
void DeviceCreator::AddLayer(std::string layerName)
{
desiredLayers.push_back(layerName);
}
#endif
};

View File

@ -0,0 +1,42 @@
#pragma once
#include "../vulkan.h"
#include <string>
#include <vector>
namespace vulkanapi {
class Device;
class Instance;
class DeviceCreator {
friend class Device;
private:
class DesiredQueue final
{
public:
std::string name;
VkQueueFlags flag;
float prioritie;
DesiredQueue(std::string name, VkQueueFlags flag, float prioritie)
: name(name), flag(flag), prioritie(prioritie){}
};
public:
VkPhysicalDeviceFeatures desiredPhysicalDeviceFeatures;
VkPhysicalDeviceType desiredPhysicalDeviceType;
std::vector<std::string> desiredExtensions;
std::vector<DesiredQueue> desiredQueues;
public:
Instance& instance;
public:
DeviceCreator(Instance& instance);
void AddQueue(std::string name, VkQueueFlags flag, float prioritie);
void AddExtension(std::string extensionName);
void AddWindowExtension();
void QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<VkQueueFamilyProperties>& queue_families);
#ifdef _USE_GRAPHIC_DEBUG
public:
std::vector<std::string> desiredLayers;
void AddLayer(std::string layerName);
#endif
private:
};

View File

@ -1,44 +0,0 @@
#pragma once
#include "../vulkan.h"
#include <string>
#include <iostream>
#include <vector>
#include "zlog.h"
namespace vulkanapi {
constexpr float DEFAULT_QUEUE_PRIORITY = 1.0f;
bool CheckAvailableQueueFamiliesAndTheirProperties(VkPhysicalDevice physical_device,std::vector<VkQueueFamilyProperties>& queue_families) {
uint32_t queue_families_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr);
if (queue_families_count == 0) {
zlog::error("Could not get the number of queue families.");
return false;
}
queue_families.resize(queue_families_count);
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, queue_families.data());
if (queue_families_count == 0) {
zlog::error("Could not acquire properties of queue families.");
return false;
}
return true;
}
void _QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<VkQueueFamilyProperties>& queue_families) {
for (uint32_t i = 0, l = queue_families.size(); i < l; i++) {
queue_create_infos.push_back({
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType
nullptr, // const void * pNext
0, // VkDeviceQueueCreateFlags flags
i, // uint32_t queueFamilyIndex
1, // uint32_t queueCount
&DEFAULT_QUEUE_PRIORITY // const float * pQueuePriorities
});
}
}
void _EnabledFeatures(VkPhysicalDeviceFeatures& device_features) {
device_features.independentBlend = true;
device_features.depthClamp = true;
//device_features.protectedMemory = true;
}
}

View File

@ -22,9 +22,9 @@ namespace vulkanapi {
Creator.apiVersion // uint32_t apiVersion
};
#ifdef _USE_GRAPHIC_DEBUG
Creator._AddDebugExtension();
Creator.AddDebugExtension();
#endif
Creator._AddWindowExtension();
Creator.AddWindowExtension();
auto extensions = Creator.EnabledExtensionNames();
auto layers = Creator.EnabledLayerNames();;
VkInstanceCreateInfo instance_create_info = {
@ -38,7 +38,7 @@ namespace vulkanapi {
extensions.data() // const char * const * ppEnabledExtensionNames
};
#ifdef _USE_GRAPHIC_DEBUG
VkDebugUtilsMessengerCreateInfoEXT debugInfo = Creator._DebugUtilsLayerNext();
VkDebugUtilsMessengerCreateInfoEXT debugInfo = Creator.DebugUtilsLayerNext();
instance_create_info.pNext = &debugInfo;
#endif
VkResult result = vkCreateInstance(&instance_create_info, nullptr, &mPtr);

View File

@ -1,9 +1,6 @@
#pragma once
#include "instance.h"
#include "instance_creator.h"
#include <string>
#include <iostream>
#include <vector>
#include "zlog.h"
namespace vulkanapi {
InstanceCreator::InstanceCreator()
@ -28,14 +25,14 @@ namespace vulkanapi {
{
desiredLayers.push_back(layerName);
}
void InstanceCreator::_AddWindowExtension()
void InstanceCreator::AddWindowExtension()
{
AddExtension("VK_KHR_win32_surface");
AddExtension(VK_KHR_SURFACE_EXTENSION_NAME);
AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddExtension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
//AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
//AddExtension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
}
void InstanceCreator::_AddDebugExtension()
void InstanceCreator::AddDebugExtension()
{
AddLayer("VK_LAYER_KHRONOS_validation");
AddLayer("VK_LAYER_RENDERDOC_Capture");
@ -79,7 +76,7 @@ namespace vulkanapi {
}
#ifdef _USE_GRAPHIC_DEBUG
VkDebugUtilsMessengerCreateInfoEXT InstanceCreator::_DebugUtilsLayerNext()
VkDebugUtilsMessengerCreateInfoEXT InstanceCreator::DebugUtilsLayerNext()
{
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;

View File

@ -20,8 +20,8 @@ namespace vulkanapi {
void AddExtension(std::string extensionName);
void AddLayer(std::string layerName);
void _AddWindowExtension();
void _AddDebugExtension();
void AddWindowExtension();
void AddDebugExtension();
std::vector<char const*> EnabledExtensionNames();
std::vector<char const*> EnabledLayerNames();
@ -31,7 +31,7 @@ namespace vulkanapi {
VkDebugUtilsMessageTypeFlagsEXT messageType;
PFN_vkDebugUtilsMessengerCallbackEXT debugCallback;
VkDebugUtilsMessengerCreateInfoEXT _DebugUtilsLayerNext();
VkDebugUtilsMessengerCreateInfoEXT DebugUtilsLayerNext();
#endif
private:

View File

@ -1,186 +0,0 @@
#pragma once
#include "../vulkan.h"
#include <string>
#include <iostream>
#include <vector>
#include "zlog.h"
namespace vulkanapi {
bool ConnectWithVulkanLoaderLibrary(LIBRARY_TYPE& vulkan_library) {
#if defined _WIN32
vulkan_library = LoadLibrary("vulkan-1.dll");
#elif defined __linux
vulkan_library = dlopen("libvulkan.so.1", RTLD_NOW);
#endif
if (vulkan_library == nullptr) {
zlog::error("Could not connect with a Vulkan Runtime library.");
return false;
}
return true;
}
bool LoadFunctionExportedFromVulkanLoaderLibrary(LIBRARY_TYPE const& vulkan_library) {
#if defined _WIN32
#define LoadFunction GetProcAddress
#elif defined __linux
#define LoadFunction dlsym
#endif
#define EXPORTED_VULKAN_FUNCTION( name ) \
name = (PFN_##name)LoadFunction( vulkan_library, #name ); \
if( name == nullptr ) { \
zlog::error( "Could not load exported Vulkan function named:"#name);\
return false; \
}
#include "engine/vulkanapi/vulkan_function_list.inl"
return true;
}
bool LoadGlobalLevelFunctions() {
#define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) \
name = (PFN_##name)vkGetInstanceProcAddr( nullptr, #name ); \
if( name == nullptr ) { \
zlog::error( "Could not load global level Vulkan function named:"#name);\
return false; \
}
#include "engine/vulkanapi/vulkan_function_list.inl"
return true;
}
bool LoadInstanceLevelFunctions(VkInstance instance,
std::vector<char const*> const& enabled_extensions) {
// Load core Vulkan API instance-level functions
#define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) \
name = (PFN_##name)vkGetInstanceProcAddr( instance, #name ); \
if( name == nullptr ) { \
zlog::error( "Could not load instance-level Vulkan function named:"#name);\
return false; \
}
// Load instance-level functions from enabled extensions
#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, extension ) \
for( auto & enabled_extension : enabled_extensions ) { \
if( std::string( enabled_extension ) == std::string( extension ) ) { \
name = (PFN_##name)vkGetInstanceProcAddr( instance, #name ); \
if( name == nullptr ) { \
zlog::error( "Could not load instance-level Vulkan function named:"#name);\
return false; \
} \
} \
}
#include "engine/vulkanapi/vulkan_function_list.inl"
return true;
}
bool IsExtensionSupported(std::vector<VkExtensionProperties> const& available_extensions,
char const* const extension) {
for (auto& available_extension : available_extensions) {
if (strstr(available_extension.extensionName, extension)) {
return true;
}
}
return false;
}
bool IsLayerSupported(std::vector<VkLayerProperties> const& available_layers,
char const* const layer) {
for (auto& available_layer : available_layers) {
if (strstr(available_layer.layerName, layer)) {
return true;
}
}
return false;
}
bool CheckAvailableInstanceLayers(std::vector<VkLayerProperties>& available_layers) {
uint32_t extensions_count = 0;
VkResult result = VK_SUCCESS;
result = vkEnumerateInstanceLayerProperties(&extensions_count, nullptr);
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not get the number of instance layers.");
return false;
}
available_layers.resize(extensions_count);
result = vkEnumerateInstanceLayerProperties(&extensions_count, available_layers.data());
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not enumerate instance layers.");
return false;
}
return true;
}
bool CheckAvailableInstanceExtensions(std::vector<VkExtensionProperties>& available_extensions) {
uint32_t extensions_count = 0;
VkResult result = VK_SUCCESS;
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, nullptr);
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not get the number of instance extensions.");
return false;
}
available_extensions.resize(extensions_count);
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, available_extensions.data());
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not enumerate instance extensions.");
return false;
}
return true;
}
std::vector<char const*> _EnabledExtensionNames(std::vector<std::string>& extensions) {
std::vector<VkExtensionProperties> available_extensions;
std::vector<char const*> _extension;
if (!CheckAvailableInstanceExtensions(available_extensions)) {
return _extension;
}
for (int i = 0, l = extensions.size(); i < l; i++) {
if (IsExtensionSupported(available_extensions, extensions[i].c_str())) {
_extension.push_back(extensions[i].c_str());
}
else {
zlog::error("cann't support extension: {}", extensions[i].c_str());
}
}
return _extension;
}
std::vector<char const*> _EnabledLayerNames(std::vector<std::string>& layers) {
std::vector<VkLayerProperties> available_layers;
std::vector<char const*> _layers;
if (!CheckAvailableInstanceLayers(available_layers)) {
return _layers;
}
for (int i = 0, l = layers.size(); i < l; i++) {
if (IsLayerSupported(available_layers, layers[i].c_str())) {
_layers.push_back(layers[i].c_str());
}
else {
zlog::error("Could not load instance-level Vulkan function named: {}", layers[i].c_str());
}
}
return _layers;
}
// debug callback
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT,
VkDebugUtilsMessageTypeFlagsEXT,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void*)
{
zlog::error("validation layer: {}", pCallbackData->pMessage);
return VK_FALSE;
}
VkDebugUtilsMessengerCreateInfoEXT _DebugUtilsLayerNext() {
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity =
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback;
return createInfo;
}
};

View File

@ -1,3 +1,4 @@
#pragma once
#include "instance.h"
#include <iostream>
#include "zlog.h"