Class Device

Class Documentation

class Device

A RAII wrapper class for VkDevice, VkPhysicalDevice and VkQueues

Note

There is no method is_layer_supported in this wrapper class because device layers are deprecated.

Public Functions

Device(const Instance &inst, VkSurfaceKHR surface, bool prefer_distinct_transfer_queue, VkPhysicalDevice physical_device, std::span<const char*> required_extensions, const VkPhysicalDeviceFeatures &required_features, const VkPhysicalDeviceFeatures &optional_features = {})

Default constructor

Note

The creation of the physical device will not fail if one of the optional device features is not available

Parameters
  • inst – The Vulkan instance

  • surface – The window surface

  • prefer_distinct_transfer_queue – Specifies if a distinct transfer queue will be preferred

  • physical_device – The physical device

  • required_extensions – The required device extensions

  • required_features – The required device features which the physical device must all support

  • optional_features – The optional device features which do not necessarily have to be present

Throws
  • std::runtime_error – The physical device is not suitable

  • std::runtime_error – No graphics queue could be found

  • std::runtime_error – No presentation queue could be found

  • VulkanException – vkCreateDevice call failed

  • VulkanException – vmaCreateAllocator call failed

Device(const Device&) = delete
Device(Device&&) noexcept
~Device()
Device &operator=(const Device&) = delete
Device &operator=(Device&&) = delete
inline VkDevice device() const
VkSurfaceCapabilitiesKHR get_surface_capabilities(VkSurfaceKHR surface) const

Call vkGetPhysicalDeviceSurfaceCapabilitiesKHR

Parameters

surface – The window surface

Throws

VulkanException – vkGetPhysicalDeviceSurfaceCapabilitiesKHR call failed

Returns

The surface capabilities

bool format_supports_feature(VkFormat format, VkFormatFeatureFlagBits feature) const

Check if a format supports a feature for images created with VK_IMAGE_TILING_OPTIMAL

Parameters
  • format – The format

  • feature – The requested format feature

Returns

true if the format feature is supported

bool is_presentation_supported(VkSurfaceKHR surface, std::uint32_t queue_family_index) const

Call vkGetPhysicalDeviceSurfaceSupportKHR

Parameters
  • surface – The window surface

  • queue_family_index – The queue family index

Throws

VulkanException – vkGetPhysicalDeviceSurfaceSupportKHR call failed

Returns

true if presentation is supported

void execute(const std::string &name, const std::function<void(const CommandBuffer &cmd_buf)> &cmd_lambda) const

A wrapper method for beginning, ending and submitting command buffers. This method calls the request method for the given command pool, begins the command buffer, executes the lambda, ends recording the command buffer, submits it and waits for it.

Parameters
  • name – The internal debug name of the command buffer (must not be empty)

  • cmd_lambda – The command lambda to execute

std::optional<std::uint32_t> find_queue_family_index_if(const std::function<bool(std::uint32_t index, const VkQueueFamilyProperties&)> &criteria_lambda)

Find a queue family index that suits a specific criteria

Parameters

criteria_lambda – The lambda to sort out unsuitable queue families

Returns

The queue family index which was found (if any), std::nullopt otherwise

inline VkPhysicalDevice physical_device() const
inline VmaAllocator allocator() const
inline const VkPhysicalDeviceFeatures &enabled_device_features() const

Note

Enabled features = required features + optional features which are supported

inline const std::string &gpu_name() const
inline VkQueue graphics_queue() const
inline VkQueue present_queue() const
inline VkQueue transfer_queue() const
inline std::uint32_t graphics_queue_family_index() const
inline std::uint32_t present_queue_family_index() const
inline std::uint32_t transfer_queue_family_index() const
void set_debug_marker_name(void *object, VkDebugReportObjectTypeEXT object_type, const std::string &name) const

Assign an internal Vulkan debug marker name to a Vulkan object. This internal name can be seen in external debuggers like RenderDoc.

Note

This method is only available in debug mode with VK_EXT_debug_marker device extension enabled.

Parameters
  • object – The Vulkan object

  • object_type – The Vulkan debug report object type

  • name – The internal name of the Vulkan object

void set_memory_block_attachment(void *object, VkDebugReportObjectTypeEXT object_type, std::uint64_t name, std::size_t memory_size, const void *memory_block) const

Assigns a block of memory to a Vulkan resource. This memory block can be seen in external debuggers like RenderDoc.

Note

This method is only available in debug mode with VK_EXT_debug_marker device extension enabled.

