Compare commits

...

2 Commits

Author SHA1 Message Date
Anish Bhobe 75bb1ca895 Device creation + cleanup. 2024-06-16 21:21:36 +02:00
Anish Bhobe ce4dd9b096 Small fixes for compat with clang. 2024-06-16 19:08:14 +02:00
11 changed files with 207 additions and 25 deletions

45
.clang-tidy Normal file
View File

@ -0,0 +1,45 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,cppcoreguidelines-pro-type-member-init,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-nullptr,readability-braces-around-statements,readability-redundant-member-init'
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none
CheckOptions:
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
value: '1'
- key: cppcoreguidelines-pro-type-member-init.UseAssignment
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-bool-literals.IgnoreMacros
value: '0'
- key: modernize-use-default-member-init.IgnoreMacros
value: '0'
- key: modernize-use-default-member-init.UseAssignment
value: '1'
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: readability-braces-around-statements.ShortStatementLines
value: '0'
...

View File

@ -10,10 +10,23 @@ find_package(Vulkan REQUIRED)
find_package(fmt CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED) find_package(VulkanMemoryAllocator CONFIG REQUIRED)
set(HEADER_FILES constants.h config.h logger.h global.h context.h window.h set(HEADER_FILES
physical_device.h) constants.h
set(SOURCE_FILES logger.cpp global.cpp context.cpp window.cpp config.h
physical_device.cpp) 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}) add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20) set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)

View File

@ -12,6 +12,9 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS #define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#if defined(NDEBUG) #if defined(NDEBUG)
#define USE_OPTICK (0) #define USE_OPTICK (0)
#else #else

View File

@ -49,21 +49,17 @@ constexpr auto ANSI_Cyan = "\u001b[36m";
constexpr auto ANSI_White = "\u001b[37m"; constexpr auto ANSI_White = "\u001b[37m";
constexpr auto ANSI_Reset = "\u001b[0m"; constexpr auto ANSI_Reset = "\u001b[0m";
using std::forward;
using std::move;
using std::tie;
template <typename T> template <typename T>
using Option = std::optional<T>; using Option = std::optional<T>;
template <typename type_t, typename from_t> template <typename type_t, typename from_t>
constexpr auto cast(from_t &&_in) { constexpr auto cast(from_t &&_in) {
return static_cast<type_t>(forward<from_t>(_in)); return static_cast<type_t>(std::forward<from_t>(_in));
} }
template <typename type_t, typename from_t> template <typename type_t, typename from_t>
constexpr auto recast(from_t &&_in) { constexpr auto recast(from_t &&_in) {
return reinterpret_cast<type_t>(forward<from_t>(_in)); return reinterpret_cast<type_t>(std::forward<from_t>(_in));
} }
constexpr f32 operator""_deg(long double degrees) { constexpr f32 operator""_deg(long double degrees) {

View File

@ -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), .applicationVersion = VK_MAKE_VERSION(_app_version.major, _app_version.minor, _app_version.patch),
.pEngineName = PROJECT_NAME, .pEngineName = PROJECT_NAME,
.engineVersion = VK_MAKE_VERSION(VERSION.major, VERSION.minor, VERSION.patch), .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 = { vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_create_info = {

80
aster/device.cpp Normal file
View File

@ -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;
}

27
aster/device.h Normal file
View File

@ -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();
};

View File

@ -9,7 +9,7 @@
#include <cstdio> #include <cstdio>
#define VMA_IMPLEMENTATION #define VMA_IMPLEMENTATION
#include <vma/vk_mem_alloc.h> #include <vk_mem_alloc.h>
// NOTE: Vulkan Dispatch Loader Storage - Should only appear once. // NOTE: Vulkan Dispatch Loader Storage - Should only appear once.
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE

View File

@ -18,6 +18,8 @@
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
constexpr u32 ASTER_API_VERSION = vk::ApiVersion13;
#define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__) #define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__)
[[nodiscard]] inline bool failed(const vk::Result _result) { [[nodiscard]] inline bool failed(const vk::Result _result) {
return _result != vk::Result::eSuccess; return _result != vk::Result::eSuccess;

View File

@ -38,6 +38,7 @@ struct Logger {
return "[DEBUG]:"; return "[DEBUG]:";
if constexpr (LogLevel == LogType::eVerbose) if constexpr (LogLevel == LogType::eVerbose)
return "[VERB]: "; return "[VERB]: ";
return "";
} }
template <LogType LogLevel> template <LogType LogLevel>
@ -52,12 +53,13 @@ struct Logger {
return ANSI_White; return ANSI_White;
if constexpr (LogLevel == LogType::eVerbose) if constexpr (LogLevel == LogType::eVerbose)
return ANSI_Blue; return ANSI_Blue;
return ANSI_White;
} }
template <LogType LogLevel> template <LogType LogLevel>
void log(const std::string_view &_message, const char *_loc, u32 _line) const { void log(const std::string_view &_message, const char *_loc, u32 _line) const {
if (cast<u32>(LogLevel) <= minimum_logging_level) { 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 !defined(NDEBUG)
if constexpr (LogLevel == LogType::eError) { if constexpr (LogLevel == LogType::eError) {
@ -69,7 +71,7 @@ struct Logger {
template <LogType LogLevel> template <LogType LogLevel>
void log_cond(const char *_expr_str, const std::string_view &_message, const char *_loc, u32 _line) const { 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) { 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 !defined(NDEBUG)
if constexpr (LogLevel == LogType::eError) { if constexpr (LogLevel == LogType::eError) {

View File

@ -1,9 +1,10 @@
#include "aster/constants.h" #include "aster/constants.h"
#include "aster/device.h"
#include "aster/glfw_context.h" #include "aster/glfw_context.h"
#include "aster/physical_device.h" #include "aster/physical_device.h"
#include "aster/window.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) { [[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) { 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."); throw std::runtime_error("No suitable device found.");
} }
int main(int, char **) { QueueAllocation find_appropriate_queue_allocation(const PhysicalDevice* _physical_device) {
const auto *glfw = new GlfwContext(); for (auto &_queue_info: _physical_device->queue_families) {
auto *context = new Context("Aster", VERSION); if ((_queue_info.support & required_queue_support) == required_queue_support) {
auto *window = new Window("Aster1", context, { 640, 480 }); 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); PhysicalDevice device_to_use = find_suitable_device(physical_devices);
INFO("Using {} as the primary device.", device_to_use.properties.deviceName.data()); 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; Device device = { &context, std::move(device_to_use), &features, {queue_allocation}, "Primary Device" };
delete context;
delete glfw; while (window.poll()) {
}
return 0; return 0;
} }