Files
OpenVulkano/openVulkanoCpp/Vulkan/Device.hpp
2021-07-21 01:59:11 +02:00

111 lines
3.9 KiB
C++

/*
* 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 <vulkan/vulkan.hpp>
#include <set>
#include <functional>
#include <fstream>
#include "Base/ICloseable.hpp"
namespace openVulkanoCpp
{
namespace Vulkan
{
class Device : virtual public ICloseable
{
public:
vk::PhysicalDevice physicalDevice;
std::vector<vk::QueueFamilyProperties> 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<std::string> 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);
[[nodiscard]] std::string GetDeviceName() const
{
return properties.deviceName.data();
}
void PrepareDevice(const vk::ArrayProxy<const std::string>& requestedExtensions, const vk::SurfaceKHR& surface);
[[nodiscard]] const std::set<std::string>& GetExtensions() const
{
return supportedExtensions;
}
[[nodiscard]] bool IsExtensionAvailable(const vk::ArrayProxy<const std::string>& 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<void(const vk::CommandBuffer& commandBuffer)>& 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<const std::string>& 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<vk::Format>& 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;
};
}
}