Browse Source

Vk: rework {Extension,Layer}Properties internals using ArrayTuple.

These were implemented long before ArrayTuple was a thing and while the
allocation saving optimization makes sense, the implementation is way
too error prone.

This also means Array (and thus <new> and other heavy shit) isn't
included in the headers, which leads to further slimming of compile
times across the library.
pull/494/head
Vladimír Vondruš 6 years ago
parent
commit
1940488da4
  1. 2
      doc/snippets/MagnumVk.cpp
  2. 47
      src/Magnum/Vk/ExtensionProperties.cpp
  3. 9
      src/Magnum/Vk/ExtensionProperties.h
  4. 24
      src/Magnum/Vk/LayerProperties.cpp
  5. 7
      src/Magnum/Vk/LayerProperties.h
  6. 1
      src/Magnum/Vk/Test/DeviceVkTest.cpp
  7. 1
      src/Magnum/Vk/Test/InstanceVkTest.cpp

2
doc/snippets/MagnumVk.cpp

@ -24,7 +24,7 @@
*/ */
#include <string> #include <string>
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Algorithms.h> #include <Corrade/Utility/Algorithms.h>
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>

47
src/Magnum/Vk/ExtensionProperties.cpp

@ -61,14 +61,11 @@ ExtensionProperties::ExtensionProperties(const Containers::ArrayView<const Conta
/* Allocate extra for a list of string views that we'll use to sort & /* Allocate extra for a list of string views that we'll use to sort &
search the values and a layer index so we can map the extensions back search the values and a layer index so we can map the extensions back
to which layer they come from */ to which layer they come from */
_extensions = Containers::Array<VkExtensionProperties>{ _data = Containers::ArrayTuple{
reinterpret_cast<VkExtensionProperties*>(new char[totalCount*(sizeof(VkExtensionProperties) + sizeof(Containers::StringView) + sizeof(UnsignedInt))]), {NoInit, totalCount, _extensions},
totalCount, {totalCount, _names},
[](VkExtensionProperties* data, std::size_t) { {NoInit, totalCount, _extensionLayers}
delete[] reinterpret_cast<char*>(data); };
}};
Containers::ArrayView<Containers::StringView> extensionNames{reinterpret_cast<Containers::StringView*>(_extensions.end()), totalCount};
Containers::ArrayView<UnsignedInt> extensionLayers{reinterpret_cast<UnsignedInt*>(extensionNames.end()), totalCount};
/* Query the extensions, save layer ID for each */ /* Query the extensions, save layer ID for each */
std::size_t offset = 0; std::size_t offset = 0;
@ -77,8 +74,8 @@ ExtensionProperties::ExtensionProperties(const Containers::ArrayView<const Conta
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(enumerator(state, MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(enumerator(state,
i == 0 ? nullptr : i == 0 ? nullptr :
Containers::String::nullTerminatedView(layers[i - 1]).data(), Containers::String::nullTerminatedView(layers[i - 1]).data(),
&count, reinterpret_cast<VkExtensionProperties*>(_extensions.data()) + offset)); &count, _extensions + offset));
for(std::size_t j = 0; j != count; ++j) extensionLayers[offset + j] = i; for(std::size_t j = 0; j != count; ++j) _extensionLayers[offset + j] = i;
offset += count; offset += count;
} }
@ -100,27 +97,24 @@ ExtensionProperties::ExtensionProperties(const Containers::ArrayView<const Conta
costly enumeration. */ costly enumeration. */
if(offset < totalCount) { if(offset < totalCount) {
Warning{} << "Vk::ExtensionProperties: inconsistent extension count reported by the driver, expected" << totalCount << "but got only" << offset; Warning{} << "Vk::ExtensionProperties: inconsistent extension count reported by the driver, expected" << totalCount << "but got only" << offset;
extensionNames = {extensionNames, offset}; _names = {_names, offset};
extensionLayers = {extensionLayers, offset}; _extensionLayers = {_extensionLayers, offset};
} else CORRADE_INTERNAL_ASSERT(offset == totalCount); } else CORRADE_INTERNAL_ASSERT(offset == totalCount);
/* Populate the views, sort them and remove duplicates so we can search in /* Populate the views, sort them and remove duplicates so we can search in
O(log n) later */ O(log n) later */
for(std::size_t i = 0; i != extensionNames.size(); ++i) for(std::size_t i = 0; i != _names.size(); ++i)
extensionNames[i] = _extensions[i].extensionName; _names[i] = _extensions[i].extensionName;
std::sort(extensionNames.begin(), extensionNames.end()); std::sort(_names.begin(), _names.end());
_uniqueExtensionCount = std::unique(extensionNames.begin(), extensionNames.end()) - extensionNames.begin(); _names = _names.prefix(std::unique(_names.begin(), _names.end()));
} }
Containers::ArrayView<const Containers::StringView> ExtensionProperties::names() const { Containers::ArrayView<const Containers::StringView> ExtensionProperties::names() const {
return {reinterpret_cast<const Containers::StringView*>(_extensions.end()), _uniqueExtensionCount}; return _names;
} }
bool ExtensionProperties::isSupported(const Containers::StringView extension) const { bool ExtensionProperties::isSupported(const Containers::StringView extension) const {
return std::binary_search( return std::binary_search(_names.begin(), _names.end(), extension);
reinterpret_cast<const Containers::StringView*>(_extensions.end()),
reinterpret_cast<const Containers::StringView*>(_extensions.end()) + _uniqueExtensionCount,
extension);
} }
bool ExtensionProperties::isSupported(const Extension& extension) const { bool ExtensionProperties::isSupported(const Extension& extension) const {
@ -148,12 +142,9 @@ UnsignedInt ExtensionProperties::revision(const UnsignedInt id) const {
} }
UnsignedInt ExtensionProperties::revision(const Containers::StringView extension) const { UnsignedInt ExtensionProperties::revision(const Containers::StringView extension) const {
/* Thanks, C++, for forcing me to do one more comparison than strictly /* Thanks, C++, for forcing me to have a larger bug surface instead of
necessary */ providing a library helper to find the damn thing. */
auto found = std::lower_bound( auto found = std::lower_bound(_names.begin(), _names.end(), extension);
reinterpret_cast<const Containers::StringView*>(_extensions.end()),
reinterpret_cast<const Containers::StringView*>(_extensions.end()) + _uniqueExtensionCount,
extension);
if(*found != extension) return 0; if(*found != extension) return 0;
/* The view target is contents of the VkExtensionProperties structure, /* The view target is contents of the VkExtensionProperties structure,
@ -164,7 +155,7 @@ UnsignedInt ExtensionProperties::revision(const Containers::StringView extension
UnsignedInt ExtensionProperties::layer(const UnsignedInt id) const { UnsignedInt ExtensionProperties::layer(const UnsignedInt id) const {
CORRADE_ASSERT(id < _extensions.size(), CORRADE_ASSERT(id < _extensions.size(),
"Vk::xtensionProperties::layer(): index" << id << "out of range for" << _extensions.size() << "entries", {}); "Vk::xtensionProperties::layer(): index" << id << "out of range for" << _extensions.size() << "entries", {});
return reinterpret_cast<const UnsignedInt*>(reinterpret_cast<const Containers::StringView*>(_extensions.end()) + _extensions.size())[id]; return _extensionLayers[id];
} }
InstanceExtensionProperties::InstanceExtensionProperties(InstanceExtensionProperties&&) noexcept = default; InstanceExtensionProperties::InstanceExtensionProperties(InstanceExtensionProperties&&) noexcept = default;

9
src/Magnum/Vk/ExtensionProperties.h

@ -30,7 +30,8 @@
* @m_since_latest * @m_since_latest
*/ */
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/ArrayView.h>
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
@ -180,8 +181,10 @@ class MAGNUM_VK_EXPORT ExtensionProperties {
explicit ExtensionProperties(const Containers::ArrayView<const Containers::StringView> layers, VkResult(*enumerator)(void*, const char*, UnsignedInt*, VkExtensionProperties*), void* state); explicit ExtensionProperties(const Containers::ArrayView<const Containers::StringView> layers, VkResult(*enumerator)(void*, const char*, UnsignedInt*, VkExtensionProperties*), void* state);
Containers::Array<VkExtensionProperties> _extensions; Containers::ArrayTuple _data;
std::size_t _uniqueExtensionCount; Containers::ArrayView<VkExtensionProperties> _extensions;
Containers::ArrayView<Containers::StringView> _names;
Containers::ArrayView<UnsignedInt> _extensionLayers;
}; };
/** /**

24
src/Magnum/Vk/LayerProperties.cpp

@ -43,14 +43,11 @@ LayerProperties::~LayerProperties() = default;
LayerProperties& LayerProperties::operator=(LayerProperties&&) noexcept = default; LayerProperties& LayerProperties::operator=(LayerProperties&&) noexcept = default;
Containers::ArrayView<const Containers::StringView> LayerProperties::names() { Containers::ArrayView<const Containers::StringView> LayerProperties::names() {
return {reinterpret_cast<const Containers::StringView*>(_layers.end()), _layers.size()}; return _names;
} }
bool LayerProperties::isSupported(const Containers::StringView layer) { bool LayerProperties::isSupported(const Containers::StringView layer) {
return std::binary_search( return std::binary_search(_names.begin(), _names.end(), layer);
reinterpret_cast<const Containers::StringView*>(_layers.end()),
reinterpret_cast<const Containers::StringView*>(_layers.end()) + _layers.size(),
layer);
} }
UnsignedInt LayerProperties::count() { UnsignedInt LayerProperties::count() {
@ -95,22 +92,19 @@ LayerProperties enumerateLayerProperties() {
/* Allocate extra for a list of string views that we'll use to sort & /* Allocate extra for a list of string views that we'll use to sort &
search the values; query the layers */ search the values; query the layers */
out._layers = Containers::Array<VkLayerProperties>{ out._data = Containers::ArrayTuple{
reinterpret_cast<VkLayerProperties*>(new char[count*(sizeof(VkLayerProperties) + sizeof(Containers::StringView))]), {NoInit, count, out._layers},
count, {count, out._names}
[](VkLayerProperties* data, std::size_t) { };
delete[] reinterpret_cast<char*>(data);
}};
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkEnumerateInstanceLayerProperties(&count, out._layers.data())); MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkEnumerateInstanceLayerProperties(&count, out._layers.data()));
/* Expect the layer count didn't change between calls */ /* Expect the layer count didn't change between calls */
CORRADE_INTERNAL_ASSERT(count == out._layers.size()); CORRADE_INTERNAL_ASSERT(count == out._layers.size());
/* Populate the views and sort them so we can search in O(log n) later */ /* 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 != out._names.size(); ++i)
for(std::size_t i = 0; i != layerNames.size(); ++i) out._names[i] = out._layers[i].layerName;
layerNames[i] = out._layers[i].layerName; std::sort(out._names.begin(), out._names.end());
std::sort(layerNames.begin(), layerNames.end());
return out; return out;
} }

7
src/Magnum/Vk/LayerProperties.h

@ -30,7 +30,8 @@
* @m_since_latest * @m_since_latest
*/ */
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/ArrayView.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
@ -146,7 +147,9 @@ class MAGNUM_VK_EXPORT LayerProperties {
explicit LayerProperties(); explicit LayerProperties();
Containers::Array<VkLayerProperties> _layers; Containers::ArrayTuple _data;
Containers::ArrayView<VkLayerProperties> _layers;
Containers::ArrayView<Containers::StringView> _names;
}; };
/** /**

1
src/Magnum/Vk/Test/DeviceVkTest.cpp

@ -24,6 +24,7 @@
*/ */
#include <sstream> #include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h> #include <Corrade/Containers/StringStl.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>

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

@ -24,6 +24,7 @@
*/ */
#include <sstream> #include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringStl.h> #include <Corrade/Containers/StringStl.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>

Loading…
Cancel
Save