/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include #include #include "Base/ICloseable.hpp" namespace OpenVulkano { namespace Vulkan { class Device : public ICloseable { public: vk::PhysicalDevice physicalDevice; std::vector queueFamilyProperties; // Queue family properties vk::PhysicalDeviceProperties properties; // Physical device properties (for e.g. checking device limits) vk::PhysicalDeviceFeatures features; // Physical device features (for e.g. checking if a feature is available) vk::PhysicalDeviceMemoryProperties memoryProperties; // available memory properties vk::Device device; // Logical device, application's view of the physical device (GPU) vk::PipelineCache pipelineCache; vk::CommandPool graphicsCommandPool; std::set supportedExtensions; vk::Queue graphicsQueue; struct QueueIndices { uint32_t graphics = VK_QUEUE_FAMILY_IGNORED; uint32_t compute = VK_QUEUE_FAMILY_IGNORED; uint32_t transfer = VK_QUEUE_FAMILY_IGNORED; uint32_t GetGraphics() const { return graphics; } uint32_t GetCompute() const { return compute != graphics ? compute : VK_QUEUE_FAMILY_IGNORED; } uint32_t GetTransfer() const { return (transfer != graphics && transfer != compute) ? transfer : VK_QUEUE_FAMILY_IGNORED; } } queueIndices; bool useDebugMarkers; public: Device(vk::PhysicalDevice& physicalDevice); ~Device() { if (device) Close(); } [[nodiscard]] std::string GetDeviceName() const { return properties.deviceName.data(); } void PrepareDevice(const vk::ArrayProxy& requestedExtensions, const vk::SurfaceKHR& surface); [[nodiscard]] const std::set& GetExtensions() const { return supportedExtensions; } [[nodiscard]] bool IsExtensionAvailable(const vk::ArrayProxy& extensions) const { for(const auto& extension : extensions) { if (supportedExtensions.count(extension) == 0) return false; } return true; } void WaitIdle() const; [[nodiscard]] vk::CommandBuffer CreateCommandBuffer(vk::CommandBufferLevel level = vk::CommandBufferLevel::ePrimary) const; void FlushCommandBuffer(vk::CommandBuffer& cmdBuffer) const; void ExecuteNow(const std::function& function) const; [[nodiscard]] vk::ShaderModule CreateShaderModule(const std::string& filename) const; vk::ShaderModule CreateShaderModule(vk::ShaderModuleCreateInfo& createInfo) const; private: void QueryDevice(); void BuildDevice(const vk::ArrayProxy& requestedExtensions); [[nodiscard]] uint32_t FindBestQueue(const vk::QueueFlags& desiredFlags, const vk::SurfaceKHR& surface = nullptr) const; public: /** * \brief Vulkan does not define a depth buffer format that must be supported. This method checks for the first supported format from an given array of formats. * \param depthFormats Array of depth formats * \return The first format supported as a depth buffer * \throws If no depth buffer format is supported */ [[nodiscard]] vk::Format GetSupportedDepthFormat(const std::vector& depthFormats = { vk::Format::eD32SfloatS8Uint, vk::Format::eD32Sfloat, vk::Format::eD24UnormS8Uint, vk::Format::eD16UnormS8Uint, vk::Format::eD16Unorm }) const; bool GetMemoryType(uint32_t typeBits, const vk::MemoryPropertyFlags& properties, uint32_t* typeIndex) const; [[nodiscard]] uint32_t GetMemoryType(uint32_t typeBits, const vk::MemoryPropertyFlags& properties) const; [[nodiscard]] vk::MemoryPropertyFlags GetMemoryFlags(uint32_t memoryType) const { return memoryProperties.memoryTypes[memoryType].propertyFlags; } void Close() override; }; } }