External Vulkan Device support
s-ol authored 2 years ago
s-ol committed 2 years ago
53 | 53 | CommandQueueVkImpl(IReferenceCounters* pRefCounters, |
54 | 54 | std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, |
55 | 55 | uint32_t QueueFamilyIndex); |
56 | CommandQueueVkImpl(IReferenceCounters* pRefCounters, | |
57 | std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, | |
58 | const VkQueue& Queue, | |
59 | uint32_t QueueFamilyIndex); | |
56 | 60 | ~CommandQueueVkImpl(); |
57 | 61 | |
58 | 62 | IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_CommandQueueVk, TBase) |
48 | 48 | uint32_t GlobalExtensionCount, |
49 | 49 | const char* const* ppGlobalExtensionNames, |
50 | 50 | VkAllocationCallbacks* pVkAllocator); |
51 | ||
52 | static std::shared_ptr<VulkanInstance> Create(const VkInstance& vkInstance, | |
53 | VkAllocationCallbacks* pVkAllocator); | |
51 | 54 | ~VulkanInstance(); |
52 | 55 | |
53 | 56 | std::shared_ptr<VulkanInstance> GetSharedPtr() |
78 | 81 | uint32_t GlobalExtensionCount, |
79 | 82 | const char* const* ppGlobalExtensionNames, |
80 | 83 | VkAllocationCallbacks* pVkAllocator); |
84 | VulkanInstance(const VkInstance& vkInstance, | |
85 | VkAllocationCallbacks* pVkAllocator); | |
81 | 86 | |
82 | bool m_DebugUtilsEnabled = false; | |
87 | bool m_DebugUtilsEnabled = false; | |
88 | bool m_InitializedExternally = false; | |
83 | 89 | VkAllocationCallbacks* const m_pVkAllocator; |
84 | 90 | VkInstance m_VkInstance = VK_NULL_HANDLE; |
85 | 91 | uint32_t m_VkVersion = VK_API_VERSION_1_0; |
94 | 94 | const ExtensionFeatures& EnabledExtFeatures, |
95 | 95 | const VkAllocationCallbacks* vkAllocator); |
96 | 96 | |
97 | static std::shared_ptr<VulkanLogicalDevice> Create(const VulkanPhysicalDevice& PhysicalDevice, | |
98 | const VkDevice& Device, | |
99 | VkPipelineStageFlags EnabledShaderStages, | |
100 | const VkAllocationCallbacks* vkAllocator); | |
101 | ||
97 | 102 | // clang-format off |
98 | 103 | VulkanLogicalDevice (const VulkanLogicalDevice&) = delete; |
99 | 104 | VulkanLogicalDevice (VulkanLogicalDevice&&) = delete; |
230 | 235 | const VkDeviceCreateInfo& DeviceCI, |
231 | 236 | const ExtensionFeatures& EnabledExtFeatures, |
232 | 237 | const VkAllocationCallbacks* vkAllocator); |
238 | VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, | |
239 | const VkDevice& Device, | |
240 | VkPipelineStageFlags EnabledShaderStages, | |
241 | const VkAllocationCallbacks* vkAllocator); | |
233 | 242 | |
234 | 243 | template <typename VkObjectType, |
235 | 244 | VulkanHandleTypeId VkTypeId, |
79 | 79 | IRenderDevice** ppDevice, |
80 | 80 | IDeviceContext** ppContexts) PURE; |
81 | 81 | |
82 | VIRTUAL void METHOD(AttachToVulkanDevice)(THIS_ | |
83 | const VkInstance REF Instance, | |
84 | const VkPhysicalDevice REF PhysicalDevice, | |
85 | const VkDevice REF LogicalDevice, | |
86 | const VkQueue REF Queue, | |
87 | uint32_t QueueFamilyIndex, | |
88 | const EngineVkCreateInfo REF EngineCI, | |
89 | IRenderDevice** ppDevice, | |
90 | IDeviceContext** ppContexts) PURE; | |
82 | 91 | |
83 | 92 | /// Creates a swap chain for Vulkan-based engine implementation |
84 | 93 | |
106 | 115 | // clang-format off |
107 | 116 | |
108 | 117 | # define IEngineFactoryVk_CreateDeviceAndContextsVk(This, ...) CALL_IFACE_METHOD(EngineFactoryVk, CreateDeviceAndContextsVk, This, __VA_ARGS__) |
118 | # define IEngineFactoryVk_AttachToVulkanDevice(This, ...) CALL_IFACE_METHOD(EngineFactoryVk, AttachToVulkanDevice, This, __VA_ARGS__) | |
109 | 119 | # define IEngineFactoryVk_CreateSwapChainVk(This, ...) CALL_IFACE_METHOD(EngineFactoryVk, CreateSwapChainVk, This, __VA_ARGS__) |
110 | 120 | |
111 | 121 | // clang-format on |
42 | 42 | TBase{pRefCounters}, |
43 | 43 | m_LogicalDevice {LogicalDevice}, |
44 | 44 | m_VkQueue {LogicalDevice->GetQueue(QueueFamilyIndex, 0)}, |
45 | m_QueueFamilyIndex {QueueFamilyIndex}, | |
46 | m_NextFenceValue {1} | |
47 | // clang-format on | |
48 | { | |
49 | } | |
50 | ||
51 | CommandQueueVkImpl::CommandQueueVkImpl(IReferenceCounters* pRefCounters, | |
52 | std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, | |
53 | const VkQueue& Queue, | |
54 | uint32_t QueueFamilyIndex) : | |
55 | // clang-format off | |
56 | TBase{pRefCounters}, | |
57 | m_LogicalDevice {LogicalDevice}, | |
58 | m_VkQueue {Queue}, | |
45 | 59 | m_QueueFamilyIndex {QueueFamilyIndex}, |
46 | 60 | m_NextFenceValue {1} |
47 | 61 | // clang-format on |
65 | 65 | IRenderDevice** ppDevice, |
66 | 66 | IDeviceContext** ppContexts) override final; |
67 | 67 | |
68 | virtual void DILIGENT_CALL_TYPE AttachToVulkanDevice(const VkInstance& Instance, | |
69 | const VkPhysicalDevice& PhysicalDevice, | |
70 | const VkDevice& LogicalDevice, | |
71 | const VkQueue& Queue, | |
72 | uint32_t QueueFamilyIndex, | |
73 | const EngineVkCreateInfo& EngineCI, | |
74 | IRenderDevice** ppDevice, | |
75 | IDeviceContext** ppContexts) override final; | |
76 | ||
68 | 77 | virtual void DILIGENT_CALL_TYPE AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, |
69 | 78 | std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice, |
70 | 79 | std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, |
531 | 540 | } |
532 | 541 | } |
533 | 542 | |
543 | void EngineFactoryVkImpl::AttachToVulkanDevice(const VkInstance& Instance, | |
544 | const VkPhysicalDevice& PhysicalDevice, | |
545 | const VkDevice& LogicalDevice, | |
546 | const VkQueue& Queue, | |
547 | uint32_t QueueFamilyIndex, | |
548 | const EngineVkCreateInfo& EngineCI, | |
549 | IRenderDevice** ppDevice, | |
550 | IDeviceContext** ppContexts) | |
551 | { | |
552 | auto& RawMemAllocator = GetRawAllocator(); | |
553 | ||
554 | auto VulkanInstance = VulkanUtilities::VulkanInstance::Create(Instance, nullptr); | |
555 | auto VulkanPhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(PhysicalDevice, *VulkanInstance); | |
556 | ||
557 | VkPipelineStageFlags PipelineStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; | |
558 | auto VulkanLogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*VulkanPhysicalDevice, LogicalDevice, PipelineStages, nullptr); | |
559 | RefCntAutoPtr<CommandQueueVkImpl> pCmdQueueVk{ | |
560 | NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(VulkanLogicalDevice, Queue, QueueFamilyIndex)}; | |
561 | std::array<ICommandQueueVk*, 1> CommandQueues = {{pCmdQueueVk}}; | |
562 | ||
563 | OnRenderDeviceCreated = [&](RenderDeviceVkImpl* pRenderDeviceVk) | |
564 | { | |
565 | FenceDesc Desc; | |
566 | Desc.Name = "Command queue internal fence"; | |
567 | constexpr bool IsDeviceInternal = false; | |
568 | ||
569 | RefCntAutoPtr<FenceVkImpl> pFenceVk{ | |
570 | NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal)}; | |
571 | pCmdQueueVk->SetFence(std::move(pFenceVk)); | |
572 | }; | |
573 | ||
574 | AttachToVulkanDevice( | |
575 | VulkanInstance, | |
576 | std::move(VulkanPhysicalDevice), | |
577 | VulkanLogicalDevice, | |
578 | CommandQueues.size(), CommandQueues.data(), | |
579 | EngineCI, | |
580 | ppDevice, | |
581 | ppContexts | |
582 | ); | |
583 | } | |
584 | ||
534 | 585 | /// Attaches to existing Vulkan device |
535 | 586 | |
536 | 587 | /// \param [in] Instance - shared pointer to a VulkanUtilities::VulkanInstance object |
88 | 88 | return std::shared_ptr<VulkanInstance>{Instance}; |
89 | 89 | } |
90 | 90 | |
91 | std::shared_ptr<VulkanInstance> VulkanInstance::Create(const VkInstance& vkInstance, | |
92 | VkAllocationCallbacks* pVkAllocator) | |
93 | { | |
94 | auto Instance = new VulkanInstance{vkInstance, pVkAllocator}; | |
95 | return std::shared_ptr<VulkanInstance>{Instance}; | |
96 | } | |
97 | ||
91 | 98 | VulkanInstance::VulkanInstance(uint32_t ApiVersion, |
92 | 99 | bool EnableValidation, |
93 | 100 | uint32_t GlobalExtensionCount, |
290 | 297 | #endif |
291 | 298 | } |
292 | 299 | |
300 | VulkanInstance::VulkanInstance(const VkInstance& vkInstance, | |
301 | VkAllocationCallbacks* pVkAllocator) : | |
302 | m_pVkAllocator{pVkAllocator}, | |
303 | m_VkInstance{vkInstance}, | |
304 | m_InitializedExternally{true} | |
305 | { | |
306 | #if DILIGENT_USE_VOLK | |
307 | if (volkInitialize() != VK_SUCCESS) | |
308 | { | |
309 | LOG_ERROR_AND_THROW("Failed to load Vulkan."); | |
310 | } | |
311 | volkLoadInstance(m_VkInstance); | |
312 | #endif | |
313 | #if !DILIGENT_NO_GLSLANG | |
314 | Diligent::GLSLangUtils::InitializeGlslang(); | |
315 | #endif | |
316 | } | |
317 | ||
293 | 318 | VulkanInstance::~VulkanInstance() |
294 | 319 | { |
295 | 320 | if (m_DebugUtilsEnabled) |
296 | 321 | { |
297 | 322 | VulkanUtilities::FreeDebugging(m_VkInstance); |
298 | 323 | } |
299 | vkDestroyInstance(m_VkInstance, m_pVkAllocator); | |
324 | if (!m_InitializedExternally) | |
325 | { | |
326 | vkDestroyInstance(m_VkInstance, m_pVkAllocator); | |
327 | } | |
300 | 328 | |
301 | 329 | #if !DILIGENT_NO_GLSLANG |
302 | 330 | Diligent::GLSLangUtils::FinalizeGlslang(); |
42 | 42 | return std::shared_ptr<VulkanLogicalDevice>{LogicalDevice}; |
43 | 43 | } |
44 | 44 | |
45 | std::shared_ptr<VulkanLogicalDevice> VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice, | |
46 | const VkDevice& Device, | |
47 | VkPipelineStageFlags EnabledShaderStages, | |
48 | const VkAllocationCallbacks* vkAllocator) | |
49 | { | |
50 | auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, Device, EnabledShaderStages, vkAllocator}; | |
51 | return std::shared_ptr<VulkanLogicalDevice>{LogicalDevice}; | |
52 | } | |
53 | ||
45 | 54 | VulkanLogicalDevice::~VulkanLogicalDevice() |
46 | 55 | { |
47 | 56 | vkDestroyDevice(m_VkDevice, m_VkAllocator); |
75 | 84 | m_EnabledShaderStages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; |
76 | 85 | } |
77 | 86 | |
87 | VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, | |
88 | const VkDevice& Device, | |
89 | VkPipelineStageFlags EnabledShaderStages, | |
90 | const VkAllocationCallbacks* vkAllocator) : | |
91 | m_VkDevice{Device}, | |
92 | m_VkAllocator{vkAllocator}, | |
93 | m_EnabledShaderStages{EnabledShaderStages}, | |
94 | m_EnabledFeatures{}, | |
95 | m_EnabledExtFeatures{} | |
96 | { | |
97 | #if DILIGENT_USE_VOLK | |
98 | // Since we only use one device at this time, load device function entries | |
99 | // https://github.com/zeux/volk#optimizing-device-calls | |
100 | volkLoadDevice(m_VkDevice); | |
101 | #endif | |
102 | } | |
103 | ||
104 | ||
78 | 105 | VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) |
79 | 106 | { |
80 | 107 | VkQueue vkQueue = VK_NULL_HANDLE; |