Browse Source

Vk: querying device queue family properties.

pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
81cafc9ddf
  1. 2
      doc/vulkan-mapping.dox
  2. 2
      src/Magnum/Vk/CMakeLists.txt
  3. 108
      src/Magnum/Vk/DeviceProperties.cpp
  4. 118
      src/Magnum/Vk/DeviceProperties.h
  5. 3
      src/Magnum/Vk/Implementation/InstanceState.cpp
  6. 1
      src/Magnum/Vk/Implementation/InstanceState.h
  7. 18
      src/Magnum/Vk/Test/DevicePropertiesTest.cpp
  8. 73
      src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp
  9. 5
      src/Magnum/Vk/Vk.h

2
doc/vulkan-mapping.dox

@ -209,7 +209,7 @@ Vulkan function | Matching API
@fn_vk{GetPhysicalDeviceImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{GetPhysicalDeviceMemoryProperties}, \n @fn_vk{GetPhysicalDeviceMemoryProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceMemoryProperties}, \n @fn_vk{GetPhysicalDeviceMemoryProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{GetPhysicalDeviceProperties}, \n @fn_vk{GetPhysicalDeviceProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties @fn_vk{GetPhysicalDeviceProperties}, \n @fn_vk{GetPhysicalDeviceProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties
@fn_vk{GetPhysicalDeviceQueueFamilyProperties}, \n @fn_vk{GetPhysicalDeviceQueueFamilyProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceQueueFamilyProperties}, \n @fn_vk{GetPhysicalDeviceQueueFamilyProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties::queueFamilyProperties()
@fn_vk{GetPhysicalDeviceSparseImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceSparseImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceSparseImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceSparseImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{GetPipelineCacheData} | | @fn_vk{GetPipelineCacheData} | |
@fn_vk{GetQueryPoolResults} | | @fn_vk{GetQueryPoolResults} | |

2
src/Magnum/Vk/CMakeLists.txt

@ -27,7 +27,6 @@
find_package(Vulkan REQUIRED) find_package(Vulkan REQUIRED)
set(MagnumVk_SRCS set(MagnumVk_SRCS
DeviceProperties.cpp
Extensions.cpp Extensions.cpp
Handle.cpp Handle.cpp
Instance.cpp Instance.cpp
@ -38,6 +37,7 @@ set(MagnumVk_SRCS
Implementation/InstanceState.cpp) Implementation/InstanceState.cpp)
set(MagnumVk_GracefulAssert_SRCS set(MagnumVk_GracefulAssert_SRCS
DeviceProperties.cpp
Enums.cpp Enums.cpp
ExtensionProperties.cpp ExtensionProperties.cpp
LayerProperties.cpp) LayerProperties.cpp)

108
src/Magnum/Vk/DeviceProperties.cpp

@ -26,6 +26,7 @@
#include "DeviceProperties.h" #include "DeviceProperties.h"
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Arguments.h> #include <Corrade/Utility/Arguments.h>
@ -42,6 +43,7 @@ namespace Magnum { namespace Vk {
struct DeviceProperties::State { struct DeviceProperties::State {
VkPhysicalDeviceProperties2 properties{}; VkPhysicalDeviceProperties2 properties{};
Containers::Array<VkQueueFamilyProperties2> queueFamilyProperties;
}; };
DeviceProperties::DeviceProperties(NoCreateT) noexcept: _instance{}, _handle{} {} DeviceProperties::DeviceProperties(NoCreateT) noexcept: _instance{}, _handle{} {}
@ -96,6 +98,84 @@ ExtensionProperties DeviceProperties::enumerateExtensionProperties(std::initiali
return enumerateExtensionProperties(Containers::arrayView(layers)); return enumerateExtensionProperties(Containers::arrayView(layers));
} }
Containers::ArrayView<const VkQueueFamilyProperties2> DeviceProperties::queueFamilyProperties() {
if(!_state) _state.emplace();
/* Fetch if not already */
if(_state->queueFamilyProperties.empty()) {
UnsignedInt count;
_instance->state().getPhysicalDeviceQueueFamilyPropertiesImplementation(*this, count, nullptr);
_state->queueFamilyProperties = Containers::Array<VkQueueFamilyProperties2>{Containers::ValueInit, count};
for(VkQueueFamilyProperties2& i: _state->queueFamilyProperties)
i.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
_instance->state().getPhysicalDeviceQueueFamilyPropertiesImplementation(*this, count, _state->queueFamilyProperties);
CORRADE_INTERNAL_ASSERT(count == _state->queueFamilyProperties.size());
}
return _state->queueFamilyProperties;
}
void DeviceProperties::getQueueFamilyPropertiesImplementationDefault(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties) {
(**self._instance).GetPhysicalDeviceQueueFamilyProperties(self._handle, &count, reinterpret_cast<VkQueueFamilyProperties*>(properties));
/* "Sparsen" the returned data to the version 2 structure layout. If the
pointer is null we were just querying the count. */
if(properties) {
Containers::ArrayView<VkQueueFamilyProperties> src{reinterpret_cast<VkQueueFamilyProperties*>(properties), count};
Containers::ArrayView<VkQueueFamilyProperties2> dst{properties, count};
/* Go backwards so we don't overwrite the yet-to-be-processed data,
additionally copy the VkQueueFamilyProperties first so we don't
overwrite them by setting sType and pNext. */
for(std::size_t i = count; i != 0; --i) {
dst[i - 1].queueFamilyProperties = src[i - 1];
dst[i - 1].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
dst[i - 1].pNext = nullptr;
}
}
}
void DeviceProperties::getQueueFamilyPropertiesImplementationKHR(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties) {
return (**self._instance).GetPhysicalDeviceQueueFamilyProperties2KHR(self._handle, &count, properties);
}
void DeviceProperties::getQueueFamilyPropertiesImplementation11(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties) {
return (**self._instance).GetPhysicalDeviceQueueFamilyProperties2(self._handle, &count, properties);
}
UnsignedInt DeviceProperties::queueFamilyCount() {
return queueFamilyProperties().size();
}
UnsignedInt DeviceProperties::queueFamilySize(const UnsignedInt id) {
const Containers::ArrayView<const VkQueueFamilyProperties2> properties = queueFamilyProperties();
CORRADE_ASSERT(id < properties.size(),
"Vk::DeviceProperties::queueFamilySize(): index" << id << "out of range for" << properties.size() << "entries", {});
return properties[id].queueFamilyProperties.queueCount;
}
QueueFlags DeviceProperties::queueFamilyFlags(const UnsignedInt id) {
const Containers::ArrayView<const VkQueueFamilyProperties2> properties = queueFamilyProperties();
CORRADE_ASSERT(id < properties.size(),
"Vk::DeviceProperties::queueFamilyFlags(): index" << id << "out of range for" << properties.size() << "entries", {});
return QueueFlag(properties[id].queueFamilyProperties.queueFlags);
}
UnsignedInt DeviceProperties::pickQueueFamily(const QueueFlags flags) {
Containers::Optional<UnsignedInt> id = tryPickQueueFamily(flags);
if(id) return *id;
std::exit(1); /* LCOV_EXCL_LINE */
}
Containers::Optional<UnsignedInt> DeviceProperties::tryPickQueueFamily(const QueueFlags flags) {
const Containers::ArrayView<const VkQueueFamilyProperties2> properties = queueFamilyProperties();
for(UnsignedInt i = 0; i != properties.size(); ++i)
if(QueueFlag(properties[i].queueFamilyProperties.queueFlags) >= flags) return i;
Error{} << "Vk::DeviceProperties::tryPickQueueFamily(): no" << flags << "found among" << properties.size() << "queue families";
return {};
}
Containers::Array<DeviceProperties> enumerateDevices(Instance& instance) { Containers::Array<DeviceProperties> enumerateDevices(Instance& instance) {
/* Retrieve total device count */ /* Retrieve total device count */
UnsignedInt count; UnsignedInt count;
@ -189,4 +269,32 @@ Debug& operator<<(Debug& debug, const DeviceType value) {
return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")";
} }
Debug& operator<<(Debug& debug, const QueueFlag value) {
debug << "Vk::QueueFlag" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case Vk::QueueFlag::value: return debug << "::" << Debug::nospace << #value;
_c(Graphics)
_c(Compute)
_c(Transfer)
_c(SparseBinding)
_c(Protected)
#undef _c
/* LCOV_EXCL_STOP */
}
/* Flag bits should be in hex, unlike plain values */
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedInt(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, const QueueFlags value) {
return Containers::enumSetDebugOutput(debug, value, "Vk::QueueFlags{}", {
Vk::QueueFlag::Graphics,
Vk::QueueFlag::Compute,
Vk::QueueFlag::Transfer,
Vk::QueueFlag::SparseBinding,
Vk::QueueFlag::Protected});
}
}} }}

118
src/Magnum/Vk/DeviceProperties.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class @ref Magnum::Vk::DeviceProperties, enum @ref Magnum::Vk::DeviceType, function @ref Magnum::Vk::enumerateDevices(), @ref Magnum::Vk::pickDevice(), @ref Magnum::Vk::tryPickDevice() * @brief Class @ref Magnum::Vk::DeviceProperties, enum @ref Magnum::Vk::DeviceType, @ref Magnum::Vk::QueueFlag, enum set @ref Magnum::Vk::QueueFlags, function @ref Magnum::Vk::enumerateDevices(), @ref Magnum::Vk::pickDevice(), @ref Magnum::Vk::tryPickDevice()
* @m_since_latest * @m_since_latest
*/ */
@ -80,12 +80,61 @@ enum class DeviceType: Int {
*/ */
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceType value); MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceType value);
/**
@brief Queue flag
@m_since_latest
Wraps a @type_vk_keyword{QueueFlagBits}.
@see @ref QueueFlags, @ref DeviceProperties::queueFamilyFlags()
@m_enum_values_as_keywords
*/
enum class QueueFlag: UnsignedInt {
/** Supports graphics operations */
Graphics = VK_QUEUE_GRAPHICS_BIT,
/** Supports compute operations */
Compute = VK_QUEUE_COMPUTE_BIT,
/** Supports transfer operations */
Transfer = VK_QUEUE_TRANSFER_BIT,
/** Supports sparse memory management operations */
SparseBinding = VK_QUEUE_SPARSE_BINDING_BIT,
/** Supports protected memory operations */
Protected = VK_QUEUE_PROTECTED_BIT
};
/**
@debugoperatorclassenum{DeviceProperties,QueueFlag}
@m_since_latest
*/
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, QueueFlag value);
/**
@brief Queue flags
@m_since_latest
Type-safe wrapper for @type_vk_keyword{QueueFlags}.
@see @ref DeviceProperties::queueFamilyFlags()
*/
typedef Containers::EnumSet<QueueFlag> QueueFlags;
CORRADE_ENUMSET_OPERATORS(QueueFlags)
/**
@debugoperatorclassenum{DeviceProperties,QueueFlags}
@m_since_latest
*/
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, QueueFlags value);
/** /**
@brief Physical device properties @brief Physical device properties
@m_since_latest @m_since_latest
Wraps a @type_vk_keyword{PhysicalDevice} along with its (lazy-populated) Wraps a @type_vk_keyword{PhysicalDevice} along with its (lazy-populated)
properties. properties such as @type_vk_keyword{PhysicalDeviceProperties2} and
@type_vk_keyword{GetPhysicalDeviceQueueFamilyProperties2}.
@see @ref enumerateDevices() @see @ref enumerateDevices()
*/ */
class MAGNUM_VK_EXPORT DeviceProperties { class MAGNUM_VK_EXPORT DeviceProperties {
@ -197,6 +246,67 @@ class MAGNUM_VK_EXPORT DeviceProperties {
/** @overload */ /** @overload */
ExtensionProperties enumerateExtensionProperties(std::initializer_list<Containers::StringView> layers); ExtensionProperties enumerateExtensionProperties(std::initializer_list<Containers::StringView> layers);
/**
* @brief Queue family properties
*
* Populated lazily on first request. If Vulkan 1.1 or the
* @vk_extension{KHR,get_physical_device_properties2} extension is not
* enabled on the originating instance, only the Vulkan 1.0 subset of
* device properties is queried.
* @see @fn_vk_keyword{GetPhysicalDeviceQueueFamilyProperties2},
* @fn_vk_keyword{GetPhysicalDeviceQueueFamilyProperties}
*/
Containers::ArrayView<const VkQueueFamilyProperties2> queueFamilyProperties();
/**
* @brief Queue family count
*
* Convenience access to @ref queueFamilyProperties() internals,
* populated lazily on first request.
*/
UnsignedInt queueFamilyCount();
/**
* @brief Queue count in given family
* @param queueFamily Queue family index, expected to be smaller than
* @ref queueFamilyCount()
*
* Convenience access to @ref queueFamilyProperties() internals,
* populated lazily on first request.
*/
UnsignedInt queueFamilySize(UnsignedInt queueFamily);
/**
* @brief Queue family flags
* @param queueFamily Queue family index, expected to be smaller than
* @ref queueFamilyCount()
*
* Convenience access to @ref queueFamilyProperties() internals,
* populated lazily on first request.
*/
QueueFlags queueFamilyFlags(UnsignedInt queueFamily);
/**
* @brief Pick a queue family satisfying given flags
* @return Queue family index for use in @ref queueFamilySize() and
* @ref queueFamilyFlags()
*
* Queries queue family properties using @ref queueFamilyProperties()
* and tries to find the first that contains all @p flags. If it is not
* found, exits. See @ref tryPickQueueFamily() for an alternative that
* doesn't exit on failure.
*/
UnsignedInt pickQueueFamily(QueueFlags flags);
/**
* @brief Try to pick a queue family satisfying given flags
*
* Compared to @ref pickQueueFamily() the function returns
* @ref Containers::NullOpt if a desired family isn't found instead of
* exiting.
*/
Containers::Optional<UnsignedInt> tryPickQueueFamily(QueueFlags flags);
private: private:
friend Implementation::InstanceState; friend Implementation::InstanceState;
@ -212,6 +322,10 @@ class MAGNUM_VK_EXPORT DeviceProperties {
MAGNUM_VK_LOCAL static void getPropertiesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); MAGNUM_VK_LOCAL static void getPropertiesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceProperties2& properties);
MAGNUM_VK_LOCAL static void getPropertiesImplementation11(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); MAGNUM_VK_LOCAL static void getPropertiesImplementation11(DeviceProperties& self, VkPhysicalDeviceProperties2& properties);
MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementationDefault(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties);
MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementationKHR(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties);
MAGNUM_VK_LOCAL static void getQueueFamilyPropertiesImplementation11(DeviceProperties& self, UnsignedInt& count, VkQueueFamilyProperties2* properties);
/* Can't be a reference because of the NoCreate constructor */ /* Can't be a reference because of the NoCreate constructor */
Instance* _instance; Instance* _instance;

3
src/Magnum/Vk/Implementation/InstanceState.cpp

@ -34,10 +34,13 @@ namespace Magnum { namespace Vk { namespace Implementation {
InstanceState::InstanceState(Instance& instance, Int argc, const char** argv): argc{argc}, argv{argv} { InstanceState::InstanceState(Instance& instance, Int argc, const char** argv): argc{argc}, argv{argv} {
if(instance.isVersionSupported(Version::Vk11)) { if(instance.isVersionSupported(Version::Vk11)) {
getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementation11; getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementation11;
getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementation11;
} else if(instance.isExtensionEnabled<Extensions::KHR::get_physical_device_properties2>()) { } else if(instance.isExtensionEnabled<Extensions::KHR::get_physical_device_properties2>()) {
getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR; getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR;
getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationKHR;
} else { } else {
getPhysicalDevicePropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault; getPhysicalDevicePropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault;
getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationDefault;
} }
} }

1
src/Magnum/Vk/Implementation/InstanceState.h

@ -37,6 +37,7 @@ struct InstanceState {
const char** argv; const char** argv;
void(*getPhysicalDevicePropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&); void(*getPhysicalDevicePropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&);
void(*getPhysicalDeviceQueueFamilyPropertiesImplementation)(DeviceProperties&, UnsignedInt&, VkQueueFamilyProperties2*);
}; };
}}} }}}

18
src/Magnum/Vk/Test/DevicePropertiesTest.cpp

@ -38,13 +38,17 @@ struct DevicePropertiesTest: TestSuite::Tester {
void constructCopy(); void constructCopy();
void debugDeviceType(); void debugDeviceType();
void debugQueueFamilyPropertiesFlag();
void debugQueueFamilyPropertiesFlags();
}; };
DevicePropertiesTest::DevicePropertiesTest() { DevicePropertiesTest::DevicePropertiesTest() {
addTests({&DevicePropertiesTest::constructNoCreate, addTests({&DevicePropertiesTest::constructNoCreate,
&DevicePropertiesTest::constructCopy, &DevicePropertiesTest::constructCopy,
&DevicePropertiesTest::debugDeviceType}); &DevicePropertiesTest::debugDeviceType,
&DevicePropertiesTest::debugQueueFamilyPropertiesFlag,
&DevicePropertiesTest::debugQueueFamilyPropertiesFlags});
} }
void DevicePropertiesTest::constructNoCreate() { void DevicePropertiesTest::constructNoCreate() {
@ -68,6 +72,18 @@ void DevicePropertiesTest::debugDeviceType() {
CORRADE_COMPARE(out.str(), "Vk::DeviceType::DiscreteGpu Vk::DeviceType(-10007655)\n"); CORRADE_COMPARE(out.str(), "Vk::DeviceType::DiscreteGpu Vk::DeviceType(-10007655)\n");
} }
void DevicePropertiesTest::debugQueueFamilyPropertiesFlag() {
std::ostringstream out;
Debug{&out} << QueueFlag::SparseBinding << QueueFlag(0xdeadcafe);
CORRADE_COMPARE(out.str(), "Vk::QueueFlag::SparseBinding Vk::QueueFlag(0xdeadcafe)\n");
}
void DevicePropertiesTest::debugQueueFamilyPropertiesFlags() {
std::ostringstream out;
Debug{&out} << (QueueFlag::Compute|QueueFlag::Graphics) << QueueFlags{};
CORRADE_COMPARE(out.str(), "Vk::QueueFlag::Graphics|Vk::QueueFlag::Compute Vk::QueueFlags{}\n");
}
}}}} }}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesTest) CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesTest)

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

