Browse Source

Vk: Add Context

Signed-off-by: Squareys <Squareys@googlemail.com>
pull/202/head
Squareys 10 years ago
parent
commit
a73b2724e1
  1. 207
      src/Magnum/Vk/Context.cpp
  2. 191
      src/Magnum/Vk/Context.h

207
src/Magnum/Vk/Context.cpp

@ -0,0 +1,207 @@
/*
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.
*/
#include "Context.h"
#include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/String.h>
#include "vulkan.h"
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
PFN_vkDebugReportMessageEXT dbgBreakCallback;
VkDebugReportCallbackEXT msgCallback;
namespace Magnum { namespace Vk {
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
"VK_LAYER_LUNARG_standard_validation"
};
Context* Context::_current = nullptr;
bool Context::hasCurrent() { return _current; }
Context& Context::current() {
CORRADE_ASSERT(_current, "Context::current(): no current context", *_current);
return *_current;
}
Context::Context(NoCreateT, Int argc, char** argv, void functionLoader()): _functionLoader{functionLoader}, _version{Version::None} {
Utility::Arguments args{"magnum"};
args.parse(argc, argv);
}
Context::Context(Flags flags): _functionLoader{nullptr}, _version{Version::None}, _flags(flags) {
create();
}
Context::Context(Context&& other): _version{std::move(other._version)},
_flags{std::move(other._flags)}
{
if(_current == &other) _current = this;
}
Context::~Context() {
if(_current == this) _current = nullptr;
if(_instance == nullptr) {
Error() << "No VkInstance to destroy";
return;
}
if (_flags >= Flag::EnableValidation) {
DestroyDebugReportCallback(_instance, msgCallback, nullptr);
}
vkDestroyInstance(_instance, nullptr);
}
void Context::create() {
/* Hard exit if the context cannot be created */
if(!tryCreate()) std::exit(1);
}
VkBool32 messageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType,
uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData) {
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
Error() << "[" << pLayerPrefix << "] Code" << msgCode << ":" << pMsg;
} else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
Warning() << "[" << pLayerPrefix << "] Code" << msgCode << ":" << pMsg;
}
return false;
}
bool Context::tryCreate() {
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Vulkan Example";
appInfo.pEngineName = "Magnum";
appInfo.apiVersion = UnsignedInt(Version::Vulkan_1_0);
std::vector<const char*> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME };
// Enable surface extensions depending on os
//enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pNext = nullptr;
instanceCreateInfo.pApplicationInfo = &appInfo;
if (_flags >= Flag::EnableValidation) {
enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
instanceCreateInfo.enabledLayerCount = 1;
instanceCreateInfo.ppEnabledLayerNames = validationLayerNames;
}
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) {
CreateDebugReportCallback = PFN_vkCreateDebugReportCallbackEXT(vkGetInstanceProcAddr(_instance, "vkCreateDebugReportCallbackEXT"));
DestroyDebugReportCallback = PFN_vkDestroyDebugReportCallbackEXT(vkGetInstanceProcAddr(_instance, "vkDestroyDebugReportCallbackEXT"));
dbgBreakCallback = PFN_vkDebugReportMessageEXT(vkGetInstanceProcAddr(_instance, "vkDebugReportMessageEXT"));
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.pfnCallback = PFN_vkDebugReportCallbackEXT(messageCallback);
dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
VkResult err = CreateDebugReportCallback(
_instance,
&dbgCreateInfo,
nullptr,
&msgCallback);
assert(!err);
}
return true;
}
bool Context::isVersionSupported(Version) const {
return true;
}
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)
#undef _c
}
return debug << "Vk::Result::(invalid)";
}
Debug& operator<<(Debug& debug, Context::Flag value) {
switch(value) {
#define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value;
_c(EnableValidation)
#undef _c
}
return debug << "Context::Flag::(invalid)";
}
}}

191
src/Magnum/Vk/Context.h

