Added many tests and fixed up api as a consequence

Added device::get_queue_families() to facilitate custom queue setups

get_swapchain_images() renamed to get_image(), made member function to
swapchain.
get_swapchain_image_views() renamed to get_image_views(), also moved to
member function of swapchain

fixed bug with headless instance not being correct

Stopped Catch2 from polluting the buildable targets
This commit is contained in:
Charles Giessen 2020-04-18 21:24:59 -06:00
parent e906cfc093
commit 1f462b42f3
6 changed files with 309 additions and 74 deletions

View File

@ -294,10 +294,8 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
} }
int create_framebuffers (Init& init, RenderData& data) { int create_framebuffers (Init& init, RenderData& data) {
data.swapchain_images = vkb::get_swapchain_images (init.swapchain).value (); data.swapchain_images = init.swapchain.get_images ().value ();
// init.swapchain.image_count = data.swapchain_images.size (); data.swapchain_image_views = init.swapchain.get_image_views ().value ();
data.swapchain_image_views =
vkb::get_swapchain_image_views (init.swapchain, data.swapchain_images).value ();
data.framebuffers.resize (data.swapchain_image_views.size ()); data.framebuffers.resize (data.swapchain_image_views.size ());

View File

@ -11,4 +11,10 @@ set(GLFW_BUILD_EXAMPLES
OFF OFF
CACHE BOOL "" FORCE) CACHE BOOL "" FORCE)
add_subdirectory(glfw) add_subdirectory(glfw)
set(CATCH_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(CATCH_ENABLE_WERROR OFF CACHE BOOL "" FORCE)
set(CATCH_INSTALL_DOCS OFF CACHE BOOL "" FORCE)
set(CATCH_INSTALL_HELPERS OFF CACHE BOOL "" FORCE)
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) #remove Catch2 target spam
add_subdirectory(Catch2) add_subdirectory(Catch2)

View File

@ -939,6 +939,9 @@ bool PhysicalDevice::has_dedicated_transfer_queue () const {
bool PhysicalDevice::has_separate_transfer_queue () const { bool PhysicalDevice::has_separate_transfer_queue () const {
return detail::get_separate_transfer_queue_index (queue_families) >= 0; return detail::get_separate_transfer_queue_index (queue_families) >= 0;
} }
std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families () const {
return queue_families;
}
// ---- Queues ---- // // ---- Queues ---- //
@ -1002,6 +1005,11 @@ detail::Expected<VkQueue, detail::Error<QueueError>> Device::get_dedicated_queue
// ---- Device ---- // // ---- Device ---- //
CustomQueueDescription::CustomQueueDescription (uint32_t index, uint32_t count, std::vector<float> priorities)
: index (index), count (count), priorities (priorities) {
assert (count == priorities.size ());
}
void destroy_device (Device device) { void destroy_device (Device device) {
vkDestroyDevice (device.device, device.allocation_callbacks); vkDestroyDevice (device.device, device.allocation_callbacks);
} }
@ -1039,6 +1047,14 @@ detail::Expected<Device, detail::Error<DeviceError>> DeviceBuilder::build () con
std::vector<const char*> extensions = info.extensions_to_enable; std::vector<const char*> extensions = info.extensions_to_enable;
if (info.surface != VK_NULL_HANDLE) extensions.push_back ({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); if (info.surface != VK_NULL_HANDLE) extensions.push_back ({ VK_KHR_SWAPCHAIN_EXTENSION_NAME });
// VUID-VkDeviceCreateInfo-pNext-00373 - don't add pEnabledFeatures if the phys_dev_features_2 is present
bool has_phys_dev_features_2 = false;
for (auto& pNext_struct : info.pNext_chain) {
if (pNext_struct->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {
has_phys_dev_features_2 = true;
}
}
VkDeviceCreateInfo device_create_info = {}; VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
detail::setup_pNext_chain (device_create_info, info.pNext_chain); detail::setup_pNext_chain (device_create_info, info.pNext_chain);
@ -1047,7 +1063,9 @@ detail::Expected<Device, detail::Error<DeviceError>> DeviceBuilder::build () con
device_create_info.pQueueCreateInfos = queueCreateInfos.data (); device_create_info.pQueueCreateInfos = queueCreateInfos.data ();
device_create_info.enabledExtensionCount = static_cast<uint32_t> (extensions.size ()); device_create_info.enabledExtensionCount = static_cast<uint32_t> (extensions.size ());
device_create_info.ppEnabledExtensionNames = extensions.data (); device_create_info.ppEnabledExtensionNames = extensions.data ();
if (!has_phys_dev_features_2) {
device_create_info.pEnabledFeatures = &info.features; device_create_info.pEnabledFeatures = &info.features;
}
Device device; Device device;
VkResult res = vkCreateDevice (info.physical_device.physical_device, VkResult res = vkCreateDevice (info.physical_device.physical_device,
@ -1067,15 +1085,13 @@ DeviceBuilder& DeviceBuilder::custom_queue_setup (std::vector<CustomQueueDescrip
info.queue_descriptions = queue_descriptions; info.queue_descriptions = queue_descriptions;
return *this; return *this;
} }
template <typename T> DeviceBuilder& DeviceBuilder::add_pNext (T* structure) {
info.pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (structure));
return *this;
}
DeviceBuilder& DeviceBuilder::set_allocation_callbacks (VkAllocationCallbacks* callbacks) { DeviceBuilder& DeviceBuilder::set_allocation_callbacks (VkAllocationCallbacks* callbacks) {
info.allocation_callbacks = callbacks; info.allocation_callbacks = callbacks;
return *this; return *this;
} }
// ---- Swapchain ---- //
namespace detail { namespace detail {
struct SurfaceSupportDetails { struct SurfaceSupportDetails {
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
@ -1245,7 +1261,10 @@ detail::Expected<Swapchain, detail::Error<SwapchainError>> SwapchainBuilder::bui
swapchain.device = info.device; swapchain.device = info.device;
swapchain.image_format = surface_format.format; swapchain.image_format = surface_format.format;
swapchain.extent = extent; swapchain.extent = extent;
auto images = get_swapchain_images (swapchain); auto images = swapchain.get_images ();
if (!images) {
return detail::Error<SwapchainError>{ SwapchainError::failed_get_swapchain_images };
}
swapchain.image_count = static_cast<uint32_t> (images.value ().size ()); swapchain.image_count = static_cast<uint32_t> (images.value ().size ());
swapchain.allocation_callbacks = info.allocation_callbacks; swapchain.allocation_callbacks = info.allocation_callbacks;
return swapchain; return swapchain;
@ -1254,27 +1273,28 @@ detail::Expected<Swapchain, detail::Error<SwapchainError>> SwapchainBuilder::rec
Swapchain const& swapchain) const { Swapchain const& swapchain) const {
return build (swapchain.swapchain); return build (swapchain.swapchain);
} }
detail::Expected<std::vector<VkImage>, detail::Error<SwapchainError>> get_swapchain_images ( detail::Expected<std::vector<VkImage>, detail::Error<SwapchainError>> Swapchain::get_images () {
Swapchain const& swapchain) { auto swapchain_images = detail::get_vector<VkImage> (vkGetSwapchainImagesKHR, device, swapchain);
auto swapchain_images =
detail::get_vector<VkImage> (vkGetSwapchainImagesKHR, swapchain.device, swapchain.swapchain);
if (!swapchain_images) { if (!swapchain_images) {
return detail::Error<SwapchainError>{ SwapchainError::failed_get_swapchain_images, return detail::Error<SwapchainError>{ SwapchainError::failed_get_swapchain_images,
swapchain_images.error () }; swapchain_images.error () };
} }
return swapchain_images.value (); return swapchain_images.value ();
} }
detail::Expected<std::vector<VkImageView>, detail::Error<SwapchainError>> Swapchain::get_image_views () {
detail::Expected<std::vector<VkImageView>, detail::Error<SwapchainError>> auto swapchain_images_ret = get_images ();
get_swapchain_image_views (Swapchain const& swapchain, std::vector<VkImage> const& images) { if (!swapchain_images_ret) return swapchain_images_ret.error ();
std::vector<VkImageView> views{ swapchain.image_count }; auto swapchain_images = swapchain_images_ret.value ();
for (size_t i = 0; i < swapchain.image_count; i++) { std::vector<VkImageView> views{ swapchain_images.size () };
for (size_t i = 0; i < swapchain_images.size (); i++) {
VkImageViewCreateInfo createInfo = {}; VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = images[i]; createInfo.image = swapchain_images[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = swapchain.image_format; createInfo.format = image_format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
@ -1285,14 +1305,17 @@ get_swapchain_image_views (Swapchain const& swapchain, std::vector<VkImage> cons
createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1; createInfo.subresourceRange.layerCount = 1;
VkResult res = vkCreateImageView (swapchain.device, &createInfo, nullptr, &views[i]); VkResult res = vkCreateImageView (device, &createInfo, allocation_callbacks, &views[i]);
if (res != VK_SUCCESS) if (res != VK_SUCCESS)
return detail::Error<SwapchainError>{ SwapchainError::failed_create_swapchain_image_views, res }; return detail::Error<SwapchainError>{ SwapchainError::failed_create_swapchain_image_views, res };
} }
return views; return views;
} }
void Swapchain::destroy_image_views (std::vector<VkImageView> const& image_views) {
for (auto& image_view : image_views) {
vkDestroyImageView (device, image_view, allocation_callbacks);
}
}
void destroy_swapchain (Swapchain const& swapchain) { void destroy_swapchain (Swapchain const& swapchain) {
if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE)
vkDestroySwapchainKHR (swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks); vkDestroySwapchainKHR (swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);

View File

@ -197,8 +197,8 @@ class InstanceBuilder {
// Adds an extension to be enabled. Will fail to create an instance if the extension isn't available. // Adds an extension to be enabled. Will fail to create an instance if the extension isn't available.
InstanceBuilder& enable_extension (const char* extension_name); InstanceBuilder& enable_extension (const char* extension_name);
// Headless Mode does not load the required extensions for presentation. Defaults to false. // Headless Mode does not load the required extensions for presentation. Defaults to true.
InstanceBuilder& set_headless (bool headless = false); InstanceBuilder& set_headless (bool headless = true);
// Enables the validation layers. Will fail to create an instance if the validation layers aren't available. // Enables the validation layers. Will fail to create an instance if the validation layers aren't available.
InstanceBuilder& enable_validation_layers (bool require_validation = true); InstanceBuilder& enable_validation_layers (bool require_validation = true);
@ -311,6 +311,9 @@ struct PhysicalDevice {
// Has a queue family that supports transfer operations but not graphics. // Has a queue family that supports transfer operations but not graphics.
bool has_separate_transfer_queue () const; bool has_separate_transfer_queue () const;
// Advanced: Get the VkQueueFamilyProperties of the device if special queue setup is needed
std::vector<VkQueueFamilyProperties> get_queue_families () const;
private: private:
std::vector<const char*> extensions_to_enable; std::vector<const char*> extensions_to_enable;
std::vector<VkQueueFamilyProperties> queue_families; std::vector<VkQueueFamilyProperties> queue_families;
@ -450,16 +453,16 @@ struct Device {
detail::Expected<VkQueue, detail::Error<QueueError>> get_dedicated_queue (QueueType type) const; detail::Expected<VkQueue, detail::Error<QueueError>> get_dedicated_queue (QueueType type) const;
}; };
void destroy_device (Device device); // For advanced device queue setup
struct CustomQueueDescription { struct CustomQueueDescription {
CustomQueueDescription (uint32_t index, uint32_t count, std::vector<float> priorities) CustomQueueDescription (uint32_t index, uint32_t count, std::vector<float> priorities);
: index (index), count (count), priorities (priorities) {}
uint32_t index = 0; uint32_t index = 0;
uint32_t count = 0; uint32_t count = 0;
std::vector<float> priorities; std::vector<float> priorities;
}; };
void destroy_device (Device device);
class DeviceBuilder { class DeviceBuilder {
public: public:
// Any features and extensions that are requested/required in PhysicalDeviceSelector are automatically enabled. // Any features and extensions that are requested/required in PhysicalDeviceSelector are automatically enabled.
@ -473,7 +476,10 @@ class DeviceBuilder {
// Add a structure to the pNext chain of VkDeviceCreateInfo. // Add a structure to the pNext chain of VkDeviceCreateInfo.
// The structure must be valid when DeviceBuilder::build() is called. // The structure must be valid when DeviceBuilder::build() is called.
template <typename T> DeviceBuilder& add_pNext (T* structure); template <typename T> DeviceBuilder& add_pNext (T* structure) {
info.pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (structure));
return *this;
}
// Provide custom allocation callbacks. // Provide custom allocation callbacks.
DeviceBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks); DeviceBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
@ -500,15 +506,18 @@ struct Swapchain {
VkFormat image_format = VK_FORMAT_UNDEFINED; VkFormat image_format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = { 0, 0 }; VkExtent2D extent = { 0, 0 };
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
// Returns a vector of VkImage handles to the swapchain
detail::Expected<std::vector<VkImage>, detail::Error<SwapchainError>> get_images ();
// Returns a vector of VkImageView's to the VkImage's of the swapchain
// VkImageViews must be destroyed
detail::Expected<std::vector<VkImageView>, detail::Error<SwapchainError>> get_image_views ();
void destroy_image_views (std::vector<VkImageView> const& image_views);
}; };
void destroy_swapchain (Swapchain const& swapchain); void destroy_swapchain (Swapchain const& swapchain);
detail::Expected<std::vector<VkImage>, detail::Error<SwapchainError>> get_swapchain_images (
Swapchain const& swapchain);
detail::Expected<std::vector<VkImageView>, detail::Error<SwapchainError>>
get_swapchain_image_views (Swapchain const& swapchain, std::vector<VkImage> const& images);
class SwapchainBuilder { class SwapchainBuilder {
public: public:
SwapchainBuilder (Device const& device); SwapchainBuilder (Device const& device);

View File

@ -5,8 +5,7 @@
// TODO // TODO
// Getting queues // Getting queues
// get dedicated vs distinct compute queues // get dedicated vs distinct compute queues
// Swapchain creation
// Swapchain recreation
// changing present modes and/or image formats // changing present modes and/or image formats
TEST_CASE ("Instance with surface") { TEST_CASE ("Instance with surface") {
@ -55,12 +54,16 @@ TEST_CASE ("Instance with surface") {
} }
} }
TEST_CASE ("basic instance") { TEST_CASE ("instance configuration") {
SECTION ("custom debug callback") {
vkb::InstanceBuilder builder; vkb::InstanceBuilder builder;
auto instance_ret = auto instance_ret =
builder.request_validation_layers () builder.request_validation_layers ()
.set_app_name ("test") .set_app_name ("test app")
.set_app_version (1, 0, 0)
.set_engine_name ("engine_name")
.set_engine_version (9, 9, 9)
.set_debug_callback ([] (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, .set_debug_callback ([] (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType, VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
@ -71,29 +74,233 @@ TEST_CASE ("basic instance") {
printf ("[%s: %s](user defined)\n%s\n", ms, mt, pCallbackData->pMessage); printf ("[%s: %s](user defined)\n%s\n", ms, mt, pCallbackData->pMessage);
return VK_FALSE; return VK_FALSE;
}) })
.require_api_version (1, 2, 111)
.build (); .build ();
REQUIRE (instance_ret.has_value ()); REQUIRE (instance_ret.has_value ());
vkb::destroy_instance (instance_ret.value ()); vkb::destroy_instance (instance_ret.value ());
} }
SECTION ("Validation configuration") {
TEST_CASE ("headless instance") {
vkb::InstanceBuilder builder; vkb::InstanceBuilder builder;
auto instance_ret = auto instance_ret =
builder.request_validation_layers () builder.request_validation_layers ()
.set_headless ()
.set_app_version (4, 5, 6)
.set_app_name ("headless")
.set_engine_name ("nick")
.require_api_version (1, 0, 34) .require_api_version (1, 0, 34)
.use_default_debug_messenger () .use_default_debug_messenger ()
.add_validation_feature_enable (VkValidationFeatureEnableEXT::VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT) .add_validation_feature_enable (VkValidationFeatureEnableEXT::VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT)
.add_validation_feature_disable (VkValidationFeatureDisableEXT::VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT) .add_validation_feature_disable (
VkValidationFeatureDisableEXT::VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT)
.add_validation_disable (VkValidationCheckEXT::VK_VALIDATION_CHECK_SHADERS_EXT) .add_validation_disable (VkValidationCheckEXT::VK_VALIDATION_CHECK_SHADERS_EXT)
.build (); .build ();
REQUIRE (instance_ret.has_value ()); REQUIRE (instance_ret.has_value ());
vkb::destroy_instance (instance_ret.value ()); vkb::destroy_instance (instance_ret.value ());
} }
}
TEST_CASE ("Headless Vulkan") {
vkb::InstanceBuilder builder;
auto instance_ret = builder.request_validation_layers ().set_headless ().build ();
REQUIRE (instance_ret.has_value ());
vkb::PhysicalDeviceSelector phys_device_selector (instance_ret.value ());
auto phys_device_ret = phys_device_selector.select ();
REQUIRE (phys_device_ret.has_value ());
auto phys_device = phys_device_ret.value ();
vkb::DeviceBuilder device_builder (phys_device);
auto device_ret = device_builder.build ();
REQUIRE (device_ret.has_value ());
vkb::destroy_device (device_ret.value ());
vkb::destroy_instance (instance_ret.value ());
}
TEST_CASE ("Device Configuration") {
auto window = create_window_glfw ();
vkb::InstanceBuilder builder;
auto instance_ret = builder.request_validation_layers ().build ();
REQUIRE (instance_ret.has_value ());
auto surface = create_surface_glfw (instance_ret.value ().instance, window);
vkb::PhysicalDeviceSelector phys_device_selector (instance_ret.value ());
auto phys_device_ret = phys_device_selector.set_surface (surface).select ();
REQUIRE (phys_device_ret.has_value ());
auto phys_device = phys_device_ret.value ();
SECTION ("Custom queue setup") {
std::vector<vkb::CustomQueueDescription> queue_descriptions;
auto queue_families = phys_device.get_queue_families ();
for (uint32_t i = 0; i < (uint32_t)queue_families.size (); i++) {
if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
queue_descriptions.push_back (vkb::CustomQueueDescription (
i, queue_families[i].queueCount, std::vector<float> (queue_families[i].queueCount, 1.0f)));
}
}
if (phys_device.has_dedicated_compute_queue ()) {
for (uint32_t i = 0; i < (uint32_t)queue_families.size (); i++) {
if ((queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
(queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
(queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
queue_descriptions.push_back (vkb::CustomQueueDescription (i,
queue_families[i].queueCount,
std::vector<float> (queue_families[i].queueCount, 1.0f)));
}
} else if (phys_device.has_separate_compute_queue ()) {
for (uint32_t i = 0; i < (uint32_t)queue_families.size (); i++) {
if ((queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
((queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
queue_descriptions.push_back (vkb::CustomQueueDescription (i,
queue_families[i].queueCount,
std::vector<float> (queue_families[i].queueCount, 1.0f)));
}
}
}
vkb::DeviceBuilder device_builder (phys_device);
auto device_ret = device_builder.custom_queue_setup (queue_descriptions).build ();
REQUIRE (device_ret.has_value ());
vkb::destroy_device (device_ret.value ());
}
SECTION ("VkPhysicalDeviceFeatures2 in pNext Chain") {
VkPhysicalDeviceFeatures2 phys_dev_feat_2{};
vkb::DeviceBuilder device_builder (phys_device);
auto device_ret = device_builder.add_pNext (&phys_dev_feat_2).build ();
REQUIRE (device_ret.has_value ());
vkb::destroy_device (device_ret.value ());
}
destroy_surface (instance_ret.value ().instance, surface);
vkb::destroy_instance (instance_ret.value ());
}
TEST_CASE ("Swapchain") {
GIVEN ("A working instance, window, surface, and device") {
auto window = create_window_glfw ();
vkb::InstanceBuilder builder;
auto instance_ret = builder.request_validation_layers ().build ();
REQUIRE (instance_ret.has_value ());
auto surface = create_surface_glfw (instance_ret.value ().instance, window);
vkb::PhysicalDeviceSelector phys_device_selector (instance_ret.value ());
auto phys_device_ret = phys_device_selector.set_surface (surface).select ();
REQUIRE (phys_device_ret.has_value ());
auto phys_device = phys_device_ret.value ();
vkb::DeviceBuilder device_builder (phys_device);
auto device_ret = device_builder.build ();
REQUIRE (device_ret.has_value ());
vkb::Device device = device_ret.value ();
THEN ("Swapchain can be made") {
vkb::SwapchainBuilder swapchain_builder (device);
auto swapchain_ret = swapchain_builder.build ();
REQUIRE (swapchain_ret.has_value ());
auto swapchain = swapchain_ret.value ();
THEN ("Acquire swapchain images and views") {
auto images = swapchain.get_images ();
REQUIRE (images.has_value ());
REQUIRE (images.value ().size () > 0);
auto image_views = swapchain.get_image_views ();
REQUIRE (image_views.has_value ());
REQUIRE (image_views.value ().size () > 0);
swapchain.destroy_image_views (image_views.value ());
}
vkb::destroy_swapchain (swapchain_ret.value ());
}
AND_THEN ("Swapchain configuration") {
vkb::SwapchainBuilder swapchain_builder (device);
auto swapchain_ret =
swapchain_builder.set_desired_extent (256, 256)
.set_desired_format ({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR })
.set_desired_present_mode (VK_PRESENT_MODE_IMMEDIATE_KHR)
.build ();
REQUIRE (swapchain_ret.has_value ());
vkb::destroy_swapchain (swapchain_ret.value ());
}
AND_THEN ("Swapchain defaults can be used") {
vkb::SwapchainBuilder swapchain_builder (device);
auto swapchain_ret = swapchain_builder.use_default_format_selection ()
.use_default_present_mode_selection ()
.build ();
REQUIRE (swapchain_ret.has_value ());
vkb::destroy_swapchain (swapchain_ret.value ());
}
AND_THEN ("Swapchain can be recreated") {
vkb::SwapchainBuilder swapchain_builder (device);
auto swapchain_ret = swapchain_builder.build ();
REQUIRE (swapchain_ret.has_value ());
auto swapchain = swapchain_ret.value ();
auto recreated_swapchain_ret = swapchain_builder.recreate (swapchain);
REQUIRE (recreated_swapchain_ret.has_value ());
vkb::destroy_swapchain (recreated_swapchain_ret.value ());
}
vkb::destroy_device (device_ret.value ());
destroy_surface (instance_ret.value ().instance, surface);
vkb::destroy_instance (instance_ret.value ());
}
}
void* VKAPI_PTR shim_vkAllocationFunction (
void* /*pUserData*/, size_t size, size_t /*alignment*/, VkSystemAllocationScope /*allocationScope*/) {
return malloc (size);
}
void* VKAPI_PTR shim_vkReallocationFunction (
void* /*pUserData*/, void* pOriginal, size_t size, size_t /*alignment*/, VkSystemAllocationScope /*allocationScope*/) {
return realloc (pOriginal, size);
}
void VKAPI_PTR shim_vkFreeFunction (void* /*pUserData*/, void* pMemory) { return free (pMemory); }
TEST_CASE ("Allocation Callbacks") {
VkAllocationCallbacks allocation_callbacks{};
allocation_callbacks.pfnAllocation = &shim_vkAllocationFunction;
allocation_callbacks.pfnReallocation = &shim_vkReallocationFunction;
allocation_callbacks.pfnFree = &shim_vkFreeFunction;
auto window = create_window_glfw ();
vkb::InstanceBuilder builder;
auto instance_ret =
builder.request_validation_layers ().set_allocation_callbacks (&allocation_callbacks).build ();
REQUIRE (instance_ret.has_value ());
auto surface = create_surface_glfw (instance_ret.value ().instance, window);
vkb::PhysicalDeviceSelector phys_device_selector (instance_ret.value ());
auto phys_device_ret = phys_device_selector.set_surface (surface).select ();
REQUIRE (phys_device_ret.has_value ());
auto phys_device = phys_device_ret.value ();
vkb::DeviceBuilder device_builder (phys_device);
auto device_ret = device_builder.set_allocation_callbacks (&allocation_callbacks).build ();
REQUIRE (device_ret.has_value ());
vkb::Device device = device_ret.value ();
vkb::SwapchainBuilder swapchain_builder (device);
auto swapchain_ret = swapchain_builder.set_allocation_callbacks (&allocation_callbacks).build ();
REQUIRE (swapchain_ret.has_value ());
auto swapchain = swapchain_ret.value ();
vkb::destroy_swapchain (swapchain_ret.value ());
vkb::destroy_device (device_ret.value ());
destroy_surface (instance_ret.value ().instance, surface);
vkb::destroy_instance (instance_ret.value ());
}

View File

@ -1,8 +0,0 @@
#include <stdio.h>
#include "common.h"
#include <catch2/catch.hpp>
#define CATCH_CONFIG_MAIN