Parameters
  • object – The Vulkan object

  • object_type – The Vulkan debug report object type

  • name – The name of the memory block which will be connected to this object

  • memory_size – The size of the memory block in bytes

  • memory_block – The memory block to read from

void bind_debug_region(VkCommandBuffer command_buffer, const std::string &name, std::array<float, 4> color) const

Annotate a rendering region in Vulkan debug markers. The rendering region will be visible in external debuggers like RenderDoc.

Parameters
  • command_buffer – The command buffer

  • name – The name of the rendering region

  • color – The rgba color of the rendering region

void insert_debug_marker(VkCommandBuffer command_buffer, const std::string &name, std::array<float, 4> color) const

Insert a debug markers into the current renderpass using vkCmdDebugMarkerInsertEXT. This debug markers can be seen in external debuggers like RenderDoc.

Parameters
  • command_buffer – The command buffer which is associated to the debug marker

  • name – The name of the debug marker

  • color – An array of red, green, blue and alpha values for the debug region’s color

void end_debug_region(VkCommandBuffer command_buffer) const

End the debug region of the current renderpass using vkCmdDebugMarkerEndEXT.

Parameters

command_buffer – The command buffer which is associated to the debug marker

void create_command_pool(const VkCommandPoolCreateInfo &command_pool_ci, VkCommandPool *command_pool, const std::string &name) const

Call vkCreateCommandPool

Parameters
  • command_pool_ci – The command pool create info structure

  • command_pool – The command pool to create

  • name – The internal debug marker name which will be assigned to this command pool

void create_descriptor_pool(const VkDescriptorPoolCreateInfo &descriptor_pool_ci, VkDescriptorPool *descriptor_pool, const std::string &name) const

Call vkCreateDescriptorPool

Parameters
  • descriptor_pool_ci – The descriptor pool create info structure

  • descriptor_pool – The descriptor pool to create

  • name – The internal debug marker name which will be assigned to this command pool

void create_descriptor_set_layout(const VkDescriptorSetLayoutCreateInfo &descriptor_set_layout_ci, VkDescriptorSetLayout *descriptor_set_layout, const std::string &name) const

Call vkCreateDescriptorSetLayout

Parameters
  • descriptor_set_layout_ci – The descriptor set layout create info structure

  • descriptor_set_layout – The descriptor set layout to create

  • name – The internal debug marker name which will be assigned to this descriptor set layout

void create_fence(const VkFenceCreateInfo &fence_ci, VkFence *fence, const std::string &name) const

Call vkCreateFence

Parameters
  • fence_ci – The fence create info structure

  • fence – The fence to create

  • name – The internal debug marker name which will be assigned to this fence

void create_framebuffer(const VkFramebufferCreateInfo &framebuffer_ci, VkFramebuffer *framebuffer, const std::string &name) const

Call vkCreateFramebuffer

Parameters
  • framebuffer_ci – The framebuffer create info structure

  • framebuffer – The Vulkan framebuffer to create

  • name – The internal debug marker name which will be assigned to this framebuffer

void create_graphics_pipeline(const VkGraphicsPipelineCreateInfo &pipeline_ci, VkPipeline *pipeline, const std::string &name) const

Call vkCreateGraphicsPipelines

Parameters
  • pipeline_ci – The graphics pipeline create info structure

  • pipeline – The graphics pipeline to create

  • name – The internal debug marker name which will be assigned to this pipeline

void create_image_view(const VkImageViewCreateInfo &image_view_ci, VkImageView *image_view, const std::string &name) const

Call vkCreateImageView

Parameters
  • image_view_ci – The image view create info structure

  • image_view – The image view to create

  • name – The internal debug marker name which will be assigned to this image view

void create_pipeline_layout(const VkPipelineLayoutCreateInfo &pipeline_layout_ci, VkPipelineLayout *pipeline_layout, const std::string &name) const

Call vkCreatePipelineLayout

Parameters
  • pipeline_layout_ci – The pipeline layout create info structure

  • pipeline_layout – The pipeline layout to create

  • name – The internal debug marker name which will be assigned to this pipeline layout

void create_render_pass(const VkRenderPassCreateInfo &render_pass_ci, VkRenderPass *render_pass, const std::string &name) const

Call vkCreateRenderPass

Parameters
  • render_pass_ci – The render pass create info structure

  • render_pass – The render pass to create

  • name – The internal debug marker name which will be assigned to this render pass

void create_sampler(const VkSamplerCreateInfo &sampler_ci, VkSampler *sampler, const std::string &name) const