@ -0,0 +1,191 @@
#ifndef Magnum_Vk_Context_h
#define Magnum_Vk_Context_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
Vladimír Vondruš <mosra@centrum.cz>
Copyright © 2016 Jonathan Hale <squareys@googlemail.com>
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.
*/
/** @file
* @brief Class @ref Magnum::Vk::Context
*/
#include "vulkan.h"
#include <cstdlib>
#include <array>
#include <bitset>
#include <vector>
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Tags.h"
#include "Magnum/Magnum.h"
#include "Magnum/Vk/visibility.h"
#include "MagnumExternal/Optional/optional.hpp"
namespace Magnum { namespace Vk {
enum class Version: UnsignedInt {
None, /**< No version */
Vulkan_1_0 = VK_API_VERSION_1_0, /**< Vulkan 1.0 */
};
enum class Result: Int {
Success = VK_SUCCESS, /**< Success */
NotReady = VK_NOT_READY, /**< Not ready */
Timeout = VK_TIMEOUT, /**< Timeout */
EventSet = VK_EVENT_SET, /**< Event set */
EventReset = VK_EVENT_RESET, /**< Event reset */
Incomplete = VK_INCOMPLETE, /**< Incomplete */
ErrorOutOfHostMemory = VK_ERROR_OUT_OF_HOST_MEMORY, /**< Out of host memory */
ErrorOutOfDevieMemory = VK_ERROR_OUT_OF_DEVICE_MEMORY, /**< Out of device memory */
ErrorInitializationFailed = VK_ERROR_INITIALIZATION_FAILED, /**< Initialization failed */
ErrorDeviceLost = VK_ERROR_DEVICE_LOST, /**< Device lost */
ErrorMemoryMapFailed = VK_ERROR_MEMORY_MAP_FAILED, /**< Memory map failed */
ErrorLayerNotPresent = VK_ERROR_LAYER_NOT_PRESENT, /**< Layer not present */
ErrorExtensionNotPresent = VK_ERROR_EXTENSION_NOT_PRESENT, /**< Extension not present */
ErrorFeatureNotPresent = VK_ERROR_FEATURE_NOT_PRESENT, /**< Feature not present */
ErrorIncompatibleDriver = VK_ERROR_INCOMPATIBLE_DRIVER, /**< Incompatible driver */
ErrorTooManyObjects = VK_ERROR_TOO_MANY_OBJECTS, /**< Too many objects */
ErrorFormatNotSupported = VK_ERROR_FORMAT_NOT_SUPPORTED, /**< Format not supported */
ErrorSurfaceLost = VK_ERROR_SURFACE_LOST_KHR, /**< Surface lost */
ErrorNativeWindowInUse = VK_ERROR_NATIVE_WINDOW_IN_USE_KHR, /**< Native window in use */
Suboptimal = VK_SUBOPTIMAL_KHR, /**< Suboptimal */
ErrorOutOfDate = VK_ERROR_OUT_OF_DATE_KHR, /**< Out of date */
ErrorIncompatibleDisplay = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR, /**< Incompatible display */
ErrorValidationFailed = VK_ERROR_VALIDATION_FAILED_EXT, /**< Validation failed */
ErrorInvalidShader = VK_ERROR_INVALID_SHADER_NV /**< Invalid shader */
};
/**
@brief Magnum context
Provides access to version and extension information. Instance available
through @ref Context::current() is automatically created during construction of
`*Application` classes in @ref Platform namespace. You can safely assume that
the instance is available during whole lifetime of `*Application` object. It's
also possible to create the context without using any `*Application` class
using @ref Platform::Context subclass, see @ref platform documentation for more
information.
## Command-line options
The context is configurable through command-line options, that are passed
either from the `Platform::*Application` classes or from the @ref Platform::Context
class. Usage:
<application> [--magnum-help] ...
Arguments:
- `...` -- main application arguments (see `-h` or `--help` for details)
- `--magnum-help` -- display this help message and exit
*/
class MAGNUM_VK_EXPORT Context {
public:
/**
* @brief Context flag
*
* @see @ref Flags, @ref flags(),
* @ref Platform::Sdl2Application::Configuration::setFlags() "Platform::*Application::Configuration::setFlags()"
*/
enum class Flag: Int {
EnableValidation, /**< Enable validation layer */
};
/**
* @brief Context flags
*
* @see @ref flags()
*/
typedef Containers::EnumSet<Flag> Flags;
/**
* @brief Whether there is any current context
*
* @see @ref current()
*/
static bool hasCurrent();
/**
* @brief Current context
*
* Expect that there is current context.
* @see @ref hasCurrent()
*/
static Context& current();
Context(Flags flags);
/** @brief Copying is not allowed */
Context(const Context&) = delete;
/** @brief Move constructor */
Context(Context&& other);
~Context();
/** @brief Copying is not allowed */
Context& operator=(const Context&) = delete;
/** @brief Move assignment is not allowed */
Context& operator=(Context&&) = delete;
/** @brief Vulkan version */
Version version() const { return _version; }
/** @brief Context flags */
Flags flags() const { return _flags; }
/**
* @brief Whether given Vulkan version is supported
*
* @see @ref MAGNUM_ASSERT_VERSION_SUPPORTED()
*/
bool isVersionSupported(Version version) const;
VkInstance vkInstance() {
return _instance;
}
private:
MAGNUM_VK_LOCAL static Context* _current;
explicit Context(NoCreateT, Int argc, char** argv, void functionLoader());
bool tryCreate();
void create();
void(*_functionLoader)();
Version _version;
Flags _flags;
VkInstance _instance;
};
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, Result value);
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, Context::Flag value);
}}
#endif
Loading…
Cancel
Save