This commit is contained in:
Neo 2025-02-25 13:49:01 -05:00
parent 32dd4568c0
commit d926d29dfa
8 changed files with 214 additions and 3 deletions

View File

@ -23,6 +23,7 @@ namespace dyn::utils {
namespace dyn::utils {
extern const std::vector<const char*> vk_validation_layers;
extern const std::vector<const char*> vk_device_extensions;
VkBool32 vk_debug_message_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
@ -42,4 +43,4 @@ namespace dyn::utils {
#define dyn_vk_verify(f) { \
VkResult res = f; \
DYN_ASSERT(res == VK_SUCCESS, "Vulkan error occured", string_VkResult(res), "at line", __LINE__, "in file", __FILE__); }
DYN_ASSERT(res == VK_SUCCESS, "Vulkan error occured", string_VkResult(res), "at line", __LINE__, "in file", __FILE__, "at function call", #f); }

View File

@ -33,14 +33,24 @@ namespace dyn::core {
[[nodiscard]] static bool check_api_version_support(uint32_t api_version);
[[nodiscard]] static ref<vulkan_device> get_last_selected_logical_device() { return s_current_device; }
void single_cmd(std::function<void(VkCommandBuffer)> cmdFunc);
private:
VkInstance _instance = nullptr;
ref<vulkan_physical_device> _physical_device;
ref<vulkan_device> _device;
VkCommandPool _command_pool;
VkDebugUtilsMessengerEXT _debug_messenger = nullptr;
VkSurfaceKHR _surface = nullptr;
ref<window> _window;
static ref<vulkan_device> s_current_device;
};
}

View File

@ -24,10 +24,12 @@ namespace dyn::core {
static queue_families find(const VkPhysicalDevice& physical_device, const VkSurfaceKHR& surface);
};
[[nodiscard]] VkPhysicalDevice get_physical_device() const { return _physical_device; }
[[nodiscard]] VkPhysicalDevice get_handle() const { return _physical_device; }
[[nodiscard]] queue_families get_queue_families() const { return _queue_families; }
[[nodiscard]] VkPhysicalDeviceProperties get_properties() const { return _device_properties; }
static VkPhysicalDevice determine_suitable_device(const std::vector<VkPhysicalDevice>& available_devices, const VkSurfaceKHR& surface);
static uint32_t score_device(const VkPhysicalDevice& device);
@ -37,5 +39,25 @@ namespace dyn::core {
VkPhysicalDevice _physical_device = nullptr;
queue_families _queue_families;
ref<vulkan_context> _ctx;
VkPhysicalDeviceProperties _device_properties;
};
class vulkan_device {
public:
explicit vulkan_device(const ref<vulkan_physical_device>& physical_device, VkPhysicalDeviceFeatures device_features);
~vulkan_device();
[[nodiscard]] VkDevice get_handle() const { return _device; }
[[nodiscard]] VkQueue get_graphics_queue() const { return _graphics_queue; }
[[nodiscard]] VkQueue get_present_queue() const { return _present_queue; }
static ref<vulkan_device> create(const std::shared_ptr<vulkan_physical_device>& device, const VkPhysicalDeviceFeatures& device_features);
private:
VkDevice _device = nullptr;
VkQueue _graphics_queue = VK_NULL_HANDLE;
VkQueue _present_queue = VK_NULL_HANDLE;
};
}

View File

@ -0,0 +1,40 @@
//
// Created by Neo on 2/25/25.
//
#pragma once
#include <dyn/platform/vulkan/vulkan_swapchain.h>
#include "dyn/renderer/swapchain.h"
namespace dyn::core {
class vulkan_swapchain : public swapchain {
public:
explicit vulkan_swapchain(const ref<vulkan_context>& ctx);
~vulkan_swapchain() override;
void prepare() override;
void present() override;
void resize(uint32_t width, uint32_t height) override;
[[nodiscard]] VkCommandBuffer current_cmd_buffer() const { return _command_buffers[_current_frame]; }
protected:
void rebuild();
private:
struct swap_image {
VkImage image;
VkImageView view;
};
std::vector<swap_image> _swap_images;
std::vector<VkCommandBuffer> _command_buffers;
uint32_t _current_frame = 0;
VkSwapchainKHR _swapchain;
ref<vulkan_context> _ctx;
};
}

View File

@ -0,0 +1,23 @@
//
// Created by Neo on 2/25/25.
//
#pragma once
#include <dyn/core/base.h>
#include <dyn/renderer/render_context.h>
namespace dyn::core {
class swapchain {
public:
swapchain() = default;
virtual ~swapchain() = default;
virtual void resize(uint32_t width, uint32_t height) = 0;
virtual void prepare() = 0;
virtual void present() = 0;
ref<swapchain> create(const ref<render_context>& ctx);
};
}

View File

@ -9,6 +9,10 @@ namespace dyn::utils {
"VK_LAYER_KHRONOS_validation"
};
const std::vector<const char*> vk_device_extensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
VkResult vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (func != nullptr) {

View File

@ -90,11 +90,27 @@ namespace dyn::core {
glfwCreateWindowSurface(_instance, _window->get_window_handle(), nullptr, &_surface);
}
// physical device
// device
{
_physical_device = vulkan_physical_device::create(self);
DYN_DEBUG_LOG("Physical Device Created");
VkPhysicalDeviceFeatures device_features{};
device_features.samplerAnisotropy = true;
_device = vulkan_device::create(_physical_device, device_features);
s_current_device = _device;
}
// command pool
{
VkCommandPoolCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
create_info.queueFamilyIndex = _physical_device->get_queue_families().graphics_family.value();
create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
dyn_vk_verify(vkCreateCommandPool(_device->get_handle(), &create_info, nullptr, &_command_pool));
}
}
@ -121,4 +137,35 @@ namespace dyn::core {
}
return true;
}
void vulkan_context::single_cmd(std::function<void(VkCommandBuffer)> cmdFunc) {
VkCommandBufferAllocateInfo cmd_allocate_info{};
cmd_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmd_allocate_info.commandPool = _command_pool;
cmd_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cmd_allocate_info.commandBufferCount = 1;
VkCommandBuffer cmd_buffer;
vkAllocateCommandBuffers(_device->get_handle(), &cmd_allocate_info, &cmd_buffer);
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(cmd_buffer, &begin_info);
cmdFunc(cmd_buffer);
vkEndCommandBuffer(cmd_buffer);
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &cmd_buffer;
vkQueueSubmit(_device->get_graphics_queue(), 1, &submit_info, VK_NULL_HANDLE);
vkQueueWaitIdle(_device->get_graphics_queue());
vkFreeCommandBuffers(_device->get_handle(), _command_pool, 1, &cmd_buffer);
}
}

