Make ActiveDescriptorSet movable and non-copyable

There should only ever be a single instance of a `ActiveDescriptorSet` that tracks the lifetime of a descriptor set as the destructor is responsible for freeing the descriptor set.

There are cases where a new object inheriting the descriptor set needs to be created in these cases we need to have move semantics and make the destructor of the prior object inert, this allows for moving to the new object without any side effects. If the copy constructor was used in these cases the older object would free the set on its destruction which would lead to the set being invalid on existing instances which is incorrect behavior and would likely lead to driver crashes.
This commit is contained in:
PixelyIon 2022-01-04 13:48:05 +05:30
parent bb14af4f7a
commit 08f29f7da4
2 changed files with 17 additions and 3 deletions

View File

@ -38,10 +38,17 @@ namespace skyline::gpu {
pool->freeSetCount--; pool->freeSetCount--;
} }
DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(DescriptorAllocator::ActiveDescriptorSet &&other) noexcept {
pool = std::move(other.pool);
static_cast<vk::DescriptorSet &>(*this) = std::exchange(static_cast<vk::DescriptorSet &>(other), vk::DescriptorSet{});
}
DescriptorAllocator::ActiveDescriptorSet::~ActiveDescriptorSet() { DescriptorAllocator::ActiveDescriptorSet::~ActiveDescriptorSet() {
std::scoped_lock lock(*pool); if (static_cast<vk::DescriptorSet &>(*this)) {
pool->getDevice().freeDescriptorSets(**pool, 1, this, *pool->getDispatcher()); std::scoped_lock lock(*pool);
pool->freeSetCount++; pool->getDevice().freeDescriptorSets(**pool, 1, this, *pool->getDispatcher());
pool->freeSetCount++;
}
} }
DescriptorAllocator::DescriptorAllocator(GPU &gpu) : gpu(gpu) { DescriptorAllocator::DescriptorAllocator(GPU &gpu) : gpu(gpu) {

View File

@ -50,6 +50,13 @@ namespace skyline::gpu {
ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pool, vk::DescriptorSet set); ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pool, vk::DescriptorSet set);
public: public:
ActiveDescriptorSet(ActiveDescriptorSet &&other) noexcept;
/* Delete the move constructor to prevent early freeing of the descriptor set */
ActiveDescriptorSet(const ActiveDescriptorSet &) = delete;
ActiveDescriptorSet &operator=(const ActiveDescriptorSet &) = delete;
~ActiveDescriptorSet(); ~ActiveDescriptorSet();
}; };