Browse Source

Vk: port away from std::pair in various internals.

Among other things this makes it possible to use Utility::copy() instead
of a manual loop and grow arrays with std::realloc() instead of always
new'ing-copy-deleting because Containers::Pair is trivially copyable.
pull/617/head
Vladimír Vondruš 3 years ago
parent
commit
f84a655ac7
  1. 33
      src/Magnum/Vk/DescriptorPool.cpp
  2. 6
      src/Magnum/Vk/DescriptorPool.h
  3. 21
      src/Magnum/Vk/Device.cpp
  4. 2
      src/Magnum/Vk/Device.h
  5. 2
      src/Magnum/Vk/Implementation/DeviceState.cpp
  6. 4
      src/Magnum/Vk/Implementation/DeviceState.h
  7. 11
      src/Magnum/Vk/Implementation/DriverWorkaround.cpp
  8. 6
      src/Magnum/Vk/Implementation/DriverWorkaround.h
  9. 14
      src/Magnum/Vk/RenderPass.cpp

33
src/Magnum/Vk/DescriptorPool.cpp

@ -28,6 +28,7 @@
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/DescriptorSet.h"
@ -128,7 +129,7 @@ DescriptorPool& DescriptorPool::operator=(DescriptorPool&& other) noexcept {
return *this;
}
std::pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout) {
Containers::Pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout) {
DescriptorSet set{NoCreate};
set._device = _device;
set._pool = _handle;
@ -161,19 +162,19 @@ std::pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescri
}
DescriptorSet DescriptorPool::allocate(const VkDescriptorSetLayout layout) {
std::pair<Result, DescriptorSet> out = allocateInternal(layout);
CORRADE_ASSERT(out.first == Result::Success,
"Vk::DescriptorPool::allocate(): allocation failed with" << out.first, std::move(out.second));
return std::move(out.second);
Containers::Pair<Result, DescriptorSet> out = allocateInternal(layout);
CORRADE_ASSERT(out.first() == Result::Success,
"Vk::DescriptorPool::allocate(): allocation failed with" << out.first(), std::move(out.second()));
return std::move(out.second());
}
Containers::Optional<DescriptorSet> DescriptorPool::tryAllocate(const VkDescriptorSetLayout layout) {
std::pair<Result, DescriptorSet> out = allocateInternal(layout);
if(out.first != Result::Success) return {};
return std::move(out.second);
Containers::Pair<Result, DescriptorSet> out = allocateInternal(layout);
if(out.first() != Result::Success) return {};
return std::move(out.second());
}
std::pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) {
Containers::Pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) {
DescriptorSet set{NoCreate};
set._device = _device;
set._pool = _handle;
@ -197,16 +198,16 @@ std::pair<Result, DescriptorSet> DescriptorPool::allocateInternal(const VkDescri
}
DescriptorSet DescriptorPool::allocate(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) {
std::pair<Result, DescriptorSet> out = allocateInternal(layout, variableDescriptorCount);
CORRADE_ASSERT(out.first == Result::Success,
"Vk::DescriptorPool::allocate(): allocation failed with" << out.first, std::move(out.second));
return std::move(out.second);
Containers::Pair<Result, DescriptorSet> out = allocateInternal(layout, variableDescriptorCount);
CORRADE_ASSERT(out.first() == Result::Success,
"Vk::DescriptorPool::allocate(): allocation failed with" << out.first(), std::move(out.second()));
return std::move(out.second());
}
Containers::Optional<DescriptorSet> DescriptorPool::tryAllocate(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) {
std::pair<Result, DescriptorSet> out = allocateInternal(layout, variableDescriptorCount);
if(out.first != Result::Success) return {};
return std::move(out.second);
Containers::Pair<Result, DescriptorSet> out = allocateInternal(layout, variableDescriptorCount);
if(out.first() != Result::Success) return {};
return std::move(out.second());
}
void DescriptorPool::reset() {

6
src/Magnum/Vk/DescriptorPool.h

@ -30,8 +30,6 @@
* @m_since_latest
*/
#include <utility>
#include "Magnum/Tags.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/visibility.h"
@ -248,8 +246,8 @@ class MAGNUM_VK_EXPORT DescriptorPool {
VkDescriptorPool release();
private:
MAGNUM_VK_LOCAL std::pair<Result, DescriptorSet> allocateInternal(VkDescriptorSetLayout layout);
MAGNUM_VK_LOCAL std::pair<Result, DescriptorSet> allocateInternal(VkDescriptorSetLayout layout, UnsignedInt variableDescriptorCount);
MAGNUM_VK_LOCAL Containers::Pair<Result, DescriptorSet> allocateInternal(VkDescriptorSetLayout layout);
MAGNUM_VK_LOCAL Containers::Pair<Result, DescriptorSet> allocateInternal(VkDescriptorSetLayout layout, UnsignedInt variableDescriptorCount);
/* Can't be a reference because of the NoCreate constructor */
Device* _device;

21
src/Magnum/Vk/Device.cpp

@ -105,9 +105,9 @@ struct DeviceCreateInfo::State {
Containers::String disabledExtensionsStorage;
Containers::Array<Containers::StringView> disabledExtensions;
/* .second = true means the workaround is disabled; the views always point
to the internal KnownWorkarounds array */
Containers::Array<std::pair<Containers::StringView, bool>> encounteredWorkarounds;
/* .second() = true means the workaround is disabled; the views always
point to the internal KnownWorkarounds array */
Containers::Array<Containers::Pair<Containers::StringView, bool>> encounteredWorkarounds;
Containers::Array<VkDeviceQueueCreateInfo> queues;
Containers::StaticArray<32, Float> queuePriorities;
Containers::StaticArray<32, Queue*> queueOutput;
@ -665,7 +665,7 @@ void Device::wrap(Instance& instance, const VkPhysicalDevice physicalDevice, con
/* Because we have no control over extensions / features, no workarounds
are used here -- better to just do nothing than just a partial attempt */
Containers::Array<std::pair<Containers::StringView, bool>> encounteredWorkarounds = Implementation::disableAllWorkarounds();
Containers::Array<Containers::Pair<Containers::StringView, bool>> encounteredWorkarounds = Implementation::disableAllWorkarounds();
initialize(instance, version, enabledExtensions, encounteredWorkarounds, enabledFeatures);
}
@ -762,11 +762,8 @@ Result Device::tryCreateInternal(Instance& instance, const DeviceCreateInfo& inf
/* Make a copy of the workarounds list coming from DeviceCreateInfo as
initialize() may modify it */
/** @todo switch to Containers::Pair once it exists and use Utility::copy()
(std::pair isn't trivially copyable, ffs) */
Containers::Array<std::pair<Containers::StringView, bool>> encounteredWorkarounds{info._state->encounteredWorkarounds.size()};
for(std::size_t i = 0; i != encounteredWorkarounds.size(); ++i)
encounteredWorkarounds[i] = info._state->encounteredWorkarounds[i];
Containers::Array<Containers::Pair<Containers::StringView, bool>> encounteredWorkarounds{NoInit, info._state->encounteredWorkarounds.size()};
Utility::copy(info._state->encounteredWorkarounds, encounteredWorkarounds);
/* Initialize the enabled extension list and feature-, extension-,
workaround-dependent function pointers */
@ -777,14 +774,14 @@ Result Device::tryCreateInternal(Instance& instance, const DeviceCreateInfo& inf
bool workaroundHeaderPrinted = false;
for(const auto& workaround: encounteredWorkarounds) {
/* Skip disabled workarounds */
if(workaround.second) continue;
if(workaround.second()) continue;
if(!workaroundHeaderPrinted) {
workaroundHeaderPrinted = true;
Debug{} << "Using device driver workarounds:";
}
Debug{} << " " << workaround.first;
Debug{} << " " << workaround.first();
}
}
@ -839,7 +836,7 @@ Result Device::tryCreateInternal(Instance& instance, const DeviceCreateInfo& inf
return Result::Success;
}
void Device::initialize(Instance& instance, const Version version, const Containers::StringIterable& enabledExtensions, Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, const DeviceFeatures& enabledFeatures) {
void Device::initialize(Instance& instance, const Version version, const Containers::StringIterable& enabledExtensions, Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, const DeviceFeatures& enabledFeatures) {
/* Mark all known extensions as enabled */
for(const Containers::StringView extension: enabledExtensions) {
for(const Version extensionVersion: KnownVersionsForExtensions) {

2
src/Magnum/Vk/Device.h

@ -499,7 +499,7 @@ class MAGNUM_VK_EXPORT Device {
tryCreate(Instance&, DeviceCreateInfo&&) */
Result tryCreateInternal(Instance& isntance, const DeviceCreateInfo&, DeviceProperties&&);
MAGNUM_VK_LOCAL void initialize(Instance& instance, Version version, const Containers::StringIterable& enabledExtensions, Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, const DeviceFeatures& enabledFeatures);
MAGNUM_VK_LOCAL void initialize(Instance& instance, Version version, const Containers::StringIterable& enabledExtensions, Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, const DeviceFeatures& enabledFeatures);
MAGNUM_VK_LOCAL static void getQueueImplementationDefault(Device& self, const VkDeviceQueueInfo2& info, VkQueue& queue);
MAGNUM_VK_LOCAL static void getQueueImplementation11(Device& self, const VkDeviceQueueInfo2& info, VkQueue& queue);

2
src/Magnum/Vk/Implementation/DeviceState.cpp

@ -40,7 +40,7 @@ namespace Magnum { namespace Vk { namespace Implementation {
using namespace Containers::Literals;
DeviceState::DeviceState(Device& device, Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds) {
DeviceState::DeviceState(Device& device, Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds) {
if(device.isVersionSupported(Version::Vk11)) {
if(device.properties().name().hasPrefix("SwiftShader"_s) && !Implementation::isDriverWorkaroundDisabled(encounteredWorkarounds, "swiftshader-crashy-getdevicequeue2"_s))
getDeviceQueueImplementation = &Device::getQueueImplementationDefault;

4
src/Magnum/Vk/Implementation/DeviceState.h

@ -25,8 +25,6 @@
DEALINGS IN THE SOFTWARE.
*/
#include <utility>
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
@ -39,7 +37,7 @@ class RenderPassCreateInfo;
namespace Implementation {
struct DeviceState {
explicit DeviceState(Device& device, Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds);
explicit DeviceState(Device& device, Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds);
void(*getDeviceQueueImplementation)(Device&, const VkDeviceQueueInfo2&, VkQueue&);

11
src/Magnum/Vk/Implementation/DriverWorkaround.cpp

@ -24,6 +24,7 @@
*/
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Debug.h>
@ -90,7 +91,7 @@ Containers::StringView findWorkaround(const Containers::StringView workaround) {
}
void disableWorkaround(Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, const Containers::StringView workaround) {
void disableWorkaround(Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, const Containers::StringView workaround) {
/* Find the workaround. Note that we'll add the found view to the array
and not the passed view, as the found view is guaranteed to stay in
scope */
@ -107,14 +108,14 @@ void disableWorkaround(Containers::Array<std::pair<Containers::StringView, bool>
arrayAppend(encounteredWorkarounds, InPlaceInit, found, true);
}
Containers::Array<std::pair<Containers::StringView, bool>> disableAllWorkarounds() {
Containers::Array<std::pair<Containers::StringView, bool>> encounteredWorkarounds;
Containers::Array<Containers::Pair<Containers::StringView, bool>> disableAllWorkarounds() {
Containers::Array<Containers::Pair<Containers::StringView, bool>> encounteredWorkarounds;
for(const Containers::StringView i: KnownWorkarounds)
arrayAppend(encounteredWorkarounds, InPlaceInit, i, true);
return encounteredWorkarounds;
}
bool isDriverWorkaroundDisabled(Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, const Containers::StringView workaround) {
bool isDriverWorkaroundDisabled(Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, const Containers::StringView workaround) {
/* Find the workaround. Note that we'll add the found view to the array
and not the passed view, as the found view is guaranteed to stay in
scope */
@ -126,7 +127,7 @@ bool isDriverWorkaroundDisabled(Containers::Array<std::pair<Containers::StringVi
compare just data pointers instead of the whole string as we store only
the views in the KnownWorkarounds list. */
for(const auto& i: encounteredWorkarounds)
if(i.first.data() == found.data()) return i.second;
if(i.first().data() == found.data()) return i.second();
arrayAppend(encounteredWorkarounds, InPlaceInit, found, false);
return false;
}

6
src/Magnum/Vk/Implementation/DriverWorkaround.h

@ -29,14 +29,14 @@
namespace Magnum { namespace Vk { namespace Implementation {
void disableWorkaround(Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, Containers::StringView workaround);
void disableWorkaround(Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, Containers::StringView workaround);
bool isDriverWorkaroundDisabled(Containers::Array<std::pair<Containers::StringView, bool>>& encounteredWorkarounds, Containers::StringView workaround);
bool isDriverWorkaroundDisabled(Containers::Array<Containers::Pair<Containers::StringView, bool>>& encounteredWorkarounds, Containers::StringView workaround);
/* Used by Device::wrap() -- because device extension setup is outside of our
control and the function doesn't print anything on the output, it's better
to just do nothing at all than silently enabling some subset */
Containers::Array<std::pair<Containers::StringView, bool>> disableAllWorkarounds();
Containers::Array<Containers::Pair<Containers::StringView, bool>> disableAllWorkarounds();
}}}

14
src/Magnum/Vk/RenderPass.cpp

@ -396,7 +396,7 @@ std::size_t vkSubpassDescriptionExtrasSize(const VkSubpassDescription2& descript
(description.pDepthStencilAttachment ? 1 : 0));
}
std::pair<VkSubpassDescription, std::size_t> vkSubpassDescriptionExtrasInto(const VkSubpassDescription2& description, char* const out) {
Containers::Pair<VkSubpassDescription, std::size_t> vkSubpassDescriptionExtrasInto(const VkSubpassDescription2& description, char* const out) {
/* Not using an array view nor arrayCast() because the output is not
guaranteed to be divisible by the structure size and we have nothing
else to do with the size either */
@ -455,9 +455,9 @@ Containers::Array<VkSubpassDescription> SubpassDescription::vkSubpassDescription
/* Fill it with data and return, faking a size of 1 and with a custom
deleter that correctly deletes as a char array again */
std::pair<VkSubpassDescription, std::size_t> out = vkSubpassDescriptionExtrasInto(_description, storage.exceptPrefix(sizeof(VkSubpassDescription)));
CORRADE_INTERNAL_ASSERT(out.second == extrasSize);
*reinterpret_cast<VkSubpassDescription*>(storage.data()) = out.first;
Containers::Pair<VkSubpassDescription, std::size_t> out = vkSubpassDescriptionExtrasInto(_description, storage.exceptPrefix(sizeof(VkSubpassDescription)));
CORRADE_INTERNAL_ASSERT(out.second() == extrasSize);
*reinterpret_cast<VkSubpassDescription*>(storage.data()) = out.first();
return Containers::Array<VkSubpassDescription>{
reinterpret_cast<VkSubpassDescription*>(storage.release()), 1,
[](VkSubpassDescription* data, std::size_t) {
@ -726,10 +726,10 @@ Containers::Array<VkRenderPassCreateInfo> RenderPassCreateInfo::vkRenderPassCrea
std::size_t extrasOffset = sizeof(VkRenderPassCreateInfo) + structuresSize;
info1.pSubpasses = reinterpret_cast<VkSubpassDescription*>(storage + offset);
for(std::size_t i = 0; i != _info.subpassCount; ++i) {
std::pair<VkSubpassDescription, std::size_t> out = vkSubpassDescriptionExtrasInto(_info.pSubpasses[i], storage + extrasOffset);
*reinterpret_cast<VkSubpassDescription*>(storage + offset) = out.first;
Containers::Pair<VkSubpassDescription, std::size_t> out = vkSubpassDescriptionExtrasInto(_info.pSubpasses[i], storage + extrasOffset);
*reinterpret_cast<VkSubpassDescription*>(storage + offset) = out.first();
offset += sizeof(VkSubpassDescription);
extrasOffset += out.second;
extrasOffset += out.second();
}
CORRADE_INTERNAL_ASSERT(extrasOffset == storage.size());

Loading…
Cancel
Save