// ============================================= // 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 &_queue_allocation, std::optional _name) : physical_device{ std::move(_physical_device) }, name{ std::move(_name) } { std::vector 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(queue_create_infos.size()), .pQueueCreateInfos = queue_create_infos.data(), .enabledLayerCount = _context->enable_validation_layers ? cast(_context->validation_layers.size()) : 0, .ppEnabledLayerNames = _context->enable_validation_layers ? _context->validation_layers.data() : nullptr, .enabledExtensionCount = cast(_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(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; }