Device creation + cleanup.
This commit is contained in:
parent
ce4dd9b096
commit
75bb1ca895
|
|
@ -10,10 +10,23 @@ find_package(Vulkan REQUIRED)
|
|||
find_package(fmt CONFIG REQUIRED)
|
||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||
|
||||
set(HEADER_FILES constants.h config.h logger.h global.h context.h window.h
|
||||
physical_device.h)
|
||||
set(SOURCE_FILES logger.cpp global.cpp context.cpp window.cpp
|
||||
physical_device.cpp)
|
||||
set(HEADER_FILES
|
||||
constants.h
|
||||
config.h
|
||||
logger.h
|
||||
global.h
|
||||
context.h
|
||||
window.h
|
||||
physical_device.h
|
||||
device.h)
|
||||
|
||||
set(SOURCE_FILES
|
||||
logger.cpp
|
||||
global.cpp
|
||||
context.cpp
|
||||
window.cpp
|
||||
physical_device.cpp
|
||||
device.cpp)
|
||||
|
||||
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define USE_OPTICK (0)
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ void Context::init(const std::string_view &_app_name, const Version &_app_versio
|
|||
.applicationVersion = VK_MAKE_VERSION(_app_version.major, _app_version.minor, _app_version.patch),
|
||||
.pEngineName = PROJECT_NAME,
|
||||
.engineVersion = VK_MAKE_VERSION(VERSION.major, VERSION.minor, VERSION.patch),
|
||||
.apiVersion = VK_API_VERSION_1_2,
|
||||
.apiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
|
||||
vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_create_info = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
// =============================================
|
||||
// Aster: device.h
|
||||
// Copyright (c) 2020-2024 Anish Bhobe
|
||||
// =============================================
|
||||
|
||||
#include "device.h"
|
||||
|
||||
Device::Device(const Context *_context, PhysicalDevice &&_physical_device, const vk::PhysicalDeviceFeatures *_enabled_features, const std::vector<QueueAllocation> &_queue_allocation, std::optional<std::string> _name) :
|
||||
physical_device{ std::move(_physical_device) },
|
||||
name{ std::move(_name) } {
|
||||
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
|
||||
queue_create_infos.reserve(_queue_allocation.size());
|
||||
|
||||
u32 num_priorities = 0;
|
||||
for (auto [_, count] : _queue_allocation) {
|
||||
num_priorities = std::max(count, num_priorities);
|
||||
}
|
||||
std::vector priorities(num_priorities, 1.0f);
|
||||
|
||||
for (auto [family, count] : _queue_allocation) {
|
||||
queue_create_infos.push_back({
|
||||
.queueFamilyIndex = family,
|
||||
.queueCount = count,
|
||||
.pQueuePriorities = priorities.data(),
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
device = physical_device.device.createDevice({
|
||||
.queueCreateInfoCount = cast<u32>(queue_create_infos.size()),
|
||||
.pQueueCreateInfos = queue_create_infos.data(),
|
||||
.enabledLayerCount = _context->enable_validation_layers ? cast<u32>(_context->validation_layers.size()) : 0,
|
||||
.ppEnabledLayerNames = _context->enable_validation_layers ? _context->validation_layers.data() : nullptr,
|
||||
.enabledExtensionCount = cast<u32>(_context->device_extensions.size()),
|
||||
.ppEnabledExtensionNames = _context->device_extensions.data(),
|
||||
.pEnabledFeatures = _enabled_features,
|
||||
});
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Could not initialize Vulkan Device. Cause: {}", _err.what());
|
||||
throw;
|
||||
}
|
||||
|
||||
INFO("{} ({}) Initialized!", name.value_or(DEFAULT_DEVICE_NAME), physical_device.properties.deviceName.data());
|
||||
|
||||
VmaVulkanFunctions vma_vulkan_functions = {
|
||||
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
||||
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
||||
};
|
||||
|
||||
const VmaAllocatorCreateInfo vma_allocator_create_info = {
|
||||
.flags = 0,
|
||||
.physicalDevice = physical_device.device,
|
||||
.device = device,
|
||||
.pVulkanFunctions = &vma_vulkan_functions,
|
||||
.instance = _context->instance,
|
||||
.vulkanApiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
|
||||
const auto result = cast<vk::Result>(vmaCreateAllocator(&vma_allocator_create_info, &allocator));
|
||||
if (failed(result)) {
|
||||
device.destroy();
|
||||
auto _err = fmt::format("Memory allocator creation failed. Cause: {}", to_string(result));
|
||||
ERROR("{}", _err);
|
||||
throw std::runtime_error(_err);
|
||||
}
|
||||
VERBOSE("Memory Allocator Created");
|
||||
|
||||
INFO("Created '{}' Successfully", name.value_or(DEFAULT_DEVICE_NAME));
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
if (allocator) {
|
||||
vmaDestroyAllocator(allocator);
|
||||
allocator = nullptr;
|
||||
VERBOSE("Memory Allocator Destroyed");
|
||||
}
|
||||
device.destroy();
|
||||
INFO("Device '{}' Destroyed", name.value_or(DEFAULT_DEVICE_NAME));
|
||||
name = std::nullopt;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// =============================================
|
||||
// Aster: device.h
|
||||
// Copyright (c) 2020-2024 Anish Bhobe
|
||||
// =============================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "global.h"
|
||||
#include "physical_device.h"
|
||||
|
||||
constexpr std::string DEFAULT_DEVICE_NAME = "<Unnamed GPU>";
|
||||
|
||||
struct QueueAllocation {
|
||||
u32 family;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct Device final {
|
||||
vk::Device device;
|
||||
PhysicalDevice physical_device;
|
||||
VmaAllocator allocator { nullptr };
|
||||
std::optional<std::string> name { nullptr };
|
||||
|
||||
Device(const Context *_context, PhysicalDevice &&_physical_device, const vk::PhysicalDeviceFeatures *_enabled_features, const std::vector<QueueAllocation> &_queue_allocation, std::optional<std::string> _name = std::nullopt);
|
||||
|
||||
~Device();
|
||||
};
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
#include <vk_mem_alloc.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
constexpr u32 ASTER_API_VERSION = vk::ApiVersion13;
|
||||
|
||||
#define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__)
|
||||
[[nodiscard]] inline bool failed(const vk::Result _result) {
|
||||
return _result != vk::Result::eSuccess;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ struct Logger {
|
|||
template <LogType LogLevel>
|
||||
void log(const std::string_view &_message, const char *_loc, u32 _line) const {
|
||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
||||
fmt::println("{}{} {}{}| at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
fmt::println("{}{} {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
}
|
||||
#if !defined(NDEBUG)
|
||||
if constexpr (LogLevel == LogType::eError) {
|
||||
|
|
@ -71,7 +71,7 @@ struct Logger {
|
|||
template <LogType LogLevel>
|
||||
void log_cond(const char *_expr_str, const std::string_view &_message, const char *_loc, u32 _line) const {
|
||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
||||
fmt::println("{}{} ({}) {}{}| at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _expr_str, _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
fmt::println("{}{} ({}) {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _expr_str, _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
}
|
||||
#if !defined(NDEBUG)
|
||||
if constexpr (LogLevel == LogType::eError) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#include "aster/constants.h"
|
||||
#include "aster/device.h"
|
||||
#include "aster/glfw_context.h"
|
||||
#include "aster/physical_device.h"
|
||||
#include "aster/window.h"
|
||||
|
||||
constexpr QueueSupportFlags required_queue_support = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eCompute;
|
||||
constexpr QueueSupportFlags required_queue_support = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer;
|
||||
|
||||
[[nodiscard]] bool is_suitable_device(const PhysicalDevice *_physical_device) {
|
||||
const bool all_required_queues = std::ranges::any_of(_physical_device->queue_families, [](const auto &_qfp) {
|
||||
|
|
@ -28,22 +29,35 @@ PhysicalDevice find_suitable_device(const PhysicalDevices &_physical_devices) {
|
|||
throw std::runtime_error("No suitable device found.");
|
||||
}
|
||||
|
||||
int main(int, char **) {
|
||||
const auto *glfw = new GlfwContext();
|
||||
auto *context = new Context("Aster", VERSION);
|
||||
auto *window = new Window("Aster1", context, { 640, 480 });
|
||||
QueueAllocation find_appropriate_queue_allocation(const PhysicalDevice* _physical_device) {
|
||||
for (auto &_queue_info: _physical_device->queue_families) {
|
||||
if ((_queue_info.support & required_queue_support) == required_queue_support) {
|
||||
return {
|
||||
.family = _queue_info.index,
|
||||
.count = _queue_info.count,
|
||||
};
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("No suitable queue family.");
|
||||
}
|
||||
|
||||
PhysicalDevices physical_devices = { window, context };
|
||||
int main(int, char **) {
|
||||
GlfwContext glfw_context = {};
|
||||
Context context = {"Aster", VERSION};
|
||||
Window window = {"Aster1", &context, { 640, 480 }};
|
||||
|
||||
PhysicalDevices physical_devices = { &window, &context };
|
||||
PhysicalDevice device_to_use = find_suitable_device(physical_devices);
|
||||
|
||||
INFO("Using {} as the primary device.", device_to_use.properties.deviceName.data());
|
||||
|
||||
while (window->poll()) {
|
||||
}
|
||||
vk::PhysicalDeviceFeatures features = {};
|
||||
QueueAllocation queue_allocation = find_appropriate_queue_allocation(&device_to_use);
|
||||
|
||||
delete window;
|
||||
delete context;
|
||||
delete glfw;
|
||||
Device device = { &context, std::move(device_to_use), &features, {queue_allocation}, "Primary Device" };
|
||||
|
||||
while (window.poll()) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue