Skip to content
Snippets Groups Projects
Verified Commit 1807c1a7 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Refactored context and core in structure

parent dfc1a650
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "QueueManager.hpp"
namespace vkcv namespace vkcv
{ {
class Context class Context
...@@ -21,10 +23,21 @@ namespace vkcv ...@@ -21,10 +23,21 @@ namespace vkcv
[[nodiscard]] [[nodiscard]]
const vk::Instance &getInstance() const; const vk::Instance &getInstance() const;
[[nodiscard]] [[nodiscard]]
const vk::PhysicalDevice &getPhysicalDevice() const; const vk::PhysicalDevice &getPhysicalDevice() const;
[[nodiscard]] [[nodiscard]]
const vk::Device &getDevice() const; const vk::Device &getDevice() const;
[[nodiscard]]
const QueueManager& getQueueManager() const;
static Context create(const char *applicationName,
uint32_t applicationVersion,
std::vector<vk::QueueFlagBits> queueFlags,
std::vector<const char *> instanceExtensions,
std::vector<const char *> deviceExtensions);
private: private:
/** /**
...@@ -34,9 +47,11 @@ namespace vkcv ...@@ -34,9 +47,11 @@ namespace vkcv
* @param physicalDevice Vulkan-PhysicalDevice * @param physicalDevice Vulkan-PhysicalDevice
* @param device Vulkan-Device * @param device Vulkan-Device
*/ */
Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device) noexcept; Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device, QueueManager&& queueManager) noexcept;
vk::Instance m_Instance; vk::Instance m_Instance;
vk::PhysicalDevice m_PhysicalDevice; vk::PhysicalDevice m_PhysicalDevice;
vk::Device m_Device; vk::Device m_Device;
QueueManager m_QueueManager;
}; };
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "vkcv/PipelineConfig.hpp" #include "vkcv/PipelineConfig.hpp"
#include "CommandResources.hpp" #include "CommandResources.hpp"
#include "SyncResources.hpp" #include "SyncResources.hpp"
#include "vkcv/QueueManager.hpp"
namespace vkcv namespace vkcv
{ {
...@@ -36,7 +35,7 @@ namespace vkcv ...@@ -36,7 +35,7 @@ namespace vkcv
* @param context encapsulates various Vulkan objects * @param context encapsulates various Vulkan objects
*/ */
Core(Context &&context, const Window &window, SwapChain swapChain, std::vector<vk::ImageView> imageViews, Core(Context &&context, const Window &window, SwapChain swapChain, std::vector<vk::ImageView> imageViews,
const CommandResources& commandResources, const SyncResources& syncResources, const QueueManager &queues) noexcept; const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
// explicit destruction of default constructor // explicit destruction of default constructor
Core() = delete; Core() = delete;
...@@ -53,7 +52,6 @@ namespace vkcv ...@@ -53,7 +52,6 @@ namespace vkcv
std::unique_ptr<PipelineManager> m_PipelineManager; std::unique_ptr<PipelineManager> m_PipelineManager;
CommandResources m_CommandResources; CommandResources m_CommandResources;
SyncResources m_SyncResources; SyncResources m_SyncResources;
QueueManager m_QueueManager;
uint32_t m_currentSwapchainImageIndex; uint32_t m_currentSwapchainImageIndex;
std::vector<vk::Framebuffer> m_TemporaryFramebuffers; std::vector<vk::Framebuffer> m_TemporaryFramebuffers;
public: public:
......
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
namespace vkcv { namespace vkcv {
struct Queue {
int familyIndex;
int queueIndex;
vk::Queue handle;
};
class QueueManager { class QueueManager {
public: public:
static QueueManager create(vk::Device device, static QueueManager create(vk::Device device,
...@@ -9,13 +17,17 @@ namespace vkcv { ...@@ -9,13 +17,17 @@ namespace vkcv {
std::vector<std::pair<int, int>> &queuePairsCompute, std::vector<std::pair<int, int>> &queuePairsCompute,
std::vector<std::pair<int, int>> &queuePairsTransfer); std::vector<std::pair<int, int>> &queuePairsTransfer);
const vk::Queue &getPresentQueue() const; [[nodiscard]]
const Queue &getPresentQueue() const;
const std::vector<vk::Queue> &getGraphicsQueues() const;
[[nodiscard]]
const std::vector<vk::Queue> &getComputeQueues() const; const std::vector<Queue> &getGraphicsQueues() const;
const std::vector<vk::Queue> &getTransferQueues() const; [[nodiscard]]
const std::vector<Queue> &getComputeQueues() const;
[[nodiscard]]
const std::vector<Queue> &getTransferQueues() const;
static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice, static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
std::vector<float> &queuePriorities, std::vector<float> &queuePriorities,
...@@ -26,11 +38,12 @@ namespace vkcv { ...@@ -26,11 +38,12 @@ namespace vkcv {
std::vector<std::pair<int, int>> &queuePairsTransfer); std::vector<std::pair<int, int>> &queuePairsTransfer);
private: private:
vk::Queue m_presentQueue; std::vector<Queue> m_graphicsQueues;
std::vector<vk::Queue> m_graphicsQueues; std::vector<Queue> m_computeQueues;
std::vector<vk::Queue> m_computeQueues; std::vector<Queue> m_transferQueues;
std::vector<vk::Queue> m_transferQueues;
size_t m_presentIndex;
QueueManager(std::vector<vk::Queue> graphicsQueues, std::vector<vk::Queue> computeQueues, std::vector<vk::Queue> transferQueues, vk::Queue presentQueue); QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex);
}; };
} }
#include <GLFW/glfw3.h>
#include "vkcv/Context.hpp" #include "vkcv/Context.hpp"
namespace vkcv namespace vkcv
...@@ -5,7 +8,8 @@ namespace vkcv ...@@ -5,7 +8,8 @@ namespace vkcv
Context::Context(Context &&other) noexcept: Context::Context(Context &&other) noexcept:
m_Instance(other.m_Instance), m_Instance(other.m_Instance),
m_PhysicalDevice(other.m_PhysicalDevice), m_PhysicalDevice(other.m_PhysicalDevice),
m_Device(other.m_Device) m_Device(other.m_Device),
m_QueueManager(other.m_QueueManager)
{ {
other.m_Instance = nullptr; other.m_Instance = nullptr;
other.m_PhysicalDevice = nullptr; other.m_PhysicalDevice = nullptr;
...@@ -17,6 +21,7 @@ namespace vkcv ...@@ -17,6 +21,7 @@ namespace vkcv
m_Instance = other.m_Instance; m_Instance = other.m_Instance;
m_PhysicalDevice = other.m_PhysicalDevice; m_PhysicalDevice = other.m_PhysicalDevice;
m_Device = other.m_Device; m_Device = other.m_Device;
m_QueueManager = other.m_QueueManager;
other.m_Instance = nullptr; other.m_Instance = nullptr;
other.m_PhysicalDevice = nullptr; other.m_PhysicalDevice = nullptr;
...@@ -27,10 +32,12 @@ namespace vkcv ...@@ -27,10 +32,12 @@ namespace vkcv
Context::Context(vk::Instance instance, Context::Context(vk::Instance instance,
vk::PhysicalDevice physicalDevice, vk::PhysicalDevice physicalDevice,
vk::Device device) noexcept : vk::Device device,
QueueManager&& queueManager) noexcept :
m_Instance{instance}, m_Instance{instance},
m_PhysicalDevice{physicalDevice}, m_PhysicalDevice{physicalDevice},
m_Device{device} m_Device{device},
m_QueueManager{queueManager}
{} {}
Context::~Context() noexcept Context::~Context() noexcept
...@@ -53,4 +60,232 @@ namespace vkcv ...@@ -53,4 +60,232 @@ namespace vkcv
{ {
return m_Device; return m_Device;
} }
const QueueManager& Context::getQueueManager() const {
return m_QueueManager;
}
/**
* @brief The physical device is evaluated by three categories:
* discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice.
* @param physicalDevice The physical device
* @return Device score as integer
*/
int deviceScore(const vk::PhysicalDevice& physicalDevice)
{
int score = 0;
vk::PhysicalDeviceProperties properties = physicalDevice.getProperties();
std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
// for every queue family compute queue flag bits and the amount of queues
for (const auto& qFamily : qFamilyProperties) {
uint32_t qCount = qFamily.queueCount;
uint32_t bitCount = (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eSparseBinding) != 0);
score += static_cast<int>(qCount * bitCount);
}
// compute the VRAM of the physical device
vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();
auto vram = static_cast<int>(memoryProperties.memoryHeaps[0].size / static_cast<uint32_t>(1E9));
score *= vram;
if (properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
score *= 2;
}
else if (properties.deviceType != vk::PhysicalDeviceType::eIntegratedGpu) {
score = -1;
}
return score;
}
/**
* @brief All existing physical devices will be evaluated by deviceScore.
* @param instance The instance
* @return The optimal physical device
* @see Context.deviceScore
*/
vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance)
{
vk::PhysicalDevice phyDevice;
std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
if (devices.empty()) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
int max_score = -1;
for (const auto& device : devices) {
int score = deviceScore(device);
if (score > max_score) {
max_score = score;
phyDevice = device;
}
}
if (max_score == -1) {
throw std::runtime_error("failed to find a suitable GPU!");
}
return phyDevice;
}
/**
* @brief With the help of the reference "supported" all elements in "check" checked,
* if they are supported by the physical device.
* @param supported The reference that can be used to check "check"
* @param check The elements to be checked
* @return True, if all elements in "check" are supported
*/
bool checkSupport(std::vector<const char*>& supported, std::vector<const char*>& check)
{
for (auto checkElem : check) {
bool found = false;
for (auto supportedElem : supported) {
if (strcmp(supportedElem, checkElem) == 0) {
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
std::vector<const char*> getRequiredExtensions() {
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
#ifndef NDEBUG
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
return extensions;
}
Context Context::create(const char *applicationName,
uint32_t applicationVersion,
std::vector<vk::QueueFlagBits> queueFlags,
std::vector<const char *> instanceExtensions,
std::vector<const char *> deviceExtensions) {
// check for layer support
const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties();
std::vector<const char*> supportedLayers;
supportedLayers.reserve(layerProperties.size());
for (auto& elem : layerProperties) {
supportedLayers.push_back(elem.layerName);
}
// if in debug mode, check if validation layers are supported. Enable them if supported
#ifndef NDEBUG
std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
if (!checkSupport(supportedLayers, validationLayers)) {
throw std::runtime_error("Validation layers requested but not available!");
}
#endif
// check for extension support
std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties();
std::vector<const char*> supportedExtensions;
supportedExtensions.reserve(instanceExtensionProperties.size());
for (auto& elem : instanceExtensionProperties) {
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, instanceExtensions)) {
throw std::runtime_error("The requested instance extensions are not supported!");
}
// for GLFW: get all required extensions
std::vector<const char*> requiredExtensions = getRequiredExtensions();
instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end());
const vk::ApplicationInfo applicationInfo(
applicationName,
applicationVersion,
"vkCV",
VK_MAKE_VERSION(0, 0, 1),
VK_HEADER_VERSION_COMPLETE
);
vk::InstanceCreateInfo instanceCreateInfo(
vk::InstanceCreateFlags(),
&applicationInfo,
0,
nullptr,
static_cast<uint32_t>(instanceExtensions.size()),
instanceExtensions.data()
);
#ifndef NDEBUG
instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
vk::Instance instance = vk::createInstance(instanceCreateInfo);
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance);
// check for physical device extension support
std::vector<vk::ExtensionProperties> deviceExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties();
supportedExtensions.clear();
for (auto& elem : deviceExtensionProperties) {
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, deviceExtensions)) {
throw std::runtime_error("The requested device extensions are not supported by the physical device!");
}
std::vector<vk::DeviceQueueCreateInfo> qCreateInfos;
// create required queues
std::vector<float> qPriorities;
qPriorities.resize(queueFlags.size(), 1.f);
std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
QueueManager::queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
vk::DeviceCreateInfo deviceCreateInfo(
vk::DeviceCreateFlags(),
qCreateInfos.size(),
qCreateInfos.data(),
0,
nullptr,
deviceExtensions.size(),
deviceExtensions.data(),
nullptr // Should our device use some features??? If yes: TODO
);
#ifndef NDEBUG
deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
// Ablauf
// qCreateInfos erstellen --> braucht das Device
// device erstellen
// jetzt koennen wir mit dem device die queues erstellen
vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
QueueManager queueManager = QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
return Context(instance, physicalDevice, device, std::move(queueManager));
}
} }
...@@ -14,110 +14,6 @@ ...@@ -14,110 +14,6 @@
namespace vkcv namespace vkcv
{ {
/**
* @brief The physical device is evaluated by three categories:
* discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice.
* @param physicalDevice The physical device
* @return Device score as integer
*/
int deviceScore(const vk::PhysicalDevice& physicalDevice)
{
int score = 0;
vk::PhysicalDeviceProperties properties = physicalDevice.getProperties();
std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
// for every queue family compute queue flag bits and the amount of queues
for (const auto& qFamily : qFamilyProperties) {
uint32_t qCount = qFamily.queueCount;
uint32_t bitCount = (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0)
+ (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eSparseBinding) != 0);
score += static_cast<int>(qCount * bitCount);
}
// compute the VRAM of the physical device
vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();
auto vram = static_cast<int>(memoryProperties.memoryHeaps[0].size / static_cast<uint32_t>(1E9));
score *= vram;
if (properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
score *= 2;
}
else if (properties.deviceType != vk::PhysicalDeviceType::eIntegratedGpu) {
score = -1;
}
return score;
}
/**
* @brief All existing physical devices will be evaluated by deviceScore.
* @param instance The instance
* @return The optimal physical device
* @see Context.deviceScore
*/
vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance)
{
vk::PhysicalDevice phyDevice;
std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
if (devices.empty()) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
int max_score = -1;
for (const auto& device : devices) {
int score = deviceScore(device);
if (score > max_score) {
max_score = score;
phyDevice = device;
}
}
if (max_score == -1) {
throw std::runtime_error("failed to find a suitable GPU!");
}
return phyDevice;
}
/**
* @brief With the help of the reference "supported" all elements in "check" checked,
* if they are supported by the physical device.
* @param supported The reference that can be used to check "check"
* @param check The elements to be checked
* @return True, if all elements in "check" are supported
*/
bool checkSupport(std::vector<const char*>& supported, std::vector<const char*>& check)
{
for (auto checkElem : check) {
bool found = false;
for (auto supportedElem : supported) {
if (strcmp(supportedElem, checkElem) == 0) {
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
std::vector<const char*> getRequiredExtensions() {
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
#ifndef NDEBUG
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
return extensions;
}
Core Core::create(const Window &window, Core Core::create(const Window &window,
const char *applicationName, const char *applicationName,
uint32_t applicationVersion, uint32_t applicationVersion,
...@@ -125,122 +21,22 @@ namespace vkcv ...@@ -125,122 +21,22 @@ namespace vkcv
std::vector<const char *> instanceExtensions, std::vector<const char *> instanceExtensions,
std::vector<const char *> deviceExtensions) std::vector<const char *> deviceExtensions)
{ {
// check for layer support Context context = Context::create(
applicationName, applicationVersion,
const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); queueFlags,
instanceExtensions,
std::vector<const char*> supportedLayers; deviceExtensions
supportedLayers.reserve(layerProperties.size()); );
for (auto& elem : layerProperties) { const vk::SurfaceKHR surface = createSurface(
supportedLayers.push_back(elem.layerName); window.getWindow(),
} context.getInstance(),
context.getPhysicalDevice()
// if in debug mode, check if validation layers are supported. Enable them if supported
#ifndef NDEBUG
std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
if (!checkSupport(supportedLayers, validationLayers)) {
throw std::runtime_error("Validation layers requested but not available!");
}
#endif
// check for extension support
std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties();
std::vector<const char*> supportedExtensions;
supportedExtensions.reserve(instanceExtensionProperties.size());
for (auto& elem : instanceExtensionProperties) {
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, instanceExtensions)) {
throw std::runtime_error("The requested instance extensions are not supported!");
}
// for GLFW: get all required extensions
std::vector<const char*> requiredExtensions = getRequiredExtensions();
instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end());
const vk::ApplicationInfo applicationInfo(
applicationName,
applicationVersion,
"vkCV",
VK_MAKE_VERSION(0, 0, 1),
VK_HEADER_VERSION_COMPLETE
);
vk::InstanceCreateInfo instanceCreateInfo(
vk::InstanceCreateFlags(),
&applicationInfo,
0,
nullptr,
static_cast<uint32_t>(instanceExtensions.size()),
instanceExtensions.data()
);
#ifndef NDEBUG
instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
vk::Instance instance = vk::createInstance(instanceCreateInfo);
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance);
// check for physical device extension support
std::vector<vk::ExtensionProperties> deviceExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties();
supportedExtensions.clear();
for (auto& elem : deviceExtensionProperties) {
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, deviceExtensions)) {
throw std::runtime_error("The requested device extensions are not supported by the physical device!");
}
const vk::SurfaceKHR surface = createSurface(window.getWindow(), instance, physicalDevice);
std::vector<vk::DeviceQueueCreateInfo> qCreateInfos;
// create required queues
std::vector<float> qPriorities;
qPriorities.resize(queueFlags.size(), 1.f);
std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
QueueManager::queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
vk::DeviceCreateInfo deviceCreateInfo(
vk::DeviceCreateFlags(),
qCreateInfos.size(),
qCreateInfos.data(),
0,
nullptr,
deviceExtensions.size(),
deviceExtensions.data(),
nullptr // Should our device use some features??? If yes: TODO
); );
#ifndef NDEBUG
deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
// Ablauf
// qCreateInfos erstellen --> braucht das Device
// device erstellen
// jetzt koennen wir mit dem device die queues erstellen
vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
QueueManager queueManager = QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
Context context (instance, physicalDevice, device);
SwapChain swapChain = SwapChain::create(window, context, surface); SwapChain swapChain = SwapChain::create(window, context, surface);
std::vector<vk::Image> swapChainImages = device.getSwapchainImagesKHR(swapChain.getSwapchain()); std::vector<vk::Image> swapChainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain());
std::vector<vk::ImageView> imageViews; std::vector<vk::ImageView> imageViews;
imageViews.reserve( swapChainImages.size() ); imageViews.reserve( swapChainImages.size() );
//here can be swizzled with vk::ComponentSwizzle if needed //here can be swizzled with vk::ComponentSwizzle if needed
...@@ -263,14 +59,16 @@ namespace vkcv ...@@ -263,14 +59,16 @@ namespace vkcv
subResourceRange subResourceRange
); );
imageViews.push_back( device.createImageView( imageViewCreateInfo )); imageViews.push_back(context.getDevice().createImageView(imageViewCreateInfo));
} }
const int graphicQueueFamilyIndex = queuePairsGraphics[0].first; const auto& queueManager = context.getQueueManager();
const int graphicQueueFamilyIndex = queueManager.getGraphicsQueues()[0].familyIndex;
const auto defaultCommandResources = createDefaultCommandResources(context.getDevice(), graphicQueueFamilyIndex); const auto defaultCommandResources = createDefaultCommandResources(context.getDevice(), graphicQueueFamilyIndex);
const auto defaultSyncResources = createDefaultSyncResources(context.getDevice()); const auto defaultSyncResources = createDefaultSyncResources(context.getDevice());
return Core(std::move(context) , window, swapChain, imageViews, defaultCommandResources, defaultSyncResources, queueManager); return Core(std::move(context) , window, swapChain, imageViews, defaultCommandResources, defaultSyncResources);
} }
const Context &Core::getContext() const const Context &Core::getContext() const
...@@ -279,7 +77,7 @@ namespace vkcv ...@@ -279,7 +77,7 @@ namespace vkcv
} }
Core::Core(Context &&context, const Window &window , SwapChain swapChain, std::vector<vk::ImageView> imageViews, Core::Core(Context &&context, const Window &window , SwapChain swapChain, std::vector<vk::ImageView> imageViews,
const CommandResources& commandResources, const SyncResources& syncResources, const QueueManager& queueManager) noexcept : const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
m_Context(std::move(context)), m_Context(std::move(context)),
m_window(window), m_window(window),
m_swapchain(swapChain), m_swapchain(swapChain),
...@@ -287,8 +85,7 @@ namespace vkcv ...@@ -287,8 +85,7 @@ namespace vkcv
m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)},
m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
m_CommandResources(commandResources), m_CommandResources(commandResources),
m_SyncResources(syncResources), m_SyncResources(syncResources)
m_QueueManager(queueManager)
{} {}
Core::~Core() noexcept { Core::~Core() noexcept {
...@@ -387,14 +184,16 @@ namespace vkcv ...@@ -387,14 +184,16 @@ namespace vkcv
m_CommandResources.commandBuffer.end(); m_CommandResources.commandBuffer.end();
const auto& queueManager = m_Context.getQueueManager();
const vk::SubmitInfo submitInfo(0, nullptr, 0, 1, &(m_CommandResources.commandBuffer), 1, &m_SyncResources.renderFinished); const vk::SubmitInfo submitInfo(0, nullptr, 0, 1, &(m_CommandResources.commandBuffer), 1, &m_SyncResources.renderFinished);
m_QueueManager.getGraphicsQueues()[0].submit(submitInfo); queueManager.getGraphicsQueues()[0].handle.submit(submitInfo);
vk::Result presentResult; vk::Result presentResult;
const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain(); const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain();
const vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &swapchain, const vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &swapchain,
&m_currentSwapchainImageIndex, &presentResult); &m_currentSwapchainImageIndex, &presentResult);
m_QueueManager.getPresentQueue().presentKHR(presentInfo); queueManager.getPresentQueue().handle.presentKHR(presentInfo);
if (presentResult != vk::Result::eSuccess) { if (presentResult != vk::Result::eSuccess) {
std::cout << "Error: swapchain present failed" << std::endl; std::cout << "Error: swapchain present failed" << std::endl;
} }
......
#include "vkcv/QueueManager.hpp"
#include <limits>
#include <unordered_set> #include <unordered_set>
#include "vkcv/QueueManager.hpp"
namespace vkcv { namespace vkcv {
/** /**
...@@ -143,14 +146,17 @@ namespace vkcv { ...@@ -143,14 +146,17 @@ namespace vkcv {
* @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics) * @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics)
* @return An array of queue handles based on the @p queuePairs * @return An array of queue handles based on the @p queuePairs
*/ */
std::vector<vk::Queue> getQueueHandles(const vk::Device device, const std::vector<std::pair<int, int>> queuePairs) { std::vector<Queue> getQueues(const vk::Device& device, const std::vector<std::pair<int, int>>& queuePairs) {
std::vector<vk::Queue> queueHandles; std::vector<Queue> queues;
for (auto q : queuePairs) { for (auto q : queuePairs) {
int queueFamilyIndex = q.first; // the queueIndex of the queue family const int queueFamilyIndex = q.first; // the queueIndex of the queue family
int queueIndex = q.second; // the queueIndex within a queue family const int queueIndex = q.second; // the queueIndex within a queue family
queueHandles.push_back(device.getQueue(queueFamilyIndex, queueIndex));
queues.push_back({ queueFamilyIndex, queueIndex, device.getQueue(queueFamilyIndex, queueIndex) });
} }
return queueHandles;
return queues;
} }
...@@ -159,30 +165,30 @@ namespace vkcv { ...@@ -159,30 +165,30 @@ namespace vkcv {
std::vector<std::pair<int, int>> &queuePairsCompute, std::vector<std::pair<int, int>> &queuePairsCompute,
std::vector<std::pair<int, int>> &queuePairsTransfer) { std::vector<std::pair<int, int>> &queuePairsTransfer) {
std::vector<vk::Queue> graphicsQueues = getQueueHandles(device, queuePairsGraphics); std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics);
std::vector<vk::Queue> computeQueues = getQueueHandles(device, queuePairsCompute ); std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute );
std::vector<vk::Queue> transferQueues = getQueueHandles(device, queuePairsTransfer); std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer);
return QueueManager( graphicsQueues, computeQueues, transferQueues, graphicsQueues[0]); return QueueManager( std::move(graphicsQueues), std::move(computeQueues), std::move(transferQueues), 0);
} }
QueueManager::QueueManager(std::vector<vk::Queue> graphicsQueues, std::vector<vk::Queue> computeQueues, std::vector<vk::Queue> transferQueues, vk::Queue presentQueue) QueueManager::QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex)
: m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentQueue(presentQueue) : m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentIndex(presentIndex)
{} {}
const vk::Queue &QueueManager::getPresentQueue() const { const Queue &QueueManager::getPresentQueue() const {
return m_presentQueue; return m_graphicsQueues[m_presentIndex];
} }
const std::vector<vk::Queue> &QueueManager::getGraphicsQueues() const { const std::vector<Queue> &QueueManager::getGraphicsQueues() const {
return m_graphicsQueues; return m_graphicsQueues;
} }
const std::vector<vk::Queue> &QueueManager::getComputeQueues() const { const std::vector<Queue> &QueueManager::getComputeQueues() const {
return m_computeQueues; return m_computeQueues;
} }
const std::vector<vk::Queue> &QueueManager::getTransferQueues() const { const std::vector<Queue> &QueueManager::getTransferQueues() const {
return m_transferQueues; return m_transferQueues;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment