diff --git a/demos/17-buffer-device-address/application.cpp b/demos/17-buffer-device-address/application.cpp index 4ddc950..e79f527 100644 --- a/demos/17-buffer-device-address/application.cpp +++ b/demos/17-buffer-device-address/application.cpp @@ -22,8 +22,7 @@ import vk; #include #define GLM_ENABLE_EXPERIMENTAL #include - -#include +#include #include @@ -301,12 +300,10 @@ main() { } // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - vk::queue_indices queue_indices = physical_device.family_indices(); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -353,7 +350,8 @@ main() { .features = device_features.data(), .queue_priorities = priorities, .extensions = extensions, - .queue_family_index = queue_indices.graphics, + // .queue_family_index = queue_indices.graphics, + .queue_family_index = 0, }; vk::device logical_device(physical_device, logical_device_params); @@ -366,9 +364,7 @@ main() { vk::swapchain_params enumerate_swapchain_settings = { .width = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, @@ -383,8 +379,6 @@ main() { // querying presentable images std::span images = main_swapchain.get_images(); - - std::println("span::size() = {}", images.size()); uint32_t image_count = static_cast(images.size()); // Creating Images @@ -434,7 +428,7 @@ main() { for (size_t i = 0; i < swapchain_command_buffers.size(); i++) { vk::command_params settings = { .levels = vk::command_levels::primary, - .queue_index = enumerate_swapchain_settings.present_index, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -807,6 +801,6 @@ main() { logical_device.destroy(); window_surface.destroy(); glfwDestroyWindow(window); - api_instance.destroy(); + // api_instance.destruct(); return 0; } diff --git a/vulkan-cpp/instance.cppm b/vulkan-cpp/instance.cppm index 6769cd7..e81fe38 100644 --- a/vulkan-cpp/instance.cppm +++ b/vulkan-cpp/instance.cppm @@ -3,11 +3,13 @@ module; #include #include #include +#include export module vk:instance; -export import :types; -export import :utilities; +import :types; +import :utilities; +import :physical_device; export namespace vk { inline namespace v1 { @@ -20,6 +22,8 @@ export namespace vk { */ class instance { public: + instance() = delete("Disallow constructing empty vk::instance"); + /** * @param p_config sets the application information that vulkan has * optionally. @@ -44,23 +48,6 @@ export namespace vk { .pApplicationInfo = &app_info }; - // Setting up validation layers properties - uint32_t layer_count = 0; - std::vector layer_properties; - vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - // std::vector layer_properties(layer_count); - layer_properties.resize(layer_count); - vkEnumerateInstanceLayerProperties(&layer_count, - layer_properties.data()); - - for (const VkLayerProperties property : layer_properties) { - m_layer_properties.emplace_back( - property.layerName, - property.specVersion, - property.implementationVersion, - property.description); - } - // Setting up instance extensions instance_ci.enabledExtensionCount = static_cast(p_config.extensions.size()); @@ -123,14 +110,81 @@ export namespace vk { #endif } + ~instance() = default; + //! @return true if a valid VkInstance [[nodiscard]] bool alive() const { return !m_instance; } - //! @return available validation layers + //! @return Requesting available validation layers std::span validation() { + uint32_t layer_count = 0; + std::vector layer_properties; + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + + layer_properties.resize(layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, + layer_properties.data()); + + for (const VkLayerProperties property : layer_properties) { + m_layer_properties.emplace_back( + property.layerName, + property.specVersion, + property.implementationVersion, + property.description); + } + return m_layer_properties; } + /** + * @brief Enumerate physical devices and select specific physical + * device to report properties from. + * + * @return vk::physical_device if successful + * @return VkResult if an unexpected error occurs + * + * + * ```C++ + * + * vk::instance api_instance = ...; + * std::expected expected = + * api_instance.enumerate_physical_device(vk::physical_device_type::integrated); + * + * vk::physical_device physical_device = expected.value(); + * + * ``` + */ + std::expected enumerate_physical_device( + physical_gpu p_device_type) { + uint32_t device_count = 0; + VkResult res = vkEnumeratePhysicalDevices( + m_instance, &device_count, nullptr); + + if (res != VK_SUCCESS) { + return std::unexpected(res); + } + + std::vector physical_devices(device_count); + res = vkEnumeratePhysicalDevices( + m_instance, &device_count, physical_devices.data()); + + if (res != VK_SUCCESS) { + return std::unexpected(res); + } + + for (const auto& device : physical_devices) { + VkPhysicalDeviceProperties device_properties; + vkGetPhysicalDeviceProperties(device, &device_properties); + + if (device_properties.deviceType == + static_cast(p_device_type)) { + return physical_device(device); + } + } + + return std::unexpected(res); + } + /** * @brief returns function pointer to allow for setting debug object * name @@ -154,7 +208,11 @@ export namespace vk { operator VkInstance() const { return m_instance; } //! @brief Invokes the destruction of the VkInstance. - void destroy() {} + void destruct() { + if (m_instance != nullptr) { + vkDestroyInstance(m_instance, nullptr); + } + } private: VkInstance m_instance = nullptr; diff --git a/vulkan-cpp/physical_device.cppm b/vulkan-cpp/physical_device.cppm index 4965d1e..b739c53 100644 --- a/vulkan-cpp/physical_device.cppm +++ b/vulkan-cpp/physical_device.cppm @@ -7,93 +7,96 @@ module; export module vk:physical_device; -export import :utilities; -export import :types; +import :utilities; +import :types; export namespace vk { inline namespace v1 { class physical_device { public: - physical_device() = default; + physical_device() = + delete("Not allowed constructing empty vk::physical_device"); - physical_device( - const VkInstance& p_instance, - const physical_enumeration& p_physical_enumeration) { - m_physical_device = enumerate_physical_devices( - p_instance, p_physical_enumeration.device_type); + physical_device(const VkPhysicalDevice& p_physical) + : m_physical_device(p_physical) {} - if (m_physical_device == nullptr) { - return; - } + ~physical_device() = default; - m_queue_family_properties = - enumerate_queue_family_properties(m_physical_device); + /** + * @brief reports the properties of this specific physical device + * + * @return VkPhysicalDeviceProperties of the selected physical + * device + */ + [[nodiscard]] VkPhysicalDeviceProperties properties() const { + VkPhysicalDeviceProperties device_properties; + vkGetPhysicalDeviceProperties(m_physical_device, + &device_properties); - // This makes sure that we get the graphics, compute, and - // transfer queue indices from the physical queue family - // assigned - uint32_t queue_index = 0; - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - m_queue_family_indices.graphics = queue_index; - break; - } + return device_properties; + } - queue_index++; - } - queue_index = 0; + /** + * @brief Query for properties for queues for you specific physical + * device. + */ + [[nodiscard]] std::span + queue_family_properties() { + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( + m_physical_device, &queue_family_count, nullptr); - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_COMPUTE_BIT) { - m_queue_family_indices.compute = queue_index; - } - queue_index++; - } - queue_index = 0; + m_queue_family_properties.resize(queue_family_count); - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_TRANSFER_BIT) { - m_queue_family_indices.transfer = queue_index; - } - queue_index++; - } - queue_index = 0; + vkGetPhysicalDeviceQueueFamilyProperties( + m_physical_device, + &queue_family_count, + m_queue_family_properties.data()); + + return m_queue_family_properties; } //! @return true if physical device is valid [[nodiscard]] bool alive() const { return m_physical_device; } - //! @return queue family indices for graphics, compute, and transfer - //! operations - [[nodiscard]] queue_indices family_indices() const { - return m_queue_family_indices; - } - - //! @return the presentation index for the presentation queue - uint32_t queue_present_index(const VkSurfaceKHR& p_surface) { - uint32_t presentation_index = 0; - uint32_t compatible = false; - uint32_t i = 0; + /** + * @brief Checks if the surface has presentation supported + * + * @param p_surface to perform presentation supported check on. + * @param p_queue_index to specify the queue family index to check + * presentation is supported. + * + * @return true if presentation supported, otherwise false + * + * + * Example: + * + * ```C++ + * + * vk::physical_device physical_device = ...; + * vk::surface surface = ...; + * + * bool is_present_supported = + * physical_device.is_present_supported(surface); + * + * if(is_present_supported) { ... } + * + * ``` + */ + [[nodiscard]] uint32_t is_present_supported( + const VkSurfaceKHR& p_surface, + uint32_t p_queue_index = 0) const { + uint32_t is_compatible = false; for (const auto& queue_family : m_queue_family_properties) { - vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( - m_physical_device, i, p_surface, &compatible), - "vkGetPhysicalDeviceSurfaceSupportKHR"); - - if (compatible) { - presentation_index = i; - } + vk_check( + vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, + p_queue_index, + p_surface, + &is_compatible), + "vkGetPhysicalDeviceSurfaceSupportKHR"); } - return presentation_index; - } - - //! @return physical device memory requirements - [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() - const { - VkPhysicalDeviceMemoryProperties physical_memory_properties; - vkGetPhysicalDeviceMemoryProperties( - m_physical_device, &physical_memory_properties); - return physical_memory_properties; + return is_compatible; } [[nodiscard]] uint32_t memory_properties( @@ -129,28 +132,54 @@ export namespace vk { [[nodiscard]] VkFormat request_depth_format( std::span p_format_supported) { - return request_compatible_formats( + return request_formats( p_format_supported, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } /** - * @brief Requests a format and select an arbitrary format if those - * are available to select those + * @brief Requests for compatible formats to select * * @param p_tiling is selecting arrangements of the data format * @param p_feature_flag is the bitmask selection for the image * format */ - [[nodiscard]] VkFormat request_format( + [[nodiscard]] VkFormat request_formats( std::span p_format_supported, uint32_t p_tiling, uint32_t p_feature_flag) { - return request_compatible_formats( - p_format_supported, - static_cast(p_tiling), - static_cast(p_feature_flag)); + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageTiling tiling = static_cast(p_tiling); + VkFormatFeatureFlags feature_flag = + static_cast(p_feature_flag); + + for (uint32_t i = 0; i < p_format_supported.size(); i++) { + VkFormat current = + static_cast(p_format_supported[i]); + VkFormatProperties format_properties; + vkGetPhysicalDeviceFormatProperties( + m_physical_device, current, &format_properties); + + switch (tiling) { + case VK_IMAGE_TILING_LINEAR: + if (format_properties.linearTilingFeatures & + feature_flag) { + format = current; + } + break; + case VK_IMAGE_TILING_OPTIMAL: + if (format_properties.optimalTilingFeatures & + feature_flag) { + format = current; + } + break; + default: + break; + } + } + + return format; } [[nodiscard]] surface_params request_surface( @@ -223,70 +252,6 @@ export namespace vk { return final_image_count; } - VkFormat request_compatible_formats( - std::span p_format_supported, - VkImageTiling p_tiling, - VkFormatFeatureFlags p_feature_flag) { - VkFormat format = VK_FORMAT_UNDEFINED; - - for (uint32_t i = 0; i < p_format_supported.size(); i++) { - VkFormat current = - static_cast(p_format_supported[i]); - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties( - m_physical_device, current, &format_properties); - - switch (p_tiling) { - case VK_IMAGE_TILING_LINEAR: - if (format_properties.linearTilingFeatures & - p_feature_flag) { - format = current; - } - break; - case VK_IMAGE_TILING_OPTIMAL: - if (format_properties.optimalTilingFeatures & - p_feature_flag) { - format = current; - } - break; - default: - break; - } - } - - return format; - } - - VkPhysicalDevice enumerate_physical_devices( - const VkInstance& p_instance, - const physical_gpu& p_physical_device_type) { - uint32_t device_count = 0; - vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); - - if (device_count == 0) { - return nullptr; - } - - // TODO: Turn this into map - std::vector physical_devices(device_count); - vkEnumeratePhysicalDevices( - p_instance, &device_count, physical_devices.data()); - VkPhysicalDevice physical_device = nullptr; - - for (const auto& device : physical_devices) { - VkPhysicalDeviceProperties device_properties; - vkGetPhysicalDeviceProperties(device, &device_properties); - - if (device_properties.deviceType == - static_cast( - p_physical_device_type)) { - physical_device = device; - } - } - return physical_device; - } - private: VkPhysicalDevice m_physical_device = nullptr; std::vector m_queue_family_properties; diff --git a/vulkan-cpp/swapchain.cppm b/vulkan-cpp/swapchain.cppm index 74d8c15..28051d5 100644 --- a/vulkan-cpp/swapchain.cppm +++ b/vulkan-cpp/swapchain.cppm @@ -1,7 +1,6 @@ module; #include -#include #include #include #include @@ -14,34 +13,37 @@ export import :device_queue; export namespace vk { inline namespace v1 { + class swapchain { public: + swapchain() = delete("Cannot construct empty swapchain"); + swapchain(const VkDevice& p_device, const VkSurfaceKHR& p_surface, const swapchain_params& p_settings, const surface_params& p_surface_properties) : m_device(p_device) - , m_surface_handler(p_surface) - , m_surface_params(p_surface_properties) { - m_image_size = m_surface_params.image_size; - - std::println("Surface Image Size = {}", m_image_size); + , m_surface_handler(p_surface) { - create(p_settings); + construct(p_settings, p_surface_properties); } - void create(const swapchain_params& p_settings) { + ~swapchain() = default; + + void construct(const swapchain_params& p_settings, + const surface_params& p_surface_properties) { VkSwapchainCreateInfoKHR swapchain_ci = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = nullptr, .surface = m_surface_handler, - .minImageCount = m_image_size, - .imageFormat = m_surface_params.format.format, - .imageColorSpace = m_surface_params.format.colorSpace, + .minImageCount = p_surface_properties.image_size, + .imageFormat = p_surface_properties.format.format, + .imageColorSpace = p_surface_properties.format.colorSpace, // use physical device surface formats to getting the right // formats in vulkan - .imageExtent = m_surface_params.capabilities.currentExtent, + .imageExtent = + p_surface_properties.capabilities.currentExtent, .imageArrayLayers = 1, // Remove COLOR_ATTACHMENT flag because its not needed @@ -49,7 +51,7 @@ export namespace vk { .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, .preTransform = - m_surface_params.capabilities.currentTransform, + p_surface_properties.capabilities.currentTransform, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, .presentMode = static_cast(p_settings.present_mode), @@ -58,7 +60,6 @@ export namespace vk { VkResult res = vkCreateSwapchainKHR( m_device, &swapchain_ci, nullptr, &m_swapchain_handler); - std::println("VkResult = {}", static_cast(res)); vk_check(res, "vkCreateSwapchainKHR"); } @@ -75,6 +76,7 @@ export namespace vk { * std::span images = main_swapchain.get_images(); * * ``` + * TODO: Have this return std::span * */ std::span get_images() { @@ -103,11 +105,6 @@ export namespace vk { VkDevice m_device = nullptr; VkSwapchainKHR m_swapchain_handler = nullptr; VkSurfaceKHR m_surface_handler = nullptr; - surface_params m_surface_params{}; - uint32_t m_image_size = 0; - - device_queue m_present_queue; - std::vector m_images; }; }; diff --git a/vulkan-cpp/types.cppm b/vulkan-cpp/types.cppm index 65681f0..1083d53 100644 --- a/vulkan-cpp/types.cppm +++ b/vulkan-cpp/types.cppm @@ -1418,7 +1418,7 @@ export namespace vk { device_address_bit = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, device_address_capture_replay_bit = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, - zero_initialize_bit = VK_MEMORY_ALLOCATE_ZERO_INITIALIZE_BIT_EXT, + // zero_initialize_bit = VK_MEMORY_ALLOCATE_ZERO_INITIALIZE_BIT_EXT, device_mask_bit_khr = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR, device_address_bit_khr = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, device_address_capture_replay_bit_khr = diff --git a/vulkan-cpp/utilities.cppm b/vulkan-cpp/utilities.cppm index b1f4957..7805bcc 100644 --- a/vulkan-cpp/utilities.cppm +++ b/vulkan-cpp/utilities.cppm @@ -9,7 +9,7 @@ module; export module vk:utilities; -export import :types; +import :types; export namespace vk { inline namespace v1 { @@ -22,20 +22,6 @@ export namespace vk { } } - std::vector enumerate_queue_family_properties( - const VkPhysicalDevice& p_physical) { - uint32_t queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( - p_physical, &queue_family_count, nullptr); - std::vector queue_family_properties( - queue_family_count); - - vkGetPhysicalDeviceQueueFamilyProperties( - p_physical, &queue_family_count, queue_family_properties.data()); - - return queue_family_properties; - } - VkSemaphore create_semaphore(const VkDevice& p_device) { // creating semaphores VkSemaphoreCreateInfo semaphore_ci = {