#pragma once #include #include #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_NO_DEFAULT_DISPATCHER #ifdef _WIN32 #define VK_USE_PLATFORM_WIN32_KHR #elif defined(__ANDROID__) #define VK_USE_PLATFORM_ANDROID_KHR #endif #include #define VMA_VULKAN_VERSION 1000000 #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #include "vk_mem_alloc.h" #if !defined(NDEBUG) && !defined(__ANDROID__) #define ENABLE_VULKAN_VALIDATION // #define ENABLE_VULKAN_VALIDATION_FEATURES // #define ENABLE_VMA_DEBUG #endif namespace mln { class ProgramParameters; namespace vulkan { using DynamicLoader = vk::detail::DynamicLoader; using DispatchLoaderDynamic = VULKAN_HPP_DISPATCH_LOADER_DYNAMIC_TYPE; template using ObjectDestroy = vk::detail::ObjectDestroy; class RendererBackend : public gfx::RendererBackend { public: RendererBackend(gfx::ContextMode); ~RendererBackend() override; /// One-time shader initialization void initShaders(gfx::ShaderRegistry&, const ProgramParameters& programParameters) override; void init(); const DispatchLoaderDynamic& getDispatcher() const { return dispatcher; } const vk::UniqueInstance& getInstance() const { return instance; } const vk::PhysicalDevice& getPhysicalDevice() const { return physicalDevice; } const vk::UniqueDevice& getDevice() const { return device; } const vk::UniqueCommandPool& getCommandPool() const { return commandPool; } const vk::Queue& getGraphicsQueue() const { return graphicsQueue; } const vk::Queue& getPresentQueue() const { return presentQueue; } uint32_t getMaxFrames() const { return maxFrames; } const VmaAllocator& getAllocator() const { return allocator; } const vk::PhysicalDeviceProperties& getDeviceProperties() const { return physicalDeviceProperties; } const vk::PhysicalDeviceFeatures& getDeviceFeatures() const { return physicalDeviceFeatures; } int32_t getGraphicsQueueIndex() const { return graphicsQueueIndex; } int32_t getPresentQueueIndex() const { return presentQueueIndex; } template requires vk::isVulkanHandleType::value void setDebugName([[maybe_unused]] const T& object, [[maybe_unused]] const std::string& name) const { #ifdef ENABLE_VULKAN_VALIDATION if (!debugUtilsEnabled) return; const uint64_t handle = reinterpret_cast(static_cast(object)); device->setDebugUtilsObjectNameEXT(vk::DebugUtilsObjectNameInfoEXT() .setObjectType(T::objectType) .setObjectHandle(handle) .setPObjectName(name.c_str()), dispatcher); #endif } void beginDebugLabel(const vk::CommandBuffer& buffer, const char* name, const std::array& color) const; void endDebugLabel(const vk::CommandBuffer& buffer) const; void insertDebugLabel(const vk::CommandBuffer& buffer, const char* name) const; void startFrameCapture(); void endFrameCapture(); void setFrameCaptureLoop(bool value); void triggerFrameCapture(uint32_t frameCount = 1, uint32_t frameDelay = 0); protected: std::unique_ptr createContext() override; virtual std::vector getLayers(); virtual std::vector getInstanceExtensions(); virtual std::vector getDeviceExtensions(); std::vector getDebugExtensions(); virtual void initInstance(); virtual void initDebug(); virtual void initSurface(); virtual void initDevice(); virtual void initAllocator(); virtual void initSwapchain(); virtual void initCommandPool(); virtual void initFrameCapture(); void destroyResources(); protected: DynamicLoader dynamicLoader; DispatchLoaderDynamic dispatcher; vk::UniqueInstance instance; vk::UniqueDebugUtilsMessengerEXT debugUtilsCallback; vk::UniqueDebugReportCallbackEXT debugReportCallback; vk::PhysicalDevice physicalDevice; vk::UniqueDevice device; vk::PhysicalDeviceProperties physicalDeviceProperties; vk::PhysicalDeviceFeatures physicalDeviceFeatures; int32_t graphicsQueueIndex = -1; int32_t presentQueueIndex = -1; vk::Queue graphicsQueue; vk::Queue presentQueue; vk::UniqueCommandPool commandPool; uint32_t maxFrames = 1; VmaAllocator allocator; bool debugUtilsEnabled{false}; bool usingSharedContext{false}; }; } // namespace vulkan } // namespace mln