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:
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
namespace Nova {
|
namespace Nova {
|
||||||
using WindowID = uptr;
|
using WindowID = uptr;
|
||||||
|
using SurfaceID = uptr;
|
||||||
|
|
||||||
|
class RenderDriver;
|
||||||
|
|
||||||
class NOVA_API WindowDriver {
|
class NOVA_API WindowDriver {
|
||||||
public:
|
public:
|
||||||
@@ -22,15 +25,15 @@ namespace Nova {
|
|||||||
virtual void poll_events() = 0;
|
virtual void poll_events() = 0;
|
||||||
virtual void beep() = 0;
|
virtual void beep() = 0;
|
||||||
|
|
||||||
virtual WindowID create_window(std::string_view title, u32 width, u32 height) = 0;
|
[[nodiscard]] virtual u32 get_window_count() const = 0;
|
||||||
|
[[nodiscard]] virtual WindowID create_window(std::string_view title, u32 width, u32 height) = 0;
|
||||||
virtual void destroy_window(WindowID window) = 0;
|
virtual void destroy_window(WindowID window) = 0;
|
||||||
|
|
||||||
virtual void set_window_title(WindowID window, std::string_view title) = 0;
|
virtual void set_window_title(WindowID window, std::string_view title) = 0;
|
||||||
virtual void set_window_size(WindowID window, u32 width, u32 height) = 0;
|
virtual void set_window_size(WindowID window, u32 width, u32 height) = 0;
|
||||||
virtual void set_window_position(WindowID window, i32 x, i32 y) = 0;
|
virtual void set_window_position(WindowID window, i32 x, i32 y) = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual u32 get_window_count() const = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual const char* get_surface_extension() const = 0;
|
[[nodiscard]] virtual const char* get_surface_extension() const = 0;
|
||||||
|
[[nodiscard]] virtual SurfaceID create_surface(WindowID window, RenderDriver* render_driver) = 0;
|
||||||
};
|
};
|
||||||
} // namespace Nova
|
} // namespace Nova
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nova/api.h>
|
#include <nova/api.h>
|
||||||
#include <nova/platform/window_driver.h>
|
|
||||||
#include <nova/render/render_api.h>
|
#include <nova/render/render_api.h>
|
||||||
#include <nova/render/render_device.h>
|
#include <nova/render/render_device.h>
|
||||||
#include <nova/types.h>
|
#include <nova/types.h>
|
||||||
@@ -15,6 +14,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Nova {
|
namespace Nova {
|
||||||
|
using WindowID = uptr;
|
||||||
|
using SurfaceID = uptr;
|
||||||
|
|
||||||
|
class WindowDriver;
|
||||||
|
|
||||||
class NOVA_API RenderDriver {
|
class NOVA_API RenderDriver {
|
||||||
public:
|
public:
|
||||||
static RenderDriver* create(RenderAPI api, WindowDriver* window_driver = nullptr);
|
static RenderDriver* create(RenderAPI api, WindowDriver* window_driver = nullptr);
|
||||||
@@ -28,5 +32,14 @@ namespace Nova {
|
|||||||
[[nodiscard]] virtual u32 get_device_count() const = 0;
|
[[nodiscard]] virtual u32 get_device_count() const = 0;
|
||||||
[[nodiscard]] virtual const RenderDevice& get_device(u32 index) const = 0;
|
[[nodiscard]] virtual const RenderDevice& get_device(u32 index) const = 0;
|
||||||
virtual void select_device(u32 index) = 0;
|
virtual void select_device(u32 index) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual SurfaceID create_surface(WindowID window) = 0;
|
||||||
|
virtual void destroy_surface(SurfaceID surface) = 0;
|
||||||
|
// TODO: get_surface_size
|
||||||
|
// TODO: get_surface_mode
|
||||||
|
// TODO: get_surface_state
|
||||||
|
// TODO: set_surface_size
|
||||||
|
// TODO: set_surface_mode
|
||||||
|
// TODO: set_surface_state
|
||||||
};
|
};
|
||||||
} // namespace Nova
|
} // namespace Nova
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "drivers/vulkan/render_driver.h"
|
#include "drivers/vulkan/render_driver.h"
|
||||||
|
|
||||||
#include <nova/core/debug.h>
|
#include <nova/core/debug.h>
|
||||||
|
#include <nova/platform/window_driver.h>
|
||||||
#include <nova/version.h>
|
#include <nova/version.h>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
@@ -31,10 +32,10 @@ VulkanRenderDriver::VulkanRenderDriver(WindowDriver* window_driver) : m_window_d
|
|||||||
VulkanRenderDriver::~VulkanRenderDriver() {
|
VulkanRenderDriver::~VulkanRenderDriver() {
|
||||||
NOVA_AUTO_TRACE();
|
NOVA_AUTO_TRACE();
|
||||||
if (m_device) {
|
if (m_device) {
|
||||||
vkDestroyDevice(m_device, _get_allocator(VK_OBJECT_TYPE_DEVICE));
|
vkDestroyDevice(m_device, get_allocator(VK_OBJECT_TYPE_DEVICE));
|
||||||
}
|
}
|
||||||
if (m_instance) {
|
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);
|
_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 {
|
void VulkanRenderDriver::_check_version() const {
|
||||||
NOVA_AUTO_TRACE();
|
NOVA_AUTO_TRACE();
|
||||||
|
|
||||||
@@ -206,7 +232,7 @@ void VulkanRenderDriver::_init_instance() {
|
|||||||
create.enabledExtensionCount = static_cast<u32>(m_extensions.size());
|
create.enabledExtensionCount = static_cast<u32>(m_extensions.size());
|
||||||
create.ppEnabledExtensionNames = m_extensions.data();
|
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");
|
throw std::runtime_error("Failed to create VkInstance");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,17 +364,11 @@ void VulkanRenderDriver::_init_device(const std::vector<VkDeviceQueueCreateInfo>
|
|||||||
create.pEnabledFeatures = &m_features;
|
create.pEnabledFeatures = &m_features;
|
||||||
// TODO: pNext for additional 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");
|
throw std::runtime_error("Failed to create VkDevice");
|
||||||
}
|
}
|
||||||
|
|
||||||
NOVA_LOG("VkDevice created");
|
NOVA_LOG("VkDevice created");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkAllocationCallbacks* VulkanRenderDriver::_get_allocator(const VkObjectType type) {
|
|
||||||
// TODO: Add custom allocator
|
|
||||||
(void)type;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NOVA_VULKAN
|
#endif // NOVA_VULKAN
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nova {
|
namespace Nova {
|
||||||
|
struct SurfaceData {
|
||||||
|
VkSurfaceKHR handle = VK_NULL_HANDLE;
|
||||||
|
// TODO: Add stuff here
|
||||||
|
};
|
||||||
|
|
||||||
class VulkanRenderDriver final : public RenderDriver {
|
class VulkanRenderDriver final : public RenderDriver {
|
||||||
public:
|
public:
|
||||||
explicit VulkanRenderDriver(WindowDriver* window_driver);
|
explicit VulkanRenderDriver(WindowDriver* window_driver);
|
||||||
@@ -28,6 +33,12 @@ namespace Nova {
|
|||||||
[[nodiscard]] const RenderDevice& get_device(u32 index) const override;
|
[[nodiscard]] const RenderDevice& get_device(u32 index) const override;
|
||||||
void select_device(u32 index) 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:
|
private:
|
||||||
WindowDriver* m_window_driver = nullptr;
|
WindowDriver* m_window_driver = nullptr;
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
@@ -50,8 +61,6 @@ namespace Nova {
|
|||||||
void _check_device_features();
|
void _check_device_features();
|
||||||
void _init_queues(std::vector<VkDeviceQueueCreateInfo>& queues) const;
|
void _init_queues(std::vector<VkDeviceQueueCreateInfo>& queues) const;
|
||||||
void _init_device(const std::vector<VkDeviceQueueCreateInfo>& queues);
|
void _init_device(const std::vector<VkDeviceQueueCreateInfo>& queues);
|
||||||
|
|
||||||
static VkAllocationCallbacks* _get_allocator(VkObjectType type);
|
|
||||||
};
|
};
|
||||||
} // namespace Nova
|
} // namespace Nova
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "drivers/x11/window_driver.h"
|
#include "drivers/x11/window_driver.h"
|
||||||
|
|
||||||
#ifdef NOVA_VULKAN
|
#ifdef NOVA_VULKAN
|
||||||
|
#include "drivers/vulkan/render_driver.h"
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <vulkan/vulkan_xlib.h>
|
#include <vulkan/vulkan_xlib.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -71,6 +73,10 @@ void X11WindowDriver::beep() {
|
|||||||
XBell(m_display, 100);
|
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) {
|
WindowID X11WindowDriver::create_window(const std::string_view title, const u32 width, const u32 height) {
|
||||||
NOVA_AUTO_TRACE();
|
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);
|
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 {
|
const char* X11WindowDriver::get_surface_extension() const {
|
||||||
#ifdef NOVA_VULKAN
|
#ifdef NOVA_VULKAN
|
||||||
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
|
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
|
||||||
@@ -126,4 +128,29 @@ const char* X11WindowDriver::get_surface_extension() const {
|
|||||||
#endif
|
#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
|
#endif // NOVA_X11
|
||||||
|
|||||||
@@ -26,16 +26,16 @@ namespace Nova {
|
|||||||
void poll_events() override;
|
void poll_events() override;
|
||||||
void beep() 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 destroy_window(WindowID window) override;
|
||||||
|
|
||||||
void set_window_title(WindowID window, std::string_view title) 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_size(WindowID window, u32 width, u32 height) override;
|
||||||
void set_window_position(WindowID window, i32 x, i32 y) 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]] const char* get_surface_extension() const override;
|
||||||
|
[[nodiscard]] SurfaceID create_surface(WindowID window, RenderDriver* render_driver) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Display* m_display = nullptr;
|
Display* m_display = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user