mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
9.3 KiB
270 lines
9.3 KiB
|
10 years ago
|
/*
|
||
|
|
This file is part of Magnum.
|
||
|
|
|
||
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
|
||
|
|
Vladimír Vondruš <mosra@centrum.cz>
|
||
|
|
|
||
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
copy of this software and associated documentation files (the "Software"),
|
||
|
|
to deal in the Software without restriction, including without limitation
|
||
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
Software is furnished to do so, subject to the following conditions:
|
||
|
|
|
||
|
|
The above copyright notice and this permission notice shall be included
|
||
|
|
in all copies or substantial portions of the Software.
|
||
|
|
|
||
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
DEALINGS IN THE SOFTWARE.
|
||
|
|
*/
|
||
|
|
|
||
|
10 years ago
|
#include "Instance.h"
|
||
|
10 years ago
|
|
||
|
|
#include <Corrade/Utility/Arguments.h>
|
||
|
|
#include <Corrade/Utility/Assert.h>
|
||
|
|
#include <Corrade/Utility/String.h>
|
||
|
10 years ago
|
#include <Corrade/Containers/Array.h>
|
||
|
10 years ago
|
|
||
|
10 years ago
|
namespace Magnum { namespace Vk {
|
||
|
|
|
||
|
10 years ago
|
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
|
||
|
|
PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT;
|
||
|
|
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
|
||
|
|
|
||
|
10 years ago
|
unsigned int layerCount = 2;
|
||
|
10 years ago
|
const char *validationLayerNames[] =
|
||
|
|
{
|
||
|
|
// This is a meta layer that enables all of the standard
|
||
|
|
// validation layers in the correct order :
|
||
|
|
// threading, parameter_validation, device_limits, object_tracker, image, core_validation, swapchain, and unique_objects
|
||
|
10 years ago
|
"VK_LAYER_LUNARG_standard_validation",
|
||
|
|
"VK_LAYER_LUNARG_api_dump"
|
||
|
10 years ago
|
};
|
||
|
|
|
||
|
10 years ago
|
Instance* Instance::_current = nullptr;
|
||
|
10 years ago
|
|
||
|
10 years ago
|
bool Instance::hasCurrent() { return _current; }
|
||
|
10 years ago
|
|
||
|
10 years ago
|
Instance& Instance::current() {
|
||
|
|
CORRADE_ASSERT(_current, "Instance::current(): no current Instance", *_current);
|
||
|
10 years ago
|
return *_current;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
|
||
|
10 years ago
|
Instance::Instance(): Instance{Flags{}} {}
|
||
|
10 years ago
|
|
||
|
10 years ago
|
Instance::Instance(Flags flags): _functionLoader{nullptr}, _version{Version::None}, _flags(flags) {
|
||
|
10 years ago
|
create();
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
Instance::Instance(Instance&& other): _version{std::move(other._version)},
|
||
|
10 years ago
|
_flags{std::move(other._flags)}
|
||
|
|
{
|
||
|
|
if(_current == &other) _current = this;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
Instance::~Instance() {
|
||
|
10 years ago
|
if(_current == this) _current = nullptr;
|
||
|
|
|
||
|
|
if(_instance == nullptr) {
|
||
|
|
Error() << "No VkInstance to destroy";
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (_flags >= Flag::EnableValidation) {
|
||
|
10 years ago
|
vkDestroyDebugReportCallbackEXT(_instance, _callback, nullptr);
|
||
|
10 years ago
|
}
|
||
|
|
vkDestroyInstance(_instance, nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
void Instance::create() {
|
||
|
|
/* Hard exit if the Instance cannot be created */
|
||
|
10 years ago
|
if(!tryCreate()) std::exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
|
||
|
|
VkDebugReportFlagsEXT flags,
|
||
|
|
VkDebugReportObjectTypeEXT objectType,
|
||
|
|
uint64_t object,
|
||
|
|
size_t location,
|
||
|
|
int32_t messageCode,
|
||
|
|
const char* pLayerPrefix,
|
||
|
|
const char* pMessage,
|
||
|
|
void* pUserData)
|
||
|
|
{
|
||
|
10 years ago
|
if(flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT != 0) {
|
||
|
|
Debug() << "[Debug][" << pLayerPrefix << "]" << pMessage;
|
||
|
|
} else if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||
|
|
Error() << "[Error][" << pLayerPrefix << "]" << pMessage;
|
||
|
|
} else if(flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||
|
|
Warning() << "[Warning][" << pLayerPrefix << "]" << pMessage;
|
||
|
|
} else if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
|
||
|
|
Warning() << "[Perf Warning][" << pLayerPrefix << "]" << pMessage;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
return VK_FALSE;
|
||
|
10 years ago
|
}
|
||
|
|
|
||
|
10 years ago
|
bool Instance::tryCreate() {
|
||
|
10 years ago
|
_version = Version::Vulkan_1_0;
|
||
|
|
|
||
|
10 years ago
|
VkApplicationInfo appInfo = {};
|
||
|
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||
|
|
appInfo.pApplicationName = "Vulkan Example";
|
||
|
|
appInfo.pEngineName = "Magnum";
|
||
|
10 years ago
|
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||
|
10 years ago
|
|
||
|
10 years ago
|
std::vector<const char*> enabledExtensions = {VK_KHR_SURFACE_EXTENSION_NAME, "VK_KHR_win32_surface"};
|
||
|
10 years ago
|
|
||
|
|
// Enable surface extensions depending on os
|
||
|
10 years ago
|
// enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||
|
10 years ago
|
|
||
|
|
VkInstanceCreateInfo instanceCreateInfo = {};
|
||
|
|
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||
|
|
instanceCreateInfo.pNext = nullptr;
|
||
|
|
instanceCreateInfo.pApplicationInfo = &appInfo;
|
||
|
|
if (_flags >= Flag::EnableValidation) {
|
||
|
10 years ago
|
Debug() << "Enabling Validation";
|
||
|
10 years ago
|
enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
|
||
|
|
|
||
|
10 years ago
|
instanceCreateInfo.enabledLayerCount = layerCount;
|
||
|
10 years ago
|
instanceCreateInfo.ppEnabledLayerNames = validationLayerNames;
|
||
|
|
}
|
||
|
10 years ago
|
|
||
|
10 years ago
|
if (!enabledExtensions.empty()) {
|
||
|
|
instanceCreateInfo.enabledExtensionCount = enabledExtensions.size();
|
||
|
|
instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data();
|
||
|
|
}
|
||
|
|
|
||
|
|
VkResult ret = vkCreateInstance(&instanceCreateInfo, nullptr, &_instance);
|
||
|
|
if(ret != VK_SUCCESS) {
|
||
|
|
Error() << "Vulkan instance creation failed with error" << ret;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
_current = this;
|
||
|
|
|
||
|
|
/* setup debugging */
|
||
|
|
if (_flags >= Flag::EnableValidation) {
|
||
|
10 years ago
|
/* Load VK_EXT_debug_report entry points in debug builds */
|
||
|
10 years ago
|
vkCreateDebugReportCallbackEXT =
|
||
|
10 years ago
|
reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
|
||
|
|
(vkGetInstanceProcAddr(_instance, "vkCreateDebugReportCallbackEXT"));
|
||
|
10 years ago
|
vkDebugReportMessageEXT =
|
||
|
10 years ago
|
reinterpret_cast<PFN_vkDebugReportMessageEXT>
|
||
|
|
(vkGetInstanceProcAddr(_instance, "vkDebugReportMessageEXT"));
|
||
|
10 years ago
|
vkDestroyDebugReportCallbackEXT =
|
||
|
10 years ago
|
reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>
|
||
|
|
(vkGetInstanceProcAddr(_instance, "vkDestroyDebugReportCallbackEXT"));
|
||
|
|
|
||
|
|
/* Setup callback creation information */
|
||
|
|
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
|
||
|
|
callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
|
||
|
|
callbackCreateInfo.pNext = nullptr;
|
||
|
|
callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
|
||
|
|
VK_DEBUG_REPORT_WARNING_BIT_EXT |
|
||
|
|
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||
|
|
callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
|
||
|
|
callbackCreateInfo.pUserData = nullptr;
|
||
|
|
|
||
|
|
/* Register the callback */
|
||
|
10 years ago
|
VkResult err = vkCreateDebugReportCallbackEXT(_instance, &callbackCreateInfo, nullptr, &_callback);
|
||
|
|
|
||
|
10 years ago
|
if (err != VK_SUCCESS) {
|
||
|
|
Error() << "Could not setup Debug callback";
|
||
|
|
}
|
||
|
10 years ago
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
bool Instance::isVersionSupported(Version) const {
|
||
|
10 years ago
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
Containers::Array<PhysicalDevice> Instance::enumeratePhysicalDevices() {
|
||
|
|
// Physical device
|
||
|
|
UnsignedInt gpuCount = 0;
|
||
|
|
// Get number of available physical devices
|
||
|
|
VkResult err = vkEnumeratePhysicalDevices(*this, &gpuCount, nullptr);
|
||
|
|
MAGNUM_VK_ASSERT_ERROR(err);
|
||
|
|
|
||
|
|
if(gpuCount <= 0) {
|
||
|
|
Error() << "No GPU with Vulkan support found.";
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<VkPhysicalDevice> physicalDevicesVk(gpuCount);
|
||
|
|
err = vkEnumeratePhysicalDevices(*this, &gpuCount, physicalDevicesVk.data());
|
||
|
|
MAGNUM_VK_ASSERT_ERROR(err);
|
||
|
|
|
||
|
|
Containers::Array<PhysicalDevice> physicalDevices{Containers::NoInit, physicalDevicesVk.size()};
|
||
|
|
for(int i = 0; i < physicalDevices.size(); ++i) {
|
||
|
|
new(&physicalDevices[i]) PhysicalDevice{physicalDevicesVk[i]};
|
||
|
|
}
|
||
|
|
|
||
|
|
return physicalDevices;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
Debug& operator<<(Debug& debug, Result value) {
|
||
|
|
switch(value) {
|
||
|
|
#define _c(value) case Result::value: return debug << "Vk::Result::" #value;
|
||
|
|
_c(Success)
|
||
|
|
_c(NotReady)
|
||
|
|
_c(Timeout)
|
||
|
|
_c(EventSet)
|
||
|
|
_c(EventReset)
|
||
|
|
_c(Incomplete)
|
||
|
|
_c(ErrorOutOfHostMemory)
|
||
|
|
_c(ErrorOutOfDevieMemory)
|
||
|
|
_c(ErrorInitializationFailed)
|
||
|
|
_c(ErrorDeviceLost)
|
||
|
|
_c(ErrorMemoryMapFailed)
|
||
|
|
_c(ErrorLayerNotPresent)
|
||
|
|
_c(ErrorExtensionNotPresent)
|
||
|
|
_c(ErrorFeatureNotPresent)
|
||
|
|
_c(ErrorIncompatibleDriver)
|
||
|
|
_c(ErrorTooManyObjects)
|
||
|
|
_c(ErrorFormatNotSupported)
|
||
|
|
_c(ErrorSurfaceLost)
|
||
|
|
_c(ErrorNativeWindowInUse)
|
||
|
|
_c(Suboptimal)
|
||
|
|
_c(ErrorOutOfDate)
|
||
|
|
_c(ErrorIncompatibleDisplay)
|
||
|
|
_c(ErrorValidationFailed)
|
||
|
|
_c(ErrorInvalidShader)
|
||
|
10 years ago
|
_c(ErrorInvalidParameter)
|
||
|
|
_c(ErrorInvalidAlignment)
|
||
|
10 years ago
|
#undef _c
|
||
|
|
}
|
||
|
|
|
||
|
|
return debug << "Vk::Result::(invalid)";
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
Debug& operator<<(Debug& debug, Instance::Flag value) {
|
||
|
10 years ago
|
switch(value) {
|
||
|
10 years ago
|
#define _c(value) case Instance::Flag::value: return debug << "Instance::Flag::" #value;
|
||
|
10 years ago
|
_c(EnableValidation)
|
||
|
|
#undef _c
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
return debug << "Instance::Flag::(invalid)";
|
||
|
10 years ago
|
}
|
||
|
|
|
||
|
10 years ago
|
Debug& operator<<(Debug& debug, Version value) {
|
||
|
|
switch(value) {
|
||
|
|
#define _c(value) case Version::value: return debug << "Vk::Version::" #value;
|
||
|
|
_c(None)
|
||
|
|
_c(Vulkan_1_0)
|
||
|
|
#undef _c
|
||
|
|
}
|
||
|
|
|
||
|
|
return debug << "Vk::Version::(invalid)";
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
}}
|