@ -60,6 +60,11 @@ struct DevicePropertiesVkTest: TestSuite::Tester {
void extensionIsSupported(); void extensionIsSupported();
void extensionNamedRevision(); void extensionNamedRevision();
void queueFamilies();
void queueFamiliesOutOfRange();
void queueFamiliesPick();
void queueFamiliesPickFailed();
void pickDevice(); void pickDevice();
void pickDeviceIndex(); void pickDeviceIndex();
void pickDeviceType(); void pickDeviceType();
@ -94,6 +99,11 @@ DevicePropertiesVkTest::DevicePropertiesVkTest(): _instance{InstanceCreateInfo{a
&DevicePropertiesVkTest::extensionIsSupported, &DevicePropertiesVkTest::extensionIsSupported,
&DevicePropertiesVkTest::extensionNamedRevision, &DevicePropertiesVkTest::extensionNamedRevision,
&DevicePropertiesVkTest::queueFamilies,
&DevicePropertiesVkTest::queueFamiliesOutOfRange,
&DevicePropertiesVkTest::queueFamiliesPick,
&DevicePropertiesVkTest::queueFamiliesPickFailed,
&DevicePropertiesVkTest::pickDevice, &DevicePropertiesVkTest::pickDevice,
&DevicePropertiesVkTest::pickDeviceIndex, &DevicePropertiesVkTest::pickDeviceIndex,
&DevicePropertiesVkTest::pickDeviceType}); &DevicePropertiesVkTest::pickDeviceType});
@ -254,6 +264,69 @@ void DevicePropertiesVkTest::extensionNamedRevision() {
TestSuite::Compare::GreaterOrEqual); TestSuite::Compare::GreaterOrEqual);
} }
void DevicePropertiesVkTest::queueFamilies() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
Debug{} << "Available queue family count:" << devices[0].queueFamilyCount();
CORRADE_COMPARE_AS(devices[0].queueFamilyCount(), 0,
TestSuite::Compare::Greater);
for(std::size_t i = 0; i != devices[0].queueFamilyCount(); ++i) {
CORRADE_ITERATION(i);
CORRADE_ITERATION(devices[0].queueFamilyFlags(i));
CORRADE_VERIFY(devices[0].queueFamilyFlags(i) != QueueFlags{});
CORRADE_COMPARE(devices[0].queueFamilyFlags(i), QueueFlag(devices[0].queueFamilyProperties()[i].queueFamilyProperties.queueFlags));
CORRADE_COMPARE_AS(devices[0].queueFamilySize(i), 0,
TestSuite::Compare::Greater);
CORRADE_COMPARE(devices[0].queueFamilySize(i), devices[0].queueFamilyProperties()[i].queueFamilyProperties.queueCount);
}
}
void DevicePropertiesVkTest::queueFamiliesOutOfRange() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
const UnsignedInt count = devices[0].queueFamilyCount();
std::ostringstream out;
Error redirectError{&out};
devices[0].queueFamilySize(count);
devices[0].queueFamilyFlags(count);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Vk::DeviceProperties::queueFamilySize(): index {0} out of range for {0} entries\n"
"Vk::DeviceProperties::queueFamilyFlags(): index {0} out of range for {0} entries\n", count));
}
void DevicePropertiesVkTest::queueFamiliesPick() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
Containers::Optional<UnsignedInt> id = devices[0].tryPickQueueFamily(QueueFlag::Compute|QueueFlag::Graphics);
CORRADE_VERIFY(id);
CORRADE_COMPARE_AS(*id, devices[0].queueFamilyCount(), TestSuite::Compare::Less);
CORRADE_COMPARE_AS(devices[0].queueFamilyFlags(*id),
QueueFlag::Compute|QueueFlag::Graphics,
TestSuite::Compare::GreaterOrEqual);
/* Pick should return the same ID, and shouldn't exit */
CORRADE_COMPARE(devices[0].pickQueueFamily(QueueFlag::Compute|QueueFlag::Graphics), id);
}
void DevicePropertiesVkTest::queueFamiliesPickFailed() {
Containers::Array<DeviceProperties> devices = enumerateDevices(_instance);
CORRADE_VERIFY(!devices.empty());
std::ostringstream out;
Error redirectError{&out};
CORRADE_VERIFY(!devices[0].tryPickQueueFamily(QueueFlag(0xc0ffeee0)));
CORRADE_COMPARE(out.str(), Utility::formatString(
"Vk::DeviceProperties::tryPickQueueFamily(): no Vk::QueueFlag(0xc0ffeee0) found among {} queue families\n", devices[0].queueFamilyCount()));
}
void DevicePropertiesVkTest::pickDevice() { void DevicePropertiesVkTest::pickDevice() {
/* Default behavior */ /* Default behavior */
Containers::Optional<DeviceProperties> device = tryPickDevice(_instance); Containers::Optional<DeviceProperties> device = tryPickDevice(_instance);

5
src/Magnum/Vk/Vk.h

@ -29,6 +29,8 @@
* @brief Forward declarations for the @ref Magnum::Vk namespace * @brief Forward declarations for the @ref Magnum::Vk namespace
*/ */
#include <Corrade/Containers/Containers.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
namespace Magnum { namespace Vk { namespace Magnum { namespace Vk {
@ -45,7 +47,8 @@ class InstanceCreateInfo;
class InstanceExtension; class InstanceExtension;
class InstanceExtensionProperties; class InstanceExtensionProperties;
class LayerProperties; class LayerProperties;
enum class QueueFlag: UnsignedInt;
typedef Containers::EnumSet<QueueFlag> QueueFlags;
enum class Result: Int; enum class Result: Int;
enum class Version: UnsignedInt; enum class Version: UnsignedInt;
#endif #endif

Loading…
Cancel
Save