From f5f9b54f387c0aef9c9cff80e7e440868c32da5f Mon Sep 17 00:00:00 2001 From: spnda <43609023+spnda@users.noreply.github.com> Date: Fri, 10 Sep 2021 19:01:43 +0200 Subject: [PATCH] Add user-defined conversion operators --- example/triangle.cpp | 66 +++++++++++++++++++-------------------- src/VkBootstrap.cpp | 15 +++++++++ src/VkBootstrap.h | 16 ++++++++++ tests/bootstrap_tests.cpp | 27 ++++++++++++++++ 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/example/triangle.cpp b/example/triangle.cpp index 5fe4bb9..2029212 100644 --- a/example/triangle.cpp +++ b/example/triangle.cpp @@ -55,9 +55,9 @@ int device_initialization (Init& init) { } init.instance = instance_ret.value (); - init.vk_lib.init(init.instance.instance); + init.vk_lib.init(init.instance); - init.surface = create_surface_glfw (init.instance.instance, init.window); + init.surface = create_surface_glfw (init.instance, init.window); vkb::PhysicalDeviceSelector phys_device_selector (init.instance); auto phys_device_ret = phys_device_selector.set_surface (init.surface).select (); @@ -74,7 +74,7 @@ int device_initialization (Init& init) { return -1; } init.device = device_ret.value (); - init.vk_lib.init(init.device.device); + init.vk_lib.init(init.device); return 0; } @@ -146,7 +146,7 @@ int create_render_pass (Init& init, RenderData& data) { render_pass_info.dependencyCount = 1; render_pass_info.pDependencies = &dependency; - if (init->vkCreateRenderPass (init.device.device, &render_pass_info, nullptr, &data.render_pass) != VK_SUCCESS) { + if (init->vkCreateRenderPass (init.device, &render_pass_info, nullptr, &data.render_pass) != VK_SUCCESS) { std::cout << "failed to create render pass\n"; return -1; // failed to create render pass! } @@ -178,7 +178,7 @@ VkShaderModule createShaderModule (Init& init, const std::vector& code) { create_info.pCode = reinterpret_cast (code.data ()); VkShaderModule shaderModule; - if (init->vkCreateShaderModule (init.device.device, &create_info, nullptr, &shaderModule) != VK_SUCCESS) { + if (init->vkCreateShaderModule (init.device, &create_info, nullptr, &shaderModule) != VK_SUCCESS) { return VK_NULL_HANDLE; // failed to create shader module } @@ -276,7 +276,7 @@ int create_graphics_pipeline (Init& init, RenderData& data) { pipeline_layout_info.pushConstantRangeCount = 0; if (init->vkCreatePipelineLayout ( - init.device.device, &pipeline_layout_info, nullptr, &data.pipeline_layout) != VK_SUCCESS) { + init.device, &pipeline_layout_info, nullptr, &data.pipeline_layout) != VK_SUCCESS) { std::cout << "failed to create pipeline layout\n"; return -1; // failed to create pipeline layout } @@ -305,13 +305,13 @@ int create_graphics_pipeline (Init& init, RenderData& data) { pipeline_info.basePipelineHandle = VK_NULL_HANDLE; if (init->vkCreateGraphicsPipelines ( - init.device.device, VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &data.graphics_pipeline) != VK_SUCCESS) { + init.device, VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &data.graphics_pipeline) != VK_SUCCESS) { std::cout << "failed to create pipline\n"; return -1; // failed to create graphics pipeline } - init->vkDestroyShaderModule (init.device.device, frag_module, nullptr); - init->vkDestroyShaderModule (init.device.device, vert_module, nullptr); + init->vkDestroyShaderModule (init.device, frag_module, nullptr); + init->vkDestroyShaderModule (init.device, vert_module, nullptr); return 0; } @@ -333,7 +333,7 @@ int create_framebuffers (Init& init, RenderData& data) { framebuffer_info.height = init.swapchain.extent.height; framebuffer_info.layers = 1; - if (init->vkCreateFramebuffer (init.device.device, &framebuffer_info, nullptr, &data.framebuffers[i]) != VK_SUCCESS) { + if (init->vkCreateFramebuffer (init.device, &framebuffer_info, nullptr, &data.framebuffers[i]) != VK_SUCCESS) { return -1; // failed to create framebuffer } } @@ -345,7 +345,7 @@ int create_command_pool (Init& init, RenderData& data) { pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; pool_info.queueFamilyIndex = init.device.get_queue_index (vkb::QueueType::graphics).value (); - if (init->vkCreateCommandPool (init.device.device, &pool_info, nullptr, &data.command_pool) != VK_SUCCESS) { + if (init->vkCreateCommandPool (init.device, &pool_info, nullptr, &data.command_pool) != VK_SUCCESS) { std::cout << "failed to create command pool\n"; return -1; // failed to create command pool } @@ -361,7 +361,7 @@ int create_command_buffers (Init& init, RenderData& data) { allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = (uint32_t)data.command_buffers.size (); - if (init->vkAllocateCommandBuffers (init.device.device, &allocInfo, data.command_buffers.data ()) != VK_SUCCESS) { + if (init->vkAllocateCommandBuffers (init.device, &allocInfo, data.command_buffers.data ()) != VK_SUCCESS) { return -1; // failed to allocate command buffers; } @@ -428,9 +428,9 @@ int create_sync_objects (Init& init, RenderData& data) { fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (init->vkCreateSemaphore (init.device.device, &semaphore_info, nullptr, &data.available_semaphores[i]) != VK_SUCCESS || - init->vkCreateSemaphore (init.device.device, &semaphore_info, nullptr, &data.finished_semaphore[i]) != VK_SUCCESS || - init->vkCreateFence (init.device.device, &fence_info, nullptr, &data.in_flight_fences[i]) != VK_SUCCESS) { + if (init->vkCreateSemaphore (init.device, &semaphore_info, nullptr, &data.available_semaphores[i]) != VK_SUCCESS || + init->vkCreateSemaphore (init.device, &semaphore_info, nullptr, &data.finished_semaphore[i]) != VK_SUCCESS || + init->vkCreateFence (init.device, &fence_info, nullptr, &data.in_flight_fences[i]) != VK_SUCCESS) { std::cout << "failed to create sync objects\n"; return -1; // failed to create synchronization objects for a frame } @@ -439,12 +439,12 @@ int create_sync_objects (Init& init, RenderData& data) { } int recreate_swapchain (Init& init, RenderData& data) { - init->vkDeviceWaitIdle (init.device.device); + init->vkDeviceWaitIdle (init.device); - init->vkDestroyCommandPool (init.device.device, data.command_pool, nullptr); + init->vkDestroyCommandPool (init.device, data.command_pool, nullptr); for (auto framebuffer : data.framebuffers) { - init->vkDestroyFramebuffer (init.device.device, framebuffer, nullptr); + init->vkDestroyFramebuffer (init.device, framebuffer, nullptr); } init.swapchain.destroy_image_views (data.swapchain_image_views); @@ -457,11 +457,11 @@ int recreate_swapchain (Init& init, RenderData& data) { } int draw_frame (Init& init, RenderData& data) { - init->vkWaitForFences (init.device.device, 1, &data.in_flight_fences[data.current_frame], VK_TRUE, UINT64_MAX); + init->vkWaitForFences (init.device, 1, &data.in_flight_fences[data.current_frame], VK_TRUE, UINT64_MAX); uint32_t image_index = 0; - VkResult result = init->vkAcquireNextImageKHR (init.device.device, - init.swapchain.swapchain, + VkResult result = init->vkAcquireNextImageKHR (init.device, + init.swapchain, UINT64_MAX, data.available_semaphores[data.current_frame], VK_NULL_HANDLE, @@ -475,7 +475,7 @@ int draw_frame (Init& init, RenderData& data) { } if (data.image_in_flight[image_index] != VK_NULL_HANDLE) { - init->vkWaitForFences (init.device.device, 1, &data.image_in_flight[image_index], VK_TRUE, UINT64_MAX); + init->vkWaitForFences (init.device, 1, &data.image_in_flight[image_index], VK_TRUE, UINT64_MAX); } data.image_in_flight[image_index] = data.in_flight_fences[data.current_frame]; @@ -495,7 +495,7 @@ int draw_frame (Init& init, RenderData& data) { submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signal_semaphores; - init->vkResetFences (init.device.device, 1, &data.in_flight_fences[data.current_frame]); + init->vkResetFences (init.device, 1, &data.in_flight_fences[data.current_frame]); if (init->vkQueueSubmit (data.graphics_queue, 1, &submitInfo, data.in_flight_fences[data.current_frame]) != VK_SUCCESS) { std::cout << "failed to submit draw command buffer\n"; @@ -508,7 +508,7 @@ int draw_frame (Init& init, RenderData& data) { present_info.waitSemaphoreCount = 1; present_info.pWaitSemaphores = signal_semaphores; - VkSwapchainKHR swapChains[] = { init.swapchain.swapchain }; + VkSwapchainKHR swapChains[] = { init.swapchain }; present_info.swapchainCount = 1; present_info.pSwapchains = swapChains; @@ -528,20 +528,20 @@ int draw_frame (Init& init, RenderData& data) { void cleanup (Init& init, RenderData& data) { for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - init->vkDestroySemaphore (init.device.device, data.finished_semaphore[i], nullptr); - init->vkDestroySemaphore (init.device.device, data.available_semaphores[i], nullptr); - init->vkDestroyFence (init.device.device, data.in_flight_fences[i], nullptr); + init->vkDestroySemaphore (init.device, data.finished_semaphore[i], nullptr); + init->vkDestroySemaphore (init.device, data.available_semaphores[i], nullptr); + init->vkDestroyFence (init.device, data.in_flight_fences[i], nullptr); } - init->vkDestroyCommandPool (init.device.device, data.command_pool, nullptr); + init->vkDestroyCommandPool (init.device, data.command_pool, nullptr); for (auto framebuffer : data.framebuffers) { - init->vkDestroyFramebuffer (init.device.device, framebuffer, nullptr); + init->vkDestroyFramebuffer (init.device, framebuffer, nullptr); } - init->vkDestroyPipeline (init.device.device, data.graphics_pipeline, nullptr); - init->vkDestroyPipelineLayout (init.device.device, data.pipeline_layout, nullptr); - init->vkDestroyRenderPass (init.device.device, data.render_pass, nullptr); + init->vkDestroyPipeline (init.device, data.graphics_pipeline, nullptr); + init->vkDestroyPipelineLayout (init.device, data.pipeline_layout, nullptr); + init->vkDestroyRenderPass (init.device, data.render_pass, nullptr); init.swapchain.destroy_image_views (data.swapchain_image_views); @@ -574,7 +574,7 @@ int main () { return -1; } } - init->vkDeviceWaitIdle (init.device.device); + init->vkDeviceWaitIdle (init.device); cleanup (init, render_data); return 0; diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 406c909..7d1339c 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -550,6 +550,10 @@ void destroy_instance(Instance instance) { } } +Instance::operator VkInstance() const { + return this->instance; +} + InstanceBuilder::InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; } @@ -1329,6 +1333,10 @@ std::vector PhysicalDevice::get_queue_families() const return queue_families; } +PhysicalDevice::operator VkPhysicalDevice() const { + return this->physical_device; +} + // ---- Queues ---- // detail::Result Device::get_queue_index(QueueType type) const { @@ -1399,6 +1407,10 @@ DispatchTable Device::make_table() const { return { device, fp_vkGetDeviceProcAd // ---- Device ---- // +Device::operator VkDevice() const { + return this->device; +} + CustomQueueDescription::CustomQueueDescription(uint32_t index, uint32_t count, std::vector priorities) : index(index), count(count), priorities(priorities) { assert(count == priorities.size()); @@ -1826,6 +1838,9 @@ void Swapchain::destroy_image_views(std::vector const& image_views) internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks); } } +Swapchain::operator VkSwapchainKHR() const { + return this->swapchain; +} SwapchainBuilder& SwapchainBuilder::set_old_swapchain(VkSwapchainKHR old_swapchain) { info.old_swapchain = old_swapchain; return *this; diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index dc065bc..065bb2e 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -236,6 +236,10 @@ struct Instance { PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr; PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; + // A conversion function which allows this Instance to be used + // in places where VkInstance would have been used. + operator VkInstance() const; + private: bool headless = false; bool supports_properties2_ext = false; @@ -412,6 +416,10 @@ struct PhysicalDevice { // Advanced: Get the VkQueueFamilyProperties of the device if special queue setup is needed std::vector get_queue_families() const; + // A conversion function which allows this PhysicalDevice to be used + // in places where VkPhysicalDevice would have been used. + operator VkPhysicalDevice() const; + private: uint32_t instance_version = VK_MAKE_VERSION(1, 0, 0); std::vector extensions_to_enable; @@ -596,6 +604,10 @@ struct Device { // Return a loaded dispatch table DispatchTable make_table() const; + // A conversion function which allows this Device to be used + // in places where VkDevice would have been used. + operator VkDevice() const; + private: struct { PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr; @@ -663,6 +675,10 @@ struct Swapchain { detail::Result> get_image_views(); void destroy_image_views(std::vector const& image_views); + // A conversion function which allows this Swapchain to be used + // in places where VkSwapchainKHR would have been used. + operator VkSwapchainKHR() const; + private: struct { PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; diff --git a/tests/bootstrap_tests.cpp b/tests/bootstrap_tests.cpp index 2c2f535..abad9bb 100644 --- a/tests/bootstrap_tests.cpp +++ b/tests/bootstrap_tests.cpp @@ -491,6 +491,33 @@ TEST_CASE("Querying Required Extension Features", "[VkBootstrap.select_features] } } +TEST_CASE("Passing vkb classes to Vulkan handles", "[VkBootstrap.pass_class_to_handle") { + GIVEN("A working instance") { + auto instance = get_instance(); + + // Check if we can get instance functions. + PFN_vkVoidFunction instanceFunction = instance.fp_vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"); // validation layers should be provided. + REQUIRE(instanceFunction != NULL); + + auto window = create_window_glfw("Conversion operators"); + auto surface = create_surface_glfw(instance, window); + + vkb::PhysicalDeviceSelector physicalDeviceSelector(instance); + auto physicalDevice = physicalDeviceSelector + .add_required_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME) + .set_surface(surface) + .select(); + REQUIRE(physicalDevice.has_value()); + vkb::DeviceBuilder deviceBuilder(physicalDevice.value()); + auto device = deviceBuilder.build(); + REQUIRE(device.has_value()); + + // Check if we can get a device function address, passing vkb::Device to the function. + PFN_vkVoidFunction deviceFunction = instance.fp_vkGetDeviceProcAddr(device.value(), "vkAcquireNextImageKHR"); + REQUIRE(deviceFunction != NULL); + } +} + #if defined(VK_API_VERSION_1_1) TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]") { GIVEN("A working instance") {