1 | #pragma once |
---|---|
2 | |
3 | #ifdef _WIN64 |
4 | #define VK_USE_PLATFORM_WIN32_KHR 1 |
5 | #endif |
6 | |
7 | #include "taichi/rhi/vulkan/vulkan_common.h" |
8 | |
9 | #include <taichi/rhi/device.h> |
10 | #include <taichi/program/kernel_profiler.h> |
11 | |
12 | #include <memory> |
13 | #include <optional> |
14 | #include <vector> |
15 | #include <string> |
16 | #include <functional> |
17 | |
18 | namespace taichi::lang { |
19 | namespace vulkan { |
20 | |
21 | class VulkanDevice; |
22 | |
23 | struct VulkanQueueFamilyIndices { |
24 | std::optional<uint32_t> compute_family; |
25 | std::optional<uint32_t> graphics_family; |
26 | std::optional<uint32_t> present_family; |
27 | // TODO: While it is the case that all COMPUTE/GRAPHICS queue also support |
28 | // TRANSFER by default, maye there are some performance benefits to find a |
29 | // TRANSFER-dedicated queue family. |
30 | // https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer#page_Transfer-queue |
31 | |
32 | bool is_complete() const { |
33 | return compute_family.has_value(); |
34 | } |
35 | |
36 | bool is_complete_for_ui() { |
37 | return graphics_family.has_value() && present_family.has_value(); |
38 | } |
39 | }; |
40 | |
41 | /** |
42 | * This class creates a VulkanDevice instance. The underlying Vk* resources are |
43 | * embedded directly inside the class. |
44 | */ |
45 | class TI_DLL_EXPORT VulkanDeviceCreator { |
46 | public: |
47 | struct Params { |
48 | // User-provided API version. If assigned, the users MUST list all |
49 | // their desired extensions in `additional_instance_extensions` and |
50 | // `additional_device_extensions`; no extension is enabled by default. |
51 | std::optional<uint32_t> api_version; |
52 | bool is_for_ui{false}; |
53 | std::vector<std::string> additional_instance_extensions; |
54 | std::vector<std::string> additional_device_extensions; |
55 | // the VkSurfaceKHR needs to be created after creating the VkInstance, but |
56 | // before creating the VkPhysicalDevice thus, we allow the user to pass in a |
57 | // custom surface creator |
58 | std::function<VkSurfaceKHR(VkInstance)> surface_creator; |
59 | bool enable_validation_layer{false}; |
60 | }; |
61 | |
62 | explicit VulkanDeviceCreator(const Params ¶ms); |
63 | ~VulkanDeviceCreator(); |
64 | |
65 | const VulkanDevice *device() const { |
66 | return ti_device_.get(); |
67 | } |
68 | |
69 | VulkanDevice *device() { |
70 | return ti_device_.get(); |
71 | } |
72 | |
73 | VkSurfaceKHR get_surface() { |
74 | return surface_; |
75 | } |
76 | |
77 | private: |
78 | void create_instance(uint32_t vk_api_version, bool manual_create); |
79 | void setup_debug_messenger(); |
80 | void create_surface(); |
81 | void pick_physical_device(); |
82 | void create_logical_device(bool manual_create); |
83 | |
84 | VkInstance instance_{VK_NULL_HANDLE}; |
85 | VkDebugUtilsMessengerEXT debug_messenger_{VK_NULL_HANDLE}; |
86 | VkPhysicalDevice physical_device_{VK_NULL_HANDLE}; |
87 | VulkanQueueFamilyIndices queue_family_indices_; |
88 | VkDevice device_{VK_NULL_HANDLE}; |
89 | |
90 | VkQueue compute_queue_{VK_NULL_HANDLE}; |
91 | VkQueue graphics_queue_{VK_NULL_HANDLE}; |
92 | |
93 | VkSurfaceKHR surface_{VK_NULL_HANDLE}; |
94 | |
95 | std::unique_ptr<VulkanDevice> ti_device_{nullptr}; |
96 | |
97 | Params params_; |
98 | }; |
99 | |
100 | } // namespace vulkan |
101 | } // namespace taichi::lang |
102 |