Plasma Engine  2.0
Loading...
Searching...
No Matches
DeviceVulkan.h
1
2#pragma once
3
4#include <Foundation/Types/Bitflags.h>
5#include <Foundation/Types/UniquePtr.h>
6#include <RendererFoundation/Device/Device.h>
7#include <RendererVulkan/Device/DispatchContext.h>
8#include <RendererVulkan/MemoryAllocator/MemoryAllocatorVulkan.h>
9#include <RendererVulkan/RendererVulkanDLL.h>
10
11#include <vulkan/vulkan.hpp>
12
13PL_DEFINE_AS_POD_TYPE(vk::Format);
14
17
19{
21 plGALFormatLookupEntryVulkan(vk::Format format)
22 {
23 m_format = format;
24 m_readback = format;
25 }
26
27 plGALFormatLookupEntryVulkan(vk::Format format, plArrayPtr<vk::Format> mutableFormats)
28 {
29 m_format = format;
30 m_readback = format;
31 m_mutableFormats = mutableFormats;
32 }
33
34 inline plGALFormatLookupEntryVulkan& R(vk::Format readbackType)
35 {
36 m_readback = readbackType;
37 return *this;
38 }
39
40 vk::Format m_format = vk::Format::eUndefined;
41 vk::Format m_readback = vk::Format::eUndefined;
42 plHybridArray<vk::Format, 6> m_mutableFormats;
43};
44
46
49class plGALPassVulkan;
55
57class PL_RENDERERVULKAN_DLL plGALDeviceVulkan : public plGALDevice
58{
59private:
60 friend plInternal::NewInstance<plGALDevice> CreateVulkanDevice(plAllocator* pAllocator, const plGALDeviceCreationDescription& Description);
62
63public:
64 virtual ~plGALDeviceVulkan();
65
66public:
68 {
69 using StorageType = plUInt32;
70
71 enum Enum
72 {
73 UsesExternalMemory = PL_BIT(0),
74 IsFileDescriptor = PL_BIT(1),
75 Default = 0
76 };
77
78 struct Bits
79 {
80 StorageType UsesExternalMemory : 1;
81 StorageType IsFileDescriptor : 1;
82 };
83 };
84
86 {
87 PL_DECLARE_POD_TYPE();
88 vk::ObjectType m_type;
90 void* m_pObject;
91 union
92 {
93 plVulkanAllocation m_allocation;
94 void* m_pContext;
95 };
96 };
97
99 {
100 PL_DECLARE_POD_TYPE();
101 vk::ObjectType m_type;
102 void* m_pObject;
103 void* m_pContext = nullptr;
104 };
105
107 {
108 bool m_bSurface = false;
109#if defined(VK_USE_PLATFORM_WIN32_KHR)
110 bool m_bWin32Surface = false;
111#elif PL_ENABLED(PL_SUPPORTS_GLFW)
112#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
113 bool m_bAndroidSurface = false;
114#else
115# error "Vulkan Platform not supported"
116#endif
117
118 bool m_bDebugUtils = false;
119 bool m_bDebugUtilsMarkers = false;
120 PFN_vkCreateDebugUtilsMessengerEXT pfn_vkCreateDebugUtilsMessengerEXT = nullptr;
121 PFN_vkDestroyDebugUtilsMessengerEXT pfn_vkDestroyDebugUtilsMessengerEXT = nullptr;
122 PFN_vkSetDebugUtilsObjectNameEXT pfn_vkSetDebugUtilsObjectNameEXT = nullptr;
123
124 bool m_bDeviceSwapChain = false;
125 bool m_bShaderViewportIndexLayer = false;
126
127 vk::PhysicalDeviceCustomBorderColorFeaturesEXT m_borderColorEXT;
128 bool m_bBorderColorFloat = false;
129
130 bool m_bImageFormatList = false;
131 vk::PhysicalDeviceTimelineSemaphoreFeatures m_timelineSemaphoresEXT;
132 bool m_bTimelineSemaphore = false;
133
134 bool m_bExternalMemoryCapabilities = false;
135 bool m_bExternalSemaphoreCapabilities = false;
136
137 bool m_bExternalMemory = false;
138 bool m_bExternalSemaphore = false;
139
140 bool m_bExternalMemoryFd = false;
141 bool m_bExternalSemaphoreFd = false;
142
143 bool m_bExternalMemoryWin32 = false;
144 bool m_bExternalSemaphoreWin32 = false;
145 };
146
147 struct Queue
148 {
149 vk::Queue m_queue;
150 plUInt32 m_uiQueueFamily = -1;
151 plUInt32 m_uiQueueIndex = 0;
152 };
153
154 vk::Instance GetVulkanInstance() const;
155 vk::Device GetVulkanDevice() const;
156 const Queue& GetGraphicsQueue() const;
157 const Queue& GetTransferQueue() const;
158
159 vk::PhysicalDevice GetVulkanPhysicalDevice() const;
160 const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const { return m_properties; }
161 const Extensions& GetExtensions() const { return m_extensions; }
162 const plVulkanDispatchContext& GetDispatchContext() const { return m_dispatchContext; }
163 vk::PipelineStageFlags GetSupportedStages() const;
164
165 vk::CommandBuffer& GetCurrentCommandBuffer();
166 plPipelineBarrierVulkan& GetCurrentPipelineBarrier();
167 plQueryPoolVulkan& GetQueryPool() const;
168 plFenceQueueVulkan& GetFenceQueue() const;
169 plStagingBufferPoolVulkan& GetStagingBufferPool() const;
170 plInitContextVulkan& GetInitContext() const;
171
172 plGALTextureHandle CreateTextureInternal(const plGALTextureCreationDescription& Description, plArrayPtr<plGALSystemMemoryDescription> pInitialData, bool bLinearCPU = false, bool bStaging = false);
173 plGALBufferHandle CreateBufferInternal(const plGALBufferCreationDescription& Description, plArrayPtr<const plUInt8> pInitialData, bool bCPU = false);
174
175 const plGALFormatLookupTableVulkan& GetFormatLookupTable() const;
176
177 plInt32 GetMemoryIndex(vk::MemoryPropertyFlags properties, const vk::MemoryRequirements& requirements) const;
178
179 vk::Fence Submit(bool bAddSignalSemaphore = true);
180
181 void DeleteLaterImpl(const PendingDeletion& deletion);
182
183 void DeleteLater(vk::Image& image, vk::DeviceMemory& externalMemory)
184 {
185 if (image)
186 {
187 PendingDeletion del = {vk::ObjectType::eImage, {PendingDeletionFlags::UsesExternalMemory}, (void*)image, nullptr};
188 del.m_pContext = (void*)externalMemory;
189 DeleteLaterImpl(del);
190 }
191 image = nullptr;
192 externalMemory = nullptr;
193 }
194
195 template <typename T>
196 void DeleteLater(T& object, plVulkanAllocation& allocation)
197 {
198 if (object)
199 {
200 DeleteLaterImpl({object.objectType, {}, (void*)object, allocation});
201 }
202 object = nullptr;
203 allocation = nullptr;
204 }
205
206 template <typename T>
207 void DeleteLater(T& object, void* pContext)
208 {
209 if (object)
210 {
211 PendingDeletion del = {object.objectType, {}, (void*)object, nullptr};
212 del.m_pContext = pContext;
213 DeleteLaterImpl(static_cast<const PendingDeletion&>(del));
214 }
215 object = nullptr;
216 }
217
218 template <typename T>
219 void DeleteLater(T& object)
220 {
221 if (object)
222 {
223 DeleteLaterImpl({object.objectType, {}, (void*)object, nullptr});
224 }
225 object = nullptr;
226 }
227
228 void ReclaimLater(const ReclaimResource& reclaim);
229
230 template <typename T>
231 void ReclaimLater(T& object, void* pContext = nullptr)
232 {
233 ReclaimLater({object.objectType, (void*)object, pContext});
234 object = nullptr;
235 }
236
237 void SetDebugName(const vk::DebugUtilsObjectNameInfoEXT& info, plVulkanAllocation allocation = nullptr);
238
239 template <typename T>
240 void SetDebugName(const char* szName, T& object, plVulkanAllocation allocation = nullptr)
241 {
242#if PL_ENABLED(PL_COMPILE_FOR_DEVELOPMENT)
243 if (object)
244 {
245 vk::DebugUtilsObjectNameInfoEXT nameInfo;
246 nameInfo.objectType = object.objectType;
247 nameInfo.objectHandle = (uint64_t) static_cast<typename T::NativeType>(object);
248 nameInfo.pObjectName = szName;
249
250 SetDebugName(nameInfo, allocation);
251 }
252#endif
253 }
254
255 void ReportLiveGpuObjects();
256
257 static void UploadBufferStaging(plStagingBufferPoolVulkan* pStagingBufferPool, plPipelineBarrierVulkan* pPipelineBarrier, vk::CommandBuffer commandBuffer, const plGALBufferVulkan* pBuffer, plArrayPtr<const plUInt8> pInitialData, vk::DeviceSize dstOffset = 0);
258 static void UploadTextureStaging(plStagingBufferPoolVulkan* pStagingBufferPool, plPipelineBarrierVulkan* pPipelineBarrier, vk::CommandBuffer commandBuffer, const plGALTextureVulkan* pTexture, const vk::ImageSubresourceLayers& subResource, const plGALSystemMemoryDescription& data);
259
261 {
262 vk::Image image;
263 plGALDeviceVulkan& GALDeviceVulkan;
264 };
265 plEvent<OnBeforeImageDestroyedData> OnBeforeImageDestroyed;
266
267 virtual const plGALSharedTexture* GetSharedTexture(plGALTextureHandle hTexture) const override;
268
270 {
271 static SemaphoreInfo MakeWaitSemaphore(vk::Semaphore semaphore, vk::PipelineStageFlagBits waitStage = vk::PipelineStageFlagBits::eAllCommands, vk::SemaphoreType type = vk::SemaphoreType::eBinary, plUInt64 uiValue = 0)
272 {
273 return SemaphoreInfo{semaphore, type, waitStage, uiValue};
274 }
275
276 static SemaphoreInfo MakeSignalSemaphore(vk::Semaphore semaphore, vk::SemaphoreType type = vk::SemaphoreType::eBinary, plUInt64 uiValue = 0)
277 {
278 return SemaphoreInfo{semaphore, type, vk::PipelineStageFlagBits::eNone, uiValue};
279 }
280
281 vk::Semaphore m_semaphore;
282 vk::SemaphoreType m_type = vk::SemaphoreType::eBinary;
283 vk::PipelineStageFlagBits m_waitStage = vk::PipelineStageFlagBits::eAllCommands;
284 plUInt64 m_uiValue = 0;
285 };
286 void AddWaitSemaphore(const SemaphoreInfo& waitSemaphore);
287 void AddSignalSemaphore(const SemaphoreInfo& signalSemaphore);
288
289 // These functions need to be implemented by a render API abstraction
290protected:
291 // Init & shutdown functions
292
293 vk::Result SelectInstanceExtensions(plHybridArray<const char*, 6>& extensions);
294 vk::Result SelectDeviceExtensions(vk::DeviceCreateInfo& deviceCreateInfo, plHybridArray<const char*, 6>& extensions);
295
296 virtual plStringView GetRendererPlatform() override;
297 virtual plResult InitPlatform() override;
298 virtual plResult ShutdownPlatform() override;
299
300 // Command encoder functions
301
302 virtual plGALCommandEncoder* BeginCommandsPlatform(const char* szName) override;
303 virtual void EndCommandsPlatform(plGALCommandEncoder* pPass) override;
304
305 virtual void FlushPlatform() override;
306
307
308 // State creation functions
309
310 virtual plGALBlendState* CreateBlendStatePlatform(const plGALBlendStateCreationDescription& Description) override;
311 virtual void DestroyBlendStatePlatform(plGALBlendState* pBlendState) override;
312
313 virtual plGALDepthStencilState* CreateDepthStencilStatePlatform(const plGALDepthStencilStateCreationDescription& Description) override;
314 virtual void DestroyDepthStencilStatePlatform(plGALDepthStencilState* pDepthStencilState) override;
315
316 virtual plGALRasterizerState* CreateRasterizerStatePlatform(const plGALRasterizerStateCreationDescription& Description) override;
317 virtual void DestroyRasterizerStatePlatform(plGALRasterizerState* pRasterizerState) override;
318
319 virtual plGALSamplerState* CreateSamplerStatePlatform(const plGALSamplerStateCreationDescription& Description) override;
320 virtual void DestroySamplerStatePlatform(plGALSamplerState* pSamplerState) override;
321
322
323 // Resource creation functions
324
325 virtual plGALShader* CreateShaderPlatform(const plGALShaderCreationDescription& Description) override;
326 virtual void DestroyShaderPlatform(plGALShader* pShader) override;
327
328 virtual plGALBuffer* CreateBufferPlatform(const plGALBufferCreationDescription& Description, plArrayPtr<const plUInt8> pInitialData) override;
329 virtual void DestroyBufferPlatform(plGALBuffer* pBuffer) override;
330
331 virtual plGALTexture* CreateTexturePlatform(const plGALTextureCreationDescription& Description, plArrayPtr<plGALSystemMemoryDescription> pInitialData) override;
332 virtual void DestroyTexturePlatform(plGALTexture* pTexture) override;
333
334 virtual plGALTexture* CreateSharedTexturePlatform(const plGALTextureCreationDescription& Description, plArrayPtr<plGALSystemMemoryDescription> pInitialData, plEnum<plGALSharedTextureType> sharedType, plGALPlatformSharedHandle handle) override;
335 virtual void DestroySharedTexturePlatform(plGALTexture* pTexture) override;
336
337 virtual plGALTextureResourceView* CreateResourceViewPlatform(plGALTexture* pResource, const plGALTextureResourceViewCreationDescription& Description) override;
338 virtual void DestroyResourceViewPlatform(plGALTextureResourceView* pResourceView) override;
339
340 virtual plGALBufferResourceView* CreateResourceViewPlatform(plGALBuffer* pResource, const plGALBufferResourceViewCreationDescription& Description) override;
341 virtual void DestroyResourceViewPlatform(plGALBufferResourceView* pResourceView) override;
342
343 virtual plGALRenderTargetView* CreateRenderTargetViewPlatform(plGALTexture* pTexture, const plGALRenderTargetViewCreationDescription& Description) override;
344 virtual void DestroyRenderTargetViewPlatform(plGALRenderTargetView* pRenderTargetView) override;
345
346 plGALTextureUnorderedAccessView* CreateUnorderedAccessViewPlatform(plGALTexture* pResource, const plGALTextureUnorderedAccessViewCreationDescription& Description) override;
347 virtual void DestroyUnorderedAccessViewPlatform(plGALTextureUnorderedAccessView* pUnorderedAccessView) override;
348
349 plGALBufferUnorderedAccessView* CreateUnorderedAccessViewPlatform(plGALBuffer* pResource, const plGALBufferUnorderedAccessViewCreationDescription& Description) override;
350 virtual void DestroyUnorderedAccessViewPlatform(plGALBufferUnorderedAccessView* pUnorderedAccessView) override;
351
352 virtual plGALVertexDeclaration* CreateVertexDeclarationPlatform(const plGALVertexDeclarationCreationDescription& Description) override;
353 virtual void DestroyVertexDeclarationPlatform(plGALVertexDeclaration* pVertexDeclaration) override;
354
355 // GPU -> CPU query functions
356
357 virtual plEnum<plGALAsyncResult> GetTimestampResultPlatform(plGALTimestampHandle hTimestamp, plTime& out_result) override;
358 virtual plEnum<plGALAsyncResult> GetOcclusionResultPlatform(plGALOcclusionHandle hOcclusion, plUInt64& out_uiResult) override;
359 virtual plEnum<plGALAsyncResult> GetFenceResultPlatform(plGALFenceHandle hFence, plTime timeout) override;
360
361 // Misc functions
362
363 virtual void BeginFramePlatform(plArrayPtr<plGALSwapChain*> swapchains, const plUInt64 uiAppFrame) override;
364 virtual void EndFramePlatform(plArrayPtr<plGALSwapChain*> swapchains) override;
365 virtual plUInt64 GetCurrentFramePlatform() const override;
366 virtual plUInt64 GetSafeFramePlatform() const override;
367
368 virtual void FillCapabilitiesPlatform() override;
369
370 virtual void WaitIdlePlatform() override;
371
373
374private:
375 struct PerFrameData
376 {
378 plHybridArray<vk::Fence, 2> m_CommandBufferFences;
379
380 vk::CommandBuffer m_currentCommandBuffer;
381 plUInt64 m_uiFrame = -1;
382
383 plMutex m_pendingDeletionsMutex;
384 plDeque<PendingDeletion> m_pendingDeletions;
385 plDeque<PendingDeletion> m_pendingDeletionsPrevious;
386
387 plMutex m_reclaimResourcesMutex;
388 plDeque<ReclaimResource> m_reclaimResources;
389 plDeque<ReclaimResource> m_reclaimResourcesPrevious;
390 };
391
392 void DeletePendingResources(plDeque<PendingDeletion>& pendingDeletions);
393 void ReclaimResources(plDeque<ReclaimResource>& resources);
394
395 void FillFormatLookupTable();
396
397 static constexpr plUInt32 FRAMES = 4;
398
399 plUInt64 m_uiFrameCounter = 1;
400 plUInt64 m_uiSafeFrame = 0;
401 plUInt8 m_uiCurrentPerFrameData = m_uiFrameCounter % FRAMES;
402
403 vk::Instance m_instance;
404 vk::PhysicalDevice m_physicalDevice;
405 vk::PhysicalDeviceProperties m_properties;
406 vk::Device m_device;
407 Queue m_graphicsQueue;
408 Queue m_transferQueue;
409
410 plGALFormatLookupTableVulkan m_FormatLookupTable;
411 vk::PipelineStageFlags m_supportedStages;
412 vk::PhysicalDeviceMemoryProperties m_memoryProperties;
413
414 plUniquePtr<plGALCommandEncoderImplVulkan> m_pCommandEncoderImpl;
415 plUniquePtr<plGALCommandEncoder> m_pCommandEncoder;
416
417 plUniquePtr<plPipelineBarrierVulkan> m_pPipelineBarrier;
418 plUniquePtr<plCommandBufferPoolVulkan> m_pCommandBufferPool;
419 plUniquePtr<plStagingBufferPoolVulkan> m_pStagingBufferPool;
423
424 // We daisy-chain all command buffers in a frame in sequential order via this semaphore for now.
425 vk::Semaphore m_lastCommandBufferFinished;
426
427 PerFrameData m_PerFrameData[FRAMES];
428
429#if PL_ENABLED(PL_USE_PROFILING)
430 struct GPUTimingScope* m_pFrameTimingScope = nullptr;
431 struct GPUTimingScope* m_pPipelineTimingScope = nullptr;
432 struct GPUTimingScope* m_pPassTimingScope = nullptr;
433#endif
434
435 Extensions m_extensions;
436 plVulkanDispatchContext m_dispatchContext;
437#if PL_ENABLED(PL_COMPILE_FOR_DEVELOPMENT)
438 VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE;
439#endif
440 plHybridArray<SemaphoreInfo, 3> m_waitSemaphores;
441 plHybridArray<SemaphoreInfo, 3> m_signalSemaphores;
442};
443
444#include <RendererVulkan/Device/Implementation/DeviceVulkan_inl.h>
Base class for all memory allocators.
Definition Allocator.h:23
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
Simple pool for command buffers.
Definition CommandBufferPoolVulkan.h:20
Definition Deque.h:270
Definition Event.h:177
Definition FencePoolVulkan.h:36
Definition State.h:7
Definition RendererFoundationDLL.h:418
Definition Buffer.h:8
Definition ResourceView.h:30
Definition UnorderedAccesView.h:28
Definition BufferVulkan.h:11
Definition CommandEncoder.h:11
Definition CommandEncoderImplVulkan.h:28
Definition State.h:20
The plRenderDevice class is the primary interface for interactions with rendering APIs It contains a ...
Definition Device.h:19
The Vulkan device implementation of the graphics abstraction layer.
Definition DeviceVulkan.h:58
Definition State.h:33
Definition RenderTargetView.h:8
Definition State.h:46
Definition Shader.h:7
Optional interface for plGALTexture if it was created via plGALDevice::CreateSharedTexture....
Definition Texture.h:33
Definition RendererFoundationDLL.h:411
Definition Texture.h:8
Definition ResourceView.h:11
Definition UnorderedAccesView.h:11
Definition TextureVulkan.h:11
Definition VertexDeclaration.h:8
A hybrid array uses in-place storage to handle the first few elements without any allocation....
Definition HybridArray.h:12
Thread-safe context for initializing resources. Records a command buffer that transitions all newly c...
Definition InitContext.h:13
Provides a simple mechanism for mutual exclusion to prevent multiple threads from accessing a shared ...
Definition Mutex.h:13
Definition PipelineBarrierVulkan.h:19
Pool for GPU queries.
Definition QueryPoolVulkan.h:11
Definition StagingBufferPoolVulkan.h:18
plStringView represent a read-only sub-string of a larger string, as it can store a dedicated string ...
Definition StringView.h:34
A Unique ptr manages an object and destroys that object when it goes out of scope....
Definition UniquePtr.h:10
Definition DispatchContext.h:15
The plBitflags class allows you to work with type-safe bitflags.
Definition Bitflags.h:82
A custom enum implementation that allows to define the underlying storage type to control its memory ...
Definition Enum.h:37
Definition Descriptors.h:70
Definition Descriptors.h:169
Definition Descriptors.h:211
Definition Descriptors.h:39
Definition DeviceVulkan.h:107
Definition DeviceVulkan.h:68
Definition DeviceVulkan.h:86
Definition DeviceVulkan.h:148
Definition DeviceVulkan.h:99
Definition DeviceVulkan.h:270
Definition DeviceVulkan.h:19
Definition Descriptors.h:277
Describes the settings for a new rasterizer state. See plGALDevice::CreateRasterizerState.
Definition Descriptors.h:105
Definition Descriptors.h:220
Definition Descriptors.h:118
Definition Descriptors.h:44
Definition RendererFoundationDLL.h:365
Definition Descriptors.h:177
Definition Descriptors.h:153
A generic id class that holds an id combined of an instance index and a generation counter.
Definition Id.h:52
Definition Allocator_inl.h:18
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54
The time class encapsulates a double value storing the time in seconds.
Definition Time.h:12