Call vkCreateSampler

Parameters
  • sampler_ci – The sampler create info structure

  • sampler – The sampler to create

  • name – The internal debug marker name which will be assigned to this sampler

void create_semaphore(const VkSemaphoreCreateInfo &semaphore_ci, VkSemaphore *semaphore, const std::string &name) const

Call vkCreateSemaphore

Parameters
  • semaphore_ci – The semaphore create info structure

  • semaphore – The semaphore to create

  • name – The internal debug marker name which will be assigned to this semaphore

void create_shader_module(const VkShaderModuleCreateInfo &shader_module_ci, VkShaderModule *shader_module, const std::string &name) const

Call vkCreateShaderModule

Parameters
  • shader_module_ci – The shader module create info structure

  • shader_module – The shader module to create

  • name – The internal debug marker name which will be assigned to this shader module

void create_swapchain(const VkSwapchainCreateInfoKHR &swapchain_ci, VkSwapchainKHR *swapchain, const std::string &name) const

Call vkCreateSwapchainKHR

Parameters
  • swapchain_ci – The swapchain_ci create info structure

  • swapchain – The swapchain to create

  • name – The internal debug marker name which will be assigned to this swapchain

const CommandBuffer &request_command_buffer(const std::string &name)

Request a command buffer from the thread_local command pool

Parameters

name – The name which will be assigned to the command buffer

Returns

A command buffer from the thread_local command pool

bool surface_supports_usage(VkSurfaceKHR surface, VkImageUsageFlagBits usage) const

Check if a surface supports a certain image usage

Parameters
  • surface – The window surface

  • usage – The requested image usage

Returns

true if the format feature is supported

void wait_idle() const

Call vkDeviceWaitIdle

Throws

VulkanException – vkDeviceWaitIdle call failed

Public Static Functions

static VkPhysicalDevice pick_best_physical_device(std::vector<DeviceInfo> &&physical_device_infos, const VkPhysicalDeviceFeatures &required_features, std::span<const char*> required_extensions)

Pick the best physical device automatically

Parameters
  • physical_device_infos – The data of the physical devices

  • required_features – The required device features

  • required_extensions – The required device extensions

Throws
  • std::runtime_error – There are no physical devices are available at all

  • std::runtime_error – No suitable physical device could be determined

Returns

The chosen physical device which is most suitable

static VkPhysicalDevice pick_best_physical_device(const Instance &inst, VkSurfaceKHR surface, const VkPhysicalDeviceFeatures &required_features, std::span<const char*> required_extensions)

Pick the best physical device automatically

Parameters
  • inst – The Vulkan instance

  • surface – The window surface

  • required_features – The required device features

  • required_extensions – The required device extensions

Returns

The chosen physical device which is most suitable

Private Functions

CommandPool &thread_graphics_pool() const

Get the thread_local command pool

Note

This method will create a command pool for the thread if it doesn’t already exist

Private Members

VkDevice m_device = {VK_NULL_HANDLE}
VkPhysicalDevice m_physical_device = {VK_NULL_HANDLE}
VmaAllocator m_allocator = {VK_NULL_HANDLE}
std::string m_gpu_name
VkPhysicalDeviceFeatures m_enabled_features = {}
VkQueue m_graphics_queue = {VK_NULL_HANDLE}
VkQueue m_present_queue = {VK_NULL_HANDLE}
VkQueue m_transfer_queue = {VK_NULL_HANDLE}
std::uint32_t m_present_queue_family_index = {0}
std::uint32_t m_graphics_queue_family_index = {0}
std::uint32_t m_transfer_queue_family_index = {0}
mutable std::vector<std::unique_ptr<CommandPool>> m_cmd_pools

According to NVidia, we should aim for one command pool per thread https://developer.nvidia.com/blog/vulkan-dos-donts/

mutable std::mutex m_mutex
PFN_vkDebugMarkerSetObjectTagEXT m_vk_debug_marker_set_object_tag = {nullptr}
PFN_vkDebugMarkerSetObjectNameEXT m_vk_debug_marker_set_object_name = {nullptr}
PFN_vkCmdDebugMarkerBeginEXT m_vk_cmd_debug_marker_begin = {nullptr}
PFN_vkCmdDebugMarkerEndEXT m_vk_cmd_debug_marker_end = {nullptr}
PFN_vkCmdDebugMarkerInsertEXT m_vk_cmd_debug_marker_insert = {nullptr}
PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name = {nullptr}