Add basic surface handling to RenderDriver and WindowDriver
This will likely require significant rework but it will do for now. A considerations worth thinking about: - What happends when the WindowDriver destroys a window, what happens to the corresponding surface?
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "drivers/vulkan/render_driver.h"
|
||||
|
||||
#include <nova/core/debug.h>
|
||||
#include <nova/platform/window_driver.h>
|
||||
#include <nova/version.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
@@ -31,10 +32,10 @@ VulkanRenderDriver::VulkanRenderDriver(WindowDriver* window_driver) : m_window_d
|
||||
VulkanRenderDriver::~VulkanRenderDriver() {
|
||||
NOVA_AUTO_TRACE();
|
||||
if (m_device) {
|
||||
vkDestroyDevice(m_device, _get_allocator(VK_OBJECT_TYPE_DEVICE));
|
||||
vkDestroyDevice(m_device, get_allocator(VK_OBJECT_TYPE_DEVICE));
|
||||
}
|
||||
if (m_instance) {
|
||||
vkDestroyInstance(m_instance, _get_allocator(VK_OBJECT_TYPE_INSTANCE));
|
||||
vkDestroyInstance(m_instance, get_allocator(VK_OBJECT_TYPE_INSTANCE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +95,31 @@ void VulkanRenderDriver::select_device(u32 index) {
|
||||
_init_device(queues);
|
||||
}
|
||||
|
||||
SurfaceID VulkanRenderDriver::create_surface(const WindowID window) {
|
||||
NOVA_AUTO_TRACE();
|
||||
NOVA_ASSERT(m_instance);
|
||||
NOVA_ASSERT(m_window_driver);
|
||||
return m_window_driver->create_surface(window, this);
|
||||
}
|
||||
|
||||
void VulkanRenderDriver::destroy_surface(const SurfaceID surface) {
|
||||
NOVA_AUTO_TRACE();
|
||||
NOVA_ASSERT(m_instance);
|
||||
SurfaceData* data = reinterpret_cast<SurfaceData*>(surface);
|
||||
vkDestroySurfaceKHR(m_instance, data->handle, get_allocator(VK_OBJECT_TYPE_SURFACE_KHR));
|
||||
delete data;
|
||||
}
|
||||
|
||||
VkInstance VulkanRenderDriver::get_instance() const {
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
VkAllocationCallbacks* VulkanRenderDriver::get_allocator(const VkObjectType type) const {
|
||||
// TODO: Add custom allocator
|
||||
(void)type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VulkanRenderDriver::_check_version() const {
|
||||
NOVA_AUTO_TRACE();
|
||||
|
||||
@@ -206,7 +232,7 @@ void VulkanRenderDriver::_init_instance() {
|
||||
create.enabledExtensionCount = static_cast<u32>(m_extensions.size());
|
||||
create.ppEnabledExtensionNames = m_extensions.data();
|
||||
|
||||
if (vkCreateInstance(&create, _get_allocator(VK_OBJECT_TYPE_INSTANCE), &m_instance) != VK_SUCCESS) {
|
||||
if (vkCreateInstance(&create, get_allocator(VK_OBJECT_TYPE_INSTANCE), &m_instance) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create VkInstance");
|
||||
}
|
||||
|
||||
@@ -338,17 +364,11 @@ void VulkanRenderDriver::_init_device(const std::vector<VkDeviceQueueCreateInfo>
|
||||
create.pEnabledFeatures = &m_features;
|
||||
// TODO: pNext for additional features
|
||||
|
||||
if (vkCreateDevice(m_physical_device, &create, _get_allocator(VK_OBJECT_TYPE_DEVICE), &m_device) != VK_SUCCESS) {
|
||||
if (vkCreateDevice(m_physical_device, &create, get_allocator(VK_OBJECT_TYPE_DEVICE), &m_device) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create VkDevice");
|
||||
}
|
||||
|
||||
NOVA_LOG("VkDevice created");
|
||||
}
|
||||
|
||||
VkAllocationCallbacks* VulkanRenderDriver::_get_allocator(const VkObjectType type) {
|
||||
// TODO: Add custom allocator
|
||||
(void)type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // NOVA_VULKAN
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
#include <vector>
|
||||
|
||||
namespace Nova {
|
||||
struct SurfaceData {
|
||||
VkSurfaceKHR handle = VK_NULL_HANDLE;
|
||||
// TODO: Add stuff here
|
||||
};
|
||||
|
||||
class VulkanRenderDriver final : public RenderDriver {
|
||||
public:
|
||||
explicit VulkanRenderDriver(WindowDriver* window_driver);
|
||||
@@ -28,6 +33,12 @@ namespace Nova {
|
||||
[[nodiscard]] const RenderDevice& get_device(u32 index) const override;
|
||||
void select_device(u32 index) override;
|
||||
|
||||
[[nodiscard]] SurfaceID create_surface(WindowID window) override;
|
||||
void destroy_surface(SurfaceID surface) override;
|
||||
|
||||
[[nodiscard]] VkInstance get_instance() const;
|
||||
[[nodiscard]] VkAllocationCallbacks* get_allocator(VkObjectType type) const;
|
||||
|
||||
private:
|
||||
WindowDriver* m_window_driver = nullptr;
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
@@ -50,8 +61,6 @@ namespace Nova {
|
||||
void _check_device_features();
|
||||
void _init_queues(std::vector<VkDeviceQueueCreateInfo>& queues) const;
|
||||
void _init_device(const std::vector<VkDeviceQueueCreateInfo>& queues);
|
||||
|
||||
static VkAllocationCallbacks* _get_allocator(VkObjectType type);
|
||||
};
|
||||
} // namespace Nova
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "drivers/x11/window_driver.h"
|
||||
|
||||
#ifdef NOVA_VULKAN
|
||||
#include "drivers/vulkan/render_driver.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
#endif
|
||||
@@ -71,6 +73,10 @@ void X11WindowDriver::beep() {
|
||||
XBell(m_display, 100);
|
||||
}
|
||||
|
||||
u32 X11WindowDriver::get_window_count() const {
|
||||
return static_cast<u32>(m_windows.size());
|
||||
}
|
||||
|
||||
WindowID X11WindowDriver::create_window(const std::string_view title, const u32 width, const u32 height) {
|
||||
NOVA_AUTO_TRACE();
|
||||
|
||||
@@ -114,10 +120,6 @@ void X11WindowDriver::set_window_position(const WindowID window, const i32 x, co
|
||||
XMoveWindow(m_display, window, x, y);
|
||||
}
|
||||
|
||||
u32 X11WindowDriver::get_window_count() const {
|
||||
return static_cast<u32>(m_windows.size());
|
||||
}
|
||||
|
||||
const char* X11WindowDriver::get_surface_extension() const {
|
||||
#ifdef NOVA_VULKAN
|
||||
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
|
||||
@@ -126,4 +128,29 @@ const char* X11WindowDriver::get_surface_extension() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
SurfaceID X11WindowDriver::create_surface(const WindowID window, RenderDriver* render_driver) {
|
||||
NOVA_AUTO_TRACE();
|
||||
NOVA_ASSERT(m_windows.contains(window));
|
||||
NOVA_ASSERT(render_driver);
|
||||
NOVA_ASSERT(render_driver->get_api() == RenderAPI::VULKAN);
|
||||
|
||||
#ifdef NOVA_VULKAN
|
||||
VkXlibSurfaceCreateInfoKHR create {};
|
||||
create.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
create.dpy = m_display;
|
||||
create.window = static_cast<Window>(window);
|
||||
|
||||
const auto vkrd = static_cast<VulkanRenderDriver*>(render_driver);
|
||||
SurfaceData* surface = new SurfaceData();
|
||||
|
||||
if (vkCreateXlibSurfaceKHR(vkrd->get_instance(), &create, vkrd->get_allocator(VK_OBJECT_TYPE_SURFACE_KHR), &surface->handle)
|
||||
!= VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create Vulkan surface");
|
||||
}
|
||||
return reinterpret_cast<SurfaceID>(surface);
|
||||
#else
|
||||
return SurfaceID();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // NOVA_X11
|
||||
|
||||
@@ -26,16 +26,16 @@ namespace Nova {
|
||||
void poll_events() override;
|
||||
void beep() override;
|
||||
|
||||
WindowID create_window(std::string_view title, u32 width, u32 height) override;
|
||||
[[nodiscard]] u32 get_window_count() const override;
|
||||
[[nodiscard]] WindowID create_window(std::string_view title, u32 width, u32 height) override;
|
||||
void destroy_window(WindowID window) override;
|
||||
|
||||
void set_window_title(WindowID window, std::string_view title) override;
|
||||
void set_window_size(WindowID window, u32 width, u32 height) override;
|
||||
void set_window_position(WindowID window, i32 x, i32 y) override;
|
||||
|
||||
[[nodiscard]] u32 get_window_count() const override;
|
||||
|
||||
[[nodiscard]] const char* get_surface_extension() const override;
|
||||
[[nodiscard]] SurfaceID create_surface(WindowID window, RenderDriver* render_driver) override;
|
||||
|
||||
private:
|
||||
Display* m_display = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user