mirror of https://github.com/mosra/magnum.git
Browse Source
Instance layers, with the same interface designed to be reused for device-level layers.pull/234/head
8 changed files with 485 additions and 2 deletions
@ -0,0 +1,118 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020 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 "LayerProperties.h" |
||||
|
||||
#include <algorithm> |
||||
#include <Corrade/Containers/StringView.h> |
||||
|
||||
#include "Magnum/Vk/Result.h" |
||||
|
||||
namespace Magnum { namespace Vk { |
||||
|
||||
LayerProperties::LayerProperties(NoCreateT) {} |
||||
|
||||
LayerProperties::LayerProperties() = default; |
||||
|
||||
LayerProperties::LayerProperties(LayerProperties&&) noexcept = default; |
||||
|
||||
LayerProperties::~LayerProperties() = default; |
||||
|
||||
LayerProperties& LayerProperties::operator=(LayerProperties&&) noexcept = default; |
||||
|
||||
Containers::ArrayView<const Containers::StringView> LayerProperties::names() { |
||||
return {reinterpret_cast<const Containers::StringView*>(_layers.end()), _layers.size()}; |
||||
} |
||||
|
||||
bool LayerProperties::isSupported(const Containers::StringView layer) { |
||||
return std::binary_search( |
||||
reinterpret_cast<const Containers::StringView*>(_layers.end()), |
||||
reinterpret_cast<const Containers::StringView*>(_layers.end()) + _layers.size(), |
||||
layer); |
||||
} |
||||
|
||||
UnsignedInt LayerProperties::count() { |
||||
return UnsignedInt(_layers.size()); |
||||
} |
||||
|
||||
Containers::StringView LayerProperties::name(const UnsignedInt id) { |
||||
CORRADE_ASSERT(id < _layers.size(), |
||||
"Vk::LayerProperties::name(): index" << id << "out of range for" << _layers.size() << "entries", {}); |
||||
/* Not returning the string views at the end because those are in a
|
||||
different order */ |
||||
return _layers[id].layerName; |
||||
} |
||||
|
||||
UnsignedInt LayerProperties::revision(const UnsignedInt id) { |
||||
CORRADE_ASSERT(id < _layers.size(), |
||||
"Vk::LayerProperties::revision(): index" << id << "out of range for" << _layers.size() << "entries", {}); |
||||
return _layers[id].implementationVersion; |
||||
} |
||||
|
||||
Version LayerProperties::version(const UnsignedInt id) { |
||||
CORRADE_ASSERT(id < _layers.size(), |
||||
"Vk::LayerProperties::version(): index" << id << "out of range for" << _layers.size() << "entries", {}); |
||||
return Version(_layers[id].specVersion); |
||||
} |
||||
|
||||
Containers::StringView LayerProperties::description(const UnsignedInt id) { |
||||
CORRADE_ASSERT(id < _layers.size(), |
||||
"Vk::LayerProperties::description(): index" << id << "out of range for" << _layers.size() << "entries", {}); |
||||
return _layers[id].description; |
||||
} |
||||
|
||||
LayerProperties enumerateLayerProperties() { |
||||
LayerProperties out; |
||||
|
||||
/* Retrieve layer count */ |
||||
UnsignedInt count; |
||||
MAGNUM_VK_INTERNAL_ASSERT_RESULT(vkEnumerateInstanceLayerProperties(&count, nullptr)); |
||||
|
||||
/* No layers, nothing to do */ |
||||
if(!count) return out; |
||||
|
||||
/* Allocate extra for a list of string views that we'll use to sort &
|
||||
search the values; query the layers */ |
||||
out._layers = Containers::Array<VkLayerProperties>{ |
||||
reinterpret_cast<VkLayerProperties*>(new char[count*(sizeof(VkLayerProperties) + sizeof(Containers::StringView))]), |
||||
count, |
||||
[](VkLayerProperties* data, std::size_t) { |
||||
delete[] reinterpret_cast<char*>(data); |
||||
}}; |
||||
MAGNUM_VK_INTERNAL_ASSERT_RESULT(vkEnumerateInstanceLayerProperties(&count, out._layers.data())); |
||||
|
||||
/* Expect the layer count didn't change between calls */ |
||||
CORRADE_INTERNAL_ASSERT(count == out._layers.size()); |
||||
|
||||
/* Populate the views and sort them so we can search in O(log n) later */ |
||||
Containers::ArrayView<Containers::StringView> layerNames{reinterpret_cast<Containers::StringView*>(out._layers.end()), count}; |
||||
for(std::size_t i = 0; i != layerNames.size(); ++i) |
||||
layerNames[i] = out._layers[i].layerName; |
||||
std::sort(layerNames.begin(), layerNames.end()); |
||||
|
||||
return out; |
||||
} |
||||
|
||||
}} |
||||
@ -0,0 +1,157 @@
|
||||
#ifndef Magnum_Vk_LayerProperties_h |
||||
#define Magnum_Vk_LayerProperties_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020 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. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class @ref Magnum::Vk::LayerProperties, function @ref Magnum::Vk::enumerateLayerProperties() |
||||
* @m_since_latest |
||||
*/ |
||||
|
||||
#include <Corrade/Containers/Array.h> |
||||
|
||||
#include "Magnum/Magnum.h" |
||||
#include "Magnum/Tags.h" |
||||
#include "Magnum/Vk/Vk.h" |
||||
#include "Magnum/Vk/Vulkan.h" |
||||
#include "Magnum/Vk/visibility.h" |
||||
|
||||
namespace Magnum { namespace Vk { |
||||
|
||||
/**
|
||||
@brief Vulkan layer properties |
||||
@m_since_latest |
||||
|
||||
Provides a searchable container of Vulkan layers enumerated with |
||||
@ref enumerateLayerProperties(). Only instance layers are enumerated, as device |
||||
layers are [deprecated since Vulkan 1.0.13](https://github.com/KhronosGroup/Vulkan-Docs/commit/2656f459333b3a1dc63619a9ebd83490eea22e93)
|
||||
and the assumption is that no drivers currently use rely on these anymore. See |
||||
[§ 37.3.1](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap38.html#extendingvulkan-layers-devicelayerdeprecation)
|
||||
for more information. |
||||
@see @ref ExtensionProperties, @ref enumerateInstanceExtensionProperties(), |
||||
@type_vk_keyword{LayerProperties} |
||||
*/ |
||||
class MAGNUM_VK_EXPORT LayerProperties { |
||||
public: |
||||
/**
|
||||
* @brief Construct without populating the contents |
||||
* |
||||
* Equivalent to a moved-from state. Move over the result of |
||||
* @ref enumerateLayerProperties() to make it usable. |
||||
*/ |
||||
explicit LayerProperties(NoCreateT); |
||||
|
||||
~LayerProperties(); |
||||
|
||||
/** @brief Copying is not allowed */ |
||||
LayerProperties(const LayerProperties&) = delete; |
||||
|
||||
/** @brief Move constructor */ |
||||
LayerProperties(LayerProperties&&) noexcept; |
||||
|
||||
/** @brief Copying is not allowed */ |
||||
LayerProperties& operator=(const LayerProperties&) = delete; |
||||
|
||||
/** @brief Move assignment */ |
||||
LayerProperties& operator=(LayerProperties&&) noexcept; |
||||
|
||||
/**
|
||||
* @brief Layer names |
||||
* |
||||
* A list of all layers reported by the driver. Use @ref isSupported() |
||||
* to query support of a particular layer name. Note that the list is |
||||
* sorted and thus may be different than the order in which the |
||||
* @ref name(), @ref revision(), @ref version() and @ref description() |
||||
* accessors return values. |
||||
* |
||||
* The returned views are owned by the @ref LayerProperties instance |
||||
* (i.e., *not* a global memory). |
||||
*/ |
||||
Containers::ArrayView<const Containers::StringView> names(); |
||||
|
||||
/**
|
||||
* @brief Whether given layer is supported |
||||
* |
||||
* Search complexity is @f$ \mathcal{O}(\log n) @f$ in the total layer |
||||
* count. |
||||
*/ |
||||
bool isSupported(Containers::StringView layer); |
||||
|
||||
/** @brief Count of layers reported by the driver */ |
||||
UnsignedInt count(); |
||||
|
||||
/**
|
||||
* @brief Layer name |
||||
* @param id Layer index, expected to be smaller than @ref count() |
||||
* |
||||
* The returned view is owned by the @ref LayerProperties instance |
||||
* (i.e., *not* a global memory). |
||||
*/ |
||||
Containers::StringView name(UnsignedInt id); |
||||
|
||||
/**
|
||||
* @brief Layer revision |
||||
* @param id Layer index, expected to be smaller than @ref count() |
||||
*/ |
||||
UnsignedInt revision(UnsignedInt id); |
||||
|
||||
/**
|
||||
* @brief Vulkan version the layer is implemented against |
||||
* @param id Layer index, expected to be smaller than @ref count() |
||||
*/ |
||||
Version version(UnsignedInt id); |
||||
|
||||
/**
|
||||
* @brief Layer description |
||||
* @param id Layer index, expected to be smaller than @ref count() |
||||
* |
||||
* The returned view is owned by the @ref LayerProperties instance |
||||
* (i.e., *not* a global memory). |
||||
*/ |
||||
Containers::StringView description(UnsignedInt id); |
||||
|
||||
private: |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
/* The DAMN THING lists this among friends, which is AN IMPLEMENTATION
|
||||
DETAIL */ |
||||
friend MAGNUM_VK_EXPORT LayerProperties enumerateLayerProperties(); |
||||
#endif |
||||
|
||||
explicit LayerProperties(); |
||||
|
||||
Containers::Array<VkLayerProperties> _layers; |
||||
}; |
||||
|
||||
/**
|
||||
@brief Enumerate instance layers |
||||
@m_since_latest |
||||
|
||||
@see @fn_vk_keyword{EnumerateInstanceLayerProperties} |
||||
*/ |
||||
MAGNUM_VK_EXPORT LayerProperties enumerateLayerProperties(); |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020 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 <Corrade/TestSuite/Tester.h> |
||||
|
||||
#include "Magnum/Vk/LayerProperties.h" |
||||
|
||||
namespace Magnum { namespace Vk { namespace Test { namespace { |
||||
|
||||
struct LayerPropertiesTest: TestSuite::Tester { |
||||
explicit LayerPropertiesTest(); |
||||
|
||||
void constructNoCreate(); |
||||
void constructCopy(); |
||||
}; |
||||
|
||||
LayerPropertiesTest::LayerPropertiesTest() { |
||||
addTests({&LayerPropertiesTest::constructNoCreate, |
||||
&LayerPropertiesTest::constructCopy}); |
||||
} |
||||
|
||||
void LayerPropertiesTest::constructNoCreate() { |
||||
{ |
||||
LayerProperties properties{NoCreate}; |
||||
CORRADE_COMPARE(properties.count(), 0); |
||||
} |
||||
|
||||
/* Implicit construction is not allowed */ |
||||
CORRADE_VERIFY(!(std::is_convertible<NoCreateT, LayerProperties>::value)); |
||||
} |
||||
|
||||
void LayerPropertiesTest::constructCopy() { |
||||
CORRADE_VERIFY(!(std::is_constructible<LayerProperties, const LayerProperties&>{})); |
||||
CORRADE_VERIFY(!(std::is_assignable<LayerProperties, const LayerProperties&>{})); |
||||
} |
||||
|
||||
}}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::Vk::Test::LayerPropertiesTest) |
||||
@ -0,0 +1,142 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020 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 <sstream> |
||||
#include <Corrade/Containers/StringStl.h> |
||||
#include <Corrade/TestSuite/Tester.h> |
||||
#include <Corrade/TestSuite/Compare/Numeric.h> |
||||
#include <Corrade/Utility/DebugStl.h> |
||||
#include <Corrade/Utility/FormatStl.h> |
||||
|
||||
#include "Magnum/Vk/LayerProperties.h" |
||||
#include "Magnum/Vk/Version.h" |
||||
|
||||
namespace Magnum { namespace Vk { namespace Test { namespace { |
||||
|
||||
struct LayerPropertiesVkTest: TestSuite::Tester { |
||||
explicit LayerPropertiesVkTest(); |
||||
|
||||
void constructMove(); |
||||
|
||||
void enumerate(); |
||||
void outOfRange(); |
||||
void isSupported(); |
||||
}; |
||||
|
||||
LayerPropertiesVkTest::LayerPropertiesVkTest() { |
||||
addTests({&LayerPropertiesVkTest::constructMove, |
||||
|
||||
&LayerPropertiesVkTest::enumerate, |
||||
&LayerPropertiesVkTest::outOfRange, |
||||
&LayerPropertiesVkTest::isSupported}); |
||||
} |
||||
|
||||
using namespace Containers::Literals; |
||||
|
||||
void LayerPropertiesVkTest::constructMove() { |
||||
LayerProperties a = enumerateLayerProperties(); |
||||
const UnsignedInt count = a.count(); |
||||
if(!count) CORRADE_SKIP("No extensions reported, can't test"); |
||||
|
||||
LayerProperties b = std::move(a); |
||||
CORRADE_COMPARE(b.count(), count); |
||||
|
||||
LayerProperties c{NoCreate}; |
||||
c = std::move(b); |
||||
CORRADE_COMPARE(c.count(), count); |
||||
|
||||
CORRADE_VERIFY(std::is_nothrow_move_constructible<LayerProperties>::value); |
||||
CORRADE_VERIFY(std::is_nothrow_move_assignable<LayerProperties>::value); |
||||
} |
||||
|
||||
void LayerPropertiesVkTest::enumerate() { |
||||
LayerProperties properties = enumerateLayerProperties(); |
||||
|
||||
if(!properties.count()) |
||||
CORRADE_SKIP("The driver reported no instance layers, can't test."); |
||||
|
||||
CORRADE_COMPARE(properties.count(), properties.names().size()); |
||||
Debug{} << "Available instance layers:" << properties.names(); |
||||
|
||||
Containers::ArrayView<const Containers::StringView> names = properties.names(); |
||||
CORRADE_COMPARE_AS(names.size(), 0, TestSuite::Compare::Greater); |
||||
/* The list should be sorted */ |
||||
for(std::size_t i = 1; i != names.size(); ++i) { |
||||
CORRADE_COMPARE_AS(names[i - 1], names[i], |
||||
TestSuite::Compare::Less); |
||||
} |
||||
|
||||
CORRADE_COMPARE_AS(properties.name(0).size(), "VK_LAYER_"_s.size(), |
||||
TestSuite::Compare::Greater); |
||||
CORRADE_COMPARE_AS(properties.revision(0), 0, |
||||
TestSuite::Compare::Greater); |
||||
CORRADE_COMPARE_AS(properties.version(0), Version::Vk10, |
||||
TestSuite::Compare::GreaterOrEqual); |
||||
CORRADE_COMPARE_AS(properties.description(0).size(), 10, |
||||
TestSuite::Compare::Greater); |
||||
} |
||||
|
||||
void LayerPropertiesVkTest::outOfRange() { |
||||
#ifdef CORRADE_NO_ASSERT |
||||
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
||||
#endif |
||||
|
||||
LayerProperties properties = enumerateLayerProperties(); |
||||
const UnsignedInt count = properties.count(); |
||||
|
||||
std::ostringstream out; |
||||
Error redirectError{&out}; |
||||
properties.name(count); |
||||
properties.revision(count); |
||||
properties.version(count); |
||||
properties.description(count); |
||||
CORRADE_COMPARE(out.str(), Utility::formatString( |
||||
"Vk::LayerProperties::name(): index {0} out of range for {0} entries\n" |
||||
"Vk::LayerProperties::revision(): index {0} out of range for {0} entries\n" |
||||
"Vk::LayerProperties::version(): index {0} out of range for {0} entries\n" |
||||
"Vk::LayerProperties::description(): index {0} out of range for {0} entries\n", count)); |
||||
} |
||||
|
||||
void LayerPropertiesVkTest::isSupported() { |
||||
LayerProperties properties = enumerateLayerProperties(); |
||||
|
||||
CORRADE_VERIFY(!properties.isSupported("this layer doesn't exist")); |
||||
|
||||
if(!properties.count()) |
||||
CORRADE_SKIP("The driver reported no instance layers, can't fully test."); |
||||
|
||||
for(UnsignedInt i = 0; i != properties.count(); ++i) { |
||||
CORRADE_ITERATION(properties.name(i)); |
||||
CORRADE_VERIFY(properties.isSupported(properties.name(i))); |
||||
} |
||||
|
||||
/* Verify that we're not just comparing a prefix */ |
||||
const std::string layer = std::string(properties.name(0)) + "_hello"; |
||||
CORRADE_VERIFY(!properties.isSupported(layer)); |
||||
} |
||||
|
||||
}}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::Vk::Test::LayerPropertiesVkTest) |
||||
Loading…
Reference in new issue