/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/Engine/RendererVulkan/Device/DeviceVulkan.h
481 строка
19 KB
Sanakan8472
Added resource bindings to extractors (#1976)
03 июл 2026, 17:05
Не верифицирован
03 июл 2026, 17:05
51b63b9
Код
Авторство
О чём код?
#pragma once #include <Foundation/Types/Bitflags.h> #include <Foundation/Types/UniquePtr.h> #include <RendererFoundation/Device/Device.h> #include <RendererVulkan/Device/DispatchContext.h> // #include <RendererVulkan/MemoryAllocator/MemoryAllocatorVulkan.h> #include <RendererVulkan/Device/DeclarationsVulkan.h> #include <RendererVulkan/RendererVulkanDLL.h> EZ_DEFINE_AS_POD_TYPE(vk::Format); class ezGALCommandEncoderImplVulkan; class ezFenceQueueVulkan; struct ezGALFormatLookupEntryVulkan { ezGALFormatLookupEntryVulkan() = default; ezGALFormatLookupEntryVulkan(vk::Format format) { m_format = format; m_readback = format; } ezGALFormatLookupEntryVulkan(vk::Format format, ezArrayPtr<vk::Format> mutableFormats) { m_format = format; m_readback = format; m_mutableFormats = mutableFormats; } inline ezGALFormatLookupEntryVulkan& R(vk::Format readbackType) { m_readback = readbackType; return *this; } vk::Format m_format = vk::Format::eUndefined; vk::Format m_readback = vk::Format::eUndefined; ezHybridArray<vk::Format, 6> m_mutableFormats; }; using ezGALFormatLookupTableVulkan = ezGALFormatLookupTable<ezGALFormatLookupEntryVulkan>; class ezGALBufferVulkan; class ezGALTextureVulkan; class ezCommandBufferPoolVulkan; class ezStagingBufferPoolVulkan; class ezQueryPoolVulkan; class ezInitContextVulkan; class ezDescriptorWritePoolVulkan; /// \brief The Vulkan device implementation of the graphics abstraction layer. class EZ_RENDERERVULKAN_DLL ezGALDeviceVulkan : public ezGALDevice { private: friend ezInternal::NewInstance<ezGALDevice> CreateVulkanDevice(ezAllocator* pAllocator, const ezGALDeviceCreationDescription& description); ezGALDeviceVulkan(const ezGALDeviceCreationDescription& Description); public: virtual ~ezGALDeviceVulkan(); public: struct PendingDeletionFlags { using StorageType = ezUInt32; enum Enum { UsesExternalMemory = EZ_BIT(0), IsFileDescriptor = EZ_BIT(1), Default = 0 }; struct Bits { StorageType UsesExternalMemory : 1; StorageType IsFileDescriptor : 1; }; }; struct PendingDeletion { EZ_DECLARE_POD_TYPE(); vk::ObjectType m_type; ///< What type to cast m_pObject to. ezBitflags<PendingDeletionFlags> m_flags; ///< In case m_type == eUnknown, defines the custom deletion to be performed. void* m_pObject; ///< The object to be deleted, usually cast to a vk::* type. union { ezVulkanAllocation m_allocation; ///< For convenience to omit casting of m_pContext. void* m_pContext; ///< 64bit of context data. }; }; struct ReclaimResource { EZ_DECLARE_POD_TYPE(); vk::ObjectType m_type; ///< What type to cast m_pObject to. ezUInt32 m_Data; ///< 32bit of context data. void* m_pObject = nullptr; ///< The object to be reclaimed, usually cast to a vk::* type. void* m_pContext = nullptr; ///< 64bit of context data. Usually the object that reclaims the resource. }; struct Extensions { bool m_bSurface = false; #if defined(VK_USE_PLATFORM_WIN32_KHR) bool m_bWin32Surface = false; #elif EZ_ENABLED(EZ_SUPPORTS_GLFW) #elif defined(VK_USE_PLATFORM_ANDROID_KHR) bool m_bAndroidSurface = false; #else # error "Vulkan Platform not supported" #endif #if EZ_ENABLED(EZ_PLATFORM_LINUX) bool m_bSurfaceXcb = false; #endif bool m_bDebugUtils = false; bool m_bDebugUtilsMarkers = false; bool m_bDeviceSwapChain = false; bool m_bShaderViewportIndexLayer = false; vk::PhysicalDeviceCustomBorderColorFeaturesEXT m_borderColorEXT; bool m_bBorderColorFloat = false; bool m_bImageFormatList = false; vk::PhysicalDeviceTimelineSemaphoreFeatures m_timelineSemaphoresEXT; bool m_bTimelineSemaphore = false; vk::PhysicalDeviceSynchronization2Features m_synchronization2Features; bool m_bSynchronization2 = false; bool m_bExternalMemoryCapabilities = false; bool m_bExternalSemaphoreCapabilities = false; bool m_bExternalFenceCapabilities = false; bool m_bExternalMemory = false; bool m_bExternalSemaphore = false; bool m_bExternalMemoryFd = false; bool m_bExternalSemaphoreFd = false; bool m_bExternalMemoryWin32 = false; bool m_bExternalSemaphoreWin32 = false; bool m_bPhysicalDeviceProperties2 = false; bool m_bSurfaceCapabilities2 = false; bool m_bSurfaceMaintenance1 = false; vk::PhysicalDeviceSwapchainMaintenance1FeaturesKHR m_swapchainMaintenance1Features; bool m_bSwapchainMaintenance1 = false; }; struct Queue { vk::Queue m_queue; ezUInt32 m_uiQueueFamily = -1; ezUInt32 m_uiQueueIndex = 0; }; vk::Instance GetVulkanInstance() const; vk::Device GetVulkanDevice() const; const Queue& GetGraphicsQueue() const; const Queue& GetTransferQueue() const; vk::PhysicalDevice GetVulkanPhysicalDevice() const; EZ_ALWAYS_INLINE const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const { return m_Properties.properties; } vk::PhysicalDeviceFeatures2 GetPhysicalDeviceFeatures(void* pNext = nullptr) const; const Extensions& GetExtensions() const { return m_Extensions; } const ezVulkanDispatchContext& GetDispatchContext() const { return m_DispatchContext; } vk::PipelineStageFlags GetSupportedStages() const; vk::CommandBuffer& GetCurrentCommandBuffer(); ezQueryPoolVulkan& GetQueryPool() const; ezFenceQueueVulkan& GetFenceQueue() const; ezStagingBufferPoolVulkan& GetStagingBufferPool() const; ezInitContextVulkan& GetInitContext() const; ezDescriptorWritePoolVulkan& GetDescriptorWritePool() const; ezGALTextureHandle CreateTextureInternal(const ezGALTextureCreationDescription& description, ezArrayPtr<ezGALSystemMemoryDescription> initialData); ezGALBufferHandle CreateBufferInternal(const ezGALBufferCreationDescription& description, ezArrayPtr<const ezUInt8> initialData); const ezGALFormatLookupTableVulkan& GetFormatLookupTable() const; ezInt32 GetMemoryIndex(vk::MemoryPropertyFlags properties, const vk::MemoryRequirements& requirements) const; vk::Fence Submit(bool bAddSignalSemaphore = true, bool bAddUpdateForNextFrameCommands = false); void DeleteLaterImpl(const PendingDeletion& deletion); void DeleteLater(vk::Image& ref_image, vk::DeviceMemory& ref_externalMemory) { if (ref_image) { PendingDeletion del = {vk::ObjectType::eImage, {PendingDeletionFlags::UsesExternalMemory}, (void*)ref_image, nullptr}; del.m_pContext = (void*)ref_externalMemory; DeleteLaterImpl(del); } ref_image = nullptr; ref_externalMemory = nullptr; } template <typename T> void DeleteLater(T& ref_object, ezVulkanAllocation& ref_pAllocation) { if (ref_object) { DeleteLaterImpl({ref_object.objectType, {}, (void*)ref_object, ref_pAllocation}); } ref_object = nullptr; ref_pAllocation = nullptr; } template <typename T> void DeleteLater(T& ref_object, void* pContext) { if (ref_object) { PendingDeletion del = {ref_object.objectType, {}, (void*)ref_object, nullptr}; del.m_pContext = pContext; DeleteLaterImpl(static_cast<const PendingDeletion&>(del)); } ref_object = nullptr; } template <typename T> void DeleteLater(T& ref_object) { if (ref_object) { DeleteLaterImpl({ref_object.objectType, {}, (void*)ref_object, nullptr}); } ref_object = nullptr; } void ReclaimLater(const ReclaimResource& reclaim); template <typename T> void ReclaimLater(T& ref_object, void* pContext = nullptr, ezUInt32 uiData = 0) { ReclaimLater({ref_object.objectType, uiData, (void*)ref_object, pContext}); ref_object = nullptr; } void SetDebugName(const vk::DebugUtilsObjectNameInfoEXT& info, ezVulkanAllocation pAllocation = nullptr); template <typename T> void SetDebugName(const char* szName, T& ref_object, ezVulkanAllocation pAllocation = nullptr) { #if EZ_ENABLED(EZ_COMPILE_FOR_DEVELOPMENT) if (ref_object) { vk::DebugUtilsObjectNameInfoEXT nameInfo; nameInfo.objectType = ref_object.objectType; nameInfo.objectHandle = (uint64_t) static_cast<typename T::NativeType>(ref_object); nameInfo.pObjectName = szName; SetDebugName(nameInfo, pAllocation); } #endif } void ReportLiveGpuObjects(); static void UploadBufferStaging(ezGALDeviceVulkan& ref_device, ezStagingBufferPoolVulkan* pStagingBufferPool, vk::CommandBuffer commandBuffer, const ezGALBufferVulkan* pBuffer, ezArrayPtr<const ezUInt8> initialData, vk::DeviceSize dstOffset = 0); static void UploadTextureStaging(ezGALDeviceVulkan& ref_device, ezStagingBufferPoolVulkan* pStagingBufferPool, vk::CommandBuffer commandBuffer, const ezGALTextureVulkan* pTexture, const vk::ImageSubresourceLayers& subResource, const vk::Offset3D& imageOffset, const vk::Extent3D& imageExtent, const ezGALSystemMemoryDescription& data); struct OnBeforeImageDestroyedData { vk::Image image; ezGALDeviceVulkan& GALDeviceVulkan; }; ezEvent<OnBeforeImageDestroyedData> OnBeforeImageDestroyed; virtual const ezGALSharedTexture* GetSharedTexture(ezGALTextureHandle hTexture) const override; struct SemaphoreInfo { static SemaphoreInfo MakeWaitSemaphore(vk::Semaphore semaphore, vk::PipelineStageFlagBits waitStage = vk::PipelineStageFlagBits::eAllCommands, vk::SemaphoreType type = vk::SemaphoreType::eBinary, ezUInt64 uiValue = 0) { return SemaphoreInfo{semaphore, type, waitStage, uiValue}; } static SemaphoreInfo MakeSignalSemaphore(vk::Semaphore semaphore, vk::SemaphoreType type = vk::SemaphoreType::eBinary, ezUInt64 uiValue = 0) { return SemaphoreInfo{semaphore, type, vk::PipelineStageFlagBits::eNone, uiValue}; } vk::Semaphore m_semaphore; vk::SemaphoreType m_type = vk::SemaphoreType::eBinary; vk::PipelineStageFlagBits m_waitStage = vk::PipelineStageFlagBits::eAllCommands; ezUInt64 m_uiValue = 0; }; void AddWaitSemaphore(const SemaphoreInfo& waitSemaphore); void AddSignalSemaphore(const SemaphoreInfo& signalSemaphore); // These functions need to be implemented by a render API abstraction protected: // Init & shutdown functions vk::Result SelectInstanceExtensions(ezDynamicArray<ezString>& extensions); vk::Result SelectDeviceExtensions(vk::DeviceCreateInfo& deviceCreateInfo, ezDynamicArray<ezString>& extensions); virtual ezStringView GetRendererPlatform() override; virtual ezResult InitPlatform() override; virtual ezResult ShutdownPlatform() override; // Command encoder functions virtual ezGALCommandEncoder* BeginCommandsPlatform(const char* szName) override; virtual void EndCommandsPlatform(ezGALCommandEncoder* pPass) override; virtual void FlushPlatform() override; // State creation functions virtual ezGALBlendState* CreateBlendStatePlatform(const ezGALBlendStateCreationDescription& Description) override; virtual void DestroyBlendStatePlatform(ezGALBlendState* pBlendState) override; virtual ezGALDepthStencilState* CreateDepthStencilStatePlatform(const ezGALDepthStencilStateCreationDescription& Description) override; virtual void DestroyDepthStencilStatePlatform(ezGALDepthStencilState* pDepthStencilState) override; virtual ezGALRasterizerState* CreateRasterizerStatePlatform(const ezGALRasterizerStateCreationDescription& Description) override; virtual void DestroyRasterizerStatePlatform(ezGALRasterizerState* pRasterizerState) override; virtual ezGALSamplerState* CreateSamplerStatePlatform(const ezGALSamplerStateCreationDescription& Description) override; virtual void DestroySamplerStatePlatform(ezGALSamplerState* pSamplerState) override; virtual void RecreateSamplerStatePlatform(ezGALSamplerState* pSamplerState) override; virtual ezGALBindGroupLayout* CreateBindGroupLayoutPlatform(const ezGALBindGroupLayoutCreationDescription& Description) override; virtual void DestroyBindGroupLayoutPlatform(ezGALBindGroupLayout* pBindGroupLayout) override; virtual ezGALBindGroup* CreateBindGroupPlatform(const ezGALBindGroupCreationDescription& Description) override; virtual void DestroyBindGroupPlatform(ezGALBindGroup* pBindGroup) override; virtual void RecreateBindGroupPlatform(ezGALBindGroup* pBindGroup) override; virtual ezGALPipelineLayout* CreatePipelineLayoutPlatform(const ezGALPipelineLayoutCreationDescription& Description) override; virtual void DestroyPipelineLayoutPlatform(ezGALPipelineLayout* pPipelineLayout) override; virtual ezGALGraphicsPipeline* CreateGraphicsPipelinePlatform(const ezGALGraphicsPipelineCreationDescription& Description) override; virtual void DestroyGraphicsPipelinePlatform(ezGALGraphicsPipeline* pGraphicsPipeline) override; virtual ezGALComputePipeline* CreateComputePipelinePlatform(const ezGALComputePipelineCreationDescription& Description) override; virtual void DestroyComputePipelinePlatform(ezGALComputePipeline* pComputePipeline) override; // Resource creation functions virtual ezGALShader* CreateShaderPlatform(const ezGALShaderCreationDescription& Description) override; virtual void DestroyShaderPlatform(ezGALShader* pShader) override; virtual ezGALBuffer* CreateBufferPlatform(const ezGALBufferCreationDescription& Description, ezArrayPtr<const ezUInt8> pInitialData) override; virtual void DestroyBufferPlatform(ezGALBuffer* pBuffer) override; virtual ezGALTexture* CreateTexturePlatform(const ezGALTextureCreationDescription& Description, ezArrayPtr<ezGALSystemMemoryDescription> pInitialData) override; virtual void DestroyTexturePlatform(ezGALTexture* pTexture) override; virtual ezGALTexture* CreateSharedTexturePlatform(const ezGALTextureCreationDescription& Description, ezArrayPtr<ezGALSystemMemoryDescription> pInitialData, ezEnum<ezGALSharedTextureType> sharedType, ezGALPlatformSharedHandle handle) override; virtual void DestroySharedTexturePlatform(ezGALTexture* pTexture) override; virtual ezGALReadbackBuffer* CreateReadbackBufferPlatform(const ezGALBufferCreationDescription& Description) override; virtual void DestroyReadbackBufferPlatform(ezGALReadbackBuffer* pReadbackBuffer) override; virtual ezGALReadbackTexture* CreateReadbackTexturePlatform(const ezGALTextureCreationDescription& Description) override; virtual void DestroyReadbackTexturePlatform(ezGALReadbackTexture* pReadbackTexture) override; virtual ezGALRenderTargetView* CreateRenderTargetViewPlatform(ezGALTexture* pTexture, const ezGALRenderTargetViewCreationDescription& Description) override; virtual void DestroyRenderTargetViewPlatform(ezGALRenderTargetView* pRenderTargetView) override; virtual ezGALVertexDeclaration* CreateVertexDeclarationPlatform(const ezGALVertexDeclarationCreationDescription& Description) override; virtual void DestroyVertexDeclarationPlatform(ezGALVertexDeclaration* pVertexDeclaration) override; // Resource update functions virtual void UpdateBufferForNextFramePlatform(const ezGALBuffer* pBuffer, ezConstByteArrayPtr sourceData, ezUInt32 uiDestOffset) override; virtual void UpdateTextureForNextFramePlatform(const ezGALTexture* pTexture, const ezGALSystemMemoryDescription& sourceData, const ezGALTextureSubresource& destinationSubResource, const ezBoundingBoxu32& destinationBox) override; // GPU -> CPU query functions virtual ezEnum<ezGALAsyncResult> GetTimestampResultPlatform(ezGALTimestampHandle hTimestamp, ezTime& out_result) override; virtual ezEnum<ezGALAsyncResult> GetOcclusionResultPlatform(ezGALOcclusionHandle hOcclusion, ezUInt64& out_uiResult) override; virtual ezEnum<ezGALAsyncResult> GetFenceResultPlatform(ezGALFenceHandle hFence, ezTime timeout) override; virtual ezResult LockBufferPlatform(const ezGALReadbackBuffer* pBuffer, ezArrayPtr<const ezUInt8>& out_Memory) const override; virtual void UnlockBufferPlatform(const ezGALReadbackBuffer* pBuffer) const override; virtual ezResult LockTexturePlatform(const ezGALReadbackTexture* pTexture, const ezArrayPtr<const ezGALTextureSubresource>& subResources, ezDynamicArray<ezGALSystemMemoryDescription>& out_Memory) const override; virtual void UnlockTexturePlatform(const ezGALReadbackTexture* pTexture, const ezArrayPtr<const ezGALTextureSubresource>& subResources) const override; // Misc functions virtual void BeginFramePlatform(ezArrayPtr<ezGALSwapChain*> swapchains, const ezUInt64 uiAppFrame) override; virtual void EndFramePlatform(ezArrayPtr<ezGALSwapChain*> swapchains) override; virtual ezUInt64 GetCurrentFramePlatform() const override; virtual ezUInt64 GetSafeFramePlatform() const override; virtual void FillCapabilitiesPlatform() override; virtual void WaitIdlePlatform() override; /// \endcond private: void WaitIdleInternal(bool bAddUpdateForNextFrameCommands); struct PerFrameData { /// \brief These are all fences passed into submit calls. For some reason waiting for the fence of the last submit is not enough. At least I can't get it to work (neither semaphores nor barriers make it past the validation layer). ezHybridArray<vk::Fence, 2> m_CommandBufferFences; vk::CommandBuffer m_currentCommandBuffer; ezUInt64 m_uiFrame = -1; ezMutex m_pendingDeletionsMutex; ezDeque<PendingDeletion> m_pendingDeletions; ezDeque<PendingDeletion> m_pendingDeletionsPrevious; ezMutex m_reclaimResourcesMutex; ezDeque<ReclaimResource> m_reclaimResources; ezDeque<ReclaimResource> m_reclaimResourcesPrevious; }; void DeletePendingResources(ezDeque<PendingDeletion>& pendingDeletions); void ReclaimResources(ezDeque<ReclaimResource>& resources); void FillFormatLookupTable(); static constexpr ezUInt32 FRAMES = 4; // These are atomic as the ezInitContextVulkan is accessing these on worker threads when uploading resources in the background. ezAtomicInteger<ezUInt64> m_uiFrameCounter = 1; ///< We start at 1 so m_uiFrameCounter and m_uiSafeFrame are not equal at the start. ezAtomicInteger<ezUInt64> m_uiSafeFrame = 0; ezUInt8 m_uiCurrentPerFrameData = m_uiFrameCounter % FRAMES; vk::Instance m_Instance; vk::PhysicalDevice m_PhysicalDevice; vk::PhysicalDeviceProperties2 m_Properties; vk::Device m_Device; Queue m_GraphicsQueue; Queue m_TransferQueue; ezGALFormatLookupTableVulkan m_FormatLookupTable; vk::PipelineStageFlags m_SupportedStages; vk::PhysicalDeviceMemoryProperties m_MemoryProperties; ezUniquePtr<ezGALCommandEncoderImplVulkan> m_pCommandEncoderImpl; ezUniquePtr<ezGALCommandEncoder> m_pCommandEncoder; ezUniquePtr<ezCommandBufferPoolVulkan> m_pCommandBufferPool; ezUniquePtr<ezStagingBufferPoolVulkan> m_pStagingBufferPool; ezUniquePtr<ezQueryPoolVulkan> m_pQueryPool; ezUniquePtr<ezFenceQueueVulkan> m_pFenceQueue; ezUniquePtr<ezInitContextVulkan> m_pInitContext; ezDynamicArray<ezPendingBufferCopyVulkan, ezLocalAllocatorWrapper> m_PendingBufferCopies; ezDynamicArray<ezPendingTextureCopyVulkan, ezLocalAllocatorWrapper> m_PendingTextureCopies; // We daisy-chain all command buffers in a frame in sequential order via this semaphore for now. vk::Semaphore m_LastCommandBufferFinished; PerFrameData m_PerFrameData[FRAMES]; #if EZ_ENABLED(EZ_USE_PROFILING) struct GPUTimingScope* m_pFrameTimingScope = nullptr; struct GPUTimingScope* m_pPipelineTimingScope = nullptr; struct GPUTimingScope* m_pPassTimingScope = nullptr; #endif Extensions m_Extensions; ezVulkanDispatchContext m_DispatchContext; #if EZ_ENABLED(EZ_COMPILE_FOR_DEVELOPMENT) vk::DebugUtilsMessengerEXT m_DebugMessenger = nullptr; #endif ezHybridArray<SemaphoreInfo, 3> m_WaitSemaphores; ezHybridArray<SemaphoreInfo, 3> m_SignalSemaphores; }; #include <RendererVulkan/Device/Implementation/DeviceVulkan_inl.h>