feat(renderer): contextn, test utils, refactors & changes
This commit is contained in:
parent
405c707e23
commit
5148b8836c
23 changed files with 836 additions and 155 deletions
|
@ -1,5 +1,6 @@
|
|||
add_library_module(renderer
|
||||
system.cpp
|
||||
vk/debug/messenger.cpp
|
||||
vk/context/instance.cpp
|
||||
vk/context/surface.cpp
|
||||
vk/context/device.cpp
|
||||
|
@ -12,6 +13,7 @@ target_link_libraries(renderer
|
|||
PUBLIC
|
||||
app
|
||||
ecs
|
||||
memory
|
||||
PRIVATE
|
||||
surface
|
||||
pthread
|
||||
|
@ -19,6 +21,8 @@ PRIVATE
|
|||
|
||||
add_test_module(renderer
|
||||
system.test.cpp
|
||||
vk/test_utils.cpp
|
||||
vk/debug/messenger.test.cpp
|
||||
vk/context/instance.test.cpp
|
||||
vk/context/surface.test.cpp
|
||||
vk/context/device.test.cpp
|
||||
|
@ -26,3 +30,8 @@ add_test_module(renderer
|
|||
vk/context/context.test.cpp
|
||||
vk/pipeline.test.cpp
|
||||
)
|
||||
target_link_libraries(renderer_tests
|
||||
PRIVATE
|
||||
surface
|
||||
pthread
|
||||
)
|
||||
|
|
|
@ -108,7 +108,7 @@ private:
|
|||
);
|
||||
};
|
||||
|
||||
Suite raii = [] {
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [&] {
|
||||
ignore = create_system();
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <ranges>
|
||||
#include <renderer/vk/context/context.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
|
||||
|
|
0
modules/renderer/private/vk/context/context.test.cpp
Normal file
0
modules/renderer/private/vk/context/context.test.cpp
Normal file
|
@ -1,9 +1,14 @@
|
|||
#include <renderer/vk/context/device.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/debug/validation.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
Device::Device(const Surface &surface)
|
||||
{
|
||||
ensure(surface.vk(), "Failed to initialize vk::Device: null vulkan surface");
|
||||
|
||||
initialize_physical_device();
|
||||
initialize_logical_device();
|
||||
Instance::load_device_functions(m_device);
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory/pointer_types/null_on_move.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(const Surface &surface);
|
||||
Device(const class Surface &surface);
|
||||
|
||||
~Device();
|
||||
|
||||
|
@ -41,7 +40,7 @@ private:
|
|||
|
||||
void initialize_logical_device();
|
||||
|
||||
void initialize_queue(const Surface &surface);
|
||||
void initialize_queue(const class Surface &surface);
|
||||
|
||||
[[nodiscard]] auto find_suitable_queue_family() const -> uint32_t;
|
||||
|
||||
|
|
99
modules/renderer/private/vk/context/device.test.cpp
Normal file
99
modules/renderer/private/vk/context/device.test.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <ranges>
|
||||
#include <renderer/vk/context/device.hpp>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <surface/components.hpp>
|
||||
#include <surface/system.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using namespace lt;
|
||||
using renderer::vk::Device;
|
||||
using renderer::vk::Surface;
|
||||
using test::Case;
|
||||
using test::expect_ne;
|
||||
using test::expect_throw;
|
||||
using test::Suite;
|
||||
|
||||
constexpr auto resolution = math::uvec2 { 800u, 600u };
|
||||
|
||||
Suite raii = "device_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto registry = create_ref<ecs::Registry>();
|
||||
auto surface_system = surface::System { registry };
|
||||
auto entity = ecs::Entity { registry, registry->create_entity() };
|
||||
entity.add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.resolution = resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
auto surface = Surface { entity };
|
||||
auto device = Device { surface };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [] {
|
||||
auto registry = create_ref<ecs::Registry>();
|
||||
auto surface_system = surface::System { registry };
|
||||
auto entity = ecs::Entity { registry, registry->create_entity() };
|
||||
entity.add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.resolution = resolution,
|
||||
.visible = true,
|
||||
});
|
||||
auto surface = Surface { entity };
|
||||
|
||||
// it takes a loong time to initialize vulkan + setup device
|
||||
for (auto idx : std::views::iota(0, 10))
|
||||
{
|
||||
Device { surface };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
auto registry = create_ref<ecs::Registry>();
|
||||
auto surface_system = surface::System { registry };
|
||||
auto entity = ecs::Entity { registry, registry->create_entity() };
|
||||
entity.add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.resolution = resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
auto moved_out_surface = Surface { entity };
|
||||
auto surface = std::move(moved_out_surface);
|
||||
|
||||
expect_throw([&] { Device { moved_out_surface }; });
|
||||
};
|
||||
|
||||
Case { "post construct has correct state" } = [] {
|
||||
auto registry = create_ref<ecs::Registry>();
|
||||
auto surface_system = surface::System { registry };
|
||||
auto entity = ecs::Entity { registry, registry->create_entity() };
|
||||
entity.add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.resolution = resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
auto surface = Surface { entity };
|
||||
auto device = Device { surface };
|
||||
|
||||
for (auto &index : device.get_family_indices())
|
||||
{
|
||||
expect_ne(index, VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
test::expect_true(device.physical());
|
||||
test::expect_true(device.vk());
|
||||
};
|
||||
|
||||
Case { "post destruct has correct state" } = [] {
|
||||
auto registry = create_ref<ecs::Registry>();
|
||||
auto surface_system = surface::System { registry };
|
||||
auto entity = ecs::Entity { registry, registry->create_entity() };
|
||||
entity.add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.resolution = resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
auto surface = Surface { entity };
|
||||
|
||||
{
|
||||
auto device = Device { surface };
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,5 +1,6 @@
|
|||
#include <app/system.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/debug/validation.hpp>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#error "Unsupported platform (currently)"
|
||||
|
@ -113,17 +114,11 @@ Instance::Instance()
|
|||
|
||||
initialize_instance();
|
||||
load_instance_functions();
|
||||
initialize_debug_messenger();
|
||||
}
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
if (m_instance)
|
||||
{
|
||||
vk_destroy_debug_messenger(m_instance, m_debug_messenger, nullptr);
|
||||
vk_destroy_instance(m_instance, nullptr);
|
||||
}
|
||||
|
||||
vk_destroy_instance(m_instance, nullptr);
|
||||
unload_library();
|
||||
}
|
||||
|
||||
|
@ -143,12 +138,83 @@ void Instance::initialize_instance()
|
|||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
const char *layer_name = "VK_LAYER_KHRONOS_validation";
|
||||
const auto setting_validate_core = VkBool32 { VK_TRUE };
|
||||
const auto setting_validate_sync = VkBool32 { VK_TRUE };
|
||||
const auto setting_thread_safety = VkBool32 { VK_TRUE };
|
||||
const auto *setting_debug_action = "";
|
||||
const auto setting_enable_message_limit = VkBool32 { VK_TRUE };
|
||||
const auto setting_duplicate_message_limit = uint32_t { 3u };
|
||||
auto setting_report_flags = std::array<const char *, 5> {
|
||||
"info", "warn", "perf", "error", "verbose",
|
||||
};
|
||||
|
||||
const auto settings = std::array<VkLayerSettingEXT, 7>({
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "validate_core",
|
||||
.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT,
|
||||
.valueCount = 1,
|
||||
.pValues = &setting_validate_core,
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "validate_sync",
|
||||
.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT,
|
||||
.valueCount = 1,
|
||||
.pValues = &setting_validate_sync,
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "thread_safety",
|
||||
.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT,
|
||||
.valueCount = 1,
|
||||
.pValues = &setting_thread_safety,
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "debug_action",
|
||||
.type = VK_LAYER_SETTING_TYPE_STRING_EXT,
|
||||
.valueCount = 1,
|
||||
.pValues = static_cast<const void *>(&setting_debug_action),
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "report_flags",
|
||||
.type = VK_LAYER_SETTING_TYPE_STRING_EXT,
|
||||
.valueCount = setting_report_flags.size(),
|
||||
.pValues = static_cast<const void *>(setting_report_flags.data()),
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "enable_message_limit",
|
||||
.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT,
|
||||
.valueCount = 1,
|
||||
.pValues = &setting_enable_message_limit,
|
||||
},
|
||||
{
|
||||
.pLayerName = layer_name,
|
||||
.pSettingName = "duplicate_message_limit",
|
||||
.type = VK_LAYER_SETTING_TYPE_UINT32_EXT,
|
||||
.valueCount = 1u,
|
||||
.pValues = &setting_duplicate_message_limit,
|
||||
},
|
||||
});
|
||||
|
||||
const VkLayerSettingsCreateInfoEXT layer_settings_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT,
|
||||
.settingCount = settings.size(),
|
||||
.pSettings = settings.data()
|
||||
};
|
||||
|
||||
auto layers = std::vector<const char *> {
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
};
|
||||
|
||||
auto instance_info = VkInstanceCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = &layer_settings_create_info,
|
||||
.pApplicationInfo = &app_info,
|
||||
.enabledLayerCount = static_cast<uint32_t>(layers.size()),
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
|
@ -174,32 +240,6 @@ void Instance::initialize_instance()
|
|||
ensure(m_instance, "Failed to create vulkan instance");
|
||||
}
|
||||
|
||||
void Instance::initialize_debug_messenger()
|
||||
{
|
||||
const auto info = VkDebugUtilsMessengerCreateInfoEXT {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
|
||||
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||
|
||||
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
|
||||
|
||||
|
||||
.pfnUserCallback = &validation_layers_callback,
|
||||
|
||||
.pUserData = {},
|
||||
};
|
||||
|
||||
ensure(
|
||||
!vk_create_debug_messenger(m_instance, &info, nullptr, &m_debug_messenger),
|
||||
"Failed to create vulkan debug utils messenger"
|
||||
);
|
||||
}
|
||||
|
||||
void Instance::load_library()
|
||||
{
|
||||
library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
|
||||
|
|
|
@ -1,103 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
#include <renderer/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
inline void vkc(VkResult result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
throw std::runtime_error {
|
||||
std::format("Vulkan call failed with result: {}", std::to_underlying(result))
|
||||
};
|
||||
}
|
||||
}
|
||||
// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
// global functions
|
||||
extern PFN_vkGetInstanceProcAddr vk_get_instance_proc_address;
|
||||
extern PFN_vkCreateInstance vk_create_instance;
|
||||
extern PFN_vkEnumerateInstanceExtensionProperties vk_enumerate_instance_extension_properties;
|
||||
extern PFN_vkEnumerateInstanceLayerProperties vk_enumerate_instance_layer_properties;
|
||||
|
||||
// instance functions
|
||||
extern PFN_vkDestroyInstance vk_destroy_instance;
|
||||
extern PFN_vkEnumeratePhysicalDevices vk_enumerate_physical_devices;
|
||||
extern PFN_vkGetPhysicalDeviceProperties vk_get_physical_device_properties;
|
||||
extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue_family_properties;
|
||||
extern PFN_vkCreateDevice vk_create_device;
|
||||
extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address;
|
||||
extern PFN_vkDestroyDevice vk_destroy_device;
|
||||
extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features;
|
||||
extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties;
|
||||
|
||||
// extension instance functions
|
||||
extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label;
|
||||
extern PFN_vkCmdEndDebugUtilsLabelEXT vk_cmd_end_debug_label;
|
||||
extern PFN_vkCmdInsertDebugUtilsLabelEXT vk_cmd_insert_debug_label;
|
||||
extern PFN_vkCreateDebugUtilsMessengerEXT vk_create_debug_messenger;
|
||||
extern PFN_vkDestroyDebugUtilsMessengerEXT vk_destroy_debug_messenger;
|
||||
extern PFN_vkQueueBeginDebugUtilsLabelEXT vk_queue_begin_debug_label;
|
||||
extern PFN_vkQueueEndDebugUtilsLabelEXT vk_queue_end_debug_label;
|
||||
extern PFN_vkQueueInsertDebugUtilsLabelEXT vk_queue_insert_debug_label;
|
||||
extern PFN_vkSetDebugUtilsObjectNameEXT vk_set_debug_object_name;
|
||||
extern PFN_vkSetDebugUtilsObjectTagEXT vk_set_debug_object_tag;
|
||||
extern PFN_vkSubmitDebugUtilsMessageEXT vk_submit_debug_message;
|
||||
|
||||
// surface instance functions
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support;
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities;
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats;
|
||||
extern PFN_vkCreateXlibSurfaceKHR vk_create_xlib_surface_khr;
|
||||
extern PFN_vkDestroySurfaceKHR vk_destroy_surface_khr;
|
||||
|
||||
// device functions
|
||||
extern PFN_vkGetDeviceQueue vk_get_device_queue;
|
||||
extern PFN_vkCreateCommandPool vk_create_command_pool;
|
||||
extern PFN_vkDestroyCommandPool vk_destroy_command_pool;
|
||||
extern PFN_vkAllocateCommandBuffers vk_allocate_command_buffers;
|
||||
extern PFN_vkFreeCommandBuffers vk_free_command_buffers;
|
||||
extern PFN_vkBeginCommandBuffer vk_begin_command_buffer;
|
||||
extern PFN_vkEndCommandBuffer vk_end_command_buffer;
|
||||
extern PFN_vkCmdPipelineBarrier vk_cmd_pipeline_barrier;
|
||||
extern PFN_vkQueueSubmit vk_queue_submit;
|
||||
extern PFN_vkQueueWaitIdle vk_queue_wait_idle;
|
||||
extern PFN_vkDeviceWaitIdle vk_device_wait_idle;
|
||||
extern PFN_vkCreateFence vk_create_fence;
|
||||
extern PFN_vkDestroyFence vk_destroy_fence;
|
||||
extern PFN_vkWaitForFences vk_wait_for_fences;
|
||||
extern PFN_vkResetFences vk_reset_fences;
|
||||
extern PFN_vkCreateSemaphore vk_create_semaphore;
|
||||
extern PFN_vkDestroySemaphore vk_destroy_semaphore;
|
||||
extern PFN_vkCreateSwapchainKHR vk_create_swapchain_khr;
|
||||
extern PFN_vkDestroySwapchainKHR vk_destroy_swapchain_khr;
|
||||
extern PFN_vkGetSwapchainImagesKHR vk_get_swapchain_images_khr;
|
||||
extern PFN_vkAcquireNextImageKHR vk_acquire_next_image_khr;
|
||||
extern PFN_vkQueuePresentKHR vk_queue_present_khr;
|
||||
extern PFN_vkCreateImageView vk_create_image_view;
|
||||
extern PFN_vkDestroyImageView vk_destroy_image_view;
|
||||
extern PFN_vkCreateRenderPass vk_create_render_pass;
|
||||
extern PFN_vkDestroyRenderPass vk_destroy_render_pass;
|
||||
extern PFN_vkCreateFramebuffer vk_create_frame_buffer;
|
||||
extern PFN_vkDestroyFramebuffer vk_destroy_frame_buffer;
|
||||
extern PFN_vkCreateShaderModule vk_create_shader_module;
|
||||
extern PFN_vkDestroyShaderModule vk_destroy_shader_module;
|
||||
extern PFN_vkCreatePipelineLayout vk_create_pipeline_layout;
|
||||
extern PFN_vkDestroyPipelineLayout vk_destroy_pipeline_layout;
|
||||
extern PFN_vkCreateGraphicsPipelines vk_create_graphics_pipelines;
|
||||
extern PFN_vkDestroyPipeline vk_destroy_pipeline;
|
||||
extern PFN_vkCmdBeginRenderPass vk_cmd_begin_render_pass;
|
||||
extern PFN_vkCmdEndRenderPass vk_cmd_end_render_pass;
|
||||
extern PFN_vkCmdBindPipeline vk_cmd_bind_pipeline;
|
||||
extern PFN_vkCmdDraw vk_cmd_draw;
|
||||
extern PFN_vkCmdSetViewport vk_cmd_set_viewport;
|
||||
extern PFN_vkCmdSetScissor vk_cmd_set_scissors;
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
/**
|
||||
* Responsible for dynamically loading Vulkan library/functions.
|
||||
*
|
||||
|
@ -141,8 +47,6 @@ private:
|
|||
|
||||
void initialize_instance();
|
||||
|
||||
void initialize_debug_messenger();
|
||||
|
||||
void load_library();
|
||||
|
||||
void unload_library();
|
||||
|
@ -154,8 +58,6 @@ private:
|
|||
void load_device_functions_impl(VkDevice device);
|
||||
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
|
||||
VkDebugUtilsMessengerEXT m_debug_messenger = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
95
modules/renderer/private/vk/context/instance.test.cpp
Normal file
95
modules/renderer/private/vk/context/instance.test.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using namespace lt;
|
||||
using renderer::vk::Instance;
|
||||
using test::Case;
|
||||
using test::expect_not_nullptr;
|
||||
using test::Suite;
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "post singleton insantiation state is correct" } = [] {
|
||||
expect_not_nullptr(Instance::get());
|
||||
|
||||
using namespace renderer::vk;
|
||||
expect_not_nullptr(vk_get_instance_proc_address);
|
||||
expect_not_nullptr(vk_create_instance);
|
||||
expect_not_nullptr(vk_enumerate_instance_extension_properties);
|
||||
expect_not_nullptr(vk_enumerate_instance_layer_properties);
|
||||
|
||||
expect_not_nullptr(vk_destroy_instance);
|
||||
expect_not_nullptr(vk_enumerate_physical_devices);
|
||||
expect_not_nullptr(vk_get_physical_device_properties);
|
||||
expect_not_nullptr(vk_get_physical_device_queue_family_properties);
|
||||
expect_not_nullptr(vk_create_device);
|
||||
expect_not_nullptr(vk_get_device_proc_address);
|
||||
expect_not_nullptr(vk_destroy_device);
|
||||
expect_not_nullptr(vk_get_physical_device_features);
|
||||
expect_not_nullptr(vk_enumerate_device_extension_properties);
|
||||
|
||||
expect_not_nullptr(vk_cmd_begin_debug_label);
|
||||
expect_not_nullptr(vk_cmd_end_debug_label);
|
||||
expect_not_nullptr(vk_cmd_insert_debug_label);
|
||||
expect_not_nullptr(vk_create_debug_messenger);
|
||||
expect_not_nullptr(vk_destroy_debug_messenger);
|
||||
expect_not_nullptr(vk_queue_begin_debug_label);
|
||||
expect_not_nullptr(vk_queue_end_debug_label);
|
||||
expect_not_nullptr(vk_queue_insert_debug_label);
|
||||
expect_not_nullptr(vk_set_debug_object_name);
|
||||
expect_not_nullptr(vk_set_debug_object_tag);
|
||||
expect_not_nullptr(vk_submit_debug_message);
|
||||
|
||||
expect_not_nullptr(vk_get_physical_device_surface_support);
|
||||
expect_not_nullptr(vk_get_physical_device_surface_capabilities);
|
||||
expect_not_nullptr(vk_get_physical_device_surface_formats);
|
||||
expect_not_nullptr(vk_create_xlib_surface_khr);
|
||||
expect_not_nullptr(vk_destroy_surface_khr);
|
||||
};
|
||||
|
||||
Case { "post load device functions state is correct" } = [] {
|
||||
using namespace renderer::vk;
|
||||
expect_not_nullptr(Instance::get());
|
||||
|
||||
expect_not_nullptr(vk_get_device_queue);
|
||||
expect_not_nullptr(vk_create_command_pool);
|
||||
expect_not_nullptr(vk_destroy_command_pool);
|
||||
expect_not_nullptr(vk_allocate_command_buffers);
|
||||
expect_not_nullptr(vk_free_command_buffers);
|
||||
expect_not_nullptr(vk_begin_command_buffer);
|
||||
expect_not_nullptr(vk_end_command_buffer);
|
||||
expect_not_nullptr(vk_cmd_pipeline_barrier);
|
||||
expect_not_nullptr(vk_queue_submit);
|
||||
expect_not_nullptr(vk_queue_wait_idle);
|
||||
expect_not_nullptr(vk_device_wait_idle);
|
||||
expect_not_nullptr(vk_create_fence);
|
||||
expect_not_nullptr(vk_destroy_fence);
|
||||
expect_not_nullptr(vk_wait_for_fences);
|
||||
expect_not_nullptr(vk_reset_fences);
|
||||
expect_not_nullptr(vk_create_semaphore);
|
||||
expect_not_nullptr(vk_destroy_semaphore);
|
||||
expect_not_nullptr(vk_create_swapchain_khr);
|
||||
expect_not_nullptr(vk_destroy_swapchain_khr);
|
||||
expect_not_nullptr(vk_get_swapchain_images_khr);
|
||||
expect_not_nullptr(vk_acquire_next_image_khr);
|
||||
expect_not_nullptr(vk_queue_present_khr);
|
||||
expect_not_nullptr(vk_create_image_view);
|
||||
expect_not_nullptr(vk_destroy_image_view);
|
||||
expect_not_nullptr(vk_create_render_pass);
|
||||
expect_not_nullptr(vk_destroy_render_pass);
|
||||
expect_not_nullptr(vk_create_frame_buffer);
|
||||
expect_not_nullptr(vk_destroy_frame_buffer);
|
||||
expect_not_nullptr(vk_create_shader_module);
|
||||
expect_not_nullptr(vk_destroy_shader_module);
|
||||
expect_not_nullptr(vk_create_pipeline_layout);
|
||||
expect_not_nullptr(vk_destroy_pipeline_layout);
|
||||
expect_not_nullptr(vk_create_graphics_pipelines);
|
||||
expect_not_nullptr(vk_destroy_pipeline);
|
||||
expect_not_nullptr(vk_cmd_begin_render_pass);
|
||||
expect_not_nullptr(vk_cmd_end_render_pass);
|
||||
expect_not_nullptr(vk_cmd_bind_pipeline);
|
||||
expect_not_nullptr(vk_cmd_draw);
|
||||
expect_not_nullptr(vk_cmd_set_viewport);
|
||||
expect_not_nullptr(vk_cmd_set_scissors);
|
||||
};
|
||||
};
|
|
@ -1,4 +1,3 @@
|
|||
#include <lt_debug/assertions.hpp>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <surface/components.hpp>
|
||||
|
||||
|
@ -8,8 +7,8 @@ Surface::Surface(const ecs::Entity &surface_entity)
|
|||
{
|
||||
const auto &component = surface_entity.get<surface::SurfaceComponent>();
|
||||
|
||||
esnure(component.get_native_data().display, "Failed to initialize usrface: null x-display");
|
||||
esnure(component.get_native_data().window, "Failed to initialize usrface: null x-window");
|
||||
ensure(component.get_native_data().display, "Failed to initialize vk::Surface: null x-display");
|
||||
ensure(component.get_native_data().window, "Failed to initialize vk::Surface: null x-window");
|
||||
|
||||
auto create_info = VkXlibSurfaceCreateInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||
|
|
51
modules/renderer/private/vk/context/surface.test.cpp
Normal file
51
modules/renderer/private/vk/context/surface.test.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/debug/messenger.hpp>
|
||||
#include <renderer/vk/test_utils.hpp>
|
||||
#include <surface/components.hpp>
|
||||
#include <surface/system.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using ::lt::ecs::Entity;
|
||||
using ::lt::ecs::Registry;
|
||||
using ::lt::renderer::vk::Surface;
|
||||
using ::lt::surface::SurfaceComponent;
|
||||
using ::lt::surface::System;
|
||||
|
||||
Suite raii = "surface"_suite = [] {
|
||||
Case { "happy path won't throw" } = [&] {
|
||||
auto observer = ValidationObserver {};
|
||||
|
||||
auto registry = lt::create_ref<Registry>();
|
||||
auto entity = Entity { registry, registry->create_entity() };
|
||||
auto surface_system = System(registry);
|
||||
|
||||
entity.add<SurfaceComponent>(SurfaceComponent::CreateInfo {
|
||||
.title = "",
|
||||
.resolution = constants::resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
const auto surface = Surface { entity };
|
||||
const auto &[x, y] = surface.get_framebuffer_size();
|
||||
|
||||
expect_eq(x, constants::resolution.x);
|
||||
expect_eq(y, constants::resolution.y);
|
||||
expect_not_nullptr(surface.vk());
|
||||
expect_false(observer.had_any_messages());
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [&] {
|
||||
auto observer = ValidationObserver {};
|
||||
auto registry = lt::create_ref<Registry>();
|
||||
auto entity = Entity { registry, registry->create_entity() };
|
||||
|
||||
entity.add<SurfaceComponent>(SurfaceComponent::CreateInfo {
|
||||
.title = "",
|
||||
.resolution = constants::resolution,
|
||||
.visible = true,
|
||||
});
|
||||
|
||||
expect_throw([&] { Surface { entity }; });
|
||||
expect_false(observer.had_any_messages());
|
||||
};
|
||||
};
|
|
@ -1,5 +1,9 @@
|
|||
#include <ranges>
|
||||
#include <renderer/vk/context/device.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/context/swapchain.hpp>
|
||||
#include <renderer/vk/debug/validation.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory/pointer_types/null_on_move.hpp>
|
||||
#include <renderer/vk/context/device.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
class Swapchain
|
||||
{
|
||||
public:
|
||||
Swapchain(const Device &device, const Surface &surface);
|
||||
Swapchain(const class Device &device, const class Surface &surface);
|
||||
|
||||
~Swapchain();
|
||||
|
||||
|
|
0
modules/renderer/private/vk/context/swapchain.test.cpp
Normal file
0
modules/renderer/private/vk/context/swapchain.test.cpp
Normal file
0
modules/renderer/private/vk/debug/messenger.cpp
Normal file
0
modules/renderer/private/vk/debug/messenger.cpp
Normal file
143
modules/renderer/private/vk/debug/messenger.hpp
Normal file
143
modules/renderer/private/vk/debug/messenger.hpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory/pointer_types/null_on_move.hpp>
|
||||
#include <renderer/vk/context/instance.hpp>
|
||||
#include <renderer/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
class Messenger
|
||||
{
|
||||
public:
|
||||
// NOLINTNEXTLINE(performance-enum-size)
|
||||
enum Severity : decltype(std::to_underlying(
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT
|
||||
))
|
||||
{
|
||||
verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
|
||||
info = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
|
||||
warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
|
||||
error = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||
|
||||
all_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(performance-enum-size)
|
||||
enum Type : decltype(std::to_underlying(VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT))
|
||||
{
|
||||
general = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
|
||||
validation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
|
||||
performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
|
||||
|
||||
// address_binding = VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT,
|
||||
|
||||
/** @note: does not include address binding yet. */
|
||||
all_type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
|
||||
};
|
||||
|
||||
using CallbackData_T = const VkDebugUtilsMessengerCallbackDataEXT *;
|
||||
|
||||
using Callback_T = std::function<void(
|
||||
Severity message_severity,
|
||||
Type message_type,
|
||||
CallbackData_T vulkan_data,
|
||||
void *user_data
|
||||
)>;
|
||||
|
||||
struct CreateInfo
|
||||
{
|
||||
Severity severity;
|
||||
|
||||
Type type;
|
||||
|
||||
Callback_T callback;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
explicit Messenger(CreateInfo info)
|
||||
: m_callback(std::move(info.callback))
|
||||
, m_user_data(info.user_data)
|
||||
{
|
||||
ensure(m_callback, "Failed to initialize vk::Messenger: null callback");
|
||||
ensure(info.severity != Severity {}, "Failed to initialize vk::Messenger: null severity");
|
||||
ensure(info.type != Type {}, "Failed to initialize vk::Messenger: null type");
|
||||
|
||||
// Instance may not be initialized yet
|
||||
// Making it get initialized inside a call to vk_create_debug_messenger
|
||||
// Which would invoke a nullptr...
|
||||
if (!vk_create_debug_messenger)
|
||||
{
|
||||
Instance::get();
|
||||
}
|
||||
|
||||
const auto vulkan_info = VkDebugUtilsMessengerCreateInfoEXT {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
.messageSeverity = info.severity,
|
||||
.messageType = info.type,
|
||||
.pfnUserCallback = &validation_layers_callback,
|
||||
.pUserData = this,
|
||||
};
|
||||
|
||||
ensure(
|
||||
!vk_create_debug_messenger(Instance::get(), &vulkan_info, nullptr, &m_debug_messenger),
|
||||
"Failed to create vulkan debug utils messenger"
|
||||
);
|
||||
}
|
||||
|
||||
~Messenger()
|
||||
{
|
||||
vk_destroy_debug_messenger(Instance::get(), m_debug_messenger, nullptr);
|
||||
}
|
||||
|
||||
Messenger(Messenger &&) = default;
|
||||
|
||||
Messenger(const Messenger &) = delete;
|
||||
|
||||
auto operator=(Messenger &&) -> Messenger & = default;
|
||||
|
||||
auto operator=(const Messenger &) const -> Messenger & = delete;
|
||||
|
||||
|
||||
private:
|
||||
static auto validation_layers_callback(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT const message_severity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT const message_type,
|
||||
VkDebugUtilsMessengerCallbackDataEXT const *const callback_data,
|
||||
void *const vulkan_user_data
|
||||
) -> VkBool32
|
||||
{
|
||||
auto *messenger = (Messenger *)vulkan_user_data; // NOLINT
|
||||
ensure(messenger, "Null vulkan_user_data received in messenger callback");
|
||||
|
||||
messenger->validation_layers_callback_impl(message_severity, message_type, callback_data);
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
void validation_layers_callback_impl(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *callback_data
|
||||
)
|
||||
{
|
||||
m_callback(
|
||||
static_cast<Severity>(message_severity),
|
||||
static_cast<Type>(message_type),
|
||||
callback_data,
|
||||
m_user_data
|
||||
);
|
||||
}
|
||||
|
||||
memory::NullOnMove<VkDebugUtilsMessengerEXT> m_debug_messenger = VK_NULL_HANDLE;
|
||||
|
||||
Callback_T m_callback;
|
||||
|
||||
void *m_user_data;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer::vk
|
149
modules/renderer/private/vk/debug/messenger.test.cpp
Normal file
149
modules/renderer/private/vk/debug/messenger.test.cpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/debug/messenger.hpp>
|
||||
#include <renderer/vk/test_utils.hpp>
|
||||
#include <surface/components.hpp>
|
||||
#include <surface/system.hpp>
|
||||
#include <test/expects.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using namespace lt;
|
||||
using renderer::vk::Messenger;
|
||||
using renderer::vk::Surface;
|
||||
using enum Messenger::Severity;
|
||||
using enum Messenger::Type;
|
||||
|
||||
void noop_callback(
|
||||
Messenger::Severity message_severity,
|
||||
Messenger::Type message_type,
|
||||
Messenger::CallbackData_T vulkan_data,
|
||||
void *user_data
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
Suite raii = "messenger_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = all_severity,
|
||||
.type = all_type,
|
||||
.callback = &noop_callback,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
expect_throw([] {
|
||||
Messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = all_severity,
|
||||
.type = all_type,
|
||||
.callback = {},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([] {
|
||||
Messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = {},
|
||||
.type = all_type,
|
||||
.callback = &noop_callback,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([] {
|
||||
Messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = all_severity,
|
||||
.type = {},
|
||||
.callback = &noop_callback,
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-interfaces-global-init)
|
||||
Suite callback = "messenger_callback"_suite = [] {
|
||||
Case { "callback gets called with correct arguments" } = [] {
|
||||
auto total_messages = 0u;
|
||||
auto first_message_is_severity = false;
|
||||
auto second_message_is_type = false;
|
||||
auto third_message_is_user_callback = false;
|
||||
auto all_messages_are_error = true;
|
||||
auto all_messages_are_validation = true;
|
||||
auto user_data_is_always_69 = true;
|
||||
|
||||
auto callback = [&](Messenger::Severity message_severity,
|
||||
Messenger::Type message_type,
|
||||
Messenger::CallbackData_T vulkan_data,
|
||||
void *user_data) {
|
||||
++total_messages;
|
||||
auto message = std::string_view { vulkan_data->pMessage };
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
user_data_is_always_69 = user_data_is_always_69 && *(size_t *)user_data == 69u;
|
||||
|
||||
all_messages_are_validation = all_messages_are_validation && message_type == validation;
|
||||
all_messages_are_error = all_messages_are_error && message_severity == error;
|
||||
|
||||
if (total_messages == 1)
|
||||
{
|
||||
first_message_is_severity = message.starts_with(
|
||||
"vkCreateDebugUtilsMessengerEXT(): pCreateInfo->messageSeverity is zero."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (total_messages == 2)
|
||||
{
|
||||
second_message_is_type = message.starts_with(
|
||||
"vkCreateDebugUtilsMessengerEXT(): pCreateInfo->messageType is zero."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (total_messages == 3)
|
||||
{
|
||||
third_message_is_user_callback = message.starts_with(
|
||||
"vkCreateDebugUtilsMessengerEXT(): pCreateInfo->pfnUserCallback is NULL."
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
auto user_data = size_t { 69 };
|
||||
auto messenger = Messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = all_severity,
|
||||
.type = all_type,
|
||||
.callback = callback,
|
||||
.user_data = &user_data,
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
auto *messenger = VkDebugUtilsMessengerEXT {};
|
||||
auto info = VkDebugUtilsMessengerCreateInfoEXT {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
};
|
||||
renderer::vk::vk_create_debug_messenger(
|
||||
renderer::vk::Instance::get(),
|
||||
&info,
|
||||
nullptr,
|
||||
&messenger
|
||||
);
|
||||
}
|
||||
|
||||
expect_eq(total_messages, 3u);
|
||||
expect_true(first_message_is_severity);
|
||||
expect_true(second_message_is_type);
|
||||
expect_true(third_message_is_user_callback);
|
||||
expect_true(all_messages_are_error);
|
||||
expect_true(all_messages_are_validation);
|
||||
expect_true(user_data_is_always_69);
|
||||
};
|
||||
};
|
17
modules/renderer/private/vk/debug/validation.hpp
Normal file
17
modules/renderer/private/vk/debug/validation.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <renderer/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
inline void vkc(VkResult result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
throw std::runtime_error {
|
||||
std::format("Vulkan call failed with result: {}", std::to_underlying(result))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
|
@ -1,22 +1,14 @@
|
|||
#include <ranges>
|
||||
#include <renderer/vk/context/context.hpp>
|
||||
#include <renderer/vk/pipeline.hpp>
|
||||
#include <renderer/vk/test_utils.hpp>
|
||||
#include <surface/system.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using namespace lt;
|
||||
|
||||
using std::ignore;
|
||||
using test::Case;
|
||||
using test::expect_throw;
|
||||
using test::expect_true;
|
||||
using test::Suite;
|
||||
|
||||
using renderer::vk::Context;
|
||||
using renderer::vk::Pipeline;
|
||||
|
||||
constexpr auto resolution = math::uvec2 { 800, 600 };
|
||||
|
||||
class VkPipelineTest
|
||||
{
|
||||
public:
|
||||
|
@ -29,7 +21,7 @@ public:
|
|||
m_surface_entity = create_scope<ecs::Entity>(m_registry, m_registry->create_entity());
|
||||
m_surface_entity->add<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {
|
||||
.title = "",
|
||||
.resolution = resolution,
|
||||
.resolution = constants::resolution,
|
||||
});
|
||||
|
||||
m_context = create_ref<Context>(*m_surface_entity, m_stats);
|
||||
|
@ -57,7 +49,7 @@ private:
|
|||
Ref<Context> m_context;
|
||||
};
|
||||
|
||||
Suite raii = [] {
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto fixture = VkPipelineTest {};
|
||||
std::ignore = Pipeline { { .context = fixture.context() } };
|
||||
|
|
1
modules/renderer/private/vk/test_utils.cpp
Normal file
1
modules/renderer/private/vk/test_utils.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include <renderer/vk/test_utils.hpp>
|
87
modules/renderer/private/vk/test_utils.hpp
Normal file
87
modules/renderer/private/vk/test_utils.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include <ranges>
|
||||
#include <renderer/vk/context/surface.hpp>
|
||||
#include <renderer/vk/debug/messenger.hpp>
|
||||
#include <surface/components.hpp>
|
||||
#include <surface/system.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_false;
|
||||
using ::lt::test::expect_not_nullptr;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::expect_true;
|
||||
using ::lt::test::Suite;
|
||||
using ::std::ignore;
|
||||
|
||||
namespace constants {
|
||||
|
||||
constexpr auto resolution = lt::math::uvec2 { 800u, 600u };
|
||||
|
||||
}
|
||||
|
||||
class ValidationObserver
|
||||
{
|
||||
using Messenger = lt::renderer::vk::Messenger;
|
||||
using enum Messenger::Type;
|
||||
using enum Messenger::Severity;
|
||||
|
||||
public:
|
||||
ValidationObserver()
|
||||
: m_messenger(
|
||||
Messenger::CreateInfo {
|
||||
.severity = all_severity,
|
||||
.type = lt::renderer::vk::Messenger::all_type,
|
||||
.callback = &callback,
|
||||
.user_data = &m_had_any_messages,
|
||||
}
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] auto had_any_messages() const -> bool
|
||||
{
|
||||
return m_had_any_messages;
|
||||
}
|
||||
|
||||
private:
|
||||
static void callback(
|
||||
Messenger::Severity message_severity,
|
||||
Messenger::Type message_type,
|
||||
Messenger::CallbackData_T vulkan_data,
|
||||
void *user_data
|
||||
)
|
||||
{
|
||||
std::ignore = message_severity;
|
||||
std::ignore = message_type;
|
||||
|
||||
std::println("Validation message: {}", vulkan_data->pMessage);
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
*(bool *)user_data = true;
|
||||
}
|
||||
|
||||
Messenger m_messenger;
|
||||
bool m_had_any_messages = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct std::formatter<VkExtent2D>
|
||||
{
|
||||
constexpr auto parse(std::format_parse_context &context)
|
||||
{
|
||||
return context.begin();
|
||||
}
|
||||
|
||||
auto format(const VkExtent2D &val, std::format_context &context) const
|
||||
{
|
||||
return std::format_to(context.out(), "{}, {}", val.width, val.height);
|
||||
}
|
||||
};
|
||||
|
||||
inline auto operator==(VkExtent2D lhs, VkExtent2D rhs) -> bool
|
||||
{
|
||||
return lhs.width == rhs.width && lhs.height == rhs.height;
|
||||
}
|
91
modules/renderer/private/vk/vulkan.hpp
Normal file
91
modules/renderer/private/vk/vulkan.hpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
// global functions
|
||||
extern PFN_vkGetInstanceProcAddr vk_get_instance_proc_address;
|
||||
extern PFN_vkCreateInstance vk_create_instance;
|
||||
extern PFN_vkEnumerateInstanceExtensionProperties vk_enumerate_instance_extension_properties;
|
||||
extern PFN_vkEnumerateInstanceLayerProperties vk_enumerate_instance_layer_properties;
|
||||
|
||||
// instance functions
|
||||
extern PFN_vkDestroyInstance vk_destroy_instance;
|
||||
extern PFN_vkEnumeratePhysicalDevices vk_enumerate_physical_devices;
|
||||
extern PFN_vkGetPhysicalDeviceProperties vk_get_physical_device_properties;
|
||||
extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue_family_properties;
|
||||
extern PFN_vkCreateDevice vk_create_device;
|
||||
extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address;
|
||||
extern PFN_vkDestroyDevice vk_destroy_device;
|
||||
extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features;
|
||||
extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties;
|
||||
|
||||
// extension instance functions
|
||||
extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label;
|
||||
extern PFN_vkCmdEndDebugUtilsLabelEXT vk_cmd_end_debug_label;
|
||||
extern PFN_vkCmdInsertDebugUtilsLabelEXT vk_cmd_insert_debug_label;
|
||||
extern PFN_vkCreateDebugUtilsMessengerEXT vk_create_debug_messenger;
|
||||
extern PFN_vkDestroyDebugUtilsMessengerEXT vk_destroy_debug_messenger;
|
||||
extern PFN_vkQueueBeginDebugUtilsLabelEXT vk_queue_begin_debug_label;
|
||||
extern PFN_vkQueueEndDebugUtilsLabelEXT vk_queue_end_debug_label;
|
||||
extern PFN_vkQueueInsertDebugUtilsLabelEXT vk_queue_insert_debug_label;
|
||||
extern PFN_vkSetDebugUtilsObjectNameEXT vk_set_debug_object_name;
|
||||
extern PFN_vkSetDebugUtilsObjectTagEXT vk_set_debug_object_tag;
|
||||
extern PFN_vkSubmitDebugUtilsMessageEXT vk_submit_debug_message;
|
||||
|
||||
// surface instance functions
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support;
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities;
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats;
|
||||
extern PFN_vkCreateXlibSurfaceKHR vk_create_xlib_surface_khr;
|
||||
extern PFN_vkDestroySurfaceKHR vk_destroy_surface_khr;
|
||||
|
||||
// device functions
|
||||
extern PFN_vkGetDeviceQueue vk_get_device_queue;
|
||||
extern PFN_vkCreateCommandPool vk_create_command_pool;
|
||||
extern PFN_vkDestroyCommandPool vk_destroy_command_pool;
|
||||
extern PFN_vkAllocateCommandBuffers vk_allocate_command_buffers;
|
||||
extern PFN_vkFreeCommandBuffers vk_free_command_buffers;
|
||||
extern PFN_vkBeginCommandBuffer vk_begin_command_buffer;
|
||||
extern PFN_vkEndCommandBuffer vk_end_command_buffer;
|
||||
extern PFN_vkCmdPipelineBarrier vk_cmd_pipeline_barrier;
|
||||
extern PFN_vkQueueSubmit vk_queue_submit;
|
||||
extern PFN_vkQueueWaitIdle vk_queue_wait_idle;
|
||||
extern PFN_vkDeviceWaitIdle vk_device_wait_idle;
|
||||
extern PFN_vkCreateFence vk_create_fence;
|
||||
extern PFN_vkDestroyFence vk_destroy_fence;
|
||||
extern PFN_vkWaitForFences vk_wait_for_fences;
|
||||
extern PFN_vkResetFences vk_reset_fences;
|
||||
extern PFN_vkCreateSemaphore vk_create_semaphore;
|
||||
extern PFN_vkDestroySemaphore vk_destroy_semaphore;
|
||||
extern PFN_vkCreateSwapchainKHR vk_create_swapchain_khr;
|
||||
extern PFN_vkDestroySwapchainKHR vk_destroy_swapchain_khr;
|
||||
extern PFN_vkGetSwapchainImagesKHR vk_get_swapchain_images_khr;
|
||||
extern PFN_vkAcquireNextImageKHR vk_acquire_next_image_khr;
|
||||
extern PFN_vkQueuePresentKHR vk_queue_present_khr;
|
||||
extern PFN_vkCreateImageView vk_create_image_view;
|
||||
extern PFN_vkDestroyImageView vk_destroy_image_view;
|
||||
extern PFN_vkCreateRenderPass vk_create_render_pass;
|
||||
extern PFN_vkDestroyRenderPass vk_destroy_render_pass;
|
||||
extern PFN_vkCreateFramebuffer vk_create_frame_buffer;
|
||||
extern PFN_vkDestroyFramebuffer vk_destroy_frame_buffer;
|
||||
extern PFN_vkCreateShaderModule vk_create_shader_module;
|
||||
extern PFN_vkDestroyShaderModule vk_destroy_shader_module;
|
||||
extern PFN_vkCreatePipelineLayout vk_create_pipeline_layout;
|
||||
extern PFN_vkDestroyPipelineLayout vk_destroy_pipeline_layout;
|
||||
extern PFN_vkCreateGraphicsPipelines vk_create_graphics_pipelines;
|
||||
extern PFN_vkDestroyPipeline vk_destroy_pipeline;
|
||||
extern PFN_vkCmdBeginRenderPass vk_cmd_begin_render_pass;
|
||||
extern PFN_vkCmdEndRenderPass vk_cmd_end_render_pass;
|
||||
extern PFN_vkCmdBindPipeline vk_cmd_bind_pipeline;
|
||||
extern PFN_vkCmdDraw vk_cmd_draw;
|
||||
extern PFN_vkCmdSetViewport vk_cmd_set_viewport;
|
||||
extern PFN_vkCmdSetScissor vk_cmd_set_scissors;
|
||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace lt::renderer::vk
|
Loading…
Add table
Reference in a new issue