mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
105 lines
3.8 KiB
C++
105 lines
3.8 KiB
C++
#include "core/device.hpp"
|
|
#include "lsfg.hpp"
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
using namespace LSFG::Core;
|
|
|
|
const std::vector<const char*> requiredExtensions = {
|
|
"VK_KHR_external_memory_fd",
|
|
"VK_EXT_robustness2",
|
|
};
|
|
|
|
Device::Device(const Instance& instance) {
|
|
// get all physical devices
|
|
uint32_t deviceCount{};
|
|
auto res = vkEnumeratePhysicalDevices(instance.handle(), &deviceCount, nullptr);
|
|
if (res != VK_SUCCESS || deviceCount == 0)
|
|
throw LSFG::vulkan_error(res, "Failed to enumerate physical devices");
|
|
|
|
std::vector<VkPhysicalDevice> devices(deviceCount);
|
|
res = vkEnumeratePhysicalDevices(instance.handle(), &deviceCount, devices.data());
|
|
if (res != VK_SUCCESS)
|
|
throw LSFG::vulkan_error(res, "Failed to get physical devices");
|
|
|
|
// find first discrete GPU
|
|
std::optional<VkPhysicalDevice> physicalDevice;
|
|
for (const auto& device : devices) {
|
|
VkPhysicalDeviceProperties properties;
|
|
vkGetPhysicalDeviceProperties(device, &properties);
|
|
|
|
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
|
physicalDevice = device;
|
|
break;
|
|
}
|
|
}
|
|
if (!physicalDevice)
|
|
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No discrete GPU found");
|
|
|
|
// find queue family indices
|
|
uint32_t familyCount{};
|
|
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &familyCount, nullptr);
|
|
|
|
std::vector<VkQueueFamilyProperties> queueFamilies(familyCount);
|
|
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &familyCount, queueFamilies.data());
|
|
|
|
std::optional<uint32_t> computeFamilyIdx;
|
|
for (uint32_t i = 0; i < familyCount; ++i) {
|
|
if (queueFamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
|
|
computeFamilyIdx = i;
|
|
}
|
|
if (!computeFamilyIdx)
|
|
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No compute queue family found");
|
|
|
|
// create logical device
|
|
const float queuePriority{1.0F}; // highest priority
|
|
VkPhysicalDeviceRobustness2FeaturesEXT robustness2{
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT,
|
|
.nullDescriptor = VK_TRUE,
|
|
};
|
|
VkPhysicalDeviceVulkan13Features features13{
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
|
.pNext = &robustness2,
|
|
.synchronization2 = VK_TRUE
|
|
};
|
|
const VkPhysicalDeviceVulkan12Features features12{
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
|
.pNext = &features13,
|
|
.timelineSemaphore = VK_TRUE,
|
|
.vulkanMemoryModel = VK_TRUE
|
|
};
|
|
const VkDeviceQueueCreateInfo computeQueueDesc{
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
|
.queueFamilyIndex = *computeFamilyIdx,
|
|
.queueCount = 1,
|
|
.pQueuePriorities = &queuePriority
|
|
};
|
|
const VkDeviceCreateInfo deviceCreateInfo{
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
|
.pNext = &features12,
|
|
.queueCreateInfoCount = 1,
|
|
.pQueueCreateInfos = &computeQueueDesc,
|
|
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
|
|
.ppEnabledExtensionNames = requiredExtensions.data()
|
|
};
|
|
VkDevice deviceHandle{};
|
|
res = vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);
|
|
if (res != VK_SUCCESS | deviceHandle == VK_NULL_HANDLE)
|
|
throw LSFG::vulkan_error(res, "Failed to create logical device");
|
|
|
|
// get compute queue
|
|
VkQueue queueHandle{};
|
|
vkGetDeviceQueue(deviceHandle, *computeFamilyIdx, 0, &queueHandle);
|
|
|
|
// store in shared ptr
|
|
this->computeQueue = queueHandle;
|
|
this->computeFamilyIdx = *computeFamilyIdx;
|
|
this->physicalDevice = *physicalDevice;
|
|
this->device = std::shared_ptr<VkDevice>(
|
|
new VkDevice(deviceHandle),
|
|
[](VkDevice* device) {
|
|
vkDestroyDevice(*device, nullptr);
|
|
}
|
|
);
|
|
}
|