Browse Source

Vk: device extension enumeration.

pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
d28442e9b1
  1. 2
      doc/vulkan-mapping.dox
  2. 13
      src/Magnum/Vk/DeviceProperties.cpp
  3. 15
      src/Magnum/Vk/DeviceProperties.h
  4. 7
      src/Magnum/Vk/ExtensionProperties.h
  5. 124
      src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp

2
doc/vulkan-mapping.dox

@ -165,7 +165,7 @@ Vulkan function | Matching API
Vulkan function | Matching API Vulkan function | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@fn_vk{EnumerateDeviceLayerProperties} @m_class{m-label m-danger} **deprecated in 1.0.13** | not exposed, [spec commit](https://github.com/KhronosGroup/Vulkan-Docs/commit/2656f459333b3a1dc63619a9ebd83490eea22e93) @fn_vk{EnumerateDeviceLayerProperties} @m_class{m-label m-danger} **deprecated in 1.0.13** | not exposed, [spec commit](https://github.com/KhronosGroup/Vulkan-Docs/commit/2656f459333b3a1dc63619a9ebd83490eea22e93)
@fn_vk{EnumerateDeviceExtensionProperties} | | @fn_vk{EnumerateDeviceExtensionProperties} | @ref DeviceProperties::enumerateExtensionProperties()
@fn_vk{EnumerateInstanceExtensionProperties} | @ref enumerateInstanceExtensionProperties() @fn_vk{EnumerateInstanceExtensionProperties} | @ref enumerateInstanceExtensionProperties()
@fn_vk{EnumerateInstanceLayerProperties} | @ref enumerateLayerProperties() @fn_vk{EnumerateInstanceLayerProperties} | @ref enumerateLayerProperties()
@fn_vk{EnumerateInstanceVersion} @m_class{m-label m-flat m-success} **1.1** | @ref enumerateInstanceVersion() @fn_vk{EnumerateInstanceVersion} @m_class{m-label m-flat m-success} **1.1** | @ref enumerateInstanceVersion()

13
src/Magnum/Vk/DeviceProperties.cpp

@ -30,6 +30,8 @@
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#include "Magnum/Vk/Instance.h" #include "Magnum/Vk/Instance.h"
#include "Magnum/Vk/ExtensionProperties.h"
#include "Magnum/Vk/LayerProperties.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
#include "Magnum/Vk/Implementation/InstanceState.h" #include "Magnum/Vk/Implementation/InstanceState.h"
@ -80,6 +82,17 @@ void DeviceProperties::getPropertiesImplementation11(DeviceProperties& self, VkP
return (**self._instance).GetPhysicalDeviceProperties2(self._handle, &properties); return (**self._instance).GetPhysicalDeviceProperties2(self._handle, &properties);
} }
ExtensionProperties DeviceProperties::enumerateExtensionProperties(Containers::ArrayView<const Containers::StringView> layers) {
return InstanceExtensionProperties{layers, [](void* state, const char* const layer, UnsignedInt* count, VkExtensionProperties* properties) {
auto& deviceProperties = *static_cast<DeviceProperties*>(state);
return (**deviceProperties._instance).EnumerateDeviceExtensionProperties(deviceProperties._handle, layer, count, properties);
}, this};
}
ExtensionProperties DeviceProperties::enumerateExtensionProperties(std::initializer_list<Containers::StringView> layers) {
return enumerateExtensionProperties(Containers::arrayView(layers));
}
Containers::Array<DeviceProperties> enumerateDevices(Instance& instance) { Containers::Array<DeviceProperties> enumerateDevices(Instance& instance) {
/* Retrieve total device count */ /* Retrieve total device count */
UnsignedInt count; UnsignedInt count;

15
src/Magnum/Vk/DeviceProperties.h

@ -30,6 +30,7 @@
* @m_since_latest * @m_since_latest
*/ */
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/Reference.h> #include <Corrade/Containers/Reference.h>
@ -182,6 +183,20 @@ class MAGNUM_VK_EXPORT DeviceProperties {
*/ */
Containers::StringView name(); Containers::StringView name();
/**
* @brief Enumerate device extensions
* @param layers Additional layers to list extensions from
*
* Expects that all listed layers are supported --- however they don't
* need to be enabled on the instance.
* @see @ref LayerProperties::isSupported(),
* @fn_vk_keyword{EnumerateDeviceExtensionProperties}
*/
ExtensionProperties enumerateExtensionProperties(Containers::ArrayView<const Containers::StringView> layers = {});
/** @overload */
ExtensionProperties enumerateExtensionProperties(std::initializer_list<Containers::StringView> layers);
private: private:
friend Implementation::InstanceState; friend Implementation::InstanceState;

7
src/Magnum/Vk/ExtensionProperties.h

@ -45,6 +45,8 @@ namespace Magnum { namespace Vk {
@brief Extension properties @brief Extension properties
@m_since_latest @m_since_latest
Provides a searchable container of Vulkan device extensions enumerated with
@ref DeviceProperties::enumerateExtensionProperties().
@see @ref InstanceExtensionProperties, @type_vk_keyword{ExtensionProperties} @see @ref InstanceExtensionProperties, @type_vk_keyword{ExtensionProperties}
*/ */
class MAGNUM_VK_EXPORT ExtensionProperties { class MAGNUM_VK_EXPORT ExtensionProperties {
@ -52,7 +54,9 @@ class MAGNUM_VK_EXPORT ExtensionProperties {
/** /**
* @brief Construct without populating the contents * @brief Construct without populating the contents
* *
* Equivalent to a moved-from state. * Equivalent to a moved-from state. Move over the result of
* @ref DeviceProperties::enumerateExtensionProperties() to make it
* usable.
*/ */
explicit ExtensionProperties(NoCreateT); explicit ExtensionProperties(NoCreateT);
@ -238,6 +242,7 @@ class MAGNUM_VK_EXPORT InstanceExtensionProperties: public ExtensionProperties {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
/* The DAMN THING forgets parameter name if this is present, FFS. It /* The DAMN THING forgets parameter name if this is present, FFS. It
also lists this among friends, which is AN IMPLEMENTATION DETAIL */ also lists this among friends, which is AN IMPLEMENTATION DETAIL */
friend DeviceProperties;
friend MAGNUM_VK_EXPORT InstanceExtensionProperties enumerateInstanceExtensionProperties(Containers::ArrayView<const Containers::StringView>); friend MAGNUM_VK_EXPORT InstanceExtensionProperties enumerateInstanceExtensionProperties(Containers::ArrayView<const Containers::StringView>);
#endif #endif

124
src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp

@ -23,13 +23,19 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <sstream>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Vk/DeviceProperties.h" #include "Magnum/Vk/DeviceProperties.h"
#include "Magnum/Vk/Extensions.h"
#include "Magnum/Vk/ExtensionProperties.h"
#include "Magnum/Vk/Instance.h" #include "Magnum/Vk/Instance.h"
#include "Magnum/Vk/LayerProperties.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
#include "Magnum/Vk/Version.h" #include "Magnum/Vk/Version.h"
@ -42,13 +48,31 @@ struct DevicePropertiesVkTest: TestSuite::Tester {
void constructMove(); void constructMove();
void wrap(); void wrap();
/* Most of this tested already in ExtensionPropertiesVkTest, this only
covers what isn't there already */
void enumerateExtensions();
void enumerateExtensionsWithKhronosValidationLayer();
void enumerateExtensionsNonexistentLayer();
void extensionConstructMove();
void extensionIsSupported();
void extensionNamedRevision();
Instance _instance; Instance _instance;
}; };
DevicePropertiesVkTest::DevicePropertiesVkTest(): _instance{InstanceCreateInfo{arguments().first, arguments().second}} { DevicePropertiesVkTest::DevicePropertiesVkTest(): _instance{InstanceCreateInfo{arguments().first, arguments().second}} {
addTests({&DevicePropertiesVkTest::enumerate, addTests({&DevicePropertiesVkTest::enumerate,
&DevicePropertiesVkTest::constructMove, &DevicePropertiesVkTest::constructMove,
&DevicePropertiesVkTest::wrap}); &DevicePropertiesVkTest::wrap,
&DevicePropertiesVkTest::enumerateExtensions,
&DevicePropertiesVkTest::enumerateExtensionsWithKhronosValidationLayer,
&DevicePropertiesVkTest::enumerateExtensionsNonexistentLayer,
&DevicePropertiesVkTest::extensionConstructMove,
&DevicePropertiesVkTest::extensionIsSupported,
&DevicePropertiesVkTest::extensionNamedRevision});
} }
void DevicePropertiesVkTest::enumerate() { void DevicePropertiesVkTest::enumerate() {
@ -105,6 +129,104 @@ void DevicePropertiesVkTest::wrap() {
CORRADE_COMPARE(wrapped.name(), devices[0].name()); CORRADE_COMPARE(wrapped.name(), devices[0].name());
} }
void DevicePropertiesVkTest::enumerateExtensions() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
ExtensionProperties properties = devices[0].enumerateExtensionProperties();
Debug{} << "Available device extension count:" << properties.names().size();
CORRADE_COMPARE_AS(properties.count(), 0, TestSuite::Compare::Greater);
/* The extension list should be sorted and unique (so Less, not
LessOrEqual) */
Containers::ArrayView<const Containers::StringView> extensions = properties.names();
for(std::size_t i = 1; i != extensions.size(); ++i) {
CORRADE_COMPARE_AS(extensions[i - 1], extensions[i],
TestSuite::Compare::Less);
}
}
void DevicePropertiesVkTest::enumerateExtensionsWithKhronosValidationLayer() {
if(!enumerateLayerProperties().isSupported("VK_LAYER_KHRONOS_validation"))
CORRADE_SKIP("VK_LAYER_KHRONOS_validation not supported, can't test");
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
/* There should be more extensions with this layer enabled */
ExtensionProperties global = devices[0].enumerateExtensionProperties();
ExtensionProperties withKhronosValidation = devices[0].enumerateExtensionProperties({"VK_LAYER_KHRONOS_validation"});
CORRADE_COMPARE_AS(global.count(),
withKhronosValidation.count(),
TestSuite::Compare::Less);
/* VK_EXT_tooling_info is only in the layer */
CORRADE_VERIFY(!global.isSupported("VK_EXT_tooling_info"));
CORRADE_VERIFY(withKhronosValidation.isSupported("VK_EXT_tooling_info"));
}
void DevicePropertiesVkTest::enumerateExtensionsNonexistentLayer() {
CORRADE_SKIP("Currently this hits an internal assert, which can't be tested.");
std::ostringstream out;
Error redirectError{&out};
enumerateInstanceExtensionProperties({"VK_LAYER_this_doesnt_exist"});
CORRADE_COMPARE(out.str(), "TODO");
}
void DevicePropertiesVkTest::extensionConstructMove() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
ExtensionProperties a = devices[0].enumerateExtensionProperties();
const UnsignedInt count = a.count();
if(!count) CORRADE_SKIP("No extensions reported, can't test");
ExtensionProperties b = std::move(a);
CORRADE_COMPARE(b.count(), count);
ExtensionProperties c{NoCreate};
c = std::move(b);
CORRADE_COMPARE(c.count(), count);
CORRADE_VERIFY(std::is_nothrow_move_constructible<ExtensionProperties>::value);
CORRADE_VERIFY(std::is_nothrow_move_assignable<ExtensionProperties>::value);
}
void DevicePropertiesVkTest::extensionIsSupported() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
ExtensionProperties properties = devices[0].enumerateExtensionProperties();
/* This extension should be available almost always */
if(!properties.isSupported("VK_KHR_maintenance1"))
CORRADE_SKIP("VK_KHR_maintenance1 not supported, can't fully test");
/* Verify the overloads that take our extension wrappers work as well */
CORRADE_VERIFY(properties.isSupported<Extensions::KHR::maintenance1>());
CORRADE_VERIFY(properties.isSupported(Extensions::KHR::maintenance1{}));
}
void DevicePropertiesVkTest::extensionNamedRevision() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
ExtensionProperties properties = devices[0].enumerateExtensionProperties();
/* This extension should be available almost always */
if(!properties.isSupported("VK_KHR_maintenance1"))
CORRADE_SKIP("VK_KHR_maintenance1 not supported, can't fully test");
/* This isn't tested in ExtensionPropertiesVkTest because there's an
overload which takes only InstanceExtensions */
CORRADE_COMPARE_AS(properties.revision<Extensions::KHR::maintenance1>(), 0,
TestSuite::Compare::GreaterOrEqual);
CORRADE_COMPARE_AS(properties.revision(Extensions::KHR::maintenance1{}), 0,
TestSuite::Compare::GreaterOrEqual);
}
}}}} }}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesVkTest) CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesVkTest)

Loading…
Cancel
Save