Toast Engine
Loading...
Searching...
No Matches
vulkan_core.hpp
1
4
5#pragma once
6
7#include "async_compute.hpp"
8#include "vulkan_common.hpp"
9
10#include <algorithm>
11#include <external/inc/renderdoc/renderdoc_app.h>
12#include <limits>
13#include <memory>
14#include <mutex>
15#include <optional>
16#include <span>
17#include <string_view>
18#include <vector>
19
20namespace renderer {
21
22enum class NsightMode : uint8_t {
23 none,
24 graphics_capture,
25 gpu_trace
26};
27
29 int total = 0;
30 int device_type = 0;
31 int memory = 0;
32 int limits = 0;
33 int features = 0;
34 int extensions = 0;
35 int vulkan_support = 0;
36 int queue_support = 0;
37
38 int graphics_idx = -1;
39 int compute_idx = -1;
40 int transfer_idx = -1;
41
42 std::vector<std::string> missing_extensions;
43
44 [[nodiscard]]
45 auto toString() const noexcept -> std::string;
46};
47
48class VulkanCore {
49public:
50 VulkanCore(
51 std::span<const char* const> required_instance_extensions, std::span<const char* const> required_device_extensions = {}
52 ) noexcept;
53 ~VulkanCore() = default;
54
55 VulkanCore(const VulkanCore&) = delete;
56 auto operator=(const VulkanCore&) -> VulkanCore& = delete;
57
58 [[nodiscard]]
59 auto getInstance() const noexcept -> const vk::raii::Instance& {
60 return m_instance;
61 }
62
63 [[nodiscard]]
64 auto getDevice() const noexcept -> const vk::raii::Device& {
65 return m_device;
66 }
67
68 [[nodiscard]]
69 auto getPhysicalDevice() const noexcept -> const vk::raii::PhysicalDevice& {
70 return m_physical_device;
71 }
72
73 [[nodiscard]]
74 auto getAllocator() const noexcept -> const vma::raii::Allocator& {
75 return *m_allocator;
76 }
77
78 [[nodiscard]]
79 auto getGraphicsQueueFamilyIndex() const noexcept -> uint32_t {
80 return m_graphics_queue_family_index;
81 }
82
83 [[nodiscard]]
84 auto getComputeQueueFamilyIndex() const noexcept -> uint32_t {
85 return m_compute_queue_family_index;
86 }
87
88 [[nodiscard]]
89 auto getTransferQueueFamilyIndex() const noexcept -> uint32_t {
90 return m_transfer_queue_family_index;
91 }
92
93 [[nodiscard]]
94 auto getGraphicsQueue() const noexcept -> vk::Queue {
95 return m_graphics_queue;
96 }
97
99 [[nodiscard]]
100 auto getComputeQueue() const noexcept -> vk::Queue {
101 return m_compute_queue;
102 }
103
104 [[nodiscard]]
105 auto getTransferQueue() const noexcept -> vk::Queue {
106 return m_transfer_queue;
107 }
108
109 [[nodiscard]]
110 auto getRenderDocAPI() const noexcept -> const RENDERDOC_API_1_6_0* {
111 return rdoc_api;
112 }
113
114 [[nodiscard]]
115 auto isRayTracingSupported() const noexcept -> bool {
116 return m_ray_tracing_supported;
117 }
118
120 [[nodiscard]]
121 auto isMeshShaderSupported() const noexcept -> bool {
122 return m_mesh_shader_supported;
123 }
124
125 [[nodiscard]]
126 auto getBufferAddress(vk::Buffer buffer) const -> vk::DeviceAddress {
127 vk::BufferDeviceAddressInfo info {};
128 info.buffer = buffer;
129 return m_device.getBufferAddress(info);
130 }
131
132 [[nodiscard]]
133 auto getScratchAllocationSize(vk::DeviceSize needed) const noexcept -> vk::DeviceSize {
134 return needed + std::max(m_as_scratch_alignment, 1u);
135 }
136
138 [[nodiscard]]
139 auto getAlignedScratchAddress(vk::Buffer buffer) const -> vk::DeviceAddress {
140 const auto alignment = static_cast<vk::DeviceAddress>(std::max(m_as_scratch_alignment, 1u));
141 return (getBufferAddress(buffer) + alignment - 1) & ~(alignment - 1);
142 }
143
144 [[nodiscard]]
145 auto isMemoryBudgetSupported() const noexcept -> bool {
146 return m_memory_budget_supported;
147 }
148
149 [[nodiscard]]
150 auto isFrameBoundarySupported() const noexcept -> bool {
151 return m_frame_boundary_supported;
152 }
153
154 [[nodiscard]]
155 auto isTextureSharingSupported() const noexcept -> bool {
156 return m_texture_sharing_supported;
157 }
158
159 [[nodiscard]]
160 auto getNsightMode() const noexcept -> NsightMode {
161 return m_nsight_mode;
162 }
163
164#if defined(_WIN32)
166 void activateNsightGpuTraceIfNeeded() const;
167#endif
168
169 [[nodiscard]]
170 auto validationEnabled() const noexcept -> bool {
171 return m_validation_enabled;
172 }
173
174 [[nodiscard]]
175 auto debugUtilsEnabled() const noexcept -> bool {
176 return m_debug_utils_enabled;
177 }
178
179 [[nodiscard]]
180 auto supportsSamplerAnisotropy() const noexcept -> bool {
181 return m_sampler_anisotropy_supported;
182 }
183
184 [[nodiscard]]
185 auto maxSamplerAnisotropy() const noexcept -> float {
186 return m_max_sampler_anisotropy;
187 }
188
190 [[nodiscard]]
191 auto getPipelineCache() const noexcept -> const vk::raii::PipelineCache& {
192 return m_pipeline_cache;
193 }
194
196 void loadPipelineCache() const;
197
198 void savePipelineCache() const;
199
201 void updateTracyMemory() const;
202
204 [[nodiscard]]
205 auto asyncCompute() const noexcept -> AsyncCompute& {
206 return *m_async_compute;
207 }
208
210 [[nodiscard]]
211 auto transferSubmitMutex() const noexcept -> std::mutex& {
212 return m_transfer_submit_mutex;
213 }
214
215 // TODO UI system should submit on the render thread
216 [[nodiscard]]
217 auto graphicsSubmitMutex() const noexcept -> std::mutex& {
218 return m_graphics_submit_mutex;
219 }
220
221private:
222 void pickPhysicalDevice(std::span<const char* const> required_device_extensions);
223 void createLogicalDeviceAndAllocator(std::span<const char* const> required_device_extensions);
224
225 [[nodiscard]]
226 auto calculateDeviceScore(const vk::PhysicalDevice& device, std::span<const char* const> required_device_extensions)
227 -> DeviceScore;
228
229 [[nodiscard]]
230 auto checkValidationLayerSupport() -> bool;
231
232 [[nodiscard]]
233 static auto checkInstanceExtensionSupport(std::string_view extension) -> bool;
234
235#if defined(_WIN32)
236 void initializeNsightActivity();
237#endif
238
239 bool m_validation_enabled = false;
240 bool m_debug_utils_enabled = false;
241
242 vk::raii::Context m_context;
243 vk::raii::Instance m_instance = nullptr;
244#ifndef NDEBUG
245 vk::raii::DebugUtilsMessengerEXT m_debug_messenger = nullptr;
246#endif
247
248 vk::raii::PhysicalDevice m_physical_device = nullptr;
249 vk::raii::Device m_device = nullptr;
251 vk::raii::PipelineCache m_pipeline_cache = nullptr;
253 std::unique_ptr<AsyncCompute> m_async_compute;
254
255 std::optional<vma::raii::Allocator> m_allocator;
256
257 uint32_t m_graphics_queue_family_index = std::numeric_limits<uint32_t>::max();
258 uint32_t m_compute_queue_family_index = std::numeric_limits<uint32_t>::max();
259 uint32_t m_transfer_queue_family_index = std::numeric_limits<uint32_t>::max();
260 vk::Queue m_graphics_queue = nullptr;
261 vk::Queue m_compute_queue = nullptr;
262 vk::Queue m_transfer_queue = nullptr;
263
264 bool m_sampler_anisotropy_supported = false;
265 float m_max_sampler_anisotropy = 1.0f;
266
267 mutable std::mutex m_graphics_submit_mutex;
268 mutable std::mutex m_transfer_submit_mutex;
269 uint32_t m_transfer_queue_index = 0;
270
271 RENDERDOC_API_1_6_0* rdoc_api = nullptr;
272
273 mutable NsightMode m_nsight_mode = NsightMode::none;
274
275 bool m_frame_boundary_supported = false;
276 bool m_memory_budget_supported = false;
277
278 bool m_texture_sharing_supported = false;
279
280 bool m_ray_tracing_supported = false;
281 bool m_mesh_shader_supported = false;
282
283 uint32_t m_as_scratch_alignment = 0;
284 mutable bool m_nsight_gputrace_activated = false;
285};
286}
Definition async_compute.hpp:19
void updateTracyMemory() const
Replays live VRAM blocks to a newly connected Tracy and plots heap usage.
Definition vulkan_core.cpp:1245
auto getAlignedScratchAddress(vk::Buffer buffer) const -> vk::DeviceAddress
Pair with getScratchAllocationSize().
Definition vulkan_core.hpp:139
auto getComputeQueue() const noexcept -> vk::Queue
Only AsyncCompute submits to it.
Definition vulkan_core.hpp:100
auto asyncCompute() const noexcept -> AsyncCompute &
The only way to submit compute work outside a frame.
Definition vulkan_core.hpp:205
void loadPipelineCache() const
Before creating pipelines. Missing or stale files are ignored.
Definition vulkan_core.cpp:1200
auto transferSubmitMutex() const noexcept -> std::mutex &
Only contended when AsyncCompute shares the transfer queue.
Definition vulkan_core.hpp:211
auto getPipelineCache() const noexcept -> const vk::raii::PipelineCache &
Usable from any thread.
Definition vulkan_core.hpp:191
auto isMeshShaderSupported() const noexcept -> bool
VK_EXT_mesh_shader with task shaders and the output limits the voxel meshlets need.
Definition vulkan_core.hpp:121
Definition vulkan_core.hpp:28