View File

@ -2,8 +2,10 @@
// Created by Neo on 2/24/25.
//
#include <set>
#include <utility>
#include "dyn/platform/vulkan/vulkan.h"
#include "dyn/platform/vulkan/vulkan_context.h"
#include "dyn/platform/vulkan/vulkan_devices.h"
@ -20,6 +22,9 @@ namespace dyn::core {
vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
_physical_device = determine_suitable_device(devices, ctx->get_surface());
vkGetPhysicalDeviceProperties(_physical_device, &_device_properties);
_queue_families = queue_families::find(_physical_device, ctx->get_surface());
}
@ -113,4 +118,63 @@ namespace dyn::core {
ref<vulkan_physical_device> vulkan_physical_device::create(const ref<vulkan_context>& ctx) {
return create_ref<vulkan_physical_device>(ctx);
}
vulkan_device::vulkan_device(const ref<vulkan_physical_device> &physical_device, VkPhysicalDeviceFeatures device_Features) {
vulkan_physical_device::queue_families families = physical_device->get_queue_families();
std::set<uint32_t> queue_family_indices = {families.graphics_family.value(), families.present_family.value()};
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
float queue_priorities = 1.0f;
for (const auto &queue_family : queue_family_indices) {
VkDeviceQueueCreateInfo queue_create_info{};
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.queueFamilyIndex = queue_family;
queue_create_info.queueCount = 1;
queue_create_info.pQueuePriorities = &queue_priorities;
queue_create_infos.push_back(queue_create_info);
}
VkDeviceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.pEnabledFeatures = &device_Features;
auto device_extensions = std::vector(utils::vk_device_extensions);
uint32_t device_extension_count = 0;
vkEnumerateDeviceExtensionProperties(physical_device->get_handle(), 0, &device_extension_count, nullptr);
std::vector<VkExtensionProperties> device_property_exts(device_extension_count);
vkEnumerateDeviceExtensionProperties(physical_device->get_handle(), 0, &device_extension_count, device_property_exts.data());
for (const auto &extension : device_property_exts) {
if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) {
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
break;
}
}
for (const auto& extension : device_extensions) {
DYN_DEBUG_LOG("Device", std::string_view(physical_device->get_properties().deviceName), "has device extension:", std::string_view{extension});
}
create_info.enabledExtensionCount = static_cast<uint32_t>(device_extensions.size());
create_info.ppEnabledExtensionNames = device_extensions.data();
create_info.queueCreateInfoCount = static_cast<uint32_t>(queue_create_infos.size());
create_info.pQueueCreateInfos = queue_create_infos.data();
dyn_vk_verify(vkCreateDevice(physical_device->get_handle(), &create_info, nullptr, &_device));
vkGetDeviceQueue(_device, families.graphics_family.value(), 0, &_graphics_queue);
vkGetDeviceQueue(_device, families.present_family.value(), 0, &_present_queue);
}
vulkan_device::~vulkan_device() {
vkDestroyDevice(_device, nullptr);
}
ref<vulkan_device> vulkan_device::create(const std::shared_ptr<vulkan_physical_device> &device, const VkPhysicalDeviceFeatures& device_Features) {
return create_ref<vulkan_device>(device, device_Features);
}
}