Implemented KRDeviceManager
This commit is contained in:
@@ -23,6 +23,7 @@ add_sources(KRCamera.cpp)
|
|||||||
add_sources(KRCollider.cpp)
|
add_sources(KRCollider.cpp)
|
||||||
add_sources(KRContext.cpp)
|
add_sources(KRContext.cpp)
|
||||||
add_sources(KRDevice.cpp)
|
add_sources(KRDevice.cpp)
|
||||||
|
add_sources(KRDeviceManager.cpp)
|
||||||
add_sources(KRSurface.cpp)
|
add_sources(KRSurface.cpp)
|
||||||
add_sources(KRSurfaceManager.cpp)
|
add_sources(KRSurfaceManager.cpp)
|
||||||
add_sources(KRStreamer.cpp)
|
add_sources(KRStreamer.cpp)
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
#include "KRAudioSample.h"
|
#include "KRAudioSample.h"
|
||||||
#include "KRBundle.h"
|
#include "KRBundle.h"
|
||||||
#include "KRPresentationThread.h"
|
#include "KRPresentationThread.h"
|
||||||
#include "KRSurfaceManager.h"
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
#if defined(ANDROID)
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -84,9 +83,7 @@ void *KRContext::s_log_callback_user_data = NULL;
|
|||||||
|
|
||||||
KRContext::KRContext(const KrInitializeInfo* initializeInfo)
|
KRContext::KRContext(const KrInitializeInfo* initializeInfo)
|
||||||
: m_streamer(*this)
|
: m_streamer(*this)
|
||||||
, m_vulkanInstance(VK_NULL_HANDLE)
|
|
||||||
, m_resourceMapSize(initializeInfo->resourceMapSize)
|
, m_resourceMapSize(initializeInfo->resourceMapSize)
|
||||||
, m_topDeviceHandle(0)
|
|
||||||
{
|
{
|
||||||
m_presentationThread = std::make_unique<KRPresentationThread>(*this);
|
m_presentationThread = std::make_unique<KRPresentationThread>(*this);
|
||||||
m_resourceMap = (KRResource **)malloc(sizeof(KRResource*) * m_resourceMapSize);
|
m_resourceMap = (KRResource **)malloc(sizeof(KRResource*) * m_resourceMapSize);
|
||||||
@@ -114,6 +111,7 @@ KRContext::KRContext(const KrInitializeInfo* initializeInfo)
|
|||||||
m_pUnknownManager = new KRUnknownManager(*this);
|
m_pUnknownManager = new KRUnknownManager(*this);
|
||||||
m_pShaderManager = new KRShaderManager(*this);
|
m_pShaderManager = new KRShaderManager(*this);
|
||||||
m_pSourceManager = new KRSourceManager(*this);
|
m_pSourceManager = new KRSourceManager(*this);
|
||||||
|
m_deviceManager = std::make_unique<KRDeviceManager>(*this);
|
||||||
m_surfaceManager = std::make_unique<KRSurfaceManager>(*this);
|
m_surfaceManager = std::make_unique<KRSurfaceManager>(*this);
|
||||||
m_streamingEnabled = true;
|
m_streamingEnabled = true;
|
||||||
|
|
||||||
@@ -133,7 +131,8 @@ KRContext::KRContext(const KrInitializeInfo* initializeInfo)
|
|||||||
#error Unsupported
|
#error Unsupported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
createDeviceContexts();
|
m_deviceManager->initialize();
|
||||||
|
|
||||||
m_presentationThread->start();
|
m_presentationThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +194,8 @@ KRContext::~KRContext() {
|
|||||||
m_pBundleManager = NULL;
|
m_pBundleManager = NULL;
|
||||||
}
|
}
|
||||||
m_surfaceManager.reset();
|
m_surfaceManager.reset();
|
||||||
|
m_deviceManager.reset();
|
||||||
|
|
||||||
destroyDeviceContexts();
|
|
||||||
if (m_resourceMap) {
|
if (m_resourceMap) {
|
||||||
delete m_resourceMap;
|
delete m_resourceMap;
|
||||||
m_resourceMap = NULL;
|
m_resourceMap = NULL;
|
||||||
@@ -265,6 +264,9 @@ KRSourceManager *KRContext::getSourceManager() {
|
|||||||
KRSurfaceManager* KRContext::getSurfaceManager() {
|
KRSurfaceManager* KRContext::getSurfaceManager() {
|
||||||
return m_surfaceManager.get();
|
return m_surfaceManager.get();
|
||||||
}
|
}
|
||||||
|
KRDeviceManager* KRContext::getDeviceManager() {
|
||||||
|
return m_deviceManager.get();
|
||||||
|
}
|
||||||
KRUnknownManager *KRContext::getUnknownManager() {
|
KRUnknownManager *KRContext::getUnknownManager() {
|
||||||
return m_pUnknownManager;
|
return m_pUnknownManager;
|
||||||
}
|
}
|
||||||
@@ -754,70 +756,6 @@ void KRContext::receivedMemoryWarning()
|
|||||||
m_last_memory_warning_frame = m_current_frame;
|
m_last_memory_warning_frame = m_current_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
KRContext::createDeviceContexts()
|
|
||||||
{
|
|
||||||
VkResult res = volkInitialize();
|
|
||||||
if (res != VK_SUCCESS) {
|
|
||||||
destroyDeviceContexts();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize the VkApplicationInfo structure
|
|
||||||
VkApplicationInfo app_info = {};
|
|
||||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
|
||||||
app_info.pNext = NULL;
|
|
||||||
app_info.pApplicationName = "Test"; // TODO - Change Me!
|
|
||||||
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
|
|
||||||
app_info.pEngineName = "Kraken Engine";
|
|
||||||
app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
|
|
||||||
app_info.apiVersion = VK_API_VERSION_1_0;
|
|
||||||
|
|
||||||
// VK_KHR_surface and VK_KHR_win32_surface
|
|
||||||
|
|
||||||
char* extensions[] = {
|
|
||||||
"VK_KHR_surface",
|
|
||||||
#ifdef WIN32
|
|
||||||
"VK_KHR_win32_surface",
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// initialize the VkInstanceCreateInfo structure
|
|
||||||
VkInstanceCreateInfo inst_info = {};
|
|
||||||
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
||||||
inst_info.pNext = NULL;
|
|
||||||
inst_info.flags = 0;
|
|
||||||
inst_info.pApplicationInfo = &app_info;
|
|
||||||
#ifdef WIN32
|
|
||||||
inst_info.enabledExtensionCount = 2;
|
|
||||||
#else
|
|
||||||
inst_info.enabledExtensionCount = 1;
|
|
||||||
#endif
|
|
||||||
inst_info.ppEnabledExtensionNames = extensions;
|
|
||||||
inst_info.enabledLayerCount = 0;
|
|
||||||
inst_info.ppEnabledLayerNames = NULL;
|
|
||||||
|
|
||||||
res = vkCreateInstance(&inst_info, NULL, &m_vulkanInstance);
|
|
||||||
if (res != VK_SUCCESS) {
|
|
||||||
destroyDeviceContexts();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
volkLoadInstance(m_vulkanInstance);
|
|
||||||
|
|
||||||
createDevices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
KRContext::destroyDeviceContexts()
|
|
||||||
{
|
|
||||||
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
|
|
||||||
m_devices.clear();
|
|
||||||
if (m_vulkanInstance != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyInstance(m_vulkanInstance, NULL);
|
|
||||||
m_vulkanInstance = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
KRContext::activateStreamerContext()
|
KRContext::activateStreamerContext()
|
||||||
@@ -904,34 +842,19 @@ void KRContext::removeResource(KRResource* resource)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KrSurfaceHandle KRContext::GetBestDeviceForSurface(const VkSurfaceKHR& surface)
|
|
||||||
{
|
|
||||||
KrDeviceHandle deviceHandle = 0;
|
|
||||||
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
|
|
||||||
KRDevice& device = *(*itr).second;
|
|
||||||
VkBool32 canPresent = false;
|
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, surface, &canPresent);
|
|
||||||
if (canPresent) {
|
|
||||||
deviceHandle = (*itr).first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return deviceHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo)
|
KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo)
|
||||||
{
|
{
|
||||||
if (createWindowSurfaceInfo->surfaceHandle < 0) {
|
if (createWindowSurfaceInfo->surfaceHandle < 0) {
|
||||||
return KR_ERROR_OUT_OF_BOUNDS;
|
return KR_ERROR_OUT_OF_BOUNDS;
|
||||||
}
|
}
|
||||||
if (m_vulkanInstance == VK_NULL_HANDLE) {
|
if (!m_deviceManager->haveVulkan()) {
|
||||||
return KR_ERROR_VULKAN_REQUIRED;
|
return KR_ERROR_VULKAN_REQUIRED;
|
||||||
}
|
}
|
||||||
if (m_surfaceHandleMap.count(createWindowSurfaceInfo->surfaceHandle)) {
|
if (m_surfaceHandleMap.count(createWindowSurfaceInfo->surfaceHandle)) {
|
||||||
return KR_ERROR_DUPLICATE_HANDLE;
|
return KR_ERROR_DUPLICATE_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_devices.size() == 0) {
|
if (!m_deviceManager->haveDevice()) {
|
||||||
return KR_ERROR_NO_DEVICE;
|
return KR_ERROR_NO_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,7 +883,7 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW
|
|||||||
if (deleteWindowSurfaceInfo->surfaceHandle < 0) {
|
if (deleteWindowSurfaceInfo->surfaceHandle < 0) {
|
||||||
return KR_ERROR_OUT_OF_BOUNDS;
|
return KR_ERROR_OUT_OF_BOUNDS;
|
||||||
}
|
}
|
||||||
if (m_vulkanInstance == VK_NULL_HANDLE) {
|
if (!m_deviceManager->haveVulkan()) {
|
||||||
return KR_ERROR_VULKAN_REQUIRED;
|
return KR_ERROR_VULKAN_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,72 +896,3 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW
|
|||||||
|
|
||||||
return m_surfaceManager->destroy(surfaceHandle);
|
return m_surfaceManager->destroy(surfaceHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRDevice& KRContext::GetDeviceInfo(KrDeviceHandle handle)
|
|
||||||
{
|
|
||||||
return *m_devices[handle];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::createDevices()
|
|
||||||
{
|
|
||||||
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
|
|
||||||
if (m_devices.size() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t deviceCount = 0;
|
|
||||||
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, nullptr);
|
|
||||||
if (deviceCount == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
|
|
||||||
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, physicalDevices.data());
|
|
||||||
|
|
||||||
const std::vector<const char*> deviceExtensions = {
|
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<KRDevice>> candidateDevices;
|
|
||||||
|
|
||||||
for (const VkPhysicalDevice& physicalDevice : physicalDevices) {
|
|
||||||
std::unique_ptr<KRDevice> device = std::make_unique<KRDevice>(physicalDevice);
|
|
||||||
if (!device->initialize(deviceExtensions)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool addDevice = false;
|
|
||||||
if (candidateDevices.empty()) {
|
|
||||||
addDevice = true;
|
|
||||||
} else {
|
|
||||||
VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType;
|
|
||||||
if (collectedType == device->m_deviceProperties.deviceType) {
|
|
||||||
addDevice = true;
|
|
||||||
} else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
|
||||||
// Discrete GPU's are always the best choice
|
|
||||||
candidateDevices.clear();
|
|
||||||
addDevice = true;
|
|
||||||
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
|
|
||||||
// Integrated GPU's are the second best choice
|
|
||||||
candidateDevices.clear();
|
|
||||||
addDevice = true;
|
|
||||||
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
|
|
||||||
// Virtual GPU's are the 3rd best choice
|
|
||||||
candidateDevices.clear();
|
|
||||||
addDevice = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (addDevice) {
|
|
||||||
candidateDevices.push_back(std::move(device));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto itr = candidateDevices.begin(); itr != candidateDevices.end(); itr++) {
|
|
||||||
std::unique_ptr<KRDevice> device = std::move(*itr);
|
|
||||||
m_devices[++m_topDeviceHandle] = std::move(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VkInstance& KRContext::GetVulkanInstance()
|
|
||||||
{
|
|
||||||
return m_vulkanInstance;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include "KRShaderManager.h"
|
#include "KRShaderManager.h"
|
||||||
#include "KRSourceManager.h"
|
#include "KRSourceManager.h"
|
||||||
#include "KRSurfaceManager.h"
|
#include "KRSurfaceManager.h"
|
||||||
|
#include "KRDeviceManager.h"
|
||||||
#include "KRStreamer.h"
|
#include "KRStreamer.h"
|
||||||
#include "KRDevice.h"
|
#include "KRDevice.h"
|
||||||
#include "KRSurface.h"
|
#include "KRSurface.h"
|
||||||
@@ -111,6 +112,7 @@ public:
|
|||||||
KRShaderManager *getShaderManager();
|
KRShaderManager *getShaderManager();
|
||||||
KRSourceManager *getSourceManager();
|
KRSourceManager *getSourceManager();
|
||||||
KRSurfaceManager* getSurfaceManager();
|
KRSurfaceManager* getSurfaceManager();
|
||||||
|
KRDeviceManager* getDeviceManager();
|
||||||
|
|
||||||
KRCamera *createCamera(int width, int height);
|
KRCamera *createCamera(int width, int height);
|
||||||
|
|
||||||
@@ -159,11 +161,12 @@ public:
|
|||||||
|
|
||||||
static std::mutex g_SurfaceInfoMutex;
|
static std::mutex g_SurfaceInfoMutex;
|
||||||
static std::mutex g_DeviceInfoMutex;
|
static std::mutex g_DeviceInfoMutex;
|
||||||
|
/*
|
||||||
KRDevice& GetDeviceInfo(KrDeviceHandle handle);
|
KRDevice& GetDeviceInfo(KrDeviceHandle handle);
|
||||||
KRSurface& GetSurfaceInfo(KrSurfaceHandle handle);
|
KRSurface& GetSurfaceInfo(KrSurfaceHandle handle);
|
||||||
VkInstance& GetVulkanInstance();
|
VkInstance& GetVulkanInstance();
|
||||||
KrSurfaceHandle GetBestDeviceForSurface(const VkSurfaceKHR& surface);
|
KrSurfaceHandle GetBestDeviceForSurface(const VkSurfaceKHR& surface);
|
||||||
|
*/
|
||||||
|
|
||||||
#if TARGET_OS_MAC
|
#if TARGET_OS_MAC
|
||||||
static void attachToView(void *view);
|
static void attachToView(void *view);
|
||||||
@@ -183,6 +186,7 @@ private:
|
|||||||
KRUnknownManager *m_pUnknownManager;
|
KRUnknownManager *m_pUnknownManager;
|
||||||
KRShaderManager *m_pShaderManager;
|
KRShaderManager *m_pShaderManager;
|
||||||
KRSourceManager *m_pSourceManager;
|
KRSourceManager *m_pSourceManager;
|
||||||
|
std::unique_ptr<KRDeviceManager> m_deviceManager;
|
||||||
std::unique_ptr<KRSurfaceManager> m_surfaceManager;
|
std::unique_ptr<KRSurfaceManager> m_surfaceManager;
|
||||||
|
|
||||||
KRResource** m_resourceMap;
|
KRResource** m_resourceMap;
|
||||||
@@ -207,20 +211,12 @@ private:
|
|||||||
static void *s_log_callback_user_data;
|
static void *s_log_callback_user_data;
|
||||||
|
|
||||||
KRStreamer m_streamer;
|
KRStreamer m_streamer;
|
||||||
VkInstance m_vulkanInstance;
|
|
||||||
|
|
||||||
void createDeviceContexts();
|
|
||||||
void createDevices();
|
|
||||||
void destroyDeviceContexts();
|
|
||||||
|
|
||||||
unordered_multimap<std::string, KRResource*> m_resources;
|
unordered_multimap<std::string, KRResource*> m_resources;
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<KRPresentationThread> m_presentationThread;
|
std::unique_ptr<KRPresentationThread> m_presentationThread;
|
||||||
|
|
||||||
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>> m_devices;
|
|
||||||
KrDeviceHandle m_topDeviceHandle;
|
|
||||||
|
|
||||||
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap;
|
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
208
kraken/KRDeviceManager.cpp
Normal file
208
kraken/KRDeviceManager.cpp
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
//
|
||||||
|
// KRDeviceManager.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2021 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KRDeviceManager.h"
|
||||||
|
|
||||||
|
KRDeviceManager::KRDeviceManager(KRContext& context)
|
||||||
|
: KRContextObject(context)
|
||||||
|
, m_vulkanInstance(VK_NULL_HANDLE)
|
||||||
|
, m_topDeviceHandle(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KRDeviceManager::~KRDeviceManager()
|
||||||
|
{
|
||||||
|
destroyDevices();
|
||||||
|
if (m_vulkanInstance != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyInstance(m_vulkanInstance, NULL);
|
||||||
|
m_vulkanInstance = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDeviceManager::haveVulkan() const
|
||||||
|
{
|
||||||
|
return m_vulkanInstance != VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDeviceManager::haveDevice() const
|
||||||
|
{
|
||||||
|
return !m_devices.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KRDeviceManager::destroyDevices()
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
|
||||||
|
m_devices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KRDeviceManager::initialize()
|
||||||
|
{
|
||||||
|
VkResult res = volkInitialize();
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
destroyDevices();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the VkApplicationInfo structure
|
||||||
|
VkApplicationInfo app_info = {};
|
||||||
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
app_info.pNext = NULL;
|
||||||
|
app_info.pApplicationName = "Test"; // TODO - Change Me!
|
||||||
|
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
|
||||||
|
app_info.pEngineName = "Kraken Engine";
|
||||||
|
app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||||
|
app_info.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
// VK_KHR_surface and VK_KHR_win32_surface
|
||||||
|
|
||||||
|
char* extensions[] = {
|
||||||
|
"VK_KHR_surface",
|
||||||
|
#ifdef WIN32
|
||||||
|
"VK_KHR_win32_surface",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// initialize the VkInstanceCreateInfo structure
|
||||||
|
VkInstanceCreateInfo inst_info = {};
|
||||||
|
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
inst_info.pNext = NULL;
|
||||||
|
inst_info.flags = 0;
|
||||||
|
inst_info.pApplicationInfo = &app_info;
|
||||||
|
#ifdef WIN32
|
||||||
|
inst_info.enabledExtensionCount = 2;
|
||||||
|
#else
|
||||||
|
inst_info.enabledExtensionCount = 1;
|
||||||
|
#endif
|
||||||
|
inst_info.ppEnabledExtensionNames = extensions;
|
||||||
|
inst_info.enabledLayerCount = 0;
|
||||||
|
inst_info.ppEnabledLayerNames = NULL;
|
||||||
|
|
||||||
|
res = vkCreateInstance(&inst_info, NULL, &m_vulkanInstance);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
destroyDevices();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
volkLoadInstance(m_vulkanInstance);
|
||||||
|
|
||||||
|
createDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDeviceManager::createDevices()
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
|
||||||
|
if (m_devices.size() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t deviceCount = 0;
|
||||||
|
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, nullptr);
|
||||||
|
if (deviceCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
|
||||||
|
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, physicalDevices.data());
|
||||||
|
|
||||||
|
const std::vector<const char*> deviceExtensions = {
|
||||||
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<KRDevice>> candidateDevices;
|
||||||
|
|
||||||
|
for (const VkPhysicalDevice& physicalDevice : physicalDevices) {
|
||||||
|
std::unique_ptr<KRDevice> device = std::make_unique<KRDevice>(physicalDevice);
|
||||||
|
if (!device->initialize(deviceExtensions)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addDevice = false;
|
||||||
|
if (candidateDevices.empty()) {
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType;
|
||||||
|
if (collectedType == device->m_deviceProperties.deviceType) {
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
|
// Discrete GPU's are always the best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
|
||||||
|
// Integrated GPU's are the second best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
|
||||||
|
// Virtual GPU's are the 3rd best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addDevice) {
|
||||||
|
candidateDevices.push_back(std::move(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto itr = candidateDevices.begin(); itr != candidateDevices.end(); itr++) {
|
||||||
|
std::unique_ptr<KRDevice> device = std::move(*itr);
|
||||||
|
m_devices[++m_topDeviceHandle] = std::move(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KRDevice& KRDeviceManager::getDeviceInfo(KrDeviceHandle handle)
|
||||||
|
{
|
||||||
|
return *m_devices[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkInstance& KRDeviceManager::getVulkanInstance()
|
||||||
|
{
|
||||||
|
return m_vulkanInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrSurfaceHandle KRDeviceManager::getBestDeviceForSurface(const VkSurfaceKHR& surface)
|
||||||
|
{
|
||||||
|
KrDeviceHandle deviceHandle = 0;
|
||||||
|
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
|
||||||
|
KRDevice& device = *(*itr).second;
|
||||||
|
VkBool32 canPresent = false;
|
||||||
|
vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, surface, &canPresent);
|
||||||
|
if (canPresent) {
|
||||||
|
deviceHandle = (*itr).first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceHandle;
|
||||||
|
}
|
||||||
64
kraken/KRDeviceManager.h
Normal file
64
kraken/KRDeviceManager.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// KRDeviceManager.h
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2021 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
|
#include "KRContext.h"
|
||||||
|
#include "KRDevice.h"
|
||||||
|
|
||||||
|
#ifndef KRDEVICEMANAGER_H
|
||||||
|
#define KRDEVICEMANAGER_H
|
||||||
|
|
||||||
|
class KRDeviceManager : KRContextObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KRDeviceManager(KRContext& context);
|
||||||
|
~KRDeviceManager();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
bool haveVulkan() const;
|
||||||
|
bool haveDevice() const;
|
||||||
|
|
||||||
|
KRDevice& getDeviceInfo(KrDeviceHandle handle);
|
||||||
|
VkInstance& getVulkanInstance();
|
||||||
|
KrSurfaceHandle getBestDeviceForSurface(const VkSurfaceKHR& surface);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>> m_devices;
|
||||||
|
KrDeviceHandle m_topDeviceHandle;
|
||||||
|
|
||||||
|
void createDevices();
|
||||||
|
void destroyDevices();
|
||||||
|
VkInstance m_vulkanInstance;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KRDEVICEMANAGER_H
|
||||||
@@ -116,7 +116,7 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat
|
|||||||
m_pipelineLayout = nullptr;
|
m_pipelineLayout = nullptr;
|
||||||
m_graphicsPipeline = nullptr;
|
m_graphicsPipeline = nullptr;
|
||||||
m_renderPass = nullptr;
|
m_renderPass = nullptr;
|
||||||
KRDevice& device = m_pContext->GetDeviceInfo(deviceHandle);
|
KRDevice& device = m_pContext->getDeviceManager()->getDeviceInfo(deviceHandle);
|
||||||
|
|
||||||
strcpy(m_szKey, szKey);
|
strcpy(m_szKey, szKey);
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
|
|
||||||
for (auto surfaceItr = surfaces.begin(); surfaceItr != surfaces.end(); surfaceItr++) {
|
for (auto surfaceItr = surfaces.begin(); surfaceItr != surfaces.end(); surfaceItr++) {
|
||||||
KRSurface& surface = *(*surfaceItr).second;
|
KRSurface& surface = *(*surfaceItr).second;
|
||||||
KRDevice& device = m_pContext->GetDeviceInfo(surface.m_deviceHandle);
|
KRDevice& device = m_pContext->getDeviceManager()->getDeviceInfo(surface.m_deviceHandle);
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|||||||
@@ -62,16 +62,16 @@ KrResult KRSurface::initialize()
|
|||||||
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
createInfo.hinstance = GetModuleHandle(nullptr);
|
createInfo.hinstance = GetModuleHandle(nullptr);
|
||||||
createInfo.hwnd = m_hWnd;
|
createInfo.hwnd = m_hWnd;
|
||||||
if (vkCreateWin32SurfaceKHR(m_pContext->GetVulkanInstance(), &createInfo, nullptr, &m_surface) != VK_SUCCESS) {
|
if (vkCreateWin32SurfaceKHR(m_pContext->getDeviceManager()->getVulkanInstance(), &createInfo, nullptr, &m_surface) != VK_SUCCESS) {
|
||||||
return KR_ERROR_VULKAN;
|
return KR_ERROR_VULKAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_deviceHandle = m_pContext->GetBestDeviceForSurface(m_surface);
|
m_deviceHandle = m_pContext->getDeviceManager()->getBestDeviceForSurface(m_surface);
|
||||||
if (m_deviceHandle == 0) {
|
if (m_deviceHandle == 0) {
|
||||||
return KR_ERROR_NO_DEVICE;
|
return KR_ERROR_NO_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRDevice* deviceInfo = &m_pContext->GetDeviceInfo(m_deviceHandle);
|
KRDevice* deviceInfo = &m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle);
|
||||||
|
|
||||||
VkSemaphoreCreateInfo semaphoreInfo{};
|
VkSemaphoreCreateInfo semaphoreInfo{};
|
||||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
@@ -230,7 +230,7 @@ KrResult KRSurface::initialize()
|
|||||||
|
|
||||||
void KRSurface::destroy()
|
void KRSurface::destroy()
|
||||||
{
|
{
|
||||||
KRDevice& deviceInfo = m_pContext->GetDeviceInfo(m_deviceHandle);
|
KRDevice& deviceInfo = m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle);
|
||||||
|
|
||||||
for (auto framebuffer : m_swapChainFramebuffers) {
|
for (auto framebuffer : m_swapChainFramebuffers) {
|
||||||
vkDestroyFramebuffer(deviceInfo.m_logicalDevice, framebuffer, nullptr);
|
vkDestroyFramebuffer(deviceInfo.m_logicalDevice, framebuffer, nullptr);
|
||||||
@@ -258,7 +258,7 @@ void KRSurface::destroy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_surface != VK_NULL_HANDLE) {
|
if (m_surface != VK_NULL_HANDLE) {
|
||||||
vkDestroySurfaceKHR(m_pContext->GetVulkanInstance(), m_surface, nullptr);
|
vkDestroySurfaceKHR(m_pContext->getDeviceManager()->getVulkanInstance(), m_surface, nullptr);
|
||||||
m_surface = VK_NULL_HANDLE;
|
m_surface = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user