Browse Source

Vk: make the Instance immovable as well.

pull/494/head
Vladimír Vondruš 5 years ago
parent
commit
9aab4fb0d9
  1. 22
      doc/snippets/MagnumVk.cpp
  2. 2
      src/Magnum/Vk/CMakeLists.txt
  3. 3
      src/Magnum/Vk/Device.h
  4. 86
      src/Magnum/Vk/Instance.cpp
  5. 87
      src/Magnum/Vk/Instance.h
  6. 2
      src/Magnum/Vk/Test/CMakeLists.txt
  7. 9
      src/Magnum/Vk/Test/InstanceTest.cpp
  8. 107
      src/Magnum/Vk/Test/InstanceVkTest.cpp
  9. 4
      src/Magnum/Vk/VulkanTester.cpp

22
doc/snippets/MagnumVk.cpp

@ -66,6 +66,26 @@ using namespace Magnum;
#define DOXYGEN_IGNORE(...) __VA_ARGS__ #define DOXYGEN_IGNORE(...) __VA_ARGS__
/* [Instance-delayed-creation] */
class MyApplication {
public:
explicit MyApplication();
private:
Vk::Instance _instance{NoCreate};
};
MyApplication::MyApplication() {
// decide on layers, extensions, ...
_instance.create(Vk::InstanceCreateInfo{DOXYGEN_IGNORE()}
DOXYGEN_IGNORE()
);
}
/* [Instance-delayed-creation] */
namespace B {
/* [Device-delayed-creation] */ /* [Device-delayed-creation] */
class MyApplication { class MyApplication {
public: public:
@ -84,6 +104,8 @@ MyApplication::MyApplication(DOXYGEN_IGNORE(Vk::Instance& instance)) {
} }
/* [Device-delayed-creation] */ /* [Device-delayed-creation] */
}
int main() { int main() {
{ {

2
src/Magnum/Vk/CMakeLists.txt

@ -33,7 +33,6 @@ set(MagnumVk_SRCS
Fence.cpp Fence.cpp
Framebuffer.cpp Framebuffer.cpp
Handle.cpp Handle.cpp
Instance.cpp
Queue.cpp Queue.cpp
Result.cpp Result.cpp
Shader.cpp Shader.cpp
@ -52,6 +51,7 @@ set(MagnumVk_GracefulAssert_SRCS
ExtensionProperties.cpp ExtensionProperties.cpp
Image.cpp Image.cpp
ImageView.cpp ImageView.cpp
Instance.cpp
LayerProperties.cpp LayerProperties.cpp
Memory.cpp Memory.cpp
RenderPass.cpp) RenderPass.cpp)

3
src/Magnum/Vk/Device.h

@ -175,7 +175,8 @@ moving a new instance over the empty one. Here you have to use the
@snippet MagnumVk.cpp Device-delayed-creation @snippet MagnumVk.cpp Device-delayed-creation
Similar case is with @ref wrap() --- instead of being @cpp static @ce, you have Similar case is with @ref wrap() --- instead of being @cpp static @ce, you have
to call it on a @ref Device(NoCreateT) "NoCreate"'d instance. to call it on a @ref Device(NoCreateT) "NoCreate"'d instance. The @ref Instance
class behaves equivalently.
*/ */
class MAGNUM_VK_EXPORT Device { class MAGNUM_VK_EXPORT Device {
public: public:

86
src/Magnum/Vk/Instance.cpp

@ -37,6 +37,7 @@
#include "Magnum/Vk/Extensions.h" #include "Magnum/Vk/Extensions.h"
#include "Magnum/Vk/ExtensionProperties.h" #include "Magnum/Vk/ExtensionProperties.h"
#include "Magnum/Vk/Handle.h" #include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/Version.h" #include "Magnum/Vk/Version.h"
#include "Magnum/Vk/Implementation/Arguments.h" #include "Magnum/Vk/Implementation/Arguments.h"
#include "Magnum/Vk/Implementation/InstanceState.h" #include "Magnum/Vk/Implementation/InstanceState.h"
@ -258,22 +259,51 @@ InstanceCreateInfo& InstanceCreateInfo::addEnabledExtensions(const std::initiali
return addEnabledExtensions(Containers::arrayView(extensions)); return addEnabledExtensions(Containers::arrayView(extensions));
} }
Instance Instance::wrap(const VkInstance handle, const Version version, const Containers::ArrayView<const Containers::StringView> enabledExtensions, const HandleFlags flags) { void Instance::wrap(const VkInstance handle, const Version version, const Containers::ArrayView<const Containers::StringView> enabledExtensions, const HandleFlags flags) {
CORRADE_ASSERT(!_handle,
"Vk::Instance::wrap(): instance already created", );
/* Compared to the constructor nothing is printed here as it would be just /* Compared to the constructor nothing is printed here as it would be just
repeating what was passed to the constructor */ repeating what was passed to the constructor */
Instance out{NoCreate}; _handle = handle;
out._handle = handle; _flags = flags;
out._flags = flags; initializeExtensions(enabledExtensions);
out.initializeExtensions(enabledExtensions); initialize(version, 0, nullptr);
out.initialize(version, 0, nullptr); }
return out;
void Instance::wrap(const VkInstance handle, const Version version, const std::initializer_list<Containers::StringView> enabledExtensions, const HandleFlags flags) {
wrap(handle, version, Containers::arrayView(enabledExtensions), flags);
}
Instance::Instance(const InstanceCreateInfo& info): Instance{NoCreate} {
create(info);
}
Instance::Instance(): Instance{NoCreate} {
create();
}
Instance::Instance(NoCreateT): _handle{}, _functionPointers{} {}
Instance::~Instance() {
if(_handle && (_flags & HandleFlag::DestroyOnDestruction))
_functionPointers.DestroyInstance(_handle, nullptr);
}
void Instance::create(const InstanceCreateInfo& info) {
if(tryCreate(info) != Result::Success) std::exit(1);
} }
Instance Instance::wrap(const VkInstance handle, const Version version, const std::initializer_list<Containers::StringView> enabledExtensions, const HandleFlags flags) { void Instance::create() {
return wrap(handle, version, Containers::arrayView(enabledExtensions), flags); if(tryCreate() != Result::Success) std::exit(1);
} }
Instance::Instance(const InstanceCreateInfo& info): _flags{HandleFlag::DestroyOnDestruction} { Result Instance::tryCreate(const InstanceCreateInfo& info) {
CORRADE_ASSERT(!_handle,
"Vk::Instance::tryCreate(): instance already created", {});
_flags = HandleFlag::DestroyOnDestruction;
const Version version = info._state && info._state->version != Version::None ? info._state->version : enumerateInstanceVersion(); const Version version = info._state && info._state->version != Version::None ? info._state->version : enumerateInstanceVersion();
/* Print all enabled layers and extensions if we're not told to be quiet */ /* Print all enabled layers and extensions if we're not told to be quiet */
@ -293,44 +323,22 @@ Instance::Instance(const InstanceCreateInfo& info): _flags{HandleFlag::DestroyOn
} }
} }
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkCreateInstance(info, nullptr, &_handle)); if(const VkResult result = vkCreateInstance(info, nullptr, &_handle)) {
Error{} << "Vk::Instance::tryCreate(): instance creation failed:" << Result(result);
return Result(result);
}
initializeExtensions<const char*>({info->ppEnabledExtensionNames, info->enabledExtensionCount}); initializeExtensions<const char*>({info->ppEnabledExtensionNames, info->enabledExtensionCount});
if(info._state) if(info._state)
initialize(version, info._state->argc, info._state->argv); initialize(version, info._state->argc, info._state->argv);
else else
initialize(version, 0, nullptr); initialize(version, 0, nullptr);
}
Instance::Instance(): Instance{InstanceCreateInfo{}} {} return Result::Success;
Instance::Instance(NoCreateT): _handle{}, _functionPointers{} {}
Instance::Instance(Instance&& other) noexcept: _handle{other._handle},
_flags{other._flags}, _version{other._version},
_extensionStatus{other._extensionStatus}, _state{std::move(other._state)},
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_functionPointers(other._functionPointers)
{
other._handle = nullptr;
other._functionPointers = {};
} }
Instance::~Instance() { Result Instance::tryCreate() {
if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) return tryCreate(InstanceCreateInfo{});
_functionPointers.DestroyInstance(_handle, nullptr);
}
Instance& Instance::operator=(Instance&& other) noexcept {
using std::swap;
swap(other._handle, _handle);
swap(other._flags, _flags);
swap(other._version, _version);
swap(other._extensionStatus, _extensionStatus);
swap(other._state, _state);
swap(other._functionPointers, _functionPointers);
return *this;
} }
template<class T> void Instance::initializeExtensions(const Containers::ArrayView<const T> enabledExtensions) { template<class T> void Instance::initializeExtensions(const Containers::ArrayView<const T> enabledExtensions) {

87
src/Magnum/Vk/Instance.h

@ -171,6 +171,21 @@ Compared to the above, the same custom code would then look like this:
Similarly you can use @ref Device::populateGlobalFunctionPointers() to populate Similarly you can use @ref Device::populateGlobalFunctionPointers() to populate
device-level global function pointers. device-level global function pointers.
@section Vk-Instance-disabled-move Disabled move and delayed instances creation
Similarly to @ref Device, for safety reasons as all instance-dependent objects
internally have to keep a pointer to the originating @ref Instance to access
Vulkan function pointers, the @ref Instance class is not movable. This leads to
a difference compared to other Vulkan object wrappers, where you can use the
@ref NoCreate tag to construct an empty instance (for example as a class
member) and do a delayed creation by moving a new instance over the empty one.
Here you have to use the @ref create() function instead:
@snippet MagnumVk.cpp Instance-delayed-creation
Similar case is with @ref wrap() --- instead of being @cpp static @ce, you have
to call it on a @ref Instance(NoCreateT) "NoCreate"'d instance.
*/ */
class MAGNUM_VK_EXPORT Instance { class MAGNUM_VK_EXPORT Instance {
public: public:
@ -183,6 +198,17 @@ class MAGNUM_VK_EXPORT Instance {
* on the instance * on the instance
* @param flags Handle flags * @param flags Handle flags
* *
* <b></b>
*
* @m_class{m-note m-warning}
*
* @par
* Unlike with other Vulkan object wrappers, this isn't a
* @cpp static @ce function returning a new @ref Instance, instead
* it's expected to be called on a @ref NoCreate "NoCreate"'d
* instance. See @ref Vk-Instance-disabled-move for more
* information.
*
* The @p handle is expected to be of an existing Vulkan instance. The * The @p handle is expected to be of an existing Vulkan instance. The
* @p version and @p enabledExtensions parameters populate internal * @p version and @p enabledExtensions parameters populate internal
* info about supported version and extensions and will be reflected in * info about supported version and extensions and will be reflected in
@ -200,15 +226,16 @@ class MAGNUM_VK_EXPORT Instance {
* behavior. * behavior.
* @see @ref release() * @see @ref release()
*/ */
static Instance wrap(VkInstance handle, Version version, Containers::ArrayView<const Containers::StringView> enabledExtensions, HandleFlags flags = {}); void wrap(VkInstance handle, Version version, Containers::ArrayView<const Containers::StringView> enabledExtensions, HandleFlags flags = {});
/** @overload */ /** @overload */
static Instance wrap(VkInstance handle, Version version, std::initializer_list<Containers::StringView> enabledExtensions, HandleFlags flags = {}); void wrap(VkInstance handle, Version version, std::initializer_list<Containers::StringView> enabledExtensions, HandleFlags flags = {});
/** /**
* @brief Constructor * @brief Constructor
* *
* @see @fn_vk_keyword{CreateInstance} * Equivalent to calling @ref Instance(NoCreateT) followed by
* @ref create(const InstanceCreateInfo&).
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
explicit Instance(const InstanceCreateInfo& info = InstanceCreateInfo{}); explicit Instance(const InstanceCreateInfo& info = InstanceCreateInfo{});
@ -230,8 +257,12 @@ class MAGNUM_VK_EXPORT Instance {
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Instance(const Instance&) = delete; Instance(const Instance&) = delete;
/** @brief Move constructor */ /**
Instance(Instance&& other) noexcept; * @brief Moving is not allowed
*
* See @ref Vk-Instance-disabled-move for more information.
*/
Instance(Instance&&) = delete;
/** /**
* @brief Destructor * @brief Destructor
@ -246,8 +277,12 @@ class MAGNUM_VK_EXPORT Instance {
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Instance& operator=(const Instance&) = delete; Instance& operator=(const Instance&) = delete;
/** @brief Move assignment */ /**
Instance& operator=(Instance&& other) noexcept; * @brief Moving is not allowed
*
* See @ref Vk-Instance-disabled-move for more information.
*/
Instance& operator=(Instance&&) = delete;
/** @brief Underlying @type_vk{Instance} handle */ /** @brief Underlying @type_vk{Instance} handle */
VkInstance handle() { return _handle; } VkInstance handle() { return _handle; }
@ -257,6 +292,44 @@ class MAGNUM_VK_EXPORT Instance {
/** @brief Handle flags */ /** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; } HandleFlags handleFlags() const { return _flags; }
/**
* @brief Create an instance
* @param info Instance creation info
*
* Meant to be called on a @ref Instance(NoCreateT) "NoCreate"'d
* instance. After creating the instance, populates instance-level
* function pointers and runtime information about enabled extensions
* based on @p info.
*
* If instance creation fails, a message is printed to error output and
* the application exits --- if you need a different behavior, use
* @ref tryCreate() instead.
* @see @ref Instance(const InstanceCreateInfo&),
* @see @fn_vk_keyword{CreateInstance}
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
void create(const InstanceCreateInfo& info = InstanceCreateInfo{});
#else
/* To avoid dependency on InstanceCreateInfo.h */
void create(const InstanceCreateInfo& info);
void create();
#endif
/**
* @brief Try to create an instance
*
* Unlike @ref create(), instead of exiting on error, prints a message
* to error output and returns a corresponding result value. On success
* returns @ref Result::Success.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Result tryCreate(const InstanceCreateInfo& info = InstanceCreateInfo{});
#else
/* To avoid dependency on InstanceCreateInfo.h */
Result tryCreate(const InstanceCreateInfo& info);
Result tryCreate();
#endif
/** /**
* @brief Version supported by the instance * @brief Version supported by the instance
* *

2
src/Magnum/Vk/Test/CMakeLists.txt

@ -163,7 +163,7 @@ if(BUILD_VK_TESTS)
corrade_add_test(VkLayerPropertiesVkTest LayerPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkLayerPropertiesVkTest LayerPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkImageVkTest ImageVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkImageVkTest ImageVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkImageViewVkTest ImageViewVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkImageViewVkTest ImageViewVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkMemoryVkTest MemoryVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkMemoryVkTest MemoryVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkRenderPassVkTest RenderPassVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkRenderPassVkTest RenderPassVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester)
corrade_add_test(VkShaderVkTest ShaderVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkShaderVkTest ShaderVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)

9
src/Magnum/Vk/Test/InstanceTest.cpp

@ -38,6 +38,7 @@ struct InstanceTest: TestSuite::Tester {
void constructNoCreate(); void constructNoCreate();
void constructCopy(); void constructCopy();
void constructMove();
}; };
InstanceTest::InstanceTest() { InstanceTest::InstanceTest() {
@ -45,7 +46,8 @@ InstanceTest::InstanceTest() {
&InstanceTest::createInfoConstructFromVk, &InstanceTest::createInfoConstructFromVk,
&InstanceTest::constructNoCreate, &InstanceTest::constructNoCreate,
&InstanceTest::constructCopy}); &InstanceTest::constructCopy,
&InstanceTest::constructMove});
} }
void InstanceTest::createInfoConstructNoInit() { void InstanceTest::createInfoConstructNoInit() {
@ -89,6 +91,11 @@ void InstanceTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_assignable<Instance>{}); CORRADE_VERIFY(!std::is_copy_assignable<Instance>{});
} }
void InstanceTest::constructMove() {
CORRADE_VERIFY(!std::is_move_constructible<Instance>{});
CORRADE_VERIFY(!std::is_move_assignable<Instance>{});
}
}}}} }}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::InstanceTest) CORRADE_TEST_MAIN(Magnum::Vk::Test::InstanceTest)

107
src/Magnum/Vk/Test/InstanceVkTest.cpp

@ -56,10 +56,14 @@ struct InstanceVkTest: TestSuite::Tester {
void constructLayerExtension(); void constructLayerExtension();
void constructCommandLineDisable(); void constructCommandLineDisable();
void constructCommandLineEnable(); void constructCommandLineEnable();
void constructMove();
void constructUnknownLayer(); void tryCreateAlreadyCreated();
void constructUnknownExtension(); void tryCreateUnknownLayer();
void tryCreateUnknownExtension();
void wrap(); void wrap();
void wrapAlreadyCreated();
void populateGlobalFunctionPointers(); void populateGlobalFunctionPointers();
}; };
@ -161,10 +165,13 @@ InstanceVkTest::InstanceVkTest() {
&InstanceVkTest::constructCommandLineEnable}, &InstanceVkTest::constructCommandLineEnable},
Containers::arraySize(ConstructCommandLineData)); Containers::arraySize(ConstructCommandLineData));
addTests({&InstanceVkTest::constructMove, addTests({&InstanceVkTest::tryCreateAlreadyCreated,
&InstanceVkTest::constructUnknownLayer, &InstanceVkTest::tryCreateUnknownLayer,
&InstanceVkTest::constructUnknownExtension, &InstanceVkTest::tryCreateUnknownExtension,
&InstanceVkTest::wrap, &InstanceVkTest::wrap,
&InstanceVkTest::wrapAlreadyCreated,
&InstanceVkTest::populateGlobalFunctionPointers}); &InstanceVkTest::populateGlobalFunctionPointers});
} }
@ -430,66 +437,38 @@ void InstanceVkTest::constructCommandLineEnable() {
CORRADE_COMPARE(!!instance->CreateDebugReportCallbackEXT, data.debugReportEnabled); CORRADE_COMPARE(!!instance->CreateDebugReportCallbackEXT, data.debugReportEnabled);
} }
void InstanceVkTest::constructMove() { void InstanceVkTest::tryCreateAlreadyCreated() {
if(std::getenv("MAGNUM_DISABLE_EXTENSIONS")) #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_EXTENSIONS environment variable set"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
InstanceExtensionProperties extensions = enumerateInstanceExtensionProperties(); Instance instance;
if(!extensions.isSupported<Extensions::KHR::get_physical_device_properties2>()) CORRADE_VERIFY(instance.handle());
CORRADE_SKIP("VK_KHR_get_physical_device_properties2 not supported, can't test");
Instance a{InstanceCreateInfo{} std::ostringstream out;
.setApplicationInfo("InstanceVkTest", version(0, 0, 1)) Error redirectError{&out};
.addEnabledExtensions<Extensions::KHR::get_physical_device_properties2>()}; instance.tryCreate();
VkInstance handle = a.handle(); CORRADE_COMPARE(out.str(), "Vk::Instance::tryCreate(): instance already created\n");
Version version = a.version();
CORRADE_VERIFY(handle);
CORRADE_VERIFY(version != Version{});
Instance b = std::move(a);
CORRADE_VERIFY(!a.handle());
CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction);
CORRADE_COMPARE(b.handle(), handle);
CORRADE_COMPARE(b.version(), version);
CORRADE_VERIFY(b.isExtensionEnabled<Extensions::KHR::get_physical_device_properties2>());
/* Function pointers in a are left in whatever state they were before, as
that doesn't matter */
CORRADE_VERIFY(b->CreateDevice);
Instance c{NoCreate};
c = std::move(b);
CORRADE_VERIFY(!b.handle());
CORRADE_COMPARE(b.handleFlags(), HandleFlags{});
CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction);
CORRADE_COMPARE(c.handle(), handle);
CORRADE_COMPARE(c.version(), version);
CORRADE_VERIFY(c.isExtensionEnabled<Extensions::KHR::get_physical_device_properties2>());
/* Everything is swapped, including function pointers */
CORRADE_VERIFY(!b->CreateDevice);
CORRADE_VERIFY(c->CreateDevice);
CORRADE_VERIFY(std::is_nothrow_move_constructible<Instance>::value);
CORRADE_VERIFY(std::is_nothrow_move_assignable<Instance>::value);
} }
void InstanceVkTest::constructUnknownLayer() { void InstanceVkTest::tryCreateUnknownLayer() {
CORRADE_SKIP("Currently this hits an internal assert, which can't be tested."); Instance instance{NoCreate};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
Instance instance{InstanceCreateInfo{} CORRADE_COMPARE(instance.tryCreate(InstanceCreateInfo{}
.addEnabledLayers({"VK_LAYER_this_doesnt_exist"_s})}; .addEnabledLayers({"VK_LAYER_this_doesnt_exist"_s})), Result::ErrorLayerNotPresent);
CORRADE_COMPARE(out.str(), "TODO"); CORRADE_COMPARE(out.str(), "Vk::Instance::tryCreate(): instance creation failed: Vk::Result::ErrorLayerNotPresent\n");
} }
void InstanceVkTest::constructUnknownExtension() { void InstanceVkTest::tryCreateUnknownExtension() {
CORRADE_SKIP("Currently this hits an internal assert, which can't be tested."); Instance instance{NoCreate};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
Instance instance{InstanceCreateInfo{} CORRADE_COMPARE(instance.tryCreate(InstanceCreateInfo{}
.addEnabledExtensions({"VK_this_doesnt_exist"_s})}; .addEnabledExtensions({"VK_this_doesnt_exist"_s})), Result::ErrorExtensionNotPresent);
CORRADE_COMPARE(out.str(), "TODO"); CORRADE_COMPARE(out.str(), "Vk::Instance::tryCreate(): instance creation failed: Vk::Result::ErrorExtensionNotPresent\n");
} }
void InstanceVkTest::wrap() { void InstanceVkTest::wrap() {
@ -515,7 +494,8 @@ void InstanceVkTest::wrap() {
{ {
/* Wrapping should load the basic function pointers */ /* Wrapping should load the basic function pointers */
auto wrapped = Instance::wrap(instance, Version::Vk11, { Instance wrapped{NoCreate};
wrapped.wrap(instance, Version::Vk11, {
Extensions::EXT::debug_report::string() Extensions::EXT::debug_report::string()
}, HandleFlag::DestroyOnDestruction); }, HandleFlag::DestroyOnDestruction);
CORRADE_VERIFY(wrapped->DestroyInstance); CORRADE_VERIFY(wrapped->DestroyInstance);
@ -540,11 +520,26 @@ void InstanceVkTest::wrap() {
} }
/* ...so we can wrap it again, non-owned, and then destroy it manually */ /* ...so we can wrap it again, non-owned, and then destroy it manually */
auto wrapped = Instance::wrap(instance, Version::Vk10, {}); Instance wrapped{NoCreate};
wrapped.wrap(instance, Version::Vk10, {});
CORRADE_VERIFY(wrapped->DestroyInstance); CORRADE_VERIFY(wrapped->DestroyInstance);
wrapped->DestroyInstance(instance, nullptr); wrapped->DestroyInstance(instance, nullptr);
} }
void InstanceVkTest::wrapAlreadyCreated() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
Instance instance;
CORRADE_VERIFY(instance.handle());
std::ostringstream out;
Error redirectError{&out};
instance.wrap({}, {}, {});
CORRADE_COMPARE(out.str(), "Vk::Instance::wrap(): instance already created\n");
}
void InstanceVkTest::populateGlobalFunctionPointers() { void InstanceVkTest::populateGlobalFunctionPointers() {
vkDestroyInstance = nullptr; vkDestroyInstance = nullptr;

4
src/Magnum/Vk/VulkanTester.cpp

@ -43,9 +43,9 @@ VulkanTester::VulkanTester(): VulkanTester{NoCreate} {
} }
VulkanTester::VulkanTester(NoCreateT): VulkanTester{NoCreate, NoCreate} { VulkanTester::VulkanTester(NoCreateT): VulkanTester{NoCreate, NoCreate} {
_instance = Vk::Instance{Vk::InstanceCreateInfo{arguments().first, arguments().second} _instance.create(Vk::InstanceCreateInfo{arguments().first, arguments().second}
.setApplicationInfo(testName(), {}) .setApplicationInfo(testName(), {})
}; );
} }
VulkanTester::VulkanTester(NoCreateT, NoCreateT): TestSuite::Tester{TestSuite::Tester::TesterConfiguration{}.setSkippedArgumentPrefixes({"magnum"})}, _instance{NoCreate}, _device{NoCreate}, _queue{NoCreate} {} VulkanTester::VulkanTester(NoCreateT, NoCreateT): TestSuite::Tester{TestSuite::Tester::TesterConfiguration{}.setSkippedArgumentPrefixes({"magnum"})}, _instance{NoCreate}, _device{NoCreate}, _queue{NoCreate} {}

Loading…
Cancel
Save