From f4f8612f7e60ffa610268a1e80cf303feecefa26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 12 May 2020 18:11:02 +0200 Subject: [PATCH] Vk: wrap VkResult, add an assert macro for it. --- src/Magnum/Vk/CMakeLists.txt | 37 ++++--- src/Magnum/Vk/Result.cpp | 65 ++++++++++++ src/Magnum/Vk/Result.h | 162 ++++++++++++++++++++++++++++++ src/Magnum/Vk/Test/CMakeLists.txt | 1 + src/Magnum/Vk/Test/ResultTest.cpp | 87 ++++++++++++++++ src/Magnum/Vk/Vk.h | 6 +- 6 files changed, 341 insertions(+), 17 deletions(-) create mode 100644 src/Magnum/Vk/Result.cpp create mode 100644 src/Magnum/Vk/Result.h create mode 100644 src/Magnum/Vk/Test/ResultTest.cpp diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index c5f9c4afa..83a99e511 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -26,39 +26,44 @@ find_package(Vulkan REQUIRED) -set(MagnumVk_SRCS ) +set(MagnumVk_SRCS + Result.cpp) + set(MagnumVk_GracefulAssert_SRCS Enums.cpp) + set(MagnumVk_HEADERS Enums.h Integration.h + Result.h Vk.h Vulkan.h visibility.h) + set(MagnumVk_PRIVATE_HEADERS Implementation/compressedPixelFormatMapping.hpp Implementation/pixelFormatMapping.hpp Implementation/vertexFormatMapping.hpp) # Objects shared between main and test library -# add_library(MagnumVkObjects OBJECT -# ${MagnumVk_SRCS} -# ${MagnumVk_HEADERS} -# ${MagnumVk_PRIVATE_HEADERS}) -# target_include_directories(MagnumVkObjects PUBLIC -# $) -# if(NOT BUILD_STATIC) -# target_compile_definitions(MagnumVkObjects PRIVATE "MagnumVkObjects_EXPORTS" "FlextVk_EXPORTS") -# endif() -# if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) -# set_target_properties(MagnumVkObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) -# endif() -# set_target_properties(MagnumVkObjects PROPERTIES FOLDER "Magnum/Vk") +add_library(MagnumVkObjects OBJECT + ${MagnumVk_SRCS} + ${MagnumVk_HEADERS} + ${MagnumVk_PRIVATE_HEADERS}) +target_include_directories(MagnumVkObjects PUBLIC + $) +if(NOT BUILD_STATIC) + target_compile_definitions(MagnumVkObjects PRIVATE "MagnumVkObjects_EXPORTS" "FlextVk_EXPORTS") +endif() +if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) + set_target_properties(MagnumVkObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() +set_target_properties(MagnumVkObjects PROPERTIES FOLDER "Magnum/Vk") # Vk library add_library(MagnumVk ${SHARED_OR_STATIC} -# $ + $ $ ${MagnumVk_GracefulAssert_SRCS}) set_target_properties(MagnumVk PROPERTIES @@ -86,7 +91,7 @@ install(FILES ${MagnumVk_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Vk) if(BUILD_TESTS) # Library with graceful assert for testing add_library(MagnumVkTestLib ${SHARED_OR_STATIC} -# $ + $ $ ${MagnumVk_GracefulAssert_SRCS}) set_target_properties(MagnumVkTestLib PROPERTIES diff --git a/src/Magnum/Vk/Result.cpp b/src/Magnum/Vk/Result.cpp new file mode 100644 index 000000000..940069689 --- /dev/null +++ b/src/Magnum/Vk/Result.cpp @@ -0,0 +1,65 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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 "Result.h" + +#include + +namespace Magnum { namespace Vk { + +Debug& operator<<(Debug& debug, const Result value) { + debug << "Vk::Result" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::Result::value: return debug << "::" << Debug::nospace << #value; + _c(Success) + _c(NotReady) + _c(Timeout) + _c(EventSet) + _c(EventReset) + _c(Incomplete) + _c(ErrorOutOfHostMemory) + _c(ErrorOutOfDeviceMemory) + _c(ErrorInitializationFailed) + _c(ErrorDeviceLost) + _c(ErrorMemoryMapFailed) + _c(ErrorLayerNotPresent) + _c(ErrorExtensionNotPresent) + _c(ErrorFeatureNotPresent) + _c(ErrorIncompatibleDriver) + _c(ErrorTooManyObjects) + _c(ErrorFormatNotSupported) + _c(ErrorFragmentedPool) + _c(ErrorUnknown) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +}} diff --git a/src/Magnum/Vk/Result.h b/src/Magnum/Vk/Result.h new file mode 100644 index 000000000..9e1fc1149 --- /dev/null +++ b/src/Magnum/Vk/Result.h @@ -0,0 +1,162 @@ +#ifndef Magnum_Vk_Result_h +#define Magnum_Vk_Result_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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 Enum @ref Magnum::Vk::Result, macro @ref MAGNUM_VK_INTERNAL_ASSERT_RESULT() + * @m_since_latest + */ + +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Result +@m_since_latest + +Wraps a @type_vk_keyword{Result}. +@m_enum_values_as_keywords +@see @ref MAGNUM_VK_INTERNAL_ASSERT_RESULT() +*/ +enum class Result: Int { + /** Command successfully completed */ + Success = VK_SUCCESS, + + /** A fence or query has not yet completed */ + NotReady = VK_NOT_READY, + + /** A wait operation has not completed in the specified time */ + Timeout = VK_TIMEOUT, + + /** An event is signaled */ + EventSet = VK_EVENT_SET, + + /** An event is unsignaled */ + EventReset = VK_EVENT_RESET, + + /** A return array was too small for the result */ + Incomplete = VK_INCOMPLETE, + + /** A host memory allocation has failed */ + ErrorOutOfHostMemory = VK_ERROR_OUT_OF_HOST_MEMORY, + + /** A device memory allocation has failed */ + ErrorOutOfDeviceMemory = VK_ERROR_OUT_OF_DEVICE_MEMORY, + + /** + * Initialization of an object could not be completed for + * implementation-specific reasons + */ + ErrorInitializationFailed = VK_ERROR_INITIALIZATION_FAILED, + + /** The logical or physical device has been lost */ + ErrorDeviceLost = VK_ERROR_DEVICE_LOST, + + /** Mapping of a memory object has failed */ + ErrorMemoryMapFailed = VK_ERROR_MEMORY_MAP_FAILED, + + /** A requested layer is not present or could not be loaded */ + ErrorLayerNotPresent = VK_ERROR_LAYER_NOT_PRESENT, + + /** A requested extension is not supported */ + ErrorExtensionNotPresent = VK_ERROR_EXTENSION_NOT_PRESENT, + + /** A requested feature is not supported */ + ErrorFeatureNotPresent = VK_ERROR_FEATURE_NOT_PRESENT, + + /** + * The requested version of Vulkan is not supported by the driver or is + * otherwise incompatible for implementation-specific reasons + */ + ErrorIncompatibleDriver = VK_ERROR_INCOMPATIBLE_DRIVER, + + /** Too many objects of the type have already been created */ + ErrorTooManyObjects = VK_ERROR_TOO_MANY_OBJECTS, + + /** A requested format is not supported on this device */ + ErrorFormatNotSupported = VK_ERROR_FORMAT_NOT_SUPPORTED, + + /** + * A pool allocation has failed due to fragmentation of the pool's memory + */ + ErrorFragmentedPool = VK_ERROR_FRAGMENTED_POOL, + + /** + * An unknown error has occurred; either the application has provided + * invalid input, or an implementation failure has occurred + */ + ErrorUnknown = VK_ERROR_UNKNOWN +}; + +/** +@debugoperatorenum{Result} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, Result value); + +/** +@brief Assert that a Vulkan function call doesn't fail +@m_since_latest + +Compared to using @ref CORRADE_INTERNAL_ASSERT_OUTPUT() to verify that +@cpp call == VK_SUCCESS @ce, this macro also prints the result value. Otherwise +the behavior is the same, including interactions with +@ref CORRADE_STANDARD_ASSERT and @ref CORRADE_NO_ASSERT. Works with both plain +Vulkan functions returning @type_vk{Result} and APIs returning +@ref Magnum::Vk::Result "Vk::Result". + +You can override this implementation by placing your own +@cpp #define MAGNUM_VK_INTERNAL_ASSERT_RESULT @ce before including the +@ref Magnum/Vk/Result.h header. +*/ +#ifndef MAGNUM_VK_INTERNAL_ASSERT_RESULT +#if defined(CORRADE_NO_ASSERT) || (defined(CORRADE_STANDARD_ASSERT) && defined(NDEBUG)) +#define MAGNUM_VK_INTERNAL_ASSERT_RESULT(call) \ + static_cast(call) +#elif defined(CORRADE_STANDARD_ASSERT) +#define MAGNUM_VK_INTERNAL_ASSERT_RESULT(call) \ + assert(Magnum::Vk::Result(call) == Magnum::Vk::Result::Success) +#else +#define MAGNUM_VK_INTERNAL_ASSERT_RESULT(call) \ + do { \ + const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) = Magnum::Vk::Result(call); \ + if(_CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) != Magnum::Vk::Result::Success) { \ + Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << "Call " #call " failed with" << _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) << "at " __FILE__ ":" CORRADE_LINE_STRING; \ + std::abort(); \ + } \ + } while(false) +#endif +#endif + +}} + +#endif diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index ea38061a0..9948569df 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -26,3 +26,4 @@ corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkIntegrationTest IntegrationTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk) diff --git a/src/Magnum/Vk/Test/ResultTest.cpp b/src/Magnum/Vk/Test/ResultTest.cpp new file mode 100644 index 000000000..2e200ca6c --- /dev/null +++ b/src/Magnum/Vk/Test/ResultTest.cpp @@ -0,0 +1,87 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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 +#include +#include +#include + +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct ResultTest: TestSuite::Tester { + explicit ResultTest(); + + void assertResult(); + void assertVkResult(); + + void debug(); + + bool _failAssertResult, _failAssertVkResult; +}; + +ResultTest::ResultTest(): TestSuite::Tester{TesterConfiguration{}.setSkippedArgumentPrefixes({"fail-on"})} { + addTests({&ResultTest::assertResult, + &ResultTest::assertVkResult, + + &ResultTest::debug}); + + Utility::Arguments args{"fail-on"}; + args.addOption("assert-result", "false").setHelp("assert-result", "fail on MAGNUM_VK_INTERNAL_ASSERT_RESULT() with Vk::Result", "BOOL") + .addOption("assert-vk-result", "false").setHelp("assert-vk-result", "fail on MAGNUM_VK_INTERNAL_ASSERT_RESULT() with VkResult", "BOOL") + .parse(arguments().first, arguments().second); + + _failAssertResult = args.value("assert-result"); + _failAssertVkResult = args.value("assert-vk-result"); +} + +void ResultTest::assertResult() { + Result a = Result::ErrorUnknown; + + Result r = _failAssertResult ? Result::ErrorFragmentedPool : Result::Success; + MAGNUM_VK_INTERNAL_ASSERT_RESULT(a = r); + + CORRADE_COMPARE(a, Result::Success); +} + +void ResultTest::assertVkResult() { + VkResult a = VK_ERROR_UNKNOWN; + + VkResult r = _failAssertVkResult ? VK_ERROR_FRAGMENTED_POOL : VK_SUCCESS; + MAGNUM_VK_INTERNAL_ASSERT_RESULT(a = r); + + CORRADE_COMPARE(Result(a), Result::Success); +} + +void ResultTest::debug() { + std::ostringstream out; + Debug{&out} << Result::ErrorExtensionNotPresent << Result(-10007655); + CORRADE_COMPARE(out.str(), "Vk::Result::ErrorExtensionNotPresent Vk::Result(-10007655)\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::ResultTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index bc7a50b34..cae3d1d96 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -29,9 +29,13 @@ * @brief Forward declarations for the @ref Magnum::Vk namespace */ -namespace Magnum { namespace Vk { +#include "Magnum/Magnum.h" +namespace Magnum { namespace Vk { +#ifndef DOXYGEN_GENERATING_OUTPUT +enum class Result: Int; +#endif }}