SpiecsEngine
 
Loading...
Searching...
No Matches
VulkanDevice.cpp
Go to the documentation of this file.
1/**
2* @file VulkanDevice.cpp.
3* @brief The VulkanDevice Class Implementation.
4* @author Spices.
5*/
6
7#include "Pchheader.h"
8#include "VulkanDevice.h"
9#include "Debugger/Perf/NsightPerfGPUProfilerHUD.h"
11
12namespace Spices {
13
18
20 VulkanState& vulkanState
21 )
22 : VulkanObject(vulkanState)
23 {
25
26 /**
27 * @brief Select one suitable physical device.
28 */
29 if (!SelectPhysicalDevice(vulkanState.m_Instance, vulkanState.m_Surface, vulkanState.m_Windows))
30 {
31 SPICES_CORE_ERROR("failed select physical device!")
32 }
33
34 /**
35 * @brief Create a queue identifies container.
36 */
37 std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::vector<VkQueue>>> queueFamilies; // family - id - queues
38
39 queueFamilies[m_QueueHelper.graphicqueuefamily .value()][0] = std::vector<VkQueue>(1 + NThreadQueue, VK_NULL_HANDLE);
40 queueFamilies[m_QueueHelper.presentqueuefamily .value()][1] = std::vector<VkQueue>(1, VK_NULL_HANDLE);
41 queueFamilies[m_QueueHelper.computequeuefamily .value()][2] = std::vector<VkQueue>(1 + NThreadQueue, VK_NULL_HANDLE);
42 queueFamilies[m_QueueHelper.transferqueuefamily.value()][3] = std::vector<VkQueue>(1, VK_NULL_HANDLE);
43
44 /**
45 * @brief Fill in VkDeviceQueueCreateInfo.
46 */
47 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
48 std::vector<std::shared_ptr<std::vector<float>>> QueuePriorities;
49 for (auto& [family, idItems] : queueFamilies)
50 {
51 uint32_t count = 0;
52 for (auto& [id, queues] : idItems)
53 {
54 count += queues.size();
55 }
56
57 std::shared_ptr<std::vector<float>> queuePriority = std::make_shared<std::vector<float>>(count, 1.0f);
58
59 /**
60 * @brief Instanced a VkDeviceQueueCreateInfo with default value.
61 */
62 VkDeviceQueueCreateInfo queueCreateInfo{};
63 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
64 queueCreateInfo.queueFamilyIndex = family;
65 queueCreateInfo.queueCount = count;
66 queueCreateInfo.pQueuePriorities = queuePriority->data();
67
68 QueuePriorities.push_back(queuePriority);
69 queueCreateInfos.push_back(queueCreateInfo);
70 }
71
72 /**
73 * @brief Create the feature chain.
74 */
75 VkPhysicalDeviceRobustness2FeaturesEXT robustness2{};
76 robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
77 robustness2.pNext = nullptr;
78
79 VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeature{};
80 hostImageCopyFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT;
81 hostImageCopyFeature.pNext = &robustness2;
82
83 VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphore{};
84 timelineSemaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES;
85 timelineSemaphore.pNext = &hostImageCopyFeature;
86
87 VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragShaderBarycentric{};
88 fragShaderBarycentric.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR;
89 fragShaderBarycentric.pNext = &timelineSemaphore;
90
91 VkPhysicalDeviceDiagnosticsConfigFeaturesNV diagnosticsConfig{};
92 diagnosticsConfig.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV;
93 diagnosticsConfig.pNext = &fragShaderBarycentric;
94
95 VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV dgcFeatures{};
96 dgcFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV;
97 dgcFeatures.pNext = &diagnosticsConfig;
98
99 VkPhysicalDeviceVulkan13Features vk13Frature{};
100 vk13Frature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
101 vk13Frature.pNext = &dgcFeatures;
102
103 VkPhysicalDeviceFragmentShadingRateFeaturesKHR fragShadingRateFeature {};
104 fragShadingRateFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
105 fragShadingRateFeature.pNext = &vk13Frature;
106
107 VkPhysicalDeviceMultiviewFeatures multiviewFeatures {};
108 multiviewFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
109 multiviewFeatures.pNext = &fragShadingRateFeature;
110
111 VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures {};
112 meshShaderFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT;
113 meshShaderFeatures.pNext = &multiviewFeatures;
114
115 VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeatures {};
116 shaderClockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR;
117 shaderClockFeatures.pNext = &meshShaderFeatures;
118
119 VkPhysicalDeviceScalarBlockLayoutFeatures layoutFeatures {};
120 layoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES;
121 layoutFeatures.pNext = &shaderClockFeatures;
122
123 VkPhysicalDeviceHostQueryResetFeatures hostQueryResetFeatures {};
124 hostQueryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES;
125 hostQueryResetFeatures.pNext = &layoutFeatures;
126
127 VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures {};
128 rayQueryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR;
129 rayQueryFeatures.pNext = &hostQueryResetFeatures;
130
131 VkPhysicalDeviceRayTracingPipelineFeaturesKHR rayTracingFeatures {};
132 rayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
133 rayTracingFeatures.pNext = &rayQueryFeatures;
134
135 VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures {};
136 accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
137 accelerationStructureFeatures.pNext = &rayTracingFeatures;
138
139 VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures {};
140 descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
141 descriptorIndexingFeatures.pNext = &accelerationStructureFeatures;
142
143 VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddressFeatures {};
144 bufferDeviceAddressFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
145 bufferDeviceAddressFeatures.pNext = &descriptorIndexingFeatures;
146
147 /**
148 * @brief Get all Features that supported.
149 */
150 VkPhysicalDeviceFeatures2 deviceFeatures{};
151 deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
152 deviceFeatures.pNext = &bufferDeviceAddressFeatures;
153
154 /**
155 * @brief Fetch all features.
156 */
157 vkGetPhysicalDeviceFeatures2(m_VulkanState.m_PhysicalDevice, &deviceFeatures);
158
159 /**
160 * @brief aftermath config.
161 */
162 VkDeviceDiagnosticsConfigCreateInfoNV aftermathInfo{};
163 aftermathInfo.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV;
164 aftermathInfo.flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | // Enable automatic call stack checkpoints.
165 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | // Enable tracking of resources.
166 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV | // Generate debug information for shaders.
167 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV ; // Enable additional runtime shader error reporting.
168 aftermathInfo.pNext = &deviceFeatures;
169
170 /**
171 * @brief Instanced a VkDeviceCreateInfo with default value.
172 */
173 VkDeviceCreateInfo createInfo{};
174 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
175 createInfo.pQueueCreateInfos = queueCreateInfos.data();
176 createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
177 createInfo.pEnabledFeatures = VK_NULL_HANDLE;
178 createInfo.enabledExtensionCount = static_cast<uint32_t>(m_ExtensionProperties.size());
179 createInfo.ppEnabledExtensionNames = m_ExtensionProperties.data();
180 createInfo.enabledLayerCount = 0;
181 createInfo.pNext = &aftermathInfo;
182
183 /**
184 * @brief Create device and set it global.
185 */
186 VK_CHECK(vkCreateDevice(vulkanState.m_PhysicalDevice, &createInfo, nullptr, &vulkanState.m_Device));
187 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_DEVICE, (uint64_t)vulkanState.m_Device, vulkanState.m_Device, m_DeviceProperties.deviceName)
188
189 /**
190 * @brief Get Queues.
191 */
192 {
193 for (auto& [ family, idItems ] : queueFamilies)
194 {
195 int index = 0;
196 for (auto& [id, items] : idItems)
197 {
198 for (size_t i = 0; i < items.size(); i++)
199 {
200 vkGetDeviceQueue(vulkanState.m_Device, family, index, &items[i]);
201 index++;
202 }
203 }
204 }
205
206#if 0 // Use One Queue for all commands. This method with higher fps.
207
208 vulkanState.m_GraphicQueue = queueFamilies[m_QueueHelper.graphicqueuefamily.value()][0];
209 vulkanState.m_PresentQueue = queueFamilies[m_QueueHelper.graphicqueuefamily.value()][0];
210 vulkanState.m_ComputeQueue = queueFamilies[m_QueueHelper.graphicqueuefamily.value()][0];
211 vulkanState.m_TransferQueue = queueFamilies[m_QueueHelper.graphicqueuefamily.value()][0];
212
213#else // Split Commands to different Queues.
214
215 vulkanState.m_GraphicQueue = queueFamilies[m_QueueHelper.graphicqueuefamily .value()][0][0];
216 vulkanState.m_PresentQueue = queueFamilies[m_QueueHelper.presentqueuefamily .value()][0][0];
217 vulkanState.m_ComputeQueue = queueFamilies[m_QueueHelper.computequeuefamily .value()][2][0];
218 vulkanState.m_TransferQueue = queueFamilies[m_QueueHelper.transferqueuefamily.value()][3][0];
219
220#endif
221
222 /**
223 * @brief Create Thread Queue.
224 */
225 for (int i = 0; i < NThreadQueue; i++)
226 {
227 VulkanThreadQueue::CreateGraphic(vulkanState, queueFamilies[m_QueueHelper.graphicqueuefamily.value()][0][i + 1]);
228 VulkanThreadQueue::CreateCompute(vulkanState, queueFamilies[m_QueueHelper.computequeuefamily.value()][2][i + 1]);
229 }
230
231 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_QUEUE, reinterpret_cast<uint64_t>(vulkanState.m_TransferQueue), vulkanState.m_Device, "TransferQueue")
232 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_QUEUE, reinterpret_cast<uint64_t>(vulkanState.m_ComputeQueue) , vulkanState.m_Device, "ComputeQueue" )
233 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_QUEUE, reinterpret_cast<uint64_t>(vulkanState.m_PresentQueue) , vulkanState.m_Device, "PresentQueue" )
234 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_QUEUE, reinterpret_cast<uint64_t>(vulkanState.m_GraphicQueue) , vulkanState.m_Device, "GraphicQueue" )
235 }
236 }
237
239 {
241
242 m_VulkanState.m_GraphicQueue = nullptr;
243 m_VulkanState.m_ComputeQueue = nullptr;
244 m_VulkanState.m_PresentQueue = nullptr;
245 m_VulkanState.m_TransferQueue = nullptr;
246
248
249 /**
250 * @brief Destroy the Vulkan Device Object.
251 * Queue is created by device, we do not need destroy queue here manually.
252 */
253 vkDestroyDevice(m_VulkanState.m_Device, nullptr);
254 m_VulkanState.m_Device = nullptr;
255 m_VulkanState.m_PhysicalDevice = nullptr;
256 }
257
259 {
261
262 m_SwapChainSupportDetails =
263 QuerySwapChainSupport(
264 m_VulkanState.m_PhysicalDevice,
265 m_VulkanState.m_Surface, m_VulkanState.m_Windows
266 );
267 }
268
270 {
272
273 /**
274 * @brief Get VkPhysicalDeviceProperties.
275 */
276 VkPhysicalDeviceProperties physicalDeviceProperties;
277 vkGetPhysicalDeviceProperties(m_VulkanState.m_PhysicalDevice, &physicalDeviceProperties);
278
279 const VkSampleCountFlags counts =
280 physicalDeviceProperties.limits.framebufferColorSampleCounts &
281 physicalDeviceProperties.limits.framebufferDepthSampleCounts;
282
283 /**
284 * @breif select one.
285 */
286 if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
287 if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
288 if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
289 if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
290 if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
291 if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
292
293 return VK_SAMPLE_COUNT_1_BIT;
294 }
295
296 bool VulkanDevice::SelectPhysicalDevice(const VkInstance& instance, const VkSurfaceKHR& surface, GLFWwindow* window)
297 {
299
300 /**
301 * @brief Get all physical device num this computer.
302 */
303 uint32_t deviceCount = 0;
304 vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
305
306 /**
307 * @brief This software requires there must be at least one physical device.
308 */
309 if (deviceCount == 0)
310 {
311 SPICES_CORE_WARN("Failed to find GPUs with Vulkan support!")
312 return false;
313 }
314
315 /**
316 * @breif Get all physical device this computer.
317 */
318 std::vector<VkPhysicalDevice> PhysicalDevices(deviceCount);
319 vkEnumeratePhysicalDevices(instance, &deviceCount, PhysicalDevices.data());
320
321 /**
322 * @brief Iter all physical and select one suitable.
323 */
324 for (const auto& physicalDevice : PhysicalDevices)
325 {
326 /**
327 * @brief All this condition need satisfied.
328 */
329 if (IsExtensionMeetDemand(physicalDevice) &&
330 IsPropertyMeetDemand(physicalDevice) &&
331 IsFeatureMeetDemand(physicalDevice) &&
332 IsQueueMeetDemand(physicalDevice, surface)
333 )
334 {
335 /**
336 * @brief Set Selected physical device.
337 */
338 m_VulkanState.m_PhysicalDevice = physicalDevice;
339
340 /**
341 * @brief Query physicaldevice's SwapChainSupport.
342 */
343 m_SwapChainSupportDetails = QuerySwapChainSupport(physicalDevice, surface, window);
344
345 SPICES_CORE_INFO("VkPhysicalDevice Selected!!!")
346 return true;
347 }
348 }
349
350 return false;
351 }
352
353 bool VulkanDevice::IsPropertyMeetDemand(const VkPhysicalDevice& device)
354 {
356
357 /**
358 * @brief Get all RayTracing Properties supported.
359 */
360 m_DGCProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV;
361 m_DGCProperties.pNext = nullptr;
362
363 m_RayTracingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
364 m_RayTracingProperties.pNext = &m_DGCProperties;
365
366 VkPhysicalDeviceMeshShaderPropertiesEXT meshShaderProperties{};
367 meshShaderProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT;
368 meshShaderProperties.pNext = &m_RayTracingProperties;
369
370 VkPhysicalDeviceSubgroupProperties subGroupProperties{};
371 subGroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
372 subGroupProperties.pNext = &meshShaderProperties;
373
374 VkPhysicalDeviceProperties2 prop2 {};
375 prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
376 prop2.pNext = &subGroupProperties;
377 vkGetPhysicalDeviceProperties2(device, &prop2);
378 m_DeviceProperties = prop2.properties;
379
380 {
381 std::stringstream ss;
382 ss << "Limits : maxFragmentOutputAttachments = " << m_DeviceProperties.limits.maxFragmentOutputAttachments;
383 SPICES_CORE_INFO(ss.str())
384 }
385
386 {
387 std::stringstream ss;
388 ss << "MeshShader : maxMeshOutputVertices = " << meshShaderProperties.maxMeshOutputVertices;
389 SPICES_CORE_INFO(ss.str())
390 }
391
392 {
393 std::stringstream ss;
394 ss << "MeshShader : maxMeshOutputPrimitives = " << meshShaderProperties.maxMeshOutputPrimitives;
395 SPICES_CORE_INFO(ss.str())
396 }
397
398 {
399 std::stringstream ss;
400 ss << "SubGroup : subgroupSize = " << subGroupProperties.subgroupSize;
401 SPICES_CORE_INFO(ss.str())
402 assert(subGroupProperties.supportedStages & VK_SHADER_STAGE_TASK_BIT_EXT);
403 assert(subGroupProperties.supportedStages & VK_SHADER_STAGE_MESH_BIT_EXT);
404 }
405
406 return true;
407 }
408
409 bool VulkanDevice::IsFeatureMeetDemand(const VkPhysicalDevice& device)
410 {
412
413 /**
414 * @brief Create the feature chain.
415 */
416 VkPhysicalDeviceRobustness2FeaturesEXT robustness2{};
417 robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
418 robustness2.pNext = nullptr;
419
420 VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeature{};
421 hostImageCopyFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT;
422 hostImageCopyFeature.pNext = &robustness2;
423
424 VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphore{};
425 timelineSemaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES;
426 timelineSemaphore.pNext = &hostImageCopyFeature;
427
428 VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragShaderBarycentric{};
429 fragShaderBarycentric.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR;
430 fragShaderBarycentric.pNext = &timelineSemaphore;
431
432 VkPhysicalDeviceDiagnosticsConfigFeaturesNV diagnosticsConfig{};
433 diagnosticsConfig.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV;
434 diagnosticsConfig.pNext = &fragShaderBarycentric;
435
436 VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV dgcFeatures{};
437 dgcFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV;
438 dgcFeatures.pNext = &diagnosticsConfig;
439
440 VkPhysicalDeviceVulkan13Features vk13Frature{};
441 vk13Frature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
442 vk13Frature.pNext = &dgcFeatures;
443
444 VkPhysicalDeviceFragmentShadingRateFeaturesKHR fragShadingRateFeature {};
445 fragShadingRateFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
446 fragShadingRateFeature.pNext = &vk13Frature;
447
448 VkPhysicalDeviceMultiviewFeatures multiviewFeatures {};
449 multiviewFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
450 multiviewFeatures.pNext = &fragShadingRateFeature;
451
452 VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures {};
453 meshShaderFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT;
454 meshShaderFeatures.pNext = &multiviewFeatures;
455
456 VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeatures{};
457 shaderClockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR;
458 shaderClockFeatures.pNext = &meshShaderFeatures;
459
460 VkPhysicalDeviceScalarBlockLayoutFeatures layoutFeatures {};
461 layoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES;
462 layoutFeatures.pNext = &shaderClockFeatures;
463
464 VkPhysicalDeviceHostQueryResetFeatures hostQueryResetFeatures {};
465 hostQueryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES;
466 hostQueryResetFeatures.pNext = &layoutFeatures;
467
468 VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures {};
469 rayQueryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR;
470 rayQueryFeatures.pNext = &hostQueryResetFeatures;
471
472 VkPhysicalDeviceRayTracingPipelineFeaturesKHR rayTracingFeatures {};
473 rayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
474 rayTracingFeatures.pNext = &rayQueryFeatures;
475
476 VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures {};
477 accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
478 accelerationStructureFeatures.pNext = &rayTracingFeatures;
479
480 VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures {};
481 descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
482 descriptorIndexingFeatures.pNext = &accelerationStructureFeatures;
483
484 VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddressFeatures {};
485 bufferDeviceAddressFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
486 bufferDeviceAddressFeatures.pNext = &descriptorIndexingFeatures;
487
488 /**
489 * @brief Get all Features that supported.
490 */
491 VkPhysicalDeviceFeatures2 deviceFeatures {};
492 deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
493 deviceFeatures.pNext = &bufferDeviceAddressFeatures;
494
495 /**
496 * @Fetch all features.
497 */
498 vkGetPhysicalDeviceFeatures2(device, &deviceFeatures);
499 m_DeviceFeatures = deviceFeatures.features;
500
501 /**
502 * @brief Just return true for we do not need a specific feature supported now.
503 * @todo Configurable.
504 */
505 ASSERT(deviceFeatures.features.samplerAnisotropy) /* @brief Enable samplerAnisotropy. */
506 ASSERT(deviceFeatures.features.sampleRateShading) /* @brief Enable sampleRateShading, for MSAA. */
507 ASSERT(deviceFeatures.features.independentBlend) /* @brief Enable Independent Attachment AlphaBlend State. */
508 ASSERT(deviceFeatures.features.geometryShader) /* @brief Enable Geometry Shader Feature. */
509 ASSERT(bufferDeviceAddressFeatures.bufferDeviceAddress) /* @brief Enable Buffer Address Feature. */
510 ASSERT(bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay) /* @brief Enable Buffer Address Capture Feature. */
511 ASSERT(accelerationStructureFeatures.accelerationStructure) /* @brief Enable RayTracing AccelerationStructure. */
512 ASSERT(rayTracingFeatures.rayTracingPipeline) /* @brief Enable RayTracing Pipeline. */
513 ASSERT(rayQueryFeatures.rayQuery) /* @brief Enable RayTracing Query Feature. */
514 ASSERT(hostQueryResetFeatures.hostQueryReset) /* @brief Enable HostQueryReset Feature. */
515 ASSERT(layoutFeatures.scalarBlockLayout) /* @brief Enable Shader ScalarBlockLayout Feature. */
516
517 ASSERT(descriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing) /* @brief Enable Shader shaderSampledImageArrayNonUniformIndexing Feature. */
518 ASSERT(descriptorIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind) /* @brief Enable Shader descriptorBindingSampledImageUpdateAfterBind Feature. */
519 ASSERT(descriptorIndexingFeatures.shaderUniformBufferArrayNonUniformIndexing) /* @brief Enable Shader shaderUniformBufferArrayNonUniformIndexing Feature. */
520 ASSERT(descriptorIndexingFeatures.descriptorBindingUniformBufferUpdateAfterBind) /* @brief Enable Shader descriptorBindingUniformBufferUpdateAfterBind Feature. */
521 ASSERT(descriptorIndexingFeatures.shaderStorageBufferArrayNonUniformIndexing) /* @brief Enable Shader shaderStorageBufferArrayNonUniformIndexing Feature. */
522 ASSERT(descriptorIndexingFeatures.descriptorBindingStorageBufferUpdateAfterBind) /* @brief Enable Shader descriptorBindingStorageBufferUpdateAfterBind Feature. */
523 ASSERT(descriptorIndexingFeatures.descriptorBindingPartiallyBound) /* @brief Enable descriptorBindingPartiallyBound Feature. */
524 ASSERT(descriptorIndexingFeatures.runtimeDescriptorArray) /* @brief Enable runtimeDescriptorArray Feature. */
525
526 ASSERT(shaderClockFeatures.shaderSubgroupClock) /* @brief Enable Shader clock time Feature. */
527
528 ASSERT(meshShaderFeatures.meshShader) /* @brief Enable Mesh Shader Feature. */
529 ASSERT(meshShaderFeatures.taskShader) /* @brief Enable Task Shader Feature. */
530
531 ASSERT(multiviewFeatures.multiview) /* @brief Enable Multiview Feature. */
532 ASSERT(fragShadingRateFeature.pipelineFragmentShadingRate) /* @brief Enable pipelineFragmentShadingRate Feature. */
533 ASSERT(vk13Frature.maintenance4) /* @brief Enable maintenance4 Feature. */
534
535 ASSERT(dgcFeatures.deviceGeneratedCommands) /* @brief Enable Nvidia GPU Generate Commands Feature. */
536
537 ASSERT(diagnosticsConfig.diagnosticsConfig) /* @brief Enable Nvidia GPU Generate Diagnostic Checkpoints Feature. */
538
539 ASSERT(fragShaderBarycentric.fragmentShaderBarycentric) /* @brief Enable FragmentShader Barycentric access Feature. */
540
541 ASSERT(timelineSemaphore.timelineSemaphore) /* @brief Enable timeline semaphore Feature. */
542
543 ASSERT(hostImageCopyFeature.hostImageCopy) /* @brief Enable image copy from host directly Feature. */
544
545 ASSERT(robustness2.nullDescriptor) /* @brief Enable Enable null Descriptor write Feature. */
546
547 return true;
548 }
549
551 {
553
554 m_ExtensionProperties.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); /* @brief Swapchain Extension. */
555 m_ExtensionProperties.push_back(VK_KHR_MAINTENANCE_1_EXTENSION_NAME); /* @brief Negative Viewport Extension. */
556 m_ExtensionProperties.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); /* @brief To build acceleration structures. */
557 m_ExtensionProperties.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); /* @brief To use vkCmdTraceRaysKHR. */
558 m_ExtensionProperties.push_back(VK_KHR_RAY_QUERY_EXTENSION_NAME); /* @brief Enable Ray Query. */
559 m_ExtensionProperties.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); /* @brief Required by ray tracing pipeline. */
560 m_ExtensionProperties.push_back(VK_KHR_SHADER_CLOCK_EXTENSION_NAME); /* @brief Enable Shader Clock Extension. */
561 m_ExtensionProperties.push_back(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); /* @brief Enable Shader Debug Print. */
562 m_ExtensionProperties.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); /* @brief Enable Shader spirv1.4. */
563 m_ExtensionProperties.push_back(VK_EXT_MESH_SHADER_EXTENSION_NAME); /* @brief Enable Mesh Shader, Task Shader. */
564 m_ExtensionProperties.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); /* @brief Enable Shader float controls. */
565 m_ExtensionProperties.push_back(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); /* @brief Enable Fragment Shading rate. */
566 m_ExtensionProperties.push_back(VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME); /* @brief Enable Nested Command Buffer. */
567 m_ExtensionProperties.push_back(VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); /* @brief Enable Nvidia GPU Generate Commands. */
568 m_ExtensionProperties.push_back(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME); /* @brief Enable Nvidia GPU Diagnostic Checkpoints. */
569 m_ExtensionProperties.push_back(VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME); /* @brief Enable Nvidia GPU Diagnostic Config. */
570 m_ExtensionProperties.push_back(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME); /* @brief Enable FragmentShaderBarycentric. */
571 m_ExtensionProperties.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); /* @brief Enable GPU Memory Statics. */
572 m_ExtensionProperties.push_back(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME); /* @brief Enable calibrated timestamps(butter than query pool's timestamps). */
573 m_ExtensionProperties.push_back(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME); /* @brief Enable reset query pool in host(without commandBuffer). */
574 m_ExtensionProperties.push_back(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME); /* @brief Enable image copy from host directly. */
575 m_ExtensionProperties.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); /* @brief Enable null Descriptor write(useful in raytracing renderer). */
576
577 /**
578 * @brief Those Extensions are enabled other place.
579 *
580 * VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME @brief Enable timeline semaphore.
581 */
582 }
583
584 bool VulkanDevice::IsExtensionMeetDemand(const VkPhysicalDevice& device)
585 {
587
588 /**
589 * @brief Get all physicaldevice extensions nums.
590 */
591 uint32_t extensionCount;
592 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
593
594 /**
595 * @brief Get all physicaldevice extensions that supported.
596 */
597 std::vector<VkExtensionProperties> availableExtensions(extensionCount);
598 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
599
600 /**
601 * @brief Get all physicaldevice extension requirements our engine needed.
602 */
604
605 /**
606 * @brief Check whether all extensions satisfied.
607 */
608 std::set<std::string> requiredExtensions(m_ExtensionProperties.begin(), m_ExtensionProperties.end());
609
610 /**
611 * @brief Get NvperfDeviceExtensions.
612 */
613 std::vector<const char*> nvperfDeviceExtensions;
614 NSIGHTPERF_GPUPROFILERHUD_QUERYDEVICEEXTENSION(m_VulkanState.m_Instance, device, nvperfDeviceExtensions)
615
616 for (auto& e : nvperfDeviceExtensions)
617 {
618 requiredExtensions.insert(e);
619 }
620
621 for (const auto& extension : availableExtensions)
622 {
623 requiredExtensions.erase(extension.extensionName);
624 }
625
626 if (requiredExtensions.empty())
627 {
628 /**
629 * @brief Add NvperfDeviceExtensions to m_ExtensionProperties.
630 */
631 m_ExtensionProperties.insert(m_ExtensionProperties.end(), nvperfDeviceExtensions.begin(), nvperfDeviceExtensions.end());
632
633 return true;
634 }
635 else
636 {
637 for (auto& set : requiredExtensions)
638 {
639 VkPhysicalDeviceProperties deviceProperties;
640 vkGetPhysicalDeviceProperties(device, &deviceProperties);
641
642 std::stringstream ss;
643 ss << "Device Extension Required: " << set << ", Which is not satisfied with device: " << deviceProperties.deviceName;
644 SPICES_CORE_WARN(ss.str())
645 }
646
647 return false;
648 }
649 }
650
651 bool VulkanDevice::IsQueueMeetDemand(const VkPhysicalDevice& device, const VkSurfaceKHR& surface)
652 {
654
655 /**
656 * @brief Get all physicaldevice queue nums.
657 */
658 uint32_t queueFamilyCount = 0;
659 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
660
661 /**
662 * @brief Get all physicaldevice queue that supported.
663 */
664 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
665 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
666
667 /**
668 * @brief Check queue identify.
669 */
670 for (uint32_t i = 0; i < queueFamilies.size(); i++) {
671 const auto& queueFamily = queueFamilies[i];
672
673 /**
674 * @brief Get graphic queue identify.
675 */
676 if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
677 {
678 m_QueueHelper.graphicqueuefamily = i;
679 m_VulkanState.m_GraphicQueueFamily = i;
680
681 VkBool32 presentSupport = false;
682 vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
683
684 /**
685 * @brief Get present queue identify.
686 */
687 if (presentSupport)
688 {
689 m_QueueHelper.presentqueuefamily = i;
690 }
691 }
692 else
693 {
694 /**
695 * @brief Get compute queue identify.
696 */
697 if (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)
698 {
699 m_QueueHelper.computequeuefamily = i;
700 m_VulkanState.m_ComputeQueueFamily = i;
701 }
702
703 /**
704 * @brief Get transfer queue identify.
705 */
706 if (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT)
707 {
708 m_QueueHelper.transferqueuefamily = i;
709 }
710 }
711
712 if (m_QueueHelper.isComplete()) return true;
713 }
714
715 return false;
716 }
717
718 SwapChainSupportDetails VulkanDevice::QuerySwapChainSupport(
719 const VkPhysicalDevice& device ,
720 const VkSurfaceKHR& surface ,
721 GLFWwindow* window
722 )
723 {
725
726 /**
727 * @brief Get VkSurfaceCapabilitiesKHR.
728 */
729 SwapChainSupportDetails swapChainSupportDetails = SwapChainSupportDetails{};
730 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapChainSupportDetails.capabilities);
731
732 /**
733 * @brief Get VkExtent2D From VkSurfaceCapabilitiesKHR or glfwWindow.
734 */
735 if (swapChainSupportDetails.capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
736 {
737 swapChainSupportDetails.surfaceSize = swapChainSupportDetails.capabilities.currentExtent;
738 }
739 else
740 {
741 int width, height;
742 glfwGetFramebufferSize(window, &width, &height);
743
744 VkExtent2D actualExtent =
745 {
746 static_cast<uint32_t>(width),
747 static_cast<uint32_t>(height)
748 };
749
750 /**
751 * @brief clamp to VkSurfaceCapabilitiesKHR's limit.
752 */
753 actualExtent.width = std::clamp(actualExtent.width,
754 swapChainSupportDetails.capabilities.minImageExtent.width,
755 swapChainSupportDetails.capabilities.maxImageExtent.width);
756
757 actualExtent.height = std::clamp(actualExtent.height,
758 swapChainSupportDetails.capabilities.minImageExtent.height,
759 swapChainSupportDetails.capabilities.maxImageExtent.height);
760
761 swapChainSupportDetails.surfaceSize = actualExtent;
762 }
763
764 /**
765 * @brief Get physicaldevice surfaceformat nums;
766 */
767 uint32_t formatCount;
768 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
769
770 if (formatCount != 0)
771 {
772 /**
773 * @brief Get physicaldevice surfaceformat;
774 */
775 swapChainSupportDetails.formats.resize(formatCount);
776 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapChainSupportDetails.formats.data());
777
778 /**
779 * @brief Get suitable surfaceformat.
780 * @note Remember this format is linear.
781 */
782 swapChainSupportDetails.format = swapChainSupportDetails.formats[0];
783
784 for (const auto& availableFormat : swapChainSupportDetails.formats)
785 {
786 if (availableFormat.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 &&
787 availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
788 {
789 swapChainSupportDetails.format = availableFormat;
790 break;
791 }
792 }
793 }
794
795 /**
796 * @brief Get physicaldevice persentmode nums;
797 */
798 uint32_t presentModeCount;
799 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
800
801 if (presentModeCount != 0)
802 {
803 /**
804 * @brief Get physicaldevice persentmode;
805 */
806 swapChainSupportDetails.presentModes.resize(presentModeCount);
807 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapChainSupportDetails.presentModes.data());
808
809 /**
810 * @brief Get suitable persentmode.
811 */
812 swapChainSupportDetails.presentMode = swapChainSupportDetails.presentModes[0];
813
814 for (const auto& availablePresentMode : swapChainSupportDetails.presentModes)
815 {
816 if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
817 {
818 swapChainSupportDetails.presentMode = availablePresentMode;
819 break;
820 }
821 }
822 }
823
824 return swapChainSupportDetails;
825 }
826}
#define ASSERT(expr)
Assert macro.
Definition Core.h:29
#define NSIGHTPERF_GPUPROFILERHUD_QUERYDEVICEEXTENSION(...)
#define SPICES_PROFILE_ZONE
#define VK_CHECK(expr)
Vulkan Check macro. Verify Vulkan API Effectiveness.
Definition VulkanUtils.h:68
VkSampleCountFlagBits GetMaxUsableSampleCount() const
Get device's max usable sample count.
bool IsQueueMeetDemand(const VkPhysicalDevice &device, const VkSurfaceKHR &surface)
Check all Queue we need meet;.
static VkPhysicalDeviceFeatures m_DeviceFeatures
Selected Physical Device Features.
virtual ~VulkanDevice() override
Destructor Function.
static VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_RayTracingProperties
Device RayTracing Properties.
bool IsPropertyMeetDemand(const VkPhysicalDevice &device)
Check all Property we need meet.
bool IsFeatureMeetDemand(const VkPhysicalDevice &device)
Check all Feature we need meet.
void GetExtensionRequirements()
Get all physical device extension requirements our engine needed. Source 1 : user Setting.
static VkPhysicalDeviceProperties m_DeviceProperties
Selected Physical Device Properties.
static VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV m_DGCProperties
Device DGC Properties.
VulkanDevice(VulkanState &vulkanState)
Constructor Function. Create vkDevice.
bool SelectPhysicalDevice(const VkInstance &instance, const VkSurfaceKHR &surface, GLFWwindow *window)
select a suitable physical device.
bool IsExtensionMeetDemand(const VkPhysicalDevice &device)
Check all Extension we need meet;.
void RequerySwapChainSupport()
Requery device's SwapChainSupportDetails. Mainly VkExtent2D.
VulkanInstance Class. This class defines the VulkanDevice behave. This class is just a wrapper of vkd...
VulkanState & m_VulkanState
The global VulkanState Referenced from VulkanRenderBackend.
VulkanObject(VulkanState &vulkanState)
Constructor Function. Init member variables.
VulkanObject Class. This class defines the basic behaves of VulkanObject. When we create an new Vulka...
static void Destroy()
Destroy all ThreadQueue.
VulkanThreadQueue Class. This class is a wrapper of Thread VkQueue.
SwapChain Utils. Queried from device.
This struct contains all Vulkan object in used global.
Definition VulkanUtils